Add diclaimer of copyright to _osname() manual page.
[unix-history] / gnu / usr.bin / cc / common / optabs.c
CommitLineData
9bf86ebb
PR
1/* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2 Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21#include "config.h"
22#include "rtl.h"
23#include "tree.h"
24#include "flags.h"
25#include "insn-flags.h"
26#include "insn-codes.h"
27#include "expr.h"
28#include "insn-config.h"
29#include "recog.h"
30#include "reload.h"
31#include <ctype.h>
32
33/* Each optab contains info on how this target machine
34 can perform a particular operation
35 for all sizes and kinds of operands.
36
37 The operation to be performed is often specified
38 by passing one of these optabs as an argument.
39
40 See expr.h for documentation of these optabs. */
41
42optab add_optab;
43optab sub_optab;
44optab smul_optab;
45optab smul_widen_optab;
46optab umul_widen_optab;
47optab sdiv_optab;
48optab sdivmod_optab;
49optab udiv_optab;
50optab udivmod_optab;
51optab smod_optab;
52optab umod_optab;
53optab flodiv_optab;
54optab ftrunc_optab;
55optab and_optab;
56optab ior_optab;
57optab xor_optab;
58optab ashl_optab;
59optab lshr_optab;
60optab lshl_optab;
61optab ashr_optab;
62optab rotl_optab;
63optab rotr_optab;
64optab smin_optab;
65optab smax_optab;
66optab umin_optab;
67optab umax_optab;
68
69optab mov_optab;
70optab movstrict_optab;
71
72optab neg_optab;
73optab abs_optab;
74optab one_cmpl_optab;
75optab ffs_optab;
76optab sqrt_optab;
77optab sin_optab;
78optab cos_optab;
79
80optab cmp_optab;
81optab ucmp_optab; /* Used only for libcalls for unsigned comparisons. */
82optab tst_optab;
83
84optab strlen_optab;
85
86/* Tables of patterns for extending one integer mode to another. */
87enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2];
88
89/* Tables of patterns for converting between fixed and floating point. */
90enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
91enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
92enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
93
94/* SYMBOL_REF rtx's for the library functions that are called
95 implicitly and not via optabs. */
96
97rtx extendsfdf2_libfunc;
98rtx extendsfxf2_libfunc;
99rtx extendsftf2_libfunc;
100rtx extenddfxf2_libfunc;
101rtx extenddftf2_libfunc;
102
103rtx truncdfsf2_libfunc;
104rtx truncxfsf2_libfunc;
105rtx trunctfsf2_libfunc;
106rtx truncxfdf2_libfunc;
107rtx trunctfdf2_libfunc;
108
109rtx memcpy_libfunc;
110rtx bcopy_libfunc;
111rtx memcmp_libfunc;
112rtx bcmp_libfunc;
113rtx memset_libfunc;
114rtx bzero_libfunc;
115
116rtx eqsf2_libfunc;
117rtx nesf2_libfunc;
118rtx gtsf2_libfunc;
119rtx gesf2_libfunc;
120rtx ltsf2_libfunc;
121rtx lesf2_libfunc;
122
123rtx eqdf2_libfunc;
124rtx nedf2_libfunc;
125rtx gtdf2_libfunc;
126rtx gedf2_libfunc;
127rtx ltdf2_libfunc;
128rtx ledf2_libfunc;
129
130rtx eqxf2_libfunc;
131rtx nexf2_libfunc;
132rtx gtxf2_libfunc;
133rtx gexf2_libfunc;
134rtx ltxf2_libfunc;
135rtx lexf2_libfunc;
136
137rtx eqtf2_libfunc;
138rtx netf2_libfunc;
139rtx gttf2_libfunc;
140rtx getf2_libfunc;
141rtx lttf2_libfunc;
142rtx letf2_libfunc;
143
144rtx floatsisf_libfunc;
145rtx floatdisf_libfunc;
146rtx floattisf_libfunc;
147
148rtx floatsidf_libfunc;
149rtx floatdidf_libfunc;
150rtx floattidf_libfunc;
151
152rtx floatsixf_libfunc;
153rtx floatdixf_libfunc;
154rtx floattixf_libfunc;
155
156rtx floatsitf_libfunc;
157rtx floatditf_libfunc;
158rtx floattitf_libfunc;
159
160rtx fixsfsi_libfunc;
161rtx fixsfdi_libfunc;
162rtx fixsfti_libfunc;
163
164rtx fixdfsi_libfunc;
165rtx fixdfdi_libfunc;
166rtx fixdfti_libfunc;
167
168rtx fixxfsi_libfunc;
169rtx fixxfdi_libfunc;
170rtx fixxfti_libfunc;
171
172rtx fixtfsi_libfunc;
173rtx fixtfdi_libfunc;
174rtx fixtfti_libfunc;
175
176rtx fixunssfsi_libfunc;
177rtx fixunssfdi_libfunc;
178rtx fixunssfti_libfunc;
179
180rtx fixunsdfsi_libfunc;
181rtx fixunsdfdi_libfunc;
182rtx fixunsdfti_libfunc;
183
184rtx fixunsxfsi_libfunc;
185rtx fixunsxfdi_libfunc;
186rtx fixunsxfti_libfunc;
187
188rtx fixunstfsi_libfunc;
189rtx fixunstfdi_libfunc;
190rtx fixunstfti_libfunc;
191
192/* from emit-rtl.c */
193extern rtx gen_highpart ();
194
195/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
196 gives the gen_function to make a branch to test that condition. */
197
198rtxfun bcc_gen_fctn[NUM_RTX_CODE];
199
200/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
201 gives the insn code to make a store-condition insn
202 to test that condition. */
203
204enum insn_code setcc_gen_code[NUM_RTX_CODE];
205
206static int add_equal_note PROTO((rtx, rtx, enum rtx_code, rtx, rtx));
207static void emit_float_lib_cmp PROTO((rtx, rtx, enum rtx_code));
208static enum insn_code can_fix_p PROTO((enum machine_mode, enum machine_mode,
209 int, int *));
210static enum insn_code can_float_p PROTO((enum machine_mode, enum machine_mode,
211 int));
212static rtx ftruncify PROTO((rtx));
213static optab init_optab PROTO((enum rtx_code));
214static void init_libfuncs PROTO((optab, int, int, char *, int));
215static void init_integral_libfuncs PROTO((optab, char *, int));
216static void init_floating_libfuncs PROTO((optab, char *, int));
217static void init_complex_libfuncs PROTO((optab, char *, int));
218\f
219/* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
220 the result of operation CODE applied to OP0 (and OP1 if it is a binary
221 operation).
222
223 If the last insn does not set TARGET, don't do anything, but return 1.
224
225 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
226 don't add the REG_EQUAL note but return 0. Our caller can then try
227 again, ensuring that TARGET is not one of the operands. */
228
229static int
230add_equal_note (seq, target, code, op0, op1)
231 rtx seq;
232 rtx target;
233 enum rtx_code code;
234 rtx op0, op1;
235{
236 rtx set;
237 int i;
238 rtx note;
239
240 if ((GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2'
241 && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<')
242 || GET_CODE (seq) != SEQUENCE
243 || (set = single_set (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))) == 0
244 || GET_CODE (target) == ZERO_EXTRACT
245 || (! rtx_equal_p (SET_DEST (set), target)
246 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
247 SUBREG. */
248 && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
249 || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)),
250 target))))
251 return 1;
252
253 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
254 besides the last insn. */
255 if (reg_overlap_mentioned_p (target, op0)
256 || (op1 && reg_overlap_mentioned_p (target, op1)))
257 for (i = XVECLEN (seq, 0) - 2; i >= 0; i--)
258 if (reg_set_p (target, XVECEXP (seq, 0, i)))
259 return 0;
260
261 if (GET_RTX_CLASS (code) == '1')
262 note = gen_rtx (code, GET_MODE (target), copy_rtx (op0));
263 else
264 note = gen_rtx (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
265
266 REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))
267 = gen_rtx (EXPR_LIST, REG_EQUAL, note,
268 REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1)));
269
270 return 1;
271}
272\f
273/* Generate code to perform an operation specified by BINOPTAB
274 on operands OP0 and OP1, with result having machine-mode MODE.
275
276 UNSIGNEDP is for the case where we have to widen the operands
277 to perform the operation. It says to use zero-extension.
278
279 If TARGET is nonzero, the value
280 is generated there, if it is convenient to do so.
281 In all cases an rtx is returned for the locus of the value;
282 this may or may not be TARGET. */
283
284rtx
285expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
286 enum machine_mode mode;
287 optab binoptab;
288 rtx op0, op1;
289 rtx target;
290 int unsignedp;
291 enum optab_methods methods;
292{
293 enum mode_class class;
294 enum machine_mode wider_mode;
295 register rtx temp;
296 int commutative_op = 0;
297 int shift_op = (binoptab->code == ASHIFT
298 || binoptab->code == ASHIFTRT
299 || binoptab->code == LSHIFT
300 || binoptab->code == LSHIFTRT
301 || binoptab->code == ROTATE
302 || binoptab->code == ROTATERT);
303 rtx entry_last = get_last_insn ();
304 rtx last;
305
306 class = GET_MODE_CLASS (mode);
307
308 op0 = protect_from_queue (op0, 0);
309 op1 = protect_from_queue (op1, 0);
310 if (target)
311 target = protect_from_queue (target, 1);
312
313 if (flag_force_mem)
314 {
315 op0 = force_not_mem (op0);
316 op1 = force_not_mem (op1);
317 }
318
319 /* If subtracting an integer constant, convert this into an addition of
320 the negated constant. */
321
322 if (binoptab == sub_optab && GET_CODE (op1) == CONST_INT)
323 {
324 op1 = negate_rtx (mode, op1);
325 binoptab = add_optab;
326 }
327
328 /* If we are inside an appropriately-short loop and one operand is an
329 expensive constant, force it into a register. */
330 if (CONSTANT_P (op0) && preserve_subexpressions_p ()
331 && rtx_cost (op0, binoptab->code) > 2)
332 op0 = force_reg (mode, op0);
333
334 if (CONSTANT_P (op1) && preserve_subexpressions_p ()
335 && rtx_cost (op1, binoptab->code) > 2)
336 op1 = force_reg (shift_op ? word_mode : mode, op1);
337
338 /* Record where to delete back to if we backtrack. */
339 last = get_last_insn ();
340
341 /* If operation is commutative,
342 try to make the first operand a register.
343 Even better, try to make it the same as the target.
344 Also try to make the last operand a constant. */
345 if (GET_RTX_CLASS (binoptab->code) == 'c'
346 || binoptab == smul_widen_optab
347 || binoptab == umul_widen_optab)
348 {
349 commutative_op = 1;
350
351 if (((target == 0 || GET_CODE (target) == REG)
352 ? ((GET_CODE (op1) == REG
353 && GET_CODE (op0) != REG)
354 || target == op1)
355 : rtx_equal_p (op1, target))
356 || GET_CODE (op0) == CONST_INT)
357 {
358 temp = op1;
359 op1 = op0;
360 op0 = temp;
361 }
362 }
363
364 /* If we can do it with a three-operand insn, do so. */
365
366 if (methods != OPTAB_MUST_WIDEN
367 && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
368 {
369 int icode = (int) binoptab->handlers[(int) mode].insn_code;
370 enum machine_mode mode0 = insn_operand_mode[icode][1];
371 enum machine_mode mode1 = insn_operand_mode[icode][2];
372 rtx pat;
373 rtx xop0 = op0, xop1 = op1;
374
375 if (target)
376 temp = target;
377 else
378 temp = gen_reg_rtx (mode);
379
380 /* If it is a commutative operator and the modes would match
381 if we would swap the operands, we can save the conversions. */
382 if (commutative_op)
383 {
384 if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
385 && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
386 {
387 register rtx tmp;
388
389 tmp = op0; op0 = op1; op1 = tmp;
390 tmp = xop0; xop0 = xop1; xop1 = tmp;
391 }
392 }
393
394 /* In case the insn wants input operands in modes different from
395 the result, convert the operands. */
396
397 if (GET_MODE (op0) != VOIDmode
398 && GET_MODE (op0) != mode0)
399 xop0 = convert_to_mode (mode0, xop0, unsignedp);
400
401 if (GET_MODE (xop1) != VOIDmode
402 && GET_MODE (xop1) != mode1)
403 xop1 = convert_to_mode (mode1, xop1, unsignedp);
404
405 /* Now, if insn's predicates don't allow our operands, put them into
406 pseudo regs. */
407
408 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
409 xop0 = copy_to_mode_reg (mode0, xop0);
410
411 if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
412 xop1 = copy_to_mode_reg (mode1, xop1);
413
414 if (! (*insn_operand_predicate[icode][0]) (temp, mode))
415 temp = gen_reg_rtx (mode);
416
417 pat = GEN_FCN (icode) (temp, xop0, xop1);
418 if (pat)
419 {
420 /* If PAT is a multi-insn sequence, try to add an appropriate
421 REG_EQUAL note to it. If we can't because TEMP conflicts with an
422 operand, call ourselves again, this time without a target. */
423 if (GET_CODE (pat) == SEQUENCE
424 && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
425 {
426 delete_insns_since (last);
427 return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
428 unsignedp, methods);
429 }
430
431 emit_insn (pat);
432 return temp;
433 }
434 else
435 delete_insns_since (last);
436 }
437
438 /* If this is a multiply, see if we can do a widening operation that
439 takes operands of this mode and makes a wider mode. */
440
441 if (binoptab == smul_optab && GET_MODE_WIDER_MODE (mode) != VOIDmode
442 && (((unsignedp ? umul_widen_optab : smul_widen_optab)
443 ->handlers[(int) GET_MODE_WIDER_MODE (mode)].insn_code)
444 != CODE_FOR_nothing))
445 {
446 temp = expand_binop (GET_MODE_WIDER_MODE (mode),
447 unsignedp ? umul_widen_optab : smul_widen_optab,
448 op0, op1, 0, unsignedp, OPTAB_DIRECT);
449
450 if (GET_MODE_CLASS (mode) == MODE_INT)
451 return gen_lowpart (mode, temp);
452 else
453 return convert_to_mode (mode, temp, unsignedp);
454 }
455
456 /* Look for a wider mode of the same class for which we think we
457 can open-code the operation. Check for a widening multiply at the
458 wider mode as well. */
459
460 if ((class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
461 && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
462 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
463 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
464 {
465 if (binoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing
466 || (binoptab == smul_optab
467 && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
468 && (((unsignedp ? umul_widen_optab : smul_widen_optab)
469 ->handlers[(int) GET_MODE_WIDER_MODE (wider_mode)].insn_code)
470 != CODE_FOR_nothing)))
471 {
472 rtx xop0 = op0, xop1 = op1;
473 int no_extend = 0;
474
475 /* For certain integer operations, we need not actually extend
476 the narrow operands, as long as we will truncate
477 the results to the same narrowness. Don't do this when
478 WIDER_MODE is wider than a word since a paradoxical SUBREG
479 isn't valid for such modes. */
480
481 if ((binoptab == ior_optab || binoptab == and_optab
482 || binoptab == xor_optab
483 || binoptab == add_optab || binoptab == sub_optab
484 || binoptab == smul_optab
485 || binoptab == ashl_optab || binoptab == lshl_optab)
486 && class == MODE_INT
487 && GET_MODE_SIZE (wider_mode) <= UNITS_PER_WORD)
488 no_extend = 1;
489
490 /* If an operand is a constant integer, we might as well
491 convert it since that is more efficient than using a SUBREG,
492 unlike the case for other operands. Similarly for
493 SUBREGs that were made due to promoted objects. */
494
495 if (no_extend && GET_MODE (xop0) != VOIDmode
496 && ! (GET_CODE (xop0) == SUBREG
497 && SUBREG_PROMOTED_VAR_P (xop0)))
498 xop0 = gen_rtx (SUBREG, wider_mode,
499 force_reg (GET_MODE (xop0), xop0), 0);
500 else
501 xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
502
503 if (no_extend && GET_MODE (xop1) != VOIDmode
504 && ! (GET_CODE (xop1) == SUBREG
505 && SUBREG_PROMOTED_VAR_P (xop1)))
506 xop1 = gen_rtx (SUBREG, wider_mode,
507 force_reg (GET_MODE (xop1), xop1), 0);
508 else
509 xop1 = convert_to_mode (wider_mode, xop1, unsignedp);
510
511 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
512 unsignedp, OPTAB_DIRECT);
513 if (temp)
514 {
515 if (class != MODE_INT)
516 {
517 if (target == 0)
518 target = gen_reg_rtx (mode);
519 convert_move (target, temp, 0);
520 return target;
521 }
522 else
523 return gen_lowpart (mode, temp);
524 }
525 else
526 delete_insns_since (last);
527 }
528 }
529
530 /* These can be done a word at a time. */
531 if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
532 && class == MODE_INT
533 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
534 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
535 {
536 int i;
537 rtx insns;
538 rtx equiv_value;
539
540 /* If TARGET is the same as one of the operands, the REG_EQUAL note
541 won't be accurate, so use a new target. */
542 if (target == 0 || target == op0 || target == op1)
543 target = gen_reg_rtx (mode);
544
545 start_sequence ();
546
547 /* Do the actual arithmetic. */
548 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
549 {
550 rtx target_piece = operand_subword (target, i, 1, mode);
551 rtx x = expand_binop (word_mode, binoptab,
552 operand_subword_force (op0, i, mode),
553 operand_subword_force (op1, i, mode),
554 target_piece, unsignedp, methods);
555 if (target_piece != x)
556 emit_move_insn (target_piece, x);
557 }
558
559 insns = get_insns ();
560 end_sequence ();
561
562 if (binoptab->code != UNKNOWN)
563 equiv_value
564 = gen_rtx (binoptab->code, mode, copy_rtx (op0), copy_rtx (op1));
565 else
566 equiv_value = 0;
567
568 emit_no_conflict_block (insns, target, op0, op1, equiv_value);
569 return target;
570 }
571
572 /* These can be done a word at a time by propagating carries. */
573 if ((binoptab == add_optab || binoptab == sub_optab)
574 && class == MODE_INT
575 && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
576 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
577 {
578 int i;
579 rtx carry_tmp = gen_reg_rtx (word_mode);
580 optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
581 int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
582 rtx carry_in, carry_out;
583 rtx xop0, xop1;
584
585 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
586 value is one of those, use it. Otherwise, use 1 since it is the
587 one easiest to get. */
588#if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
589 int normalizep = STORE_FLAG_VALUE;
590#else
591 int normalizep = 1;
592#endif
593
594 /* Prepare the operands. */
595 xop0 = force_reg (mode, op0);
596 xop1 = force_reg (mode, op1);
597
598 if (target == 0 || GET_CODE (target) != REG
599 || target == xop0 || target == xop1)
600 target = gen_reg_rtx (mode);
601
602 /* Indicate for flow that the entire target reg is being set. */
603 if (GET_CODE (target) == REG)
604 emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
605
606 /* Do the actual arithmetic. */
607 for (i = 0; i < nwords; i++)
608 {
609 int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
610 rtx target_piece = operand_subword (target, index, 1, mode);
611 rtx op0_piece = operand_subword_force (xop0, index, mode);
612 rtx op1_piece = operand_subword_force (xop1, index, mode);
613 rtx x;
614
615 /* Main add/subtract of the input operands. */
616 x = expand_binop (word_mode, binoptab,
617 op0_piece, op1_piece,
618 target_piece, unsignedp, methods);
619 if (x == 0)
620 break;
621
622 if (i + 1 < nwords)
623 {
624 /* Store carry from main add/subtract. */
625 carry_out = gen_reg_rtx (word_mode);
626 carry_out = emit_store_flag (carry_out,
627 binoptab == add_optab ? LTU : GTU,
628 x, op0_piece,
629 word_mode, 1, normalizep);
630 if (!carry_out)
631 break;
632 }
633
634 if (i > 0)
635 {
636 /* Add/subtract previous carry to main result. */
637 x = expand_binop (word_mode,
638 normalizep == 1 ? binoptab : otheroptab,
639 x, carry_in,
640 target_piece, 1, methods);
641 if (target_piece != x)
642 emit_move_insn (target_piece, x);
643
644 if (i + 1 < nwords)
645 {
646 /* THIS CODE HAS NOT BEEN TESTED. */
647 /* Get out carry from adding/subtracting carry in. */
648 carry_tmp = emit_store_flag (carry_tmp,
649 binoptab == add_optab
650 ? LTU : GTU,
651 x, carry_in,
652 word_mode, 1, normalizep);
653 /* Logical-ior the two poss. carry together. */
654 carry_out = expand_binop (word_mode, ior_optab,
655 carry_out, carry_tmp,
656 carry_out, 0, methods);
657 if (!carry_out)
658 break;
659 }
660 }
661
662 carry_in = carry_out;
663 }
664
665 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
666 {
667 rtx temp;
668
669 temp = emit_move_insn (target, target);
670 REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL,
671 gen_rtx (binoptab->code, mode,
672 copy_rtx (xop0),
673 copy_rtx (xop1)),
674 REG_NOTES (temp));
675 return target;
676 }
677 else
678 delete_insns_since (last);
679 }
680
681 /* If we want to multiply two two-word values and have normal and widening
682 multiplies of single-word values, we can do this with three smaller
683 multiplications. Note that we do not make a REG_NO_CONFLICT block here
684 because we are not operating on one word at a time.
685
686 The multiplication proceeds as follows:
687 _______________________
688 [__op0_high_|__op0_low__]
689 _______________________
690 * [__op1_high_|__op1_low__]
691 _______________________________________________
692 _______________________
693 (1) [__op0_low__*__op1_low__]
694 _______________________
695 (2a) [__op0_low__*__op1_high_]
696 _______________________
697 (2b) [__op0_high_*__op1_low__]
698 _______________________
699 (3) [__op0_high_*__op1_high_]
700
701
702 This gives a 4-word result. Since we are only interested in the
703 lower 2 words, partial result (3) and the upper words of (2a) and
704 (2b) don't need to be calculated. Hence (2a) and (2b) can be
705 calculated using non-widening multiplication.
706
707 (1), however, needs to be calculated with an unsigned widening
708 multiplication. If this operation is not directly supported we
709 try using a signed widening multiplication and adjust the result.
710 This adjustment works as follows:
711
712 If both operands are positive then no adjustment is needed.
713
714 If the operands have different signs, for example op0_low < 0 and
715 op1_low >= 0, the instruction treats the most significant bit of
716 op0_low as a sign bit instead of a bit with significance
717 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
718 with 2**BITS_PER_WORD - op0_low, and two's complements the
719 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
720 the result.
721
722 Similarly, if both operands are negative, we need to add
723 (op0_low + op1_low) * 2**BITS_PER_WORD.
724
725 We use a trick to adjust quickly. We logically shift op0_low right
726 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
727 op0_high (op1_high) before it is used to calculate 2b (2a). If no
728 logical shift exists, we do an arithmetic right shift and subtract
729 the 0 or -1. */
730
731 if (binoptab == smul_optab
732 && class == MODE_INT
733 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
734 && smul_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
735 && add_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
736 && ((umul_widen_optab->handlers[(int) mode].insn_code
737 != CODE_FOR_nothing)
738 || (smul_widen_optab->handlers[(int) mode].insn_code
739 != CODE_FOR_nothing)))
740 {
741 int low = (WORDS_BIG_ENDIAN ? 1 : 0);
742 int high = (WORDS_BIG_ENDIAN ? 0 : 1);
743 rtx op0_high = operand_subword_force (op0, high, mode);
744 rtx op0_low = operand_subword_force (op0, low, mode);
745 rtx op1_high = operand_subword_force (op1, high, mode);
746 rtx op1_low = operand_subword_force (op1, low, mode);
747 rtx product = 0;
748 rtx op0_xhigh;
749 rtx op1_xhigh;
750
751 /* If the target is the same as one of the inputs, don't use it. This
752 prevents problems with the REG_EQUAL note. */
753 if (target == op0 || target == op1)
754 target = 0;
755
756 /* Multiply the two lower words to get a double-word product.
757 If unsigned widening multiplication is available, use that;
758 otherwise use the signed form and compensate. */
759
760 if (umul_widen_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
761 {
762 product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
763 target, 1, OPTAB_DIRECT);
764
765 /* If we didn't succeed, delete everything we did so far. */
766 if (product == 0)
767 delete_insns_since (last);
768 else
769 op0_xhigh = op0_high, op1_xhigh = op1_high;
770 }
771
772 if (product == 0
773 && smul_widen_optab->handlers[(int) mode].insn_code
774 != CODE_FOR_nothing)
775 {
776 rtx wordm1 = GEN_INT (BITS_PER_WORD - 1);
777 product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
778 target, 1, OPTAB_DIRECT);
779 op0_xhigh = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
780 NULL_RTX, 1, OPTAB_DIRECT);
781 if (op0_xhigh)
782 op0_xhigh = expand_binop (word_mode, add_optab, op0_high,
783 op0_xhigh, op0_xhigh, 0, OPTAB_DIRECT);
784 else
785 {
786 op0_xhigh = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
787 NULL_RTX, 0, OPTAB_DIRECT);
788 if (op0_xhigh)
789 op0_xhigh = expand_binop (word_mode, sub_optab, op0_high,
790 op0_xhigh, op0_xhigh, 0,
791 OPTAB_DIRECT);
792 }
793
794 op1_xhigh = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
795 NULL_RTX, 1, OPTAB_DIRECT);
796 if (op1_xhigh)
797 op1_xhigh = expand_binop (word_mode, add_optab, op1_high,
798 op1_xhigh, op1_xhigh, 0, OPTAB_DIRECT);
799 else
800 {
801 op1_xhigh = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
802 NULL_RTX, 0, OPTAB_DIRECT);
803 if (op1_xhigh)
804 op1_xhigh = expand_binop (word_mode, sub_optab, op1_high,
805 op1_xhigh, op1_xhigh, 0,
806 OPTAB_DIRECT);
807 }
808 }
809
810 /* If we have been able to directly compute the product of the
811 low-order words of the operands and perform any required adjustments
812 of the operands, we proceed by trying two more multiplications
813 and then computing the appropriate sum.
814
815 We have checked above that the required addition is provided.
816 Full-word addition will normally always succeed, especially if
817 it is provided at all, so we don't worry about its failure. The
818 multiplication may well fail, however, so we do handle that. */
819
820 if (product && op0_xhigh && op1_xhigh)
821 {
822 rtx product_piece;
823 rtx product_high = operand_subword (product, high, 1, mode);
824 rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh,
825 NULL_RTX, 0, OPTAB_DIRECT);
826
827 if (temp)
828 {
829 product_piece = expand_binop (word_mode, add_optab, temp,
830 product_high, product_high,
831 0, OPTAB_LIB_WIDEN);
832 if (product_piece != product_high)
833 emit_move_insn (product_high, product_piece);
834
835 temp = expand_binop (word_mode, binoptab, op1_low, op0_xhigh,
836 NULL_RTX, 0, OPTAB_DIRECT);
837
838 product_piece = expand_binop (word_mode, add_optab, temp,
839 product_high, product_high,
840 0, OPTAB_LIB_WIDEN);
841 if (product_piece != product_high)
842 emit_move_insn (product_high, product_piece);
843
844 temp = emit_move_insn (product, product);
845 REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL,
846 gen_rtx (MULT, mode, copy_rtx (op0),
847 copy_rtx (op1)),
848 REG_NOTES (temp));
849
850 return product;
851 }
852 }
853
854 /* If we get here, we couldn't do it for some reason even though we
855 originally thought we could. Delete anything we've emitted in
856 trying to do it. */
857
858 delete_insns_since (last);
859 }
860
861 /* We need to open-code the complex type operations: '+, -, * and /' */
862
863 /* At this point we allow operations between two similar complex
864 numbers, and also if one of the operands is not a complex number
865 but rather of MODE_FLOAT or MODE_INT. However, the caller
866 must make sure that the MODE of the non-complex operand matches
867 the SUBMODE of the complex operand. */
868
869 if (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
870 {
871 rtx real0 = (rtx) 0;
872 rtx imag0 = (rtx) 0;
873 rtx real1 = (rtx) 0;
874 rtx imag1 = (rtx) 0;
875 rtx realr;
876 rtx imagr;
877 rtx res;
878 rtx seq;
879 rtx equiv_value;
880
881 /* Find the correct mode for the real and imaginary parts */
882 enum machine_mode submode
883 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
884 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
885 0);
886
887 if (submode == BLKmode)
888 abort ();
889
890 if (! target)
891 target = gen_reg_rtx (mode);
892
893 start_sequence ();
894
895 realr = gen_realpart (submode, target);
896 imagr = gen_imagpart (submode, target);
897
898 if (GET_MODE (op0) == mode)
899 {
900 real0 = gen_realpart (submode, op0);
901 imag0 = gen_imagpart (submode, op0);
902 }
903 else
904 real0 = op0;
905
906 if (GET_MODE (op1) == mode)
907 {
908 real1 = gen_realpart (submode, op1);
909 imag1 = gen_imagpart (submode, op1);
910 }
911 else
912 real1 = op1;
913
914 if (! real0 || ! real1 || ! (imag0 || imag1))
915 abort ();
916
917 switch (binoptab->code)
918 {
919 case PLUS:
920 /* (a+ib) + (c+id) = (a+c) + i(b+d) */
921 case MINUS:
922 /* (a+ib) - (c+id) = (a-c) + i(b-d) */
923 res = expand_binop (submode, binoptab, real0, real1,
924 realr, unsignedp, methods);
925 if (res != realr)
926 emit_move_insn (realr, res);
927
928 if (imag0 && imag1)
929 res = expand_binop (submode, binoptab, imag0, imag1,
930 imagr, unsignedp, methods);
931 else if (imag0)
932 res = imag0;
933 else if (binoptab->code == MINUS)
934 res = expand_unop (submode, neg_optab, imag1, imagr, unsignedp);
935 else
936 res = imag1;
937
938 if (res != imagr)
939 emit_move_insn (imagr, res);
940 break;
941
942 case MULT:
943 /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */
944
945 if (imag0 && imag1)
946 {
947 /* Don't fetch these from memory more than once. */
948 real0 = force_reg (submode, real0);
949 real1 = force_reg (submode, real1);
950 imag0 = force_reg (submode, imag0);
951 imag1 = force_reg (submode, imag1);
952
953 res = expand_binop (submode, sub_optab,
954 expand_binop (submode, binoptab, real0,
955 real1, 0, unsignedp, methods),
956 expand_binop (submode, binoptab, imag0,
957 imag1, 0, unsignedp, methods),
958 realr, unsignedp, methods);
959
960 if (res != realr)
961 emit_move_insn (realr, res);
962
963 res = expand_binop (submode, add_optab,
964 expand_binop (submode, binoptab,
965 real0, imag1,
966 0, unsignedp, methods),
967 expand_binop (submode, binoptab,
968 real1, imag0,
969 0, unsignedp, methods),
970 imagr, unsignedp, methods);
971 if (res != imagr)
972 emit_move_insn (imagr, res);
973 }
974 else
975 {
976 /* Don't fetch these from memory more than once. */
977 real0 = force_reg (submode, real0);
978 real1 = force_reg (submode, real1);
979
980 res = expand_binop (submode, binoptab, real0, real1,
981 realr, unsignedp, methods);
982 if (res != realr)
983 emit_move_insn (realr, res);
984
985 if (imag0)
986 res = expand_binop (submode, binoptab,
987 real1, imag0, imagr, unsignedp, methods);
988 else
989 res = expand_binop (submode, binoptab,
990 real0, imag1, imagr, unsignedp, methods);
991 if (res != imagr)
992 emit_move_insn (imagr, res);
993 }
994 break;
995
996 case DIV:
997 /* (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) */
998
999 if (! imag1)
1000 { /* (a+ib) / (c+i0) = (a/c) + i(b/c) */
1001
1002 /* Don't fetch these from memory more than once. */
1003 real1 = force_reg (submode, real1);
1004
1005 /* Simply divide the real and imaginary parts by `c' */
1006 res = expand_binop (submode, binoptab, real0, real1,
1007 realr, unsignedp, methods);
1008 if (res != realr)
1009 emit_move_insn (realr, res);
1010
1011 res = expand_binop (submode, binoptab, imag0, real1,
1012 imagr, unsignedp, methods);
1013 if (res != imagr)
1014 emit_move_insn (imagr, res);
1015 }
1016 else /* Divisor is of complex type */
1017 { /* X/(a+ib) */
1018
1019 rtx divisor;
1020 rtx real_t;
1021 rtx imag_t;
1022
1023 optab mulopt = unsignedp ? umul_widen_optab : smul_optab;
1024
1025 /* Don't fetch these from memory more than once. */
1026 real0 = force_reg (submode, real0);
1027 real1 = force_reg (submode, real1);
1028 if (imag0)
1029 imag0 = force_reg (submode, imag0);
1030 imag1 = force_reg (submode, imag1);
1031
1032 /* Divisor: c*c + d*d */
1033 divisor = expand_binop (submode, add_optab,
1034 expand_binop (submode, mulopt,
1035 real1, real1,
1036 0, unsignedp, methods),
1037 expand_binop (submode, mulopt,
1038 imag1, imag1,
1039 0, unsignedp, methods),
1040 0, unsignedp, methods);
1041
1042 if (! imag0) /* ((a)(c-id))/divisor */
1043 { /* (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)) */
1044 /* Calculate the dividend */
1045 real_t = expand_binop (submode, mulopt, real0, real1,
1046 0, unsignedp, methods);
1047
1048 imag_t
1049 = expand_unop (submode, neg_optab,
1050 expand_binop (submode, mulopt, real0, imag1,
1051 0, unsignedp, methods),
1052 0, unsignedp);
1053 }
1054 else /* ((a+ib)(c-id))/divider */
1055 {
1056 /* Calculate the dividend */
1057 real_t = expand_binop (submode, add_optab,
1058 expand_binop (submode, mulopt,
1059 real0, real1,
1060 0, unsignedp, methods),
1061 expand_binop (submode, mulopt,
1062 imag0, imag1,
1063 0, unsignedp, methods),
1064 0, unsignedp, methods);
1065
1066 imag_t = expand_binop (submode, sub_optab,
1067 expand_binop (submode, mulopt,
1068 imag0, real1,
1069 0, unsignedp, methods),
1070 expand_binop (submode, mulopt,
1071 real0, imag1,
1072 0, unsignedp, methods),
1073 0, unsignedp, methods);
1074
1075 }
1076
1077 res = expand_binop (submode, binoptab, real_t, divisor,
1078 realr, unsignedp, methods);
1079 if (res != realr)
1080 emit_move_insn (realr, res);
1081
1082 res = expand_binop (submode, binoptab, imag_t, divisor,
1083 imagr, unsignedp, methods);
1084 if (res != imagr)
1085 emit_move_insn (imagr, res);
1086 }
1087 break;
1088
1089 default:
1090 abort ();
1091 }
1092
1093 seq = get_insns ();
1094 end_sequence ();
1095
1096 if (binoptab->code != UNKNOWN)
1097 equiv_value
1098 = gen_rtx (binoptab->code, mode, copy_rtx (op0), copy_rtx (op1));
1099 else
1100 equiv_value = 0;
1101
1102 emit_no_conflict_block (seq, target, op0, op1, equiv_value);
1103
1104 return target;
1105 }
1106
1107 /* It can't be open-coded in this mode.
1108 Use a library call if one is available and caller says that's ok. */
1109
1110 if (binoptab->handlers[(int) mode].libfunc
1111 && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
1112 {
1113 rtx insns;
1114 rtx funexp = binoptab->handlers[(int) mode].libfunc;
1115 rtx op1x = op1;
1116 enum machine_mode op1_mode = mode;
1117
1118 start_sequence ();
1119
1120 if (shift_op)
1121 {
1122 op1_mode = word_mode;
1123 /* Specify unsigned here,
1124 since negative shift counts are meaningless. */
1125 op1x = convert_to_mode (word_mode, op1, 1);
1126 }
1127
1128 /* Pass 1 for NO_QUEUE so we don't lose any increments
1129 if the libcall is cse'd or moved. */
1130 emit_library_call (binoptab->handlers[(int) mode].libfunc,
1131 1, mode, 2, op0, mode, op1x, op1_mode);
1132
1133 insns = get_insns ();
1134 end_sequence ();
1135
1136 target = gen_reg_rtx (mode);
1137 emit_libcall_block (insns, target, hard_libcall_value (mode),
1138 gen_rtx (binoptab->code, mode, op0, op1));
1139
1140 return target;
1141 }
1142
1143 delete_insns_since (last);
1144
1145 /* It can't be done in this mode. Can we do it in a wider mode? */
1146
1147 if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
1148 || methods == OPTAB_MUST_WIDEN))
1149 {
1150 /* Caller says, don't even try. */
1151 delete_insns_since (entry_last);
1152 return 0;
1153 }
1154
1155 /* Compute the value of METHODS to pass to recursive calls.
1156 Don't allow widening to be tried recursively. */
1157
1158 methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
1159
1160 /* Look for a wider mode of the same class for which it appears we can do
1161 the operation. */
1162
1163 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1164 {
1165 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1166 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1167 {
1168 if ((binoptab->handlers[(int) wider_mode].insn_code
1169 != CODE_FOR_nothing)
1170 || (methods == OPTAB_LIB
1171 && binoptab->handlers[(int) wider_mode].libfunc))
1172 {
1173 rtx xop0 = op0, xop1 = op1;
1174 int no_extend = 0;
1175
1176 /* For certain integer operations, we need not actually extend
1177 the narrow operands, as long as we will truncate
1178 the results to the same narrowness. Don't do this when
1179 WIDER_MODE is wider than a word since a paradoxical SUBREG
1180 isn't valid for such modes. */
1181
1182 if ((binoptab == ior_optab || binoptab == and_optab
1183 || binoptab == xor_optab
1184 || binoptab == add_optab || binoptab == sub_optab
1185 || binoptab == smul_optab
1186 || binoptab == ashl_optab || binoptab == lshl_optab)
1187 && class == MODE_INT
1188 && GET_MODE_SIZE (wider_mode) <= UNITS_PER_WORD)
1189 no_extend = 1;
1190
1191 /* If an operand is a constant integer, we might as well
1192 convert it since that is more efficient than using a SUBREG,
1193 unlike the case for other operands. Similarly for
1194 SUBREGs that were made due to promoted objects.*/
1195
1196 if (no_extend && GET_MODE (xop0) != VOIDmode
1197 && ! (GET_CODE (xop0) == SUBREG
1198 && SUBREG_PROMOTED_VAR_P (xop0)))
1199 xop0 = gen_rtx (SUBREG, wider_mode,
1200 force_reg (GET_MODE (xop0), xop0), 0);
1201 else
1202 xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
1203
1204 if (no_extend && GET_MODE (xop1) != VOIDmode
1205 && ! (GET_CODE (xop1) == SUBREG
1206 && SUBREG_PROMOTED_VAR_P (xop1)))
1207 xop1 = gen_rtx (SUBREG, wider_mode,
1208 force_reg (GET_MODE (xop1), xop1), 0);
1209 else
1210 xop1 = convert_to_mode (wider_mode, xop1, unsignedp);
1211
1212 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
1213 unsignedp, methods);
1214 if (temp)
1215 {
1216 if (class != MODE_INT)
1217 {
1218 if (target == 0)
1219 target = gen_reg_rtx (mode);
1220 convert_move (target, temp, 0);
1221 return target;
1222 }
1223 else
1224 return gen_lowpart (mode, temp);
1225 }
1226 else
1227 delete_insns_since (last);
1228 }
1229 }
1230 }
1231
1232 delete_insns_since (entry_last);
1233 return 0;
1234}
1235\f
1236/* Expand a binary operator which has both signed and unsigned forms.
1237 UOPTAB is the optab for unsigned operations, and SOPTAB is for
1238 signed operations.
1239
1240 If we widen unsigned operands, we may use a signed wider operation instead
1241 of an unsigned wider operation, since the result would be the same. */
1242
1243rtx
1244sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods)
1245 enum machine_mode mode;
1246 optab uoptab, soptab;
1247 rtx op0, op1, target;
1248 int unsignedp;
1249 enum optab_methods methods;
1250{
1251 register rtx temp;
1252 optab direct_optab = unsignedp ? uoptab : soptab;
1253 struct optab wide_soptab;
1254
1255 /* Do it without widening, if possible. */
1256 temp = expand_binop (mode, direct_optab, op0, op1, target,
1257 unsignedp, OPTAB_DIRECT);
1258 if (temp || methods == OPTAB_DIRECT)
1259 return temp;
1260
1261 /* Try widening to a signed int. Make a fake signed optab that
1262 hides any signed insn for direct use. */
1263 wide_soptab = *soptab;
1264 wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing;
1265 wide_soptab.handlers[(int) mode].libfunc = 0;
1266
1267 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
1268 unsignedp, OPTAB_WIDEN);
1269
1270 /* For unsigned operands, try widening to an unsigned int. */
1271 if (temp == 0 && unsignedp)
1272 temp = expand_binop (mode, uoptab, op0, op1, target,
1273 unsignedp, OPTAB_WIDEN);
1274 if (temp || methods == OPTAB_WIDEN)
1275 return temp;
1276
1277 /* Use the right width lib call if that exists. */
1278 temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
1279 if (temp || methods == OPTAB_LIB)
1280 return temp;
1281
1282 /* Must widen and use a lib call, use either signed or unsigned. */
1283 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
1284 unsignedp, methods);
1285 if (temp != 0)
1286 return temp;
1287 if (unsignedp)
1288 return expand_binop (mode, uoptab, op0, op1, target,
1289 unsignedp, methods);
1290 return 0;
1291}
1292\f
1293/* Generate code to perform an operation specified by BINOPTAB
1294 on operands OP0 and OP1, with two results to TARG1 and TARG2.
1295 We assume that the order of the operands for the instruction
1296 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
1297 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
1298
1299 Either TARG0 or TARG1 may be zero, but what that means is that
1300 that result is not actually wanted. We will generate it into
1301 a dummy pseudo-reg and discard it. They may not both be zero.
1302
1303 Returns 1 if this operation can be performed; 0 if not. */
1304
1305int
1306expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
1307 optab binoptab;
1308 rtx op0, op1;
1309 rtx targ0, targ1;
1310 int unsignedp;
1311{
1312 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
1313 enum mode_class class;
1314 enum machine_mode wider_mode;
1315 rtx entry_last = get_last_insn ();
1316 rtx last;
1317
1318 class = GET_MODE_CLASS (mode);
1319
1320 op0 = protect_from_queue (op0, 0);
1321 op1 = protect_from_queue (op1, 0);
1322
1323 if (flag_force_mem)
1324 {
1325 op0 = force_not_mem (op0);
1326 op1 = force_not_mem (op1);
1327 }
1328
1329 /* If we are inside an appropriately-short loop and one operand is an
1330 expensive constant, force it into a register. */
1331 if (CONSTANT_P (op0) && preserve_subexpressions_p ()
1332 && rtx_cost (op0, binoptab->code) > 2)
1333 op0 = force_reg (mode, op0);
1334
1335 if (CONSTANT_P (op1) && preserve_subexpressions_p ()
1336 && rtx_cost (op1, binoptab->code) > 2)
1337 op1 = force_reg (mode, op1);
1338
1339 if (targ0)
1340 targ0 = protect_from_queue (targ0, 1);
1341 else
1342 targ0 = gen_reg_rtx (mode);
1343 if (targ1)
1344 targ1 = protect_from_queue (targ1, 1);
1345 else
1346 targ1 = gen_reg_rtx (mode);
1347
1348 /* Record where to go back to if we fail. */
1349 last = get_last_insn ();
1350
1351 if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1352 {
1353 int icode = (int) binoptab->handlers[(int) mode].insn_code;
1354 enum machine_mode mode0 = insn_operand_mode[icode][1];
1355 enum machine_mode mode1 = insn_operand_mode[icode][2];
1356 rtx pat;
1357 rtx xop0 = op0, xop1 = op1;
1358
1359 /* In case this insn wants input operands in modes different from the
1360 result, convert the operands. */
1361 if (GET_MODE (op0) != VOIDmode && GET_MODE (op0) != mode0)
1362 xop0 = convert_to_mode (mode0, xop0, unsignedp);
1363
1364 if (GET_MODE (op1) != VOIDmode && GET_MODE (op1) != mode1)
1365 xop1 = convert_to_mode (mode1, xop1, unsignedp);
1366
1367 /* Now, if insn doesn't accept these operands, put them into pseudos. */
1368 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
1369 xop0 = copy_to_mode_reg (mode0, xop0);
1370
1371 if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
1372 xop1 = copy_to_mode_reg (mode1, xop1);
1373
1374 /* We could handle this, but we should always be called with a pseudo
1375 for our targets and all insns should take them as outputs. */
1376 if (! (*insn_operand_predicate[icode][0]) (targ0, mode)
1377 || ! (*insn_operand_predicate[icode][3]) (targ1, mode))
1378 abort ();
1379
1380 pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
1381 if (pat)
1382 {
1383 emit_insn (pat);
1384 return 1;
1385 }
1386 else
1387 delete_insns_since (last);
1388 }
1389
1390 /* It can't be done in this mode. Can we do it in a wider mode? */
1391
1392 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1393 {
1394 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1395 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1396 {
1397 if (binoptab->handlers[(int) wider_mode].insn_code
1398 != CODE_FOR_nothing)
1399 {
1400 register rtx t0 = gen_reg_rtx (wider_mode);
1401 register rtx t1 = gen_reg_rtx (wider_mode);
1402
1403 if (expand_twoval_binop (binoptab,
1404 convert_to_mode (wider_mode, op0,
1405 unsignedp),
1406 convert_to_mode (wider_mode, op1,
1407 unsignedp),
1408 t0, t1, unsignedp))
1409 {
1410 convert_move (targ0, t0, unsignedp);
1411 convert_move (targ1, t1, unsignedp);
1412 return 1;
1413 }
1414 else
1415 delete_insns_since (last);
1416 }
1417 }
1418 }
1419
1420 delete_insns_since (entry_last);
1421 return 0;
1422}
1423\f
1424/* Generate code to perform an operation specified by UNOPTAB
1425 on operand OP0, with result having machine-mode MODE.
1426
1427 UNSIGNEDP is for the case where we have to widen the operands
1428 to perform the operation. It says to use zero-extension.
1429
1430 If TARGET is nonzero, the value
1431 is generated there, if it is convenient to do so.
1432 In all cases an rtx is returned for the locus of the value;
1433 this may or may not be TARGET. */
1434
1435rtx
1436expand_unop (mode, unoptab, op0, target, unsignedp)
1437 enum machine_mode mode;
1438 optab unoptab;
1439 rtx op0;
1440 rtx target;
1441 int unsignedp;
1442{
1443 enum mode_class class;
1444 enum machine_mode wider_mode;
1445 register rtx temp;
1446 rtx last = get_last_insn ();
1447 rtx pat;
1448
1449 class = GET_MODE_CLASS (mode);
1450
1451 op0 = protect_from_queue (op0, 0);
1452
1453 if (flag_force_mem)
1454 {
1455 op0 = force_not_mem (op0);
1456 }
1457
1458 if (target)
1459 target = protect_from_queue (target, 1);
1460
1461 if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1462 {
1463 int icode = (int) unoptab->handlers[(int) mode].insn_code;
1464 enum machine_mode mode0 = insn_operand_mode[icode][1];
1465 rtx xop0 = op0;
1466
1467 if (target)
1468 temp = target;
1469 else
1470 temp = gen_reg_rtx (mode);
1471
1472 if (GET_MODE (xop0) != VOIDmode
1473 && GET_MODE (xop0) != mode0)
1474 xop0 = convert_to_mode (mode0, xop0, unsignedp);
1475
1476 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
1477
1478 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
1479 xop0 = copy_to_mode_reg (mode0, xop0);
1480
1481 if (! (*insn_operand_predicate[icode][0]) (temp, mode))
1482 temp = gen_reg_rtx (mode);
1483
1484 pat = GEN_FCN (icode) (temp, xop0);
1485 if (pat)
1486 {
1487 if (GET_CODE (pat) == SEQUENCE
1488 && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
1489 {
1490 delete_insns_since (last);
1491 return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
1492 }
1493
1494 emit_insn (pat);
1495
1496 return temp;
1497 }
1498 else
1499 delete_insns_since (last);
1500 }
1501
1502 /* It can't be done in this mode. Can we open-code it in a wider mode? */
1503
1504 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1505 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1506 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1507 {
1508 if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
1509 {
1510 rtx xop0 = op0;
1511
1512 /* For certain operations, we need not actually extend
1513 the narrow operand, as long as we will truncate the
1514 results to the same narrowness. But it is faster to
1515 convert a SUBREG due to mode promotion. */
1516
1517 if ((unoptab == neg_optab || unoptab == one_cmpl_optab)
1518 && GET_MODE_SIZE (wider_mode) <= UNITS_PER_WORD
1519 && class == MODE_INT
1520 && ! (GET_CODE (xop0) == SUBREG
1521 && SUBREG_PROMOTED_VAR_P (xop0)))
1522 xop0 = gen_rtx (SUBREG, wider_mode, force_reg (mode, xop0), 0);
1523 else
1524 xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
1525
1526 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
1527 unsignedp);
1528
1529 if (temp)
1530 {
1531 if (class != MODE_INT)
1532 {
1533 if (target == 0)
1534 target = gen_reg_rtx (mode);
1535 convert_move (target, temp, 0);
1536 return target;
1537 }
1538 else
1539 return gen_lowpart (mode, temp);
1540 }
1541 else
1542 delete_insns_since (last);
1543 }
1544 }
1545
1546 /* These can be done a word at a time. */
1547 if (unoptab == one_cmpl_optab
1548 && class == MODE_INT
1549 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
1550 && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
1551 {
1552 int i;
1553 rtx insns;
1554
1555 if (target == 0 || target == op0)
1556 target = gen_reg_rtx (mode);
1557
1558 start_sequence ();
1559
1560 /* Do the actual arithmetic. */
1561 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
1562 {
1563 rtx target_piece = operand_subword (target, i, 1, mode);
1564 rtx x = expand_unop (word_mode, unoptab,
1565 operand_subword_force (op0, i, mode),
1566 target_piece, unsignedp);
1567 if (target_piece != x)
1568 emit_move_insn (target_piece, x);
1569 }
1570
1571 insns = get_insns ();
1572 end_sequence ();
1573
1574 emit_no_conflict_block (insns, target, op0, NULL_RTX,
1575 gen_rtx (unoptab->code, mode, copy_rtx (op0)));
1576 return target;
1577 }
1578
1579 /* Open-code the complex negation operation. */
1580 else if (unoptab == neg_optab
1581 && (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT))
1582 {
1583 rtx target_piece;
1584 rtx x;
1585 rtx seq;
1586
1587 /* Find the correct mode for the real and imaginary parts */
1588 enum machine_mode submode
1589 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
1590 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
1591 0);
1592
1593 if (submode == BLKmode)
1594 abort ();
1595
1596 if (target == 0)
1597 target = gen_reg_rtx (mode);
1598
1599 start_sequence ();
1600
1601 target_piece = gen_imagpart (submode, target);
1602 x = expand_unop (submode, unoptab,
1603 gen_imagpart (submode, op0),
1604 target_piece, unsignedp);
1605 if (target_piece != x)
1606 emit_move_insn (target_piece, x);
1607
1608 target_piece = gen_realpart (submode, target);
1609 x = expand_unop (submode, unoptab,
1610 gen_realpart (submode, op0),
1611 target_piece, unsignedp);
1612 if (target_piece != x)
1613 emit_move_insn (target_piece, x);
1614
1615 seq = get_insns ();
1616 end_sequence ();
1617
1618 emit_no_conflict_block (seq, target, op0, 0,
1619 gen_rtx (unoptab->code, mode, copy_rtx (op0)));
1620 return target;
1621 }
1622
1623 /* Now try a library call in this mode. */
1624 if (unoptab->handlers[(int) mode].libfunc)
1625 {
1626 rtx insns;
1627 rtx funexp = unoptab->handlers[(int) mode].libfunc;
1628
1629 start_sequence ();
1630
1631 /* Pass 1 for NO_QUEUE so we don't lose any increments
1632 if the libcall is cse'd or moved. */
1633 emit_library_call (unoptab->handlers[(int) mode].libfunc,
1634 1, mode, 1, op0, mode);
1635 insns = get_insns ();
1636 end_sequence ();
1637
1638 target = gen_reg_rtx (mode);
1639 emit_libcall_block (insns, target, hard_libcall_value (mode),
1640 gen_rtx (unoptab->code, mode, op0));
1641
1642 return target;
1643 }
1644
1645 /* It can't be done in this mode. Can we do it in a wider mode? */
1646
1647 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1648 {
1649 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1650 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1651 {
1652 if ((unoptab->handlers[(int) wider_mode].insn_code
1653 != CODE_FOR_nothing)
1654 || unoptab->handlers[(int) wider_mode].libfunc)
1655 {
1656 rtx xop0 = op0;
1657
1658 /* For certain operations, we need not actually extend
1659 the narrow operand, as long as we will truncate the
1660 results to the same narrowness. */
1661
1662 if ((unoptab == neg_optab || unoptab == one_cmpl_optab)
1663 && GET_MODE_SIZE (wider_mode) <= UNITS_PER_WORD
1664 && class == MODE_INT
1665 && ! (GET_CODE (xop0) == SUBREG
1666 && SUBREG_PROMOTED_VAR_P (xop0)))
1667 xop0 = gen_rtx (SUBREG, wider_mode, force_reg (mode, xop0), 0);
1668 else
1669 xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
1670
1671 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
1672 unsignedp);
1673
1674 if (temp)
1675 {
1676 if (class != MODE_INT)
1677 {
1678 if (target == 0)
1679 target = gen_reg_rtx (mode);
1680 convert_move (target, temp, 0);
1681 return target;
1682 }
1683 else
1684 return gen_lowpart (mode, temp);
1685 }
1686 else
1687 delete_insns_since (last);
1688 }
1689 }
1690 }
1691
1692 return 0;
1693}
1694\f
1695/* Emit code to compute the absolute value of OP0, with result to
1696 TARGET if convenient. (TARGET may be 0.) The return value says
1697 where the result actually is to be found.
1698
1699 MODE is the mode of the operand; the mode of the result is
1700 different but can be deduced from MODE.
1701
1702 UNSIGNEDP is relevant for complex integer modes. */
1703
1704rtx
1705expand_complex_abs (mode, op0, target, unsignedp)
1706 enum machine_mode mode;
1707 rtx op0;
1708 rtx target;
1709 int unsignedp;
1710{
1711 enum mode_class class = GET_MODE_CLASS (mode);
1712 enum machine_mode wider_mode;
1713 register rtx temp;
1714 rtx entry_last = get_last_insn ();
1715 rtx last;
1716 rtx pat;
1717
1718 /* Find the correct mode for the real and imaginary parts. */
1719 enum machine_mode submode
1720 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
1721 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
1722 0);
1723
1724 if (submode == BLKmode)
1725 abort ();
1726
1727 op0 = protect_from_queue (op0, 0);
1728
1729 if (flag_force_mem)
1730 {
1731 op0 = force_not_mem (op0);
1732 }
1733
1734 last = get_last_insn ();
1735
1736 if (target)
1737 target = protect_from_queue (target, 1);
1738
1739 if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1740 {
1741 int icode = (int) abs_optab->handlers[(int) mode].insn_code;
1742 enum machine_mode mode0 = insn_operand_mode[icode][1];
1743 rtx xop0 = op0;
1744
1745 if (target)
1746 temp = target;
1747 else
1748 temp = gen_reg_rtx (submode);
1749
1750 if (GET_MODE (xop0) != VOIDmode
1751 && GET_MODE (xop0) != mode0)
1752 xop0 = convert_to_mode (mode0, xop0, unsignedp);
1753
1754 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
1755
1756 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
1757 xop0 = copy_to_mode_reg (mode0, xop0);
1758
1759 if (! (*insn_operand_predicate[icode][0]) (temp, submode))
1760 temp = gen_reg_rtx (submode);
1761
1762 pat = GEN_FCN (icode) (temp, xop0);
1763 if (pat)
1764 {
1765 if (GET_CODE (pat) == SEQUENCE
1766 && ! add_equal_note (pat, temp, abs_optab->code, xop0, NULL_RTX))
1767 {
1768 delete_insns_since (last);
1769 return expand_unop (mode, abs_optab, op0, NULL_RTX, unsignedp);
1770 }
1771
1772 emit_insn (pat);
1773
1774 return temp;
1775 }
1776 else
1777 delete_insns_since (last);
1778 }
1779
1780 /* It can't be done in this mode. Can we open-code it in a wider mode? */
1781
1782 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1783 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1784 {
1785 if (abs_optab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
1786 {
1787 rtx xop0 = op0;
1788
1789 xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
1790 temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
1791
1792 if (temp)
1793 {
1794 if (class != MODE_COMPLEX_INT)
1795 {
1796 if (target == 0)
1797 target = gen_reg_rtx (submode);
1798 convert_move (target, temp, 0);
1799 return target;
1800 }
1801 else
1802 return gen_lowpart (submode, temp);
1803 }
1804 else
1805 delete_insns_since (last);
1806 }
1807 }
1808
1809 /* Open-code the complex absolute-value operation
1810 if we can open-code sqrt. Otherwise it's not worth while. */
1811 if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing)
1812 {
1813 rtx real, imag, total;
1814
1815 real = gen_realpart (submode, op0);
1816 imag = gen_imagpart (submode, op0);
1817 /* Square both parts. */
1818 real = expand_mult (mode, real, real, NULL_RTX, 0);
1819 imag = expand_mult (mode, imag, imag, NULL_RTX, 0);
1820 /* Sum the parts. */
1821 total = expand_binop (submode, add_optab, real, imag, 0,
1822 0, OPTAB_LIB_WIDEN);
1823 /* Get sqrt in TARGET. Set TARGET to where the result is. */
1824 target = expand_unop (submode, sqrt_optab, total, target, 0);
1825 if (target == 0)
1826 delete_insns_since (last);
1827 else
1828 return target;
1829 }
1830
1831 /* Now try a library call in this mode. */
1832 if (abs_optab->handlers[(int) mode].libfunc)
1833 {
1834 rtx insns;
1835 rtx funexp = abs_optab->handlers[(int) mode].libfunc;
1836
1837 start_sequence ();
1838
1839 /* Pass 1 for NO_QUEUE so we don't lose any increments
1840 if the libcall is cse'd or moved. */
1841 emit_library_call (abs_optab->handlers[(int) mode].libfunc,
1842 1, mode, 1, op0, mode);
1843 insns = get_insns ();
1844 end_sequence ();
1845
1846 target = gen_reg_rtx (submode);
1847 emit_libcall_block (insns, target, hard_libcall_value (submode),
1848 gen_rtx (abs_optab->code, mode, op0));
1849
1850 return target;
1851 }
1852
1853 /* It can't be done in this mode. Can we do it in a wider mode? */
1854
1855 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1856 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1857 {
1858 if ((abs_optab->handlers[(int) wider_mode].insn_code
1859 != CODE_FOR_nothing)
1860 || abs_optab->handlers[(int) wider_mode].libfunc)
1861 {
1862 rtx xop0 = op0;
1863
1864 xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
1865
1866 temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
1867
1868 if (temp)
1869 {
1870 if (class != MODE_COMPLEX_INT)
1871 {
1872 if (target == 0)
1873 target = gen_reg_rtx (submode);
1874 convert_move (target, temp, 0);
1875 return target;
1876 }
1877 else
1878 return gen_lowpart (submode, temp);
1879 }
1880 else
1881 delete_insns_since (last);
1882 }
1883 }
1884
1885 delete_insns_since (entry_last);
1886 return 0;
1887}
1888\f
1889/* Generate an instruction whose insn-code is INSN_CODE,
1890 with two operands: an output TARGET and an input OP0.
1891 TARGET *must* be nonzero, and the output is always stored there.
1892 CODE is an rtx code such that (CODE OP0) is an rtx that describes
1893 the value that is stored into TARGET. */
1894
1895void
1896emit_unop_insn (icode, target, op0, code)
1897 int icode;
1898 rtx target;
1899 rtx op0;
1900 enum rtx_code code;
1901{
1902 register rtx temp;
1903 enum machine_mode mode0 = insn_operand_mode[icode][1];
1904 rtx pat;
1905
1906 temp = target = protect_from_queue (target, 1);
1907
1908 op0 = protect_from_queue (op0, 0);
1909
1910 if (flag_force_mem)
1911 op0 = force_not_mem (op0);
1912
1913 /* Now, if insn does not accept our operands, put them into pseudos. */
1914
1915 if (! (*insn_operand_predicate[icode][1]) (op0, mode0))
1916 op0 = copy_to_mode_reg (mode0, op0);
1917
1918 if (! (*insn_operand_predicate[icode][0]) (temp, GET_MODE (temp))
1919 || (flag_force_mem && GET_CODE (temp) == MEM))
1920 temp = gen_reg_rtx (GET_MODE (temp));
1921
1922 pat = GEN_FCN (icode) (temp, op0);
1923
1924 if (GET_CODE (pat) == SEQUENCE && code != UNKNOWN)
1925 add_equal_note (pat, temp, code, op0, NULL_RTX);
1926
1927 emit_insn (pat);
1928
1929 if (temp != target)
1930 emit_move_insn (target, temp);
1931}
1932\f
1933/* Emit code to perform a series of operations on a multi-word quantity, one
1934 word at a time.
1935
1936 Such a block is preceded by a CLOBBER of the output, consists of multiple
1937 insns, each setting one word of the output, and followed by a SET copying
1938 the output to itself.
1939
1940 Each of the insns setting words of the output receives a REG_NO_CONFLICT
1941 note indicating that it doesn't conflict with the (also multi-word)
1942 inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
1943 notes.
1944
1945 INSNS is a block of code generated to perform the operation, not including
1946 the CLOBBER and final copy. All insns that compute intermediate values
1947 are first emitted, followed by the block as described above. Only
1948 INSNs are allowed in the block; no library calls or jumps may be
1949 present.
1950
1951 TARGET, OP0, and OP1 are the output and inputs of the operations,
1952 respectively. OP1 may be zero for a unary operation.
1953
1954 EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
1955 on the last insn.
1956
1957 If TARGET is not a register, INSNS is simply emitted with no special
1958 processing.
1959
1960 The final insn emitted is returned. */
1961
1962rtx
1963emit_no_conflict_block (insns, target, op0, op1, equiv)
1964 rtx insns;
1965 rtx target;
1966 rtx op0, op1;
1967 rtx equiv;
1968{
1969 rtx prev, next, first, last, insn;
1970
1971 if (GET_CODE (target) != REG || reload_in_progress)
1972 return emit_insns (insns);
1973
1974 /* First emit all insns that do not store into words of the output and remove
1975 these from the list. */
1976 for (insn = insns; insn; insn = next)
1977 {
1978 rtx set = 0;
1979 int i;
1980
1981 next = NEXT_INSN (insn);
1982
1983 if (GET_CODE (insn) != INSN)
1984 abort ();
1985
1986 if (GET_CODE (PATTERN (insn)) == SET)
1987 set = PATTERN (insn);
1988 else if (GET_CODE (PATTERN (insn)) == PARALLEL)
1989 {
1990 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
1991 if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
1992 {
1993 set = XVECEXP (PATTERN (insn), 0, i);
1994 break;
1995 }
1996 }
1997
1998 if (set == 0)
1999 abort ();
2000
2001 if (! reg_overlap_mentioned_p (target, SET_DEST (set)))
2002 {
2003 if (PREV_INSN (insn))
2004 NEXT_INSN (PREV_INSN (insn)) = next;
2005 else
2006 insns = next;
2007
2008 if (next)
2009 PREV_INSN (next) = PREV_INSN (insn);
2010
2011 add_insn (insn);
2012 }
2013 }
2014
2015 prev = get_last_insn ();
2016
2017 /* Now write the CLOBBER of the output, followed by the setting of each
2018 of the words, followed by the final copy. */
2019 if (target != op0 && target != op1)
2020 emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
2021
2022 for (insn = insns; insn; insn = next)
2023 {
2024 next = NEXT_INSN (insn);
2025 add_insn (insn);
2026
2027 if (op1 && GET_CODE (op1) == REG)
2028 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_NO_CONFLICT, op1,
2029 REG_NOTES (insn));
2030
2031 if (op0 && GET_CODE (op0) == REG)
2032 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_NO_CONFLICT, op0,
2033 REG_NOTES (insn));
2034 }
2035
2036 if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
2037 != CODE_FOR_nothing)
2038 {
2039 last = emit_move_insn (target, target);
2040 if (equiv)
2041 REG_NOTES (last)
2042 = gen_rtx (EXPR_LIST, REG_EQUAL, equiv, REG_NOTES (last));
2043 }
2044 else
2045 last = get_last_insn ();
2046
2047 if (prev == 0)
2048 first = get_insns ();
2049 else
2050 first = NEXT_INSN (prev);
2051
2052 /* Encapsulate the block so it gets manipulated as a unit. */
2053 REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last,
2054 REG_NOTES (first));
2055 REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last));
2056
2057 return last;
2058}
2059\f
2060/* Emit code to make a call to a constant function or a library call.
2061
2062 INSNS is a list containing all insns emitted in the call.
2063 These insns leave the result in RESULT. Our block is to copy RESULT
2064 to TARGET, which is logically equivalent to EQUIV.
2065
2066 We first emit any insns that set a pseudo on the assumption that these are
2067 loading constants into registers; doing so allows them to be safely cse'ed
2068 between blocks. Then we emit all the other insns in the block, followed by
2069 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
2070 note with an operand of EQUIV.
2071
2072 Moving assignments to pseudos outside of the block is done to improve
2073 the generated code, but is not required to generate correct code,
2074 hence being unable to move an assignment is not grounds for not making
2075 a libcall block. There are two reasons why it is safe to leave these
2076 insns inside the block: First, we know that these pseudos cannot be
2077 used in generated RTL outside the block since they are created for
2078 temporary purposes within the block. Second, CSE will not record the
2079 values of anything set inside a libcall block, so we know they must
2080 be dead at the end of the block.
2081
2082 Except for the first group of insns (the ones setting pseudos), the
2083 block is delimited by REG_RETVAL and REG_LIBCALL notes. */
2084
2085void
2086emit_libcall_block (insns, target, result, equiv)
2087 rtx insns;
2088 rtx target;
2089 rtx result;
2090 rtx equiv;
2091{
2092 rtx prev, next, first, last, insn;
2093
2094 /* First emit all insns that set pseudos. Remove them from the list as
2095 we go. Avoid insns that set pseudo which were referenced in previous
2096 insns. These can be generated by move_by_pieces, for example,
2097 to update an address. */
2098
2099 for (insn = insns; insn; insn = next)
2100 {
2101 rtx set = single_set (insn);
2102
2103 next = NEXT_INSN (insn);
2104
2105 if (set != 0 && GET_CODE (SET_DEST (set)) == REG
2106 && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
2107 && (insn == insns
2108 || (! reg_mentioned_p (SET_DEST (set), PATTERN (insns))
2109 && ! reg_used_between_p (SET_DEST (set), insns, insn))))
2110 {
2111 if (PREV_INSN (insn))
2112 NEXT_INSN (PREV_INSN (insn)) = next;
2113 else
2114 insns = next;
2115
2116 if (next)
2117 PREV_INSN (next) = PREV_INSN (insn);
2118
2119 add_insn (insn);
2120 }
2121 }
2122
2123 prev = get_last_insn ();
2124
2125 /* Write the remaining insns followed by the final copy. */
2126
2127 for (insn = insns; insn; insn = next)
2128 {
2129 next = NEXT_INSN (insn);
2130
2131 add_insn (insn);
2132 }
2133
2134 last = emit_move_insn (target, result);
2135 REG_NOTES (last) = gen_rtx (EXPR_LIST,
2136 REG_EQUAL, copy_rtx (equiv), REG_NOTES (last));
2137
2138 if (prev == 0)
2139 first = get_insns ();
2140 else
2141 first = NEXT_INSN (prev);
2142
2143 /* Encapsulate the block so it gets manipulated as a unit. */
2144 REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last,
2145 REG_NOTES (first));
2146 REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last));
2147}
2148\f
2149/* Generate code to store zero in X. */
2150
2151void
2152emit_clr_insn (x)
2153 rtx x;
2154{
2155 emit_move_insn (x, const0_rtx);
2156}
2157
2158/* Generate code to store 1 in X
2159 assuming it contains zero beforehand. */
2160
2161void
2162emit_0_to_1_insn (x)
2163 rtx x;
2164{
2165 emit_move_insn (x, const1_rtx);
2166}
2167
2168/* Generate code to compare X with Y
2169 so that the condition codes are set.
2170
2171 MODE is the mode of the inputs (in case they are const_int).
2172 UNSIGNEDP nonzero says that X and Y are unsigned;
2173 this matters if they need to be widened.
2174
2175 If they have mode BLKmode, then SIZE specifies the size of both X and Y,
2176 and ALIGN specifies the known shared alignment of X and Y.
2177
2178 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
2179 It is ignored for fixed-point and block comparisons;
2180 it is used only for floating-point comparisons. */
2181
2182void
2183emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
2184 rtx x, y;
2185 enum rtx_code comparison;
2186 rtx size;
2187 enum machine_mode mode;
2188 int unsignedp;
2189 int align;
2190{
2191 enum mode_class class;
2192 enum machine_mode wider_mode;
2193
2194 class = GET_MODE_CLASS (mode);
2195
2196 /* They could both be VOIDmode if both args are immediate constants,
2197 but we should fold that at an earlier stage.
2198 With no special code here, this will call abort,
2199 reminding the programmer to implement such folding. */
2200
2201 if (mode != BLKmode && flag_force_mem)
2202 {
2203 x = force_not_mem (x);
2204 y = force_not_mem (y);
2205 }
2206
2207 /* If we are inside an appropriately-short loop and one operand is an
2208 expensive constant, force it into a register. */
2209 if (CONSTANT_P (x) && preserve_subexpressions_p () && rtx_cost (x, COMPARE) > 2)
2210 x = force_reg (mode, x);
2211
2212 if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2)
2213 y = force_reg (mode, y);
2214
2215 /* Don't let both operands fail to indicate the mode. */
2216 if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
2217 x = force_reg (mode, x);
2218
2219 /* Handle all BLKmode compares. */
2220
2221 if (mode == BLKmode)
2222 {
2223 emit_queue ();
2224 x = protect_from_queue (x, 0);
2225 y = protect_from_queue (y, 0);
2226
2227 if (size == 0)
2228 abort ();
2229#ifdef HAVE_cmpstrqi
2230 if (HAVE_cmpstrqi
2231 && GET_CODE (size) == CONST_INT
2232 && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
2233 {
2234 enum machine_mode result_mode
2235 = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0];
2236 rtx result = gen_reg_rtx (result_mode);
2237 emit_insn (gen_cmpstrqi (result, x, y, size, GEN_INT (align)));
2238 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
2239 result_mode, 0, 0);
2240 }
2241 else
2242#endif
2243#ifdef HAVE_cmpstrhi
2244 if (HAVE_cmpstrhi
2245 && GET_CODE (size) == CONST_INT
2246 && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
2247 {
2248 enum machine_mode result_mode
2249 = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0];
2250 rtx result = gen_reg_rtx (result_mode);
2251 emit_insn (gen_cmpstrhi (result, x, y, size, GEN_INT (align)));
2252 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
2253 result_mode, 0, 0);
2254 }
2255 else
2256#endif
2257#ifdef HAVE_cmpstrsi
2258 if (HAVE_cmpstrsi)
2259 {
2260 enum machine_mode result_mode
2261 = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0];
2262 rtx result = gen_reg_rtx (result_mode);
2263 size = protect_from_queue (size, 0);
2264 emit_insn (gen_cmpstrsi (result, x, y,
2265 convert_to_mode (SImode, size, 1),
2266 GEN_INT (align)));
2267 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
2268 result_mode, 0, 0);
2269 }
2270 else
2271#endif
2272 {
2273#ifdef TARGET_MEM_FUNCTIONS
2274 emit_library_call (memcmp_libfunc, 0,
2275 TYPE_MODE (integer_type_node), 3,
2276 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
2277 size, Pmode);
2278#else
2279 emit_library_call (bcmp_libfunc, 0,
2280 TYPE_MODE (integer_type_node), 3,
2281 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
2282 size, Pmode);
2283#endif
2284 emit_cmp_insn (hard_libcall_value (TYPE_MODE (integer_type_node)),
2285 const0_rtx, comparison, NULL_RTX,
2286 TYPE_MODE (integer_type_node), 0, 0);
2287 }
2288 return;
2289 }
2290
2291 /* Handle some compares against zero. */
2292
2293 if (y == CONST0_RTX (mode)
2294 && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2295 {
2296 int icode = (int) tst_optab->handlers[(int) mode].insn_code;
2297
2298 emit_queue ();
2299 x = protect_from_queue (x, 0);
2300 y = protect_from_queue (y, 0);
2301
2302 /* Now, if insn does accept these operands, put them into pseudos. */
2303 if (! (*insn_operand_predicate[icode][0])
2304 (x, insn_operand_mode[icode][0]))
2305 x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
2306
2307 emit_insn (GEN_FCN (icode) (x));
2308 return;
2309 }
2310
2311 /* Handle compares for which there is a directly suitable insn. */
2312
2313 if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2314 {
2315 int icode = (int) cmp_optab->handlers[(int) mode].insn_code;
2316
2317 emit_queue ();
2318 x = protect_from_queue (x, 0);
2319 y = protect_from_queue (y, 0);
2320
2321 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2322 if (! (*insn_operand_predicate[icode][0])
2323 (x, insn_operand_mode[icode][0]))
2324 x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
2325
2326 if (! (*insn_operand_predicate[icode][1])
2327 (y, insn_operand_mode[icode][1]))
2328 y = copy_to_mode_reg (insn_operand_mode[icode][1], y);
2329
2330 emit_insn (GEN_FCN (icode) (x, y));
2331 return;
2332 }
2333
2334 /* Try widening if we can find a direct insn that way. */
2335
2336 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
2337 {
2338 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2339 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2340 {
2341 if (cmp_optab->handlers[(int) wider_mode].insn_code
2342 != CODE_FOR_nothing)
2343 {
2344 x = protect_from_queue (x, 0);
2345 y = protect_from_queue (y, 0);
2346 x = convert_to_mode (wider_mode, x, unsignedp);
2347 y = convert_to_mode (wider_mode, y, unsignedp);
2348 emit_cmp_insn (x, y, comparison, NULL_RTX,
2349 wider_mode, unsignedp, align);
2350 return;
2351 }
2352 }
2353 }
2354
2355 /* Handle a lib call just for the mode we are using. */
2356
2357 if (cmp_optab->handlers[(int) mode].libfunc
2358 && class != MODE_FLOAT)
2359 {
2360 rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
2361 /* If we want unsigned, and this mode has a distinct unsigned
2362 comparison routine, use that. */
2363 if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
2364 libfunc = ucmp_optab->handlers[(int) mode].libfunc;
2365
2366 emit_library_call (libfunc, 1,
2367 word_mode, 2, x, mode, y, mode);
2368
2369 /* Integer comparison returns a result that must be compared against 1,
2370 so that even if we do an unsigned compare afterward,
2371 there is still a value that can represent the result "less than". */
2372
2373 emit_cmp_insn (hard_libcall_value (word_mode), const1_rtx,
2374 comparison, NULL_RTX, word_mode, unsignedp, 0);
2375 return;
2376 }
2377
2378 if (class == MODE_FLOAT)
2379 emit_float_lib_cmp (x, y, comparison);
2380
2381 else
2382 abort ();
2383}
2384
2385/* Nonzero if a compare of mode MODE can be done straightforwardly
2386 (without splitting it into pieces). */
2387
2388int
2389can_compare_p (mode)
2390 enum machine_mode mode;
2391{
2392 do
2393 {
2394 if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
2395 return 1;
2396 mode = GET_MODE_WIDER_MODE (mode);
2397 } while (mode != VOIDmode);
2398
2399 return 0;
2400}
2401\f
2402/* Emit a library call comparison between floating point X and Y.
2403 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
2404
2405static void
2406emit_float_lib_cmp (x, y, comparison)
2407 rtx x, y;
2408 enum rtx_code comparison;
2409{
2410 enum machine_mode mode = GET_MODE (x);
2411 rtx libfunc;
2412
2413 if (mode == SFmode)
2414 switch (comparison)
2415 {
2416 case EQ:
2417 libfunc = eqsf2_libfunc;
2418 break;
2419
2420 case NE:
2421 libfunc = nesf2_libfunc;
2422 break;
2423
2424 case GT:
2425 libfunc = gtsf2_libfunc;
2426 break;
2427
2428 case GE:
2429 libfunc = gesf2_libfunc;
2430 break;
2431
2432 case LT:
2433 libfunc = ltsf2_libfunc;
2434 break;
2435
2436 case LE:
2437 libfunc = lesf2_libfunc;
2438 break;
2439 }
2440 else if (mode == DFmode)
2441 switch (comparison)
2442 {
2443 case EQ:
2444 libfunc = eqdf2_libfunc;
2445 break;
2446
2447 case NE:
2448 libfunc = nedf2_libfunc;
2449 break;
2450
2451 case GT:
2452 libfunc = gtdf2_libfunc;
2453 break;
2454
2455 case GE:
2456 libfunc = gedf2_libfunc;
2457 break;
2458
2459 case LT:
2460 libfunc = ltdf2_libfunc;
2461 break;
2462
2463 case LE:
2464 libfunc = ledf2_libfunc;
2465 break;
2466 }
2467 else if (mode == XFmode)
2468 switch (comparison)
2469 {
2470 case EQ:
2471 libfunc = eqxf2_libfunc;
2472 break;
2473
2474 case NE:
2475 libfunc = nexf2_libfunc;
2476 break;
2477
2478 case GT:
2479 libfunc = gtxf2_libfunc;
2480 break;
2481
2482 case GE:
2483 libfunc = gexf2_libfunc;
2484 break;
2485
2486 case LT:
2487 libfunc = ltxf2_libfunc;
2488 break;
2489
2490 case LE:
2491 libfunc = lexf2_libfunc;
2492 break;
2493 }
2494 else if (mode == TFmode)
2495 switch (comparison)
2496 {
2497 case EQ:
2498 libfunc = eqtf2_libfunc;
2499 break;
2500
2501 case NE:
2502 libfunc = netf2_libfunc;
2503 break;
2504
2505 case GT:
2506 libfunc = gttf2_libfunc;
2507 break;
2508
2509 case GE:
2510 libfunc = getf2_libfunc;
2511 break;
2512
2513 case LT:
2514 libfunc = lttf2_libfunc;
2515 break;
2516
2517 case LE:
2518 libfunc = letf2_libfunc;
2519 break;
2520 }
2521 else
2522 {
2523 enum machine_mode wider_mode;
2524
2525 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2526 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2527 {
2528 if ((cmp_optab->handlers[(int) wider_mode].insn_code
2529 != CODE_FOR_nothing)
2530 || (cmp_optab->handlers[(int) wider_mode].libfunc != 0))
2531 {
2532 x = protect_from_queue (x, 0);
2533 y = protect_from_queue (y, 0);
2534 x = convert_to_mode (wider_mode, x, 0);
2535 y = convert_to_mode (wider_mode, y, 0);
2536 emit_float_lib_cmp (x, y, comparison);
2537 return;
2538 }
2539 }
2540 abort ();
2541 }
2542
2543 emit_library_call (libfunc, 1,
2544 word_mode, 2, x, mode, y, mode);
2545
2546 emit_cmp_insn (hard_libcall_value (word_mode), const0_rtx, comparison,
2547 NULL_RTX, word_mode, 0, 0);
2548}
2549\f
2550/* Generate code to indirectly jump to a location given in the rtx LOC. */
2551
2552void
2553emit_indirect_jump (loc)
2554 rtx loc;
2555{
2556 if (! ((*insn_operand_predicate[(int)CODE_FOR_indirect_jump][0])
2557 (loc, Pmode)))
2558 loc = copy_to_mode_reg (Pmode, loc);
2559
2560 emit_jump_insn (gen_indirect_jump (loc));
2561 emit_barrier ();
2562}
2563\f
2564/* These three functions generate an insn body and return it
2565 rather than emitting the insn.
2566
2567 They do not protect from queued increments,
2568 because they may be used 1) in protect_from_queue itself
2569 and 2) in other passes where there is no queue. */
2570
2571/* Generate and return an insn body to add Y to X. */
2572
2573rtx
2574gen_add2_insn (x, y)
2575 rtx x, y;
2576{
2577 int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code;
2578
2579 if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
2580 || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
2581 || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
2582 abort ();
2583
2584 return (GEN_FCN (icode) (x, x, y));
2585}
2586
2587int
2588have_add2_insn (mode)
2589 enum machine_mode mode;
2590{
2591 return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
2592}
2593
2594/* Generate and return an insn body to subtract Y from X. */
2595
2596rtx
2597gen_sub2_insn (x, y)
2598 rtx x, y;
2599{
2600 int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code;
2601
2602 if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
2603 || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
2604 || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
2605 abort ();
2606
2607 return (GEN_FCN (icode) (x, x, y));
2608}
2609
2610int
2611have_sub2_insn (mode)
2612 enum machine_mode mode;
2613{
2614 return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
2615}
2616
2617/* Generate the body of an instruction to copy Y into X.
2618 It may be a SEQUENCE, if one insn isn't enough. */
2619
2620rtx
2621gen_move_insn (x, y)
2622 rtx x, y;
2623{
2624 register enum machine_mode mode = GET_MODE (x);
2625 enum insn_code insn_code;
2626 rtx seq;
2627
2628 if (mode == VOIDmode)
2629 mode = GET_MODE (y);
2630
2631 insn_code = mov_optab->handlers[(int) mode].insn_code;
2632
2633 /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
2634 find a mode to do it in. If we have a movcc, use it. Otherwise,
2635 find the MODE_INT mode of the same width. */
2636
2637 if (GET_MODE_CLASS (mode) == MODE_CC && insn_code == CODE_FOR_nothing)
2638 {
2639 enum machine_mode tmode = VOIDmode;
2640 rtx x1 = x, y1 = y;
2641
2642 if (mode != CCmode
2643 && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing)
2644 tmode = CCmode;
2645 else
2646 for (tmode = QImode; tmode != VOIDmode;
2647 tmode = GET_MODE_WIDER_MODE (tmode))
2648 if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode))
2649 break;
2650
2651 if (tmode == VOIDmode)
2652 abort ();
2653
2654 /* Get X and Y in TMODE. We can't use gen_lowpart here because it
2655 may call change_address which is not appropriate if we were
2656 called when a reload was in progress. We don't have to worry
2657 about changing the address since the size in bytes is supposed to
2658 be the same. Copy the MEM to change the mode and move any
2659 substitutions from the old MEM to the new one. */
2660
2661 if (reload_in_progress)
2662 {
2663 x = gen_lowpart_common (tmode, x1);
2664 if (x == 0 && GET_CODE (x1) == MEM)
2665 {
2666 x = gen_rtx (MEM, tmode, XEXP (x1, 0));
2667 RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1);
2668 MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (x1);
2669 MEM_VOLATILE_P (x) = MEM_VOLATILE_P (x1);
2670 copy_replacements (x1, x);
2671 }
2672
2673 y = gen_lowpart_common (tmode, y1);
2674 if (y == 0 && GET_CODE (y1) == MEM)
2675 {
2676 y = gen_rtx (MEM, tmode, XEXP (y1, 0));
2677 RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1);
2678 MEM_IN_STRUCT_P (y) = MEM_IN_STRUCT_P (y1);
2679 MEM_VOLATILE_P (y) = MEM_VOLATILE_P (y1);
2680 copy_replacements (y1, y);
2681 }
2682 }
2683 else
2684 {
2685 x = gen_lowpart (tmode, x);
2686 y = gen_lowpart (tmode, y);
2687 }
2688
2689 insn_code = mov_optab->handlers[(int) tmode].insn_code;
2690 return (GEN_FCN (insn_code) (x, y));
2691 }
2692
2693 start_sequence ();
2694 emit_move_insn_1 (x, y);
2695 seq = gen_sequence ();
2696 end_sequence ();
2697 return seq;
2698}
2699\f
2700/* Return the insn code used to extend FROM_MODE to TO_MODE.
2701 UNSIGNEDP specifies zero-extension instead of sign-extension. If
2702 no such operation exists, CODE_FOR_nothing will be returned. */
2703
2704enum insn_code
2705can_extend_p (to_mode, from_mode, unsignedp)
2706 enum machine_mode to_mode, from_mode;
2707 int unsignedp;
2708{
2709 return extendtab[(int) to_mode][(int) from_mode][unsignedp];
2710}
2711
2712/* Generate the body of an insn to extend Y (with mode MFROM)
2713 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
2714
2715rtx
2716gen_extend_insn (x, y, mto, mfrom, unsignedp)
2717 rtx x, y;
2718 enum machine_mode mto, mfrom;
2719 int unsignedp;
2720{
2721 return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp]) (x, y));
2722}
2723\f
2724/* can_fix_p and can_float_p say whether the target machine
2725 can directly convert a given fixed point type to
2726 a given floating point type, or vice versa.
2727 The returned value is the CODE_FOR_... value to use,
2728 or CODE_FOR_nothing if these modes cannot be directly converted.
2729
2730 *TRUNCP_PTR is set to 1 if it is necessary to output
2731 an explicit FTRUNC insn before the fix insn; otherwise 0. */
2732
2733static enum insn_code
2734can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
2735 enum machine_mode fltmode, fixmode;
2736 int unsignedp;
2737 int *truncp_ptr;
2738{
2739 *truncp_ptr = 0;
2740 if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp] != CODE_FOR_nothing)
2741 return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp];
2742
2743 if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
2744 {
2745 *truncp_ptr = 1;
2746 return fixtab[(int) fltmode][(int) fixmode][unsignedp];
2747 }
2748 return CODE_FOR_nothing;
2749}
2750
2751static enum insn_code
2752can_float_p (fltmode, fixmode, unsignedp)
2753 enum machine_mode fixmode, fltmode;
2754 int unsignedp;
2755{
2756 return floattab[(int) fltmode][(int) fixmode][unsignedp];
2757}
2758\f
2759/* Generate code to convert FROM to floating point
2760 and store in TO. FROM must be fixed point and not VOIDmode.
2761 UNSIGNEDP nonzero means regard FROM as unsigned.
2762 Normally this is done by correcting the final value
2763 if it is negative. */
2764
2765void
2766expand_float (to, from, unsignedp)
2767 rtx to, from;
2768 int unsignedp;
2769{
2770 enum insn_code icode;
2771 register rtx target = to;
2772 enum machine_mode fmode, imode;
2773
2774 /* Crash now, because we won't be able to decide which mode to use. */
2775 if (GET_MODE (from) == VOIDmode)
2776 abort ();
2777
2778 /* Look for an insn to do the conversion. Do it in the specified
2779 modes if possible; otherwise convert either input, output or both to
2780 wider mode. If the integer mode is wider than the mode of FROM,
2781 we can do the conversion signed even if the input is unsigned. */
2782
2783 for (imode = GET_MODE (from); imode != VOIDmode;
2784 imode = GET_MODE_WIDER_MODE (imode))
2785 for (fmode = GET_MODE (to); fmode != VOIDmode;
2786 fmode = GET_MODE_WIDER_MODE (fmode))
2787 {
2788 int doing_unsigned = unsignedp;
2789
2790 icode = can_float_p (fmode, imode, unsignedp);
2791 if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
2792 icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;
2793
2794 if (icode != CODE_FOR_nothing)
2795 {
2796 to = protect_from_queue (to, 1);
2797 from = protect_from_queue (from, 0);
2798
2799 if (imode != GET_MODE (from))
2800 from = convert_to_mode (imode, from, unsignedp);
2801
2802 if (fmode != GET_MODE (to))
2803 target = gen_reg_rtx (fmode);
2804
2805 emit_unop_insn (icode, target, from,
2806 doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
2807
2808 if (target != to)
2809 convert_move (to, target, 0);
2810 return;
2811 }
2812 }
2813
2814#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
2815
2816 /* Unsigned integer, and no way to convert directly.
2817 Convert as signed, then conditionally adjust the result. */
2818 if (unsignedp)
2819 {
2820 rtx label = gen_label_rtx ();
2821 rtx temp;
2822 REAL_VALUE_TYPE offset;
2823
2824 emit_queue ();
2825
2826 to = protect_from_queue (to, 1);
2827 from = protect_from_queue (from, 0);
2828
2829 if (flag_force_mem)
2830 from = force_not_mem (from);
2831
2832 /* Look for a usable floating mode FMODE wider than the source and at
2833 least as wide as the target. Using FMODE will avoid rounding woes
2834 with unsigned values greater than the signed maximum value. */
2835 for (fmode = GET_MODE (to); fmode != VOIDmode;
2836 fmode = GET_MODE_WIDER_MODE (fmode))
2837 if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
2838 && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
2839 break;
2840 if (fmode == VOIDmode)
2841 {
2842 /* There is no such mode. Pretend the target is wide enough.
2843 This may cause rounding problems, unfortunately. */
2844 fmode = GET_MODE (to);
2845 }
2846
2847 /* If we are about to do some arithmetic to correct for an
2848 unsigned operand, do it in a pseudo-register. */
2849
2850 if (GET_MODE (to) != fmode
2851 || GET_CODE (to) != REG || REGNO (to) <= LAST_VIRTUAL_REGISTER)
2852 target = gen_reg_rtx (fmode);
2853
2854 /* Convert as signed integer to floating. */
2855 expand_float (target, from, 0);
2856
2857 /* If FROM is negative (and therefore TO is negative),
2858 correct its value by 2**bitwidth. */
2859
2860 do_pending_stack_adjust ();
2861 emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, GET_MODE (from), 0, 0);
2862 emit_jump_insn (gen_bge (label));
2863 /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
2864 Rather than setting up a dconst_dot_5, let's hope SCO
2865 fixes the bug. */
2866 offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from)));
2867 temp = expand_binop (fmode, add_optab, target,
2868 immed_real_const_1 (offset, fmode),
2869 target, 0, OPTAB_LIB_WIDEN);
2870 if (temp != target)
2871 emit_move_insn (target, temp);
2872 do_pending_stack_adjust ();
2873 emit_label (label);
2874 }
2875 else
2876#endif
2877
2878 /* No hardware instruction available; call a library rotine to convert from
2879 SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */
2880 {
2881 rtx libfcn;
2882 rtx insns;
2883
2884 to = protect_from_queue (to, 1);
2885 from = protect_from_queue (from, 0);
2886
2887 if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
2888 from = convert_to_mode (SImode, from, unsignedp);
2889
2890 if (flag_force_mem)
2891 from = force_not_mem (from);
2892
2893 if (GET_MODE (to) == SFmode)
2894 {
2895 if (GET_MODE (from) == SImode)
2896 libfcn = floatsisf_libfunc;
2897 else if (GET_MODE (from) == DImode)
2898 libfcn = floatdisf_libfunc;
2899 else if (GET_MODE (from) == TImode)
2900 libfcn = floattisf_libfunc;
2901 else
2902 abort ();
2903 }
2904 else if (GET_MODE (to) == DFmode)
2905 {
2906 if (GET_MODE (from) == SImode)
2907 libfcn = floatsidf_libfunc;
2908 else if (GET_MODE (from) == DImode)
2909 libfcn = floatdidf_libfunc;
2910 else if (GET_MODE (from) == TImode)
2911 libfcn = floattidf_libfunc;
2912 else
2913 abort ();
2914 }
2915 else if (GET_MODE (to) == XFmode)
2916 {
2917 if (GET_MODE (from) == SImode)
2918 libfcn = floatsixf_libfunc;
2919 else if (GET_MODE (from) == DImode)
2920 libfcn = floatdixf_libfunc;
2921 else if (GET_MODE (from) == TImode)
2922 libfcn = floattixf_libfunc;
2923 else
2924 abort ();
2925 }
2926 else if (GET_MODE (to) == TFmode)
2927 {
2928 if (GET_MODE (from) == SImode)
2929 libfcn = floatsitf_libfunc;
2930 else if (GET_MODE (from) == DImode)
2931 libfcn = floatditf_libfunc;
2932 else if (GET_MODE (from) == TImode)
2933 libfcn = floattitf_libfunc;
2934 else
2935 abort ();
2936 }
2937 else
2938 abort ();
2939
2940 start_sequence ();
2941
2942 emit_library_call (libfcn, 1, GET_MODE (to), 1, from, GET_MODE (from));
2943 insns = get_insns ();
2944 end_sequence ();
2945
2946 emit_libcall_block (insns, target, hard_libcall_value (GET_MODE (to)),
2947 gen_rtx (FLOAT, GET_MODE (to), from));
2948 }
2949
2950 /* Copy result to requested destination
2951 if we have been computing in a temp location. */
2952
2953 if (target != to)
2954 {
2955 if (GET_MODE (target) == GET_MODE (to))
2956 emit_move_insn (to, target);
2957 else
2958 convert_move (to, target, 0);
2959 }
2960}
2961\f
2962/* expand_fix: generate code to convert FROM to fixed point
2963 and store in TO. FROM must be floating point. */
2964
2965static rtx
2966ftruncify (x)
2967 rtx x;
2968{
2969 rtx temp = gen_reg_rtx (GET_MODE (x));
2970 return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0);
2971}
2972
2973void
2974expand_fix (to, from, unsignedp)
2975 register rtx to, from;
2976 int unsignedp;
2977{
2978 enum insn_code icode;
2979 register rtx target = to;
2980 enum machine_mode fmode, imode;
2981 int must_trunc = 0;
2982 rtx libfcn = 0;
2983
2984 /* We first try to find a pair of modes, one real and one integer, at
2985 least as wide as FROM and TO, respectively, in which we can open-code
2986 this conversion. If the integer mode is wider than the mode of TO,
2987 we can do the conversion either signed or unsigned. */
2988
2989 for (imode = GET_MODE (to); imode != VOIDmode;
2990 imode = GET_MODE_WIDER_MODE (imode))
2991 for (fmode = GET_MODE (from); fmode != VOIDmode;
2992 fmode = GET_MODE_WIDER_MODE (fmode))
2993 {
2994 int doing_unsigned = unsignedp;
2995
2996 icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
2997 if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
2998 icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
2999
3000 if (icode != CODE_FOR_nothing)
3001 {
3002 to = protect_from_queue (to, 1);
3003 from = protect_from_queue (from, 0);
3004
3005 if (fmode != GET_MODE (from))
3006 from = convert_to_mode (fmode, from, 0);
3007
3008 if (must_trunc)
3009 from = ftruncify (from);
3010
3011 if (imode != GET_MODE (to))
3012 target = gen_reg_rtx (imode);
3013
3014 emit_unop_insn (icode, target, from,
3015 doing_unsigned ? UNSIGNED_FIX : FIX);
3016 if (target != to)
3017 convert_move (to, target, unsignedp);
3018 return;
3019 }
3020 }
3021
3022#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3023 /* For an unsigned conversion, there is one more way to do it.
3024 If we have a signed conversion, we generate code that compares
3025 the real value to the largest representable positive number. If if
3026 is smaller, the conversion is done normally. Otherwise, subtract
3027 one plus the highest signed number, convert, and add it back.
3028
3029 We only need to check all real modes, since we know we didn't find
3030 anything with a wider integer mode. */
3031
3032 if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
3033 for (fmode = GET_MODE (from); fmode != VOIDmode;
3034 fmode = GET_MODE_WIDER_MODE (fmode))
3035 /* Make sure we won't lose significant bits doing this. */
3036 if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))
3037 && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
3038 &must_trunc))
3039 {
3040 int bitsize;
3041 REAL_VALUE_TYPE offset;
3042 rtx limit, lab1, lab2, insn;
3043
3044 bitsize = GET_MODE_BITSIZE (GET_MODE (to));
3045 offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1);
3046 limit = immed_real_const_1 (offset, fmode);
3047 lab1 = gen_label_rtx ();
3048 lab2 = gen_label_rtx ();
3049
3050 emit_queue ();
3051 to = protect_from_queue (to, 1);
3052 from = protect_from_queue (from, 0);
3053
3054 if (flag_force_mem)
3055 from = force_not_mem (from);
3056
3057 if (fmode != GET_MODE (from))
3058 from = convert_to_mode (fmode, from, 0);
3059
3060 /* See if we need to do the subtraction. */
3061 do_pending_stack_adjust ();
3062 emit_cmp_insn (from, limit, GE, NULL_RTX, GET_MODE (from), 0, 0);
3063 emit_jump_insn (gen_bge (lab1));
3064
3065 /* If not, do the signed "fix" and branch around fixup code. */
3066 expand_fix (to, from, 0);
3067 emit_jump_insn (gen_jump (lab2));
3068 emit_barrier ();
3069
3070 /* Otherwise, subtract 2**(N-1), convert to signed number,
3071 then add 2**(N-1). Do the addition using XOR since this
3072 will often generate better code. */
3073 emit_label (lab1);
3074 target = expand_binop (GET_MODE (from), sub_optab, from, limit,
3075 NULL_RTX, 0, OPTAB_LIB_WIDEN);
3076 expand_fix (to, target, 0);
3077 target = expand_binop (GET_MODE (to), xor_optab, to,
3078 GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)),
3079 to, 1, OPTAB_LIB_WIDEN);
3080
3081 if (target != to)
3082 emit_move_insn (to, target);
3083
3084 emit_label (lab2);
3085
3086 /* Make a place for a REG_NOTE and add it. */
3087 insn = emit_move_insn (to, to);
3088 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
3089 gen_rtx (UNSIGNED_FIX, GET_MODE (to),
3090 copy_rtx (from)),
3091 REG_NOTES (insn));
3092
3093 return;
3094 }
3095#endif
3096
3097 /* We can't do it with an insn, so use a library call. But first ensure
3098 that the mode of TO is at least as wide as SImode, since those are the
3099 only library calls we know about. */
3100
3101 if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
3102 {
3103 target = gen_reg_rtx (SImode);
3104
3105 expand_fix (target, from, unsignedp);
3106 }
3107 else if (GET_MODE (from) == SFmode)
3108 {
3109 if (GET_MODE (to) == SImode)
3110 libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc;
3111 else if (GET_MODE (to) == DImode)
3112 libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc;
3113 else if (GET_MODE (to) == TImode)
3114 libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc;
3115 else
3116 abort ();
3117 }
3118 else if (GET_MODE (from) == DFmode)
3119 {
3120 if (GET_MODE (to) == SImode)
3121 libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc;
3122 else if (GET_MODE (to) == DImode)
3123 libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc;
3124 else if (GET_MODE (to) == TImode)
3125 libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc;
3126 else
3127 abort ();
3128 }
3129 else if (GET_MODE (from) == XFmode)
3130 {
3131 if (GET_MODE (to) == SImode)
3132 libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc;
3133 else if (GET_MODE (to) == DImode)
3134 libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc;
3135 else if (GET_MODE (to) == TImode)
3136 libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc;
3137 else
3138 abort ();
3139 }
3140 else if (GET_MODE (from) == TFmode)
3141 {
3142 if (GET_MODE (to) == SImode)
3143 libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc;
3144 else if (GET_MODE (to) == DImode)
3145 libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc;
3146 else if (GET_MODE (to) == TImode)
3147 libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc;
3148 else
3149 abort ();
3150 }
3151 else
3152 abort ();
3153
3154 if (libfcn)
3155 {
3156 rtx insns;
3157
3158 to = protect_from_queue (to, 1);
3159 from = protect_from_queue (from, 0);
3160
3161 if (flag_force_mem)
3162 from = force_not_mem (from);
3163
3164 start_sequence ();
3165
3166 emit_library_call (libfcn, 1, GET_MODE (to), 1, from, GET_MODE (from));
3167 insns = get_insns ();
3168 end_sequence ();
3169
3170 emit_libcall_block (insns, target, hard_libcall_value (GET_MODE (to)),
3171 gen_rtx (unsignedp ? FIX : UNSIGNED_FIX,
3172 GET_MODE (to), from));
3173 }
3174
3175 if (GET_MODE (to) == GET_MODE (target))
3176 emit_move_insn (to, target);
3177 else
3178 convert_move (to, target, 0);
3179}
3180\f
3181static optab
3182init_optab (code)
3183 enum rtx_code code;
3184{
3185 int i;
3186 optab op = (optab) xmalloc (sizeof (struct optab));
3187 op->code = code;
3188 for (i = 0; i < NUM_MACHINE_MODES; i++)
3189 {
3190 op->handlers[i].insn_code = CODE_FOR_nothing;
3191 op->handlers[i].libfunc = 0;
3192 }
3193 return op;
3194}
3195
3196/* Initialize the libfunc fields of an entire group of entries in some
3197 optab. Each entry is set equal to a string consisting of a leading
3198 pair of underscores followed by a generic operation name followed by
3199 a mode name (downshifted to lower case) followed by a single character
3200 representing the number of operands for the given operation (which is
3201 usually one of the characters '2', '3', or '4').
3202
3203 OPTABLE is the table in which libfunc fields are to be initialized.
3204 FIRST_MODE is the first machine mode index in the given optab to
3205 initialize.
3206 LAST_MODE is the last machine mode index in the given optab to
3207 initialize.
3208 OPNAME is the generic (string) name of the operation.
3209 SUFFIX is the character which specifies the number of operands for
3210 the given generic operation.
3211*/
3212
3213static void
3214init_libfuncs (optable, first_mode, last_mode, opname, suffix)
3215 register optab optable;
3216 register int first_mode;
3217 register int last_mode;
3218 register char *opname;
3219 register char suffix;
3220{
3221 register int mode;
3222 register unsigned opname_len = strlen (opname);
3223
3224 for (mode = first_mode; (int) mode <= (int) last_mode;
3225 mode = (enum machine_mode) ((int) mode + 1))
3226 {
3227 register char *mname = mode_name[(int) mode];
3228 register unsigned mname_len = strlen (mname);
3229 register char *libfunc_name
3230 = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1);
3231 register char *p;
3232 register char *q;
3233
3234 p = libfunc_name;
3235 *p++ = '_';
3236 *p++ = '_';
3237 for (q = opname; *q; )
3238 *p++ = *q++;
3239 for (q = mname; *q; q++)
3240 *p++ = tolower (*q);
3241 *p++ = suffix;
3242 *p++ = '\0';
3243 optable->handlers[(int) mode].libfunc
3244 = gen_rtx (SYMBOL_REF, Pmode, libfunc_name);
3245 }
3246}
3247
3248/* Initialize the libfunc fields of an entire group of entries in some
3249 optab which correspond to all integer mode operations. The parameters
3250 have the same meaning as similarly named ones for the `init_libfuncs'
3251 routine. (See above). */
3252
3253static void
3254init_integral_libfuncs (optable, opname, suffix)
3255 register optab optable;
3256 register char *opname;
3257 register char suffix;
3258{
3259 init_libfuncs (optable, SImode, TImode, opname, suffix);
3260}
3261
3262/* Initialize the libfunc fields of an entire group of entries in some
3263 optab which correspond to all real mode operations. The parameters
3264 have the same meaning as similarly named ones for the `init_libfuncs'
3265 routine. (See above). */
3266
3267static void
3268init_floating_libfuncs (optable, opname, suffix)
3269 register optab optable;
3270 register char *opname;
3271 register char suffix;
3272{
3273 init_libfuncs (optable, SFmode, TFmode, opname, suffix);
3274}
3275
3276/* Initialize the libfunc fields of an entire group of entries in some
3277 optab which correspond to all complex floating modes. The parameters
3278 have the same meaning as similarly named ones for the `init_libfuncs'
3279 routine. (See above). */
3280
3281static void
3282init_complex_libfuncs (optable, opname, suffix)
3283 register optab optable;
3284 register char *opname;
3285 register char suffix;
3286{
3287 init_libfuncs (optable, SCmode, TCmode, opname, suffix);
3288}
3289
3290/* Call this once to initialize the contents of the optabs
3291 appropriately for the current target machine. */
3292
3293void
3294init_optabs ()
3295{
3296 int i, j;
3297 enum insn_code *p;
3298
3299 /* Start by initializing all tables to contain CODE_FOR_nothing. */
3300
3301 for (p = fixtab[0][0];
3302 p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]);
3303 p++)
3304 *p = CODE_FOR_nothing;
3305
3306 for (p = fixtrunctab[0][0];
3307 p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]);
3308 p++)
3309 *p = CODE_FOR_nothing;
3310
3311 for (p = floattab[0][0];
3312 p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]);
3313 p++)
3314 *p = CODE_FOR_nothing;
3315
3316 for (p = extendtab[0][0];
3317 p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0];
3318 p++)
3319 *p = CODE_FOR_nothing;
3320
3321 for (i = 0; i < NUM_RTX_CODE; i++)
3322 setcc_gen_code[i] = CODE_FOR_nothing;
3323
3324 add_optab = init_optab (PLUS);
3325 sub_optab = init_optab (MINUS);
3326 smul_optab = init_optab (MULT);
3327 smul_widen_optab = init_optab (UNKNOWN);
3328 umul_widen_optab = init_optab (UNKNOWN);
3329 sdiv_optab = init_optab (DIV);
3330 sdivmod_optab = init_optab (UNKNOWN);
3331 udiv_optab = init_optab (UDIV);
3332 udivmod_optab = init_optab (UNKNOWN);
3333 smod_optab = init_optab (MOD);
3334 umod_optab = init_optab (UMOD);
3335 flodiv_optab = init_optab (DIV);
3336 ftrunc_optab = init_optab (UNKNOWN);
3337 and_optab = init_optab (AND);
3338 ior_optab = init_optab (IOR);
3339 xor_optab = init_optab (XOR);
3340 ashl_optab = init_optab (ASHIFT);
3341 ashr_optab = init_optab (ASHIFTRT);
3342 lshl_optab = init_optab (LSHIFT);
3343 lshr_optab = init_optab (LSHIFTRT);
3344 rotl_optab = init_optab (ROTATE);
3345 rotr_optab = init_optab (ROTATERT);
3346 smin_optab = init_optab (SMIN);
3347 smax_optab = init_optab (SMAX);
3348 umin_optab = init_optab (UMIN);
3349 umax_optab = init_optab (UMAX);
3350 mov_optab = init_optab (UNKNOWN);
3351 movstrict_optab = init_optab (UNKNOWN);
3352 cmp_optab = init_optab (UNKNOWN);
3353 ucmp_optab = init_optab (UNKNOWN);
3354 tst_optab = init_optab (UNKNOWN);
3355 neg_optab = init_optab (NEG);
3356 abs_optab = init_optab (ABS);
3357 one_cmpl_optab = init_optab (NOT);
3358 ffs_optab = init_optab (FFS);
3359 sqrt_optab = init_optab (SQRT);
3360 sin_optab = init_optab (UNKNOWN);
3361 cos_optab = init_optab (UNKNOWN);
3362 strlen_optab = init_optab (UNKNOWN);
3363
3364 for (i = 0; i < NUM_MACHINE_MODES; i++)
3365 {
3366 movstr_optab[i] = CODE_FOR_nothing;
3367
3368#ifdef HAVE_SECONDARY_RELOADS
3369 reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
3370#endif
3371 }
3372
3373 /* Fill in the optabs with the insns we support. */
3374 init_all_optabs ();
3375
3376#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
3377 /* This flag says the same insns that convert to a signed fixnum
3378 also convert validly to an unsigned one. */
3379 for (i = 0; i < NUM_MACHINE_MODES; i++)
3380 for (j = 0; j < NUM_MACHINE_MODES; j++)
3381 fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
3382#endif
3383
3384#ifdef EXTRA_CC_MODES
3385 init_mov_optab ();
3386#endif
3387
3388 /* Initialize the optabs with the names of the library functions. */
3389 init_integral_libfuncs (add_optab, "add", '3');
3390 init_floating_libfuncs (add_optab, "add", '3');
3391 init_integral_libfuncs (sub_optab, "sub", '3');
3392 init_floating_libfuncs (sub_optab, "sub", '3');
3393 init_integral_libfuncs (smul_optab, "mul", '3');
3394 init_floating_libfuncs (smul_optab, "mul", '3');
3395 init_integral_libfuncs (sdiv_optab, "div", '3');
3396 init_integral_libfuncs (udiv_optab, "udiv", '3');
3397 init_integral_libfuncs (sdivmod_optab, "divmod", '4');
3398 init_integral_libfuncs (udivmod_optab, "udivmod", '4');
3399 init_integral_libfuncs (smod_optab, "mod", '3');
3400 init_integral_libfuncs (umod_optab, "umod", '3');
3401 init_floating_libfuncs (flodiv_optab, "div", '3');
3402 init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
3403 init_integral_libfuncs (and_optab, "and", '3');
3404 init_integral_libfuncs (ior_optab, "ior", '3');
3405 init_integral_libfuncs (xor_optab, "xor", '3');
3406 init_integral_libfuncs (ashl_optab, "ashl", '3');
3407 init_integral_libfuncs (ashr_optab, "ashr", '3');
3408 init_integral_libfuncs (lshl_optab, "lshl", '3');
3409 init_integral_libfuncs (lshr_optab, "lshr", '3');
3410 init_integral_libfuncs (rotl_optab, "rotl", '3');
3411 init_integral_libfuncs (rotr_optab, "rotr", '3');
3412 init_integral_libfuncs (smin_optab, "min", '3');
3413 init_floating_libfuncs (smin_optab, "min", '3');
3414 init_integral_libfuncs (smax_optab, "max", '3');
3415 init_floating_libfuncs (smax_optab, "max", '3');
3416 init_integral_libfuncs (umin_optab, "umin", '3');
3417 init_integral_libfuncs (umax_optab, "umax", '3');
3418 init_integral_libfuncs (neg_optab, "neg", '2');
3419 init_floating_libfuncs (neg_optab, "neg", '2');
3420 init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
3421 init_integral_libfuncs (ffs_optab, "ffs", '2');
3422
3423 /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
3424 init_integral_libfuncs (cmp_optab, "cmp", '2');
3425 init_integral_libfuncs (ucmp_optab, "ucmp", '2');
3426 init_floating_libfuncs (cmp_optab, "cmp", '2');
3427
3428#ifdef MULSI3_LIBCALL
3429 smul_optab->handlers[(int) SImode].libfunc
3430 = gen_rtx (SYMBOL_REF, Pmode, MULSI3_LIBCALL);
3431#endif
3432#ifdef MULDI3_LIBCALL
3433 smul_optab->handlers[(int) DImode].libfunc
3434 = gen_rtx (SYMBOL_REF, Pmode, MULDI3_LIBCALL);
3435#endif
3436#ifdef MULTI3_LIBCALL
3437 smul_optab->handlers[(int) TImode].libfunc
3438 = gen_rtx (SYMBOL_REF, Pmode, MULTI3_LIBCALL);
3439#endif
3440
3441#ifdef DIVSI3_LIBCALL
3442 sdiv_optab->handlers[(int) SImode].libfunc
3443 = gen_rtx (SYMBOL_REF, Pmode, DIVSI3_LIBCALL);
3444#endif
3445#ifdef DIVDI3_LIBCALL
3446 sdiv_optab->handlers[(int) DImode].libfunc
3447 = gen_rtx (SYMBOL_REF, Pmode, DIVDI3_LIBCALL);
3448#endif
3449#ifdef DIVTI3_LIBCALL
3450 sdiv_optab->handlers[(int) TImode].libfunc
3451 = gen_rtx (SYMBOL_REF, Pmode, DIVTI3_LIBCALL);
3452#endif
3453
3454#ifdef UDIVSI3_LIBCALL
3455 udiv_optab->handlers[(int) SImode].libfunc
3456 = gen_rtx (SYMBOL_REF, Pmode, UDIVSI3_LIBCALL);
3457#endif
3458#ifdef UDIVDI3_LIBCALL
3459 udiv_optab->handlers[(int) DImode].libfunc
3460 = gen_rtx (SYMBOL_REF, Pmode, UDIVDI3_LIBCALL);
3461#endif
3462#ifdef UDIVTI3_LIBCALL
3463 udiv_optab->handlers[(int) TImode].libfunc
3464 = gen_rtx (SYMBOL_REF, Pmode, UDIVTI3_LIBCALL);
3465#endif
3466
3467
3468#ifdef MODSI3_LIBCALL
3469 smod_optab->handlers[(int) SImode].libfunc
3470 = gen_rtx (SYMBOL_REF, Pmode, MODSI3_LIBCALL);
3471#endif
3472#ifdef MODDI3_LIBCALL
3473 smod_optab->handlers[(int) DImode].libfunc
3474 = gen_rtx (SYMBOL_REF, Pmode, MODDI3_LIBCALL);
3475#endif
3476#ifdef MODTI3_LIBCALL
3477 smod_optab->handlers[(int) TImode].libfunc
3478 = gen_rtx (SYMBOL_REF, Pmode, MODTI3_LIBCALL);
3479#endif
3480
3481
3482#ifdef UMODSI3_LIBCALL
3483 umod_optab->handlers[(int) SImode].libfunc
3484 = gen_rtx (SYMBOL_REF, Pmode, UMODSI3_LIBCALL);
3485#endif
3486#ifdef UMODDI3_LIBCALL
3487 umod_optab->handlers[(int) DImode].libfunc
3488 = gen_rtx (SYMBOL_REF, Pmode, UMODDI3_LIBCALL);
3489#endif
3490#ifdef UMODTI3_LIBCALL
3491 umod_optab->handlers[(int) TImode].libfunc
3492 = gen_rtx (SYMBOL_REF, Pmode, UMODTI3_LIBCALL);
3493#endif
3494
3495 /* Use cabs for DC complex abs, since systems generally have cabs.
3496 Don't define any libcall for SCmode, so that cabs will be used. */
3497 abs_optab->handlers[(int) DCmode].libfunc
3498 = gen_rtx (SYMBOL_REF, Pmode, "cabs");
3499
3500 ffs_optab->handlers[(int) mode_for_size (BITS_PER_WORD, MODE_INT, 0)] .libfunc
3501 = gen_rtx (SYMBOL_REF, Pmode, "ffs");
3502
3503 extendsfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfdf2");
3504 extendsfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfxf2");
3505 extendsftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsftf2");
3506 extenddfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddfxf2");
3507 extenddftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddftf2");
3508
3509 truncdfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncdfsf2");
3510 truncxfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfsf2");
3511 trunctfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfsf2");
3512 truncxfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfdf2");
3513 trunctfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfdf2");
3514
3515 memcpy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcpy");
3516 bcopy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bcopy");
3517 memcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcmp");
3518 bcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gcc_bcmp");
3519 memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset");
3520 bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero");
3521
3522 eqsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqsf2");
3523 nesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nesf2");
3524 gtsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtsf2");
3525 gesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gesf2");
3526 ltsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltsf2");
3527 lesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lesf2");
3528
3529 eqdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqdf2");
3530 nedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nedf2");
3531 gtdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtdf2");
3532 gedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gedf2");
3533 ltdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltdf2");
3534 ledf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ledf2");
3535
3536 eqxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqxf2");
3537 nexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nexf2");
3538 gtxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtxf2");
3539 gexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gexf2");
3540 ltxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltxf2");
3541 lexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lexf2");
3542
3543 eqtf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqtf2");
3544 netf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__netf2");
3545 gttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gttf2");
3546 getf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__getf2");
3547 lttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lttf2");
3548 letf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__letf2");
3549
3550 floatsisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsisf");
3551 floatdisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdisf");
3552 floattisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattisf");
3553
3554 floatsidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsidf");
3555 floatdidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdidf");
3556 floattidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattidf");
3557
3558 floatsixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsixf");
3559 floatdixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdixf");
3560 floattixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattixf");
3561
3562 floatsitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsitf");
3563 floatditf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatditf");
3564 floattitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattitf");
3565
3566 fixsfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfsi");
3567 fixsfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfdi");
3568 fixsfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfti");
3569
3570 fixdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfsi");
3571 fixdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfdi");
3572 fixdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfti");
3573
3574 fixxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfsi");
3575 fixxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfdi");
3576 fixxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfti");
3577
3578 fixtfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfsi");
3579 fixtfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfdi");
3580 fixtfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfti");
3581
3582 fixunssfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfsi");
3583 fixunssfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfdi");
3584 fixunssfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfti");
3585
3586 fixunsdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfsi");
3587 fixunsdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfdi");
3588 fixunsdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfti");
3589
3590 fixunsxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfsi");
3591 fixunsxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfdi");
3592 fixunsxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfti");
3593
3594 fixunstfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfsi");
3595 fixunstfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfdi");
3596 fixunstfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfti");
3597}
3598\f
3599#ifdef BROKEN_LDEXP
3600
3601/* SCO 3.2 apparently has a broken ldexp. */
3602
3603double
3604ldexp(x,n)
3605 double x;
3606 int n;
3607{
3608 if (n > 0)
3609 while (n--)
3610 x *= 2;
3611
3612 return x;
3613}
3614#endif /* BROKEN_LDEXP */