1 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2 Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
25 #include "insn-flags.h"
26 #include "insn-codes.h"
28 #include "insn-config.h"
32 /* Each optab contains info on how this target machine
33 can perform a particular operation
34 for all sizes and kinds of operands.
36 The operation to be performed is often specified
37 by passing one of these optabs as an argument.
39 See expr.h for documentation of these optabs. */
44 optab smul_widen_optab
;
45 optab umul_widen_optab
;
69 optab movstrict_optab
;
78 optab ucmp_optab
; /* Used only for libcalls for unsigned comparisons. */
83 /* SYMBOL_REF rtx's for the library functions that are called
84 implicitly and not via optabs. */
86 rtx extendsfdf2_libfunc
;
87 rtx extendsfxf2_libfunc
;
88 rtx extendsftf2_libfunc
;
89 rtx extenddfxf2_libfunc
;
90 rtx extenddftf2_libfunc
;
92 rtx truncdfsf2_libfunc
;
93 rtx truncxfsf2_libfunc
;
94 rtx trunctfsf2_libfunc
;
95 rtx truncxfdf2_libfunc
;
96 rtx trunctfdf2_libfunc
;
133 rtx floatsisf_libfunc
;
134 rtx floatdisf_libfunc
;
135 rtx floattisf_libfunc
;
137 rtx floatsidf_libfunc
;
138 rtx floatdidf_libfunc
;
139 rtx floattidf_libfunc
;
141 rtx floatsixf_libfunc
;
142 rtx floatdixf_libfunc
;
143 rtx floattixf_libfunc
;
145 rtx floatsitf_libfunc
;
146 rtx floatditf_libfunc
;
147 rtx floattitf_libfunc
;
165 rtx fixunssfsi_libfunc
;
166 rtx fixunssfdi_libfunc
;
167 rtx fixunssfti_libfunc
;
169 rtx fixunsdfsi_libfunc
;
170 rtx fixunsdfdi_libfunc
;
171 rtx fixunsdfti_libfunc
;
173 rtx fixunsxfsi_libfunc
;
174 rtx fixunsxfdi_libfunc
;
175 rtx fixunsxfti_libfunc
;
177 rtx fixunstfsi_libfunc
;
178 rtx fixunstfdi_libfunc
;
179 rtx fixunstfti_libfunc
;
181 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
182 gives the gen_function to make a branch to test that condition. */
184 rtxfun bcc_gen_fctn
[NUM_RTX_CODE
];
186 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
187 gives the insn code to make a store-condition insn
188 to test that condition. */
190 enum insn_code setcc_gen_code
[NUM_RTX_CODE
];
192 static void emit_float_lib_cmp ();
194 /* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
195 the result of operation CODE applied to OP0 (and OP1 if it is a binary
198 If the last insn does not set TARGET, don't do anything, but return 1.
200 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
201 don't add the REG_EQUAL note but return 0. Our caller can then try
202 again, ensuring that TARGET is not one of the operands. */
205 add_equal_note (seq
, target
, code
, op0
, op1
)
215 if ((GET_RTX_CLASS (code
) != '1' && GET_RTX_CLASS (code
) != '2'
216 && GET_RTX_CLASS (code
) != 'c' && GET_RTX_CLASS (code
) != '<')
217 || GET_CODE (seq
) != SEQUENCE
218 || (set
= single_set (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1))) == 0
219 || GET_CODE (target
) == ZERO_EXTRACT
220 || (! rtx_equal_p (SET_DEST (set
), target
)
221 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
223 && (GET_CODE (SET_DEST (set
)) != STRICT_LOW_PART
224 || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set
), 0)),
228 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
229 besides the last insn. */
230 if (reg_overlap_mentioned_p (target
, op0
)
231 || (op1
&& reg_overlap_mentioned_p (target
, op1
)))
232 for (i
= XVECLEN (seq
, 0) - 2; i
>= 0; i
--)
233 if (reg_set_p (target
, XVECEXP (seq
, 0, i
)))
236 if (GET_RTX_CLASS (code
) == '1')
237 note
= gen_rtx (code
, GET_MODE (target
), op0
);
239 note
= gen_rtx (code
, GET_MODE (target
), op0
, op1
);
241 REG_NOTES (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1))
242 = gen_rtx (EXPR_LIST
, REG_EQUAL
, note
,
243 REG_NOTES (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1)));
248 /* Generate code to perform an operation specified by BINOPTAB
249 on operands OP0 and OP1, with result having machine-mode MODE.
251 UNSIGNEDP is for the case where we have to widen the operands
252 to perform the operation. It says to use zero-extension.
254 If TARGET is nonzero, the value
255 is generated there, if it is convenient to do so.
256 In all cases an rtx is returned for the locus of the value;
257 this may or may not be TARGET. */
260 expand_binop (mode
, binoptab
, op0
, op1
, target
, unsignedp
, methods
)
261 enum machine_mode mode
;
266 enum optab_methods methods
;
268 enum mode_class
class;
269 enum machine_mode wider_mode
;
271 int commutative_op
= 0;
272 int shift_op
= (binoptab
->code
== ASHIFT
273 || binoptab
->code
== ASHIFTRT
274 || binoptab
->code
== LSHIFT
275 || binoptab
->code
== LSHIFTRT
276 || binoptab
->code
== ROTATE
277 || binoptab
->code
== ROTATERT
);
280 class = GET_MODE_CLASS (mode
);
282 op0
= protect_from_queue (op0
, 0);
283 op1
= protect_from_queue (op1
, 0);
285 target
= protect_from_queue (target
, 1);
289 op0
= force_not_mem (op0
);
290 op1
= force_not_mem (op1
);
293 /* If we are inside an appropriately-short loop and one operand is an
294 expensive constant, force it into a register. */
295 if (CONSTANT_P (op0
) && preserve_subexpressions_p ()
296 && rtx_cost (op0
, binoptab
->code
) > 2)
297 op0
= force_reg (mode
, op0
);
299 if (CONSTANT_P (op1
) && preserve_subexpressions_p ()
300 && rtx_cost (op1
, binoptab
->code
) > 2)
301 op1
= force_reg (shift_op
? word_mode
: mode
, op1
);
303 #if 0 /* Turned off because it seems to be a kludgy method. */
304 /* If subtracting integer from pointer, and the pointer has a special mode,
305 then change it to an add. We use the add insn of Pmode for combining
306 integers with pointers, and the sub insn to subtract two pointers. */
308 if (binoptab
== sub_optab
309 && GET_MODE (op0
) == Pmode
&& GET_MODE (op1
) != Pmode
)
311 op1
= negate_rtx (GET_MODE(op1
), op1
);
312 binoptab
= add_optab
;
316 /* Record where to delete back to if we backtrack. */
317 last
= get_last_insn ();
319 /* If operation is commutative,
320 try to make the first operand a register.
321 Even better, try to make it the same as the target.
322 Also try to make the last operand a constant. */
323 if (GET_RTX_CLASS (binoptab
->code
) == 'c'
324 || binoptab
== smul_widen_optab
325 || binoptab
== umul_widen_optab
)
329 if (((target
== 0 || GET_CODE (target
) == REG
)
330 ? ((GET_CODE (op1
) == REG
331 && GET_CODE (op0
) != REG
)
333 : rtx_equal_p (op1
, target
))
334 || GET_CODE (op0
) == CONST_INT
)
342 /* If we can do it with a three-operand insn, do so. */
344 if (methods
!= OPTAB_MUST_WIDEN
345 && binoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
347 int icode
= (int) binoptab
->handlers
[(int) mode
].insn_code
;
348 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
349 enum machine_mode mode1
= insn_operand_mode
[icode
][2];
351 rtx xop0
= op0
, xop1
= op1
;
356 temp
= gen_reg_rtx (mode
);
358 /* If it is a commutative operator and the modes would match
359 if we would swap the operands, we can save the conversions. */
362 if (GET_MODE (op0
) != mode0
&& GET_MODE (op1
) != mode1
363 && GET_MODE (op0
) == mode1
&& GET_MODE (op1
) == mode0
)
367 tmp
= op0
; op0
= op1
; op1
= tmp
;
368 tmp
= xop0
; xop0
= xop1
; xop1
= tmp
;
372 /* In case the insn wants input operands in modes different from
373 the result, convert the operands. */
375 if (GET_MODE (op0
) != VOIDmode
376 && GET_MODE (op0
) != mode0
)
377 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
379 if (GET_MODE (xop1
) != VOIDmode
380 && GET_MODE (xop1
) != mode1
)
381 xop1
= convert_to_mode (mode1
, xop1
, unsignedp
);
383 /* Now, if insn's predicates don't allow our operands, put them into
386 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
387 xop0
= copy_to_mode_reg (mode0
, xop0
);
389 if (! (*insn_operand_predicate
[icode
][2]) (xop1
, mode1
))
390 xop1
= copy_to_mode_reg (mode1
, xop1
);
392 if (! (*insn_operand_predicate
[icode
][0]) (temp
, mode
))
393 temp
= gen_reg_rtx (mode
);
395 pat
= GEN_FCN (icode
) (temp
, xop0
, xop1
);
398 /* If PAT is a multi-insn sequence, try to add an appropriate
399 REG_EQUAL note to it. If we can't because TEMP conflicts with an
400 operand, call ourselves again, this time without a target. */
401 if (GET_CODE (pat
) == SEQUENCE
402 && ! add_equal_note (pat
, temp
, binoptab
->code
, xop0
, xop1
))
404 delete_insns_since (last
);
405 return expand_binop (mode
, binoptab
, op0
, op1
, NULL_RTX
,
413 delete_insns_since (last
);
416 /* If this is a multiply, see if we can do a widening operation that
417 takes operands of this mode and makes a wider mode. */
419 if (binoptab
== smul_optab
&& GET_MODE_WIDER_MODE (mode
) != VOIDmode
420 && (((unsignedp
? umul_widen_optab
: smul_widen_optab
)
421 ->handlers
[(int) GET_MODE_WIDER_MODE (mode
)].insn_code
)
422 != CODE_FOR_nothing
))
424 temp
= expand_binop (GET_MODE_WIDER_MODE (mode
),
425 unsignedp
? umul_widen_optab
: smul_widen_optab
,
426 op0
, op1
, 0, unsignedp
, OPTAB_DIRECT
);
428 if (GET_MODE_CLASS (mode
) == MODE_INT
)
429 return gen_lowpart (mode
, temp
);
431 return convert_to_mode (mode
, temp
, unsignedp
);
434 /* Look for a wider mode of the same class for which we think we
435 can open-code the operation. Check for a widening multiply at the
436 wider mode as well. */
438 if ((class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
439 && mode
!= OPTAB_DIRECT
&& mode
!= OPTAB_LIB
)
440 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
441 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
443 if (binoptab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
444 || (binoptab
== smul_optab
445 && GET_MODE_WIDER_MODE (wider_mode
) != VOIDmode
446 && (((unsignedp
? umul_widen_optab
: smul_widen_optab
)
447 ->handlers
[(int) GET_MODE_WIDER_MODE (wider_mode
)].insn_code
)
448 != CODE_FOR_nothing
)))
450 rtx xop0
= op0
, xop1
= op1
;
453 /* For certain integer operations, we need not actually extend
454 the narrow operands, as long as we will truncate
455 the results to the same narrowness. */
457 if ((binoptab
== ior_optab
|| binoptab
== and_optab
458 || binoptab
== xor_optab
459 || binoptab
== add_optab
|| binoptab
== sub_optab
460 || binoptab
== smul_optab
461 || binoptab
== ashl_optab
|| binoptab
== lshl_optab
)
462 && class == MODE_INT
)
465 /* If an operand is a constant integer, we might as well
466 convert it since that is more efficient than using a SUBREG,
467 unlike the case for other operands. */
469 if (no_extend
&& GET_MODE (xop0
) != VOIDmode
)
470 xop0
= gen_rtx (SUBREG
, wider_mode
,
471 force_reg (GET_MODE (xop0
), xop0
), 0);
473 xop0
= convert_to_mode (wider_mode
, xop0
, unsignedp
);
475 if (no_extend
&& GET_MODE (xop1
) != VOIDmode
)
476 xop1
= gen_rtx (SUBREG
, wider_mode
,
477 force_reg (GET_MODE (xop1
), xop1
), 0);
479 xop1
= convert_to_mode (wider_mode
, xop1
, unsignedp
);
481 temp
= expand_binop (wider_mode
, binoptab
, xop0
, xop1
, NULL_RTX
,
482 unsignedp
, OPTAB_DIRECT
);
485 if (class != MODE_INT
)
488 target
= gen_reg_rtx (mode
);
489 convert_move (target
, temp
, 0);
493 return gen_lowpart (mode
, temp
);
496 delete_insns_since (last
);
500 /* These can be done a word at a time. */
501 if ((binoptab
== and_optab
|| binoptab
== ior_optab
|| binoptab
== xor_optab
)
503 && GET_MODE_SIZE (mode
) > UNITS_PER_WORD
504 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
510 /* If TARGET is the same as one of the operands, the REG_EQUAL note
511 won't be accurate, so use a new target. */
512 if (target
== 0 || target
== op0
|| target
== op1
)
513 target
= gen_reg_rtx (mode
);
517 /* Do the actual arithmetic. */
518 for (i
= 0; i
< GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
; i
++)
520 rtx target_piece
= operand_subword (target
, i
, 1, mode
);
521 rtx x
= expand_binop (word_mode
, binoptab
,
522 operand_subword_force (op0
, i
, mode
),
523 operand_subword_force (op1
, i
, mode
),
524 target_piece
, unsignedp
, methods
);
525 if (target_piece
!= x
)
526 emit_move_insn (target_piece
, x
);
529 insns
= get_insns ();
532 if (binoptab
->code
!= UNKNOWN
)
533 equiv_value
= gen_rtx (binoptab
->code
, mode
, op0
, op1
);
537 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv_value
);
541 /* These can be done a word at a time by propagating carries. */
542 if ((binoptab
== add_optab
|| binoptab
== sub_optab
)
544 && GET_MODE_SIZE (mode
) >= 2 * UNITS_PER_WORD
545 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
548 rtx carry_tmp
= gen_reg_rtx (word_mode
);
549 optab otheroptab
= binoptab
== add_optab
? sub_optab
: add_optab
;
550 int nwords
= GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
;
551 rtx carry_in
, carry_out
;
553 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
554 value is one of those, use it. Otherwise, use 1 since it is the
555 one easiest to get. */
556 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
557 int normalizep
= STORE_FLAG_VALUE
;
562 /* Prepare the operands. */
563 op0
= force_reg (mode
, op0
);
564 op1
= force_reg (mode
, op1
);
566 if (target
== 0 || GET_CODE (target
) != REG
567 || target
== op0
|| target
== op1
)
568 target
= gen_reg_rtx (mode
);
570 /* Do the actual arithmetic. */
571 for (i
= 0; i
< nwords
; i
++)
573 int index
= (WORDS_BIG_ENDIAN
? nwords
- i
- 1 : i
);
574 rtx target_piece
= operand_subword (target
, index
, 1, mode
);
575 rtx op0_piece
= operand_subword_force (op0
, index
, mode
);
576 rtx op1_piece
= operand_subword_force (op1
, index
, mode
);
579 /* Main add/subtract of the input operands. */
580 x
= expand_binop (word_mode
, binoptab
,
581 op0_piece
, op1_piece
,
582 target_piece
, unsignedp
, methods
);
588 /* Store carry from main add/subtract. */
589 carry_out
= gen_reg_rtx (word_mode
);
590 carry_out
= emit_store_flag (carry_out
,
591 binoptab
== add_optab
? LTU
: GTU
,
593 word_mode
, 1, normalizep
);
600 /* Add/subtract previous carry to main result. */
601 x
= expand_binop (word_mode
,
602 normalizep
== 1 ? binoptab
: otheroptab
,
604 target_piece
, 1, methods
);
605 if (target_piece
!= x
)
606 emit_move_insn (target_piece
, x
);
610 /* THIS CODE HAS NOT BEEN TESTED. */
611 /* Get out carry from adding/subtracting carry in. */
612 carry_tmp
= emit_store_flag (carry_tmp
,
613 binoptab
== add_optab
616 word_mode
, 1, normalizep
);
617 /* Logical-ior the two poss. carry together. */
618 carry_out
= expand_binop (word_mode
, ior_optab
,
619 carry_out
, carry_tmp
,
620 carry_out
, 0, methods
);
626 carry_in
= carry_out
;
629 if (i
== GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
)
633 temp
= emit_move_insn (target
, target
);
634 REG_NOTES (temp
) = gen_rtx (EXPR_LIST
, REG_EQUAL
,
635 gen_rtx (binoptab
->code
, mode
, op0
, op1
),
640 delete_insns_since (last
);
643 /* If we want to multiply two two-word values and have normal and widening
644 multiplies of single-word values, we can do this with three smaller
645 multiplications. Note that we do not make a REG_NO_CONFLICT block here
646 because we are not operating on one word at a time.
648 The multiplication proceeds as follows:
649 _______________________
650 [__op0_high_|__op0_low__]
651 _______________________
652 * [__op1_high_|__op1_low__]
653 _______________________________________________
654 _______________________
655 (1) [__op0_low__*__op1_low__]
656 _______________________
657 (2a) [__op0_low__*__op1_high_]
658 _______________________
659 (2b) [__op0_high_*__op1_low__]
660 _______________________
661 (3) [__op0_high_*__op1_high_]
664 This gives a 4-word result. Since we are only interested in the
665 lower 2 words, partial result (3) and the upper words of (2a) and
666 (2b) don't need to be calculated. Hence (2a) and (2b) can be
667 calculated using non-widening multiplication.
669 (1), however, needs to be calculated with an unsigned widening
670 multiplication. If this operation is not directly supported we
671 try using a signed widening multiplication and adjust the result.
672 This adjustment works as follows:
674 If both operands are positive then no adjustment is needed.
676 If the operands have different signs, for example op0_low < 0 and
677 op1_low >= 0, the instruction treats the most significant bit of
678 op0_low as a sign bit instead of a bit with significance
679 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
680 with 2**BITS_PER_WORD - op0_low, and two's complements the
681 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
684 Similarly, if both operands are negative, we need to add
685 (op0_low + op1_low) * 2**BITS_PER_WORD.
687 We use a trick to adjust quickly. We logically shift op0_low right
688 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
689 op0_high (op1_high) before it is used to calculate 2b (2a). If no
690 logical shift exists, we do an arithmetic right shift and subtract
693 if (binoptab
== smul_optab
695 && GET_MODE_SIZE (mode
) == 2 * UNITS_PER_WORD
696 && smul_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
697 && add_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
698 && ((umul_widen_optab
->handlers
[(int) mode
].insn_code
700 || (smul_widen_optab
->handlers
[(int) mode
].insn_code
701 != CODE_FOR_nothing
)))
703 int low
= (WORDS_BIG_ENDIAN
? 1 : 0);
704 int high
= (WORDS_BIG_ENDIAN
? 0 : 1);
705 rtx op0_high
= operand_subword_force (op0
, high
, mode
);
706 rtx op0_low
= operand_subword_force (op0
, low
, mode
);
707 rtx op1_high
= operand_subword_force (op1
, high
, mode
);
708 rtx op1_low
= operand_subword_force (op1
, low
, mode
);
713 /* If the target is the same as one of the inputs, don't use it. This
714 prevents problems with the REG_EQUAL note. */
715 if (target
== op0
|| target
== op1
)
718 /* Multiply the two lower words to get a double-word product.
719 If unsigned widening multiplication is available, use that;
720 otherwise use the signed form and compensate. */
722 if (umul_widen_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
724 product
= expand_binop (mode
, umul_widen_optab
, op0_low
, op1_low
,
725 target
, 1, OPTAB_DIRECT
);
727 /* If we didn't succeed, delete everything we did so far. */
729 delete_insns_since (last
);
731 op0_xhigh
= op0_high
, op1_xhigh
= op1_high
;
735 && smul_widen_optab
->handlers
[(int) mode
].insn_code
738 rtx wordm1
= GEN_INT (BITS_PER_WORD
- 1);
739 product
= expand_binop (mode
, smul_widen_optab
, op0_low
, op1_low
,
740 target
, 1, OPTAB_DIRECT
);
741 op0_xhigh
= expand_binop (word_mode
, lshr_optab
, op0_low
, wordm1
,
742 NULL_RTX
, 1, OPTAB_DIRECT
);
744 op0_xhigh
= expand_binop (word_mode
, add_optab
, op0_high
,
745 op0_xhigh
, op0_xhigh
, 0, OPTAB_DIRECT
);
748 op0_xhigh
= expand_binop (word_mode
, ashr_optab
, op0_low
, wordm1
,
749 NULL_RTX
, 0, OPTAB_DIRECT
);
751 op0_xhigh
= expand_binop (word_mode
, sub_optab
, op0_high
,
752 op0_xhigh
, op0_xhigh
, 0,
756 op1_xhigh
= expand_binop (word_mode
, lshr_optab
, op1_low
, wordm1
,
757 NULL_RTX
, 1, OPTAB_DIRECT
);
759 op1_xhigh
= expand_binop (word_mode
, add_optab
, op1_high
,
760 op1_xhigh
, op1_xhigh
, 0, OPTAB_DIRECT
);
763 op1_xhigh
= expand_binop (word_mode
, ashr_optab
, op1_low
, wordm1
,
764 NULL_RTX
, 0, OPTAB_DIRECT
);
766 op1_xhigh
= expand_binop (word_mode
, sub_optab
, op1_high
,
767 op1_xhigh
, op1_xhigh
, 0,
772 /* If we have been able to directly compute the product of the
773 low-order words of the operands and perform any required adjustments
774 of the operands, we proceed by trying two more multiplications
775 and then computing the appropriate sum.
777 We have checked above that the required addition is provided.
778 Full-word addition will normally always succeed, especially if
779 it is provided at all, so we don't worry about its failure. The
780 multiplication may well fail, however, so we do handle that. */
782 if (product
&& op0_xhigh
&& op1_xhigh
)
785 rtx product_high
= operand_subword (product
, high
, 1, mode
);
786 rtx temp
= expand_binop (word_mode
, binoptab
, op0_low
, op1_xhigh
,
787 NULL_RTX
, 0, OPTAB_DIRECT
);
791 product_piece
= expand_binop (word_mode
, add_optab
, temp
,
792 product_high
, product_high
,
794 if (product_piece
!= product_high
)
795 emit_move_insn (product_high
, product_piece
);
797 temp
= expand_binop (word_mode
, binoptab
, op1_low
, op0_xhigh
,
798 NULL_RTX
, 0, OPTAB_DIRECT
);
800 product_piece
= expand_binop (word_mode
, add_optab
, temp
,
801 product_high
, product_high
,
803 if (product_piece
!= product_high
)
804 emit_move_insn (product_high
, product_piece
);
806 temp
= emit_move_insn (product
, product
);
807 REG_NOTES (temp
) = gen_rtx (EXPR_LIST
, REG_EQUAL
,
808 gen_rtx (MULT
, mode
, op0
, op1
),
815 /* If we get here, we couldn't do it for some reason even though we
816 originally thought we could. Delete anything we've emitted in
819 delete_insns_since (last
);
822 /* It can't be open-coded in this mode.
823 Use a library call if one is available and caller says that's ok. */
825 if (binoptab
->handlers
[(int) mode
].libfunc
826 && (methods
== OPTAB_LIB
|| methods
== OPTAB_LIB_WIDEN
))
829 rtx funexp
= binoptab
->handlers
[(int) mode
].libfunc
;
833 /* Pass 1 for NO_QUEUE so we don't lose any increments
834 if the libcall is cse'd or moved. */
835 emit_library_call (binoptab
->handlers
[(int) mode
].libfunc
,
836 1, mode
, 2, op0
, mode
, op1
,
837 (shift_op
? word_mode
: mode
));
839 insns
= get_insns ();
842 target
= gen_reg_rtx (mode
);
843 emit_libcall_block (insns
, target
, hard_libcall_value (mode
),
844 gen_rtx (binoptab
->code
, mode
, op0
, op1
));
849 delete_insns_since (last
);
851 /* It can't be done in this mode. Can we do it in a wider mode? */
853 if (! (methods
== OPTAB_WIDEN
|| methods
== OPTAB_LIB_WIDEN
854 || methods
== OPTAB_MUST_WIDEN
))
855 return 0; /* Caller says, don't even try. */
857 /* Compute the value of METHODS to pass to recursive calls.
858 Don't allow widening to be tried recursively. */
860 methods
= (methods
== OPTAB_LIB_WIDEN
? OPTAB_LIB
: OPTAB_DIRECT
);
862 /* Look for a wider mode of the same class for which it appears we can do
865 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
867 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
868 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
870 if ((binoptab
->handlers
[(int) wider_mode
].insn_code
872 || (methods
== OPTAB_LIB
873 && binoptab
->handlers
[(int) wider_mode
].libfunc
))
875 rtx xop0
= op0
, xop1
= op1
;
878 /* For certain integer operations, we need not actually extend
879 the narrow operands, as long as we will truncate
880 the results to the same narrowness. */
882 if ((binoptab
== ior_optab
|| binoptab
== and_optab
883 || binoptab
== xor_optab
884 || binoptab
== add_optab
|| binoptab
== sub_optab
885 || binoptab
== smul_optab
886 || binoptab
== ashl_optab
|| binoptab
== lshl_optab
)
887 && class == MODE_INT
)
890 /* If an operand is a constant integer, we might as well
891 convert it since that is more efficient than using a SUBREG,
892 unlike the case for other operands. */
894 if (no_extend
&& GET_MODE (xop0
) != VOIDmode
)
895 xop0
= gen_rtx (SUBREG
, wider_mode
,
896 force_reg (GET_MODE (xop0
), xop0
), 0);
898 xop0
= convert_to_mode (wider_mode
, xop0
, unsignedp
);
900 if (no_extend
&& GET_MODE (xop1
) != VOIDmode
)
901 xop1
= gen_rtx (SUBREG
, wider_mode
,
902 force_reg (GET_MODE (xop1
), xop1
), 0);
904 xop1
= convert_to_mode (wider_mode
, xop1
, unsignedp
);
906 temp
= expand_binop (wider_mode
, binoptab
, xop0
, xop1
, NULL_RTX
,
910 if (class != MODE_INT
)
913 target
= gen_reg_rtx (mode
);
914 convert_move (target
, temp
, 0);
918 return gen_lowpart (mode
, temp
);
921 delete_insns_since (last
);
929 /* Expand a binary operator which has both signed and unsigned forms.
930 UOPTAB is the optab for unsigned operations, and SOPTAB is for
933 If we widen unsigned operands, we may use a signed wider operation instead
934 of an unsigned wider operation, since the result would be the same. */
937 sign_expand_binop (mode
, uoptab
, soptab
, op0
, op1
, target
, unsignedp
, methods
)
938 enum machine_mode mode
;
939 optab uoptab
, soptab
;
940 rtx op0
, op1
, target
;
942 enum optab_methods methods
;
945 optab direct_optab
= unsignedp
? uoptab
: soptab
;
946 struct optab wide_soptab
;
948 /* Do it without widening, if possible. */
949 temp
= expand_binop (mode
, direct_optab
, op0
, op1
, target
,
950 unsignedp
, OPTAB_DIRECT
);
951 if (temp
|| methods
== OPTAB_DIRECT
)
954 /* Try widening to a signed int. Make a fake signed optab that
955 hides any signed insn for direct use. */
956 wide_soptab
= *soptab
;
957 wide_soptab
.handlers
[(int) mode
].insn_code
= CODE_FOR_nothing
;
958 wide_soptab
.handlers
[(int) mode
].libfunc
= 0;
960 temp
= expand_binop (mode
, &wide_soptab
, op0
, op1
, target
,
961 unsignedp
, OPTAB_WIDEN
);
963 /* For unsigned operands, try widening to an unsigned int. */
964 if (temp
== 0 && unsignedp
)
965 temp
= expand_binop (mode
, uoptab
, op0
, op1
, target
,
966 unsignedp
, OPTAB_WIDEN
);
967 if (temp
|| methods
== OPTAB_WIDEN
)
970 /* Use the right width lib call if that exists. */
971 temp
= expand_binop (mode
, direct_optab
, op0
, op1
, target
, unsignedp
, OPTAB_LIB
);
972 if (temp
|| methods
== OPTAB_LIB
)
975 /* Must widen and use a lib call, use either signed or unsigned. */
976 temp
= expand_binop (mode
, &wide_soptab
, op0
, op1
, target
,
981 return expand_binop (mode
, uoptab
, op0
, op1
, target
,
986 /* Generate code to perform an operation specified by BINOPTAB
987 on operands OP0 and OP1, with two results to TARG1 and TARG2.
988 We assume that the order of the operands for the instruction
989 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
990 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
992 Either TARG0 or TARG1 may be zero, but what that means is that
993 that result is not actually wanted. We will generate it into
994 a dummy pseudo-reg and discard it. They may not both be zero.
996 Returns 1 if this operation can be performed; 0 if not. */
999 expand_twoval_binop (binoptab
, op0
, op1
, targ0
, targ1
, unsignedp
)
1005 enum machine_mode mode
= GET_MODE (targ0
? targ0
: targ1
);
1006 enum mode_class
class;
1007 enum machine_mode wider_mode
;
1010 class = GET_MODE_CLASS (mode
);
1012 op0
= protect_from_queue (op0
, 0);
1013 op1
= protect_from_queue (op1
, 0);
1017 op0
= force_not_mem (op0
);
1018 op1
= force_not_mem (op1
);
1021 /* If we are inside an appropriately-short loop and one operand is an
1022 expensive constant, force it into a register. */
1023 if (CONSTANT_P (op0
) && preserve_subexpressions_p ()
1024 && rtx_cost (op0
, binoptab
->code
) > 2)
1025 op0
= force_reg (mode
, op0
);
1027 if (CONSTANT_P (op1
) && preserve_subexpressions_p ()
1028 && rtx_cost (op1
, binoptab
->code
) > 2)
1029 op1
= force_reg (mode
, op1
);
1032 targ0
= protect_from_queue (targ0
, 1);
1034 targ0
= gen_reg_rtx (mode
);
1036 targ1
= protect_from_queue (targ1
, 1);
1038 targ1
= gen_reg_rtx (mode
);
1040 /* Record where to go back to if we fail. */
1041 last
= get_last_insn ();
1043 if (binoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1045 int icode
= (int) binoptab
->handlers
[(int) mode
].insn_code
;
1046 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
1047 enum machine_mode mode1
= insn_operand_mode
[icode
][2];
1049 rtx xop0
= op0
, xop1
= op1
;
1051 /* In case this insn wants input operands in modes different from the
1052 result, convert the operands. */
1053 if (GET_MODE (op0
) != VOIDmode
&& GET_MODE (op0
) != mode0
)
1054 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
1056 if (GET_MODE (op1
) != VOIDmode
&& GET_MODE (op1
) != mode1
)
1057 xop1
= convert_to_mode (mode1
, xop1
, unsignedp
);
1059 /* Now, if insn doesn't accept these operands, put them into pseudos. */
1060 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
1061 xop0
= copy_to_mode_reg (mode0
, xop0
);
1063 if (! (*insn_operand_predicate
[icode
][2]) (xop1
, mode1
))
1064 xop1
= copy_to_mode_reg (mode1
, xop1
);
1066 /* We could handle this, but we should always be called with a pseudo
1067 for our targets and all insns should take them as outputs. */
1068 if (! (*insn_operand_predicate
[icode
][0]) (targ0
, mode
)
1069 || ! (*insn_operand_predicate
[icode
][3]) (targ1
, mode
))
1072 pat
= GEN_FCN (icode
) (targ0
, xop0
, xop1
, targ1
);
1079 delete_insns_since (last
);
1082 /* It can't be done in this mode. Can we do it in a wider mode? */
1084 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1086 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1087 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1089 if (binoptab
->handlers
[(int) wider_mode
].insn_code
1090 != CODE_FOR_nothing
)
1092 register rtx t0
= gen_reg_rtx (wider_mode
);
1093 register rtx t1
= gen_reg_rtx (wider_mode
);
1095 if (expand_twoval_binop (binoptab
,
1096 convert_to_mode (wider_mode
, op0
,
1098 convert_to_mode (wider_mode
, op1
,
1102 convert_move (targ0
, t0
, unsignedp
);
1103 convert_move (targ1
, t1
, unsignedp
);
1107 delete_insns_since (last
);
1115 /* Generate code to perform an operation specified by UNOPTAB
1116 on operand OP0, with result having machine-mode MODE.
1118 UNSIGNEDP is for the case where we have to widen the operands
1119 to perform the operation. It says to use zero-extension.
1121 If TARGET is nonzero, the value
1122 is generated there, if it is convenient to do so.
1123 In all cases an rtx is returned for the locus of the value;
1124 this may or may not be TARGET. */
1127 expand_unop (mode
, unoptab
, op0
, target
, unsignedp
)
1128 enum machine_mode mode
;
1134 enum mode_class
class;
1135 enum machine_mode wider_mode
;
1137 rtx last
= get_last_insn ();
1140 class = GET_MODE_CLASS (mode
);
1142 op0
= protect_from_queue (op0
, 0);
1146 op0
= force_not_mem (op0
);
1150 target
= protect_from_queue (target
, 1);
1152 if (unoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1154 int icode
= (int) unoptab
->handlers
[(int) mode
].insn_code
;
1155 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
1161 temp
= gen_reg_rtx (mode
);
1163 if (GET_MODE (xop0
) != VOIDmode
1164 && GET_MODE (xop0
) != mode0
)
1165 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
1167 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
1169 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
1170 xop0
= copy_to_mode_reg (mode0
, xop0
);
1172 if (! (*insn_operand_predicate
[icode
][0]) (temp
, mode
))
1173 temp
= gen_reg_rtx (mode
);
1175 pat
= GEN_FCN (icode
) (temp
, xop0
);
1178 if (GET_CODE (pat
) == SEQUENCE
1179 && ! add_equal_note (pat
, temp
, unoptab
->code
, xop0
, NULL_RTX
))
1181 delete_insns_since (last
);
1182 return expand_unop (mode
, unoptab
, op0
, NULL_RTX
, unsignedp
);
1190 delete_insns_since (last
);
1193 /* It can't be done in this mode. Can we open-code it in a wider mode? */
1195 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1196 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1197 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1199 if (unoptab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
)
1203 /* For certain operations, we need not actually extend
1204 the narrow operand, as long as we will truncate the
1205 results to the same narrowness. */
1207 if ((unoptab
== neg_optab
|| unoptab
== one_cmpl_optab
)
1208 && class == MODE_INT
)
1209 xop0
= gen_rtx (SUBREG
, wider_mode
, force_reg (mode
, xop0
), 0);
1211 xop0
= convert_to_mode (wider_mode
, xop0
, unsignedp
);
1213 temp
= expand_unop (wider_mode
, unoptab
, xop0
, NULL_RTX
,
1218 if (class != MODE_INT
)
1221 target
= gen_reg_rtx (mode
);
1222 convert_move (target
, temp
, 0);
1226 return gen_lowpart (mode
, temp
);
1229 delete_insns_since (last
);
1233 /* These can be done a word at a time. */
1234 if (unoptab
== one_cmpl_optab
1235 && class == MODE_INT
1236 && GET_MODE_SIZE (mode
) > UNITS_PER_WORD
1237 && unoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
1242 if (target
== 0 || target
== op0
)
1243 target
= gen_reg_rtx (mode
);
1247 /* Do the actual arithmetic. */
1248 for (i
= 0; i
< GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
; i
++)
1250 rtx target_piece
= operand_subword (target
, i
, 1, mode
);
1251 rtx x
= expand_unop (word_mode
, unoptab
,
1252 operand_subword_force (op0
, i
, mode
),
1253 target_piece
, unsignedp
);
1254 if (target_piece
!= x
)
1255 emit_move_insn (target_piece
, x
);
1258 insns
= get_insns ();
1261 emit_no_conflict_block (insns
, target
, op0
, NULL_RTX
,
1262 gen_rtx (unoptab
->code
, mode
, op0
));
1266 if (unoptab
->handlers
[(int) mode
].libfunc
)
1269 rtx funexp
= unoptab
->handlers
[(int) mode
].libfunc
;
1273 /* Pass 1 for NO_QUEUE so we don't lose any increments
1274 if the libcall is cse'd or moved. */
1275 emit_library_call (unoptab
->handlers
[(int) mode
].libfunc
,
1276 1, mode
, 1, op0
, mode
);
1277 insns
= get_insns ();
1280 target
= gen_reg_rtx (mode
);
1281 emit_libcall_block (insns
, target
, hard_libcall_value (mode
),
1282 gen_rtx (unoptab
->code
, mode
, op0
));
1287 /* It can't be done in this mode. Can we do it in a wider mode? */
1289 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1291 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1292 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1294 if ((unoptab
->handlers
[(int) wider_mode
].insn_code
1295 != CODE_FOR_nothing
)
1296 || unoptab
->handlers
[(int) wider_mode
].libfunc
)
1300 /* For certain operations, we need not actually extend
1301 the narrow operand, as long as we will truncate the
1302 results to the same narrowness. */
1304 if ((unoptab
== neg_optab
|| unoptab
== one_cmpl_optab
)
1305 && class == MODE_INT
)
1306 xop0
= gen_rtx (SUBREG
, wider_mode
, force_reg (mode
, xop0
), 0);
1308 xop0
= convert_to_mode (wider_mode
, xop0
, unsignedp
);
1310 temp
= expand_unop (wider_mode
, unoptab
, xop0
, NULL_RTX
,
1315 if (class != MODE_INT
)
1318 target
= gen_reg_rtx (mode
);
1319 convert_move (target
, temp
, 0);
1323 return gen_lowpart (mode
, temp
);
1326 delete_insns_since (last
);
1334 /* Generate an instruction whose insn-code is INSN_CODE,
1335 with two operands: an output TARGET and an input OP0.
1336 TARGET *must* be nonzero, and the output is always stored there.
1337 CODE is an rtx code such that (CODE OP0) is an rtx that describes
1338 the value that is stored into TARGET. */
1341 emit_unop_insn (icode
, target
, op0
, code
)
1348 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
1351 temp
= target
= protect_from_queue (target
, 1);
1353 op0
= protect_from_queue (op0
, 0);
1356 op0
= force_not_mem (op0
);
1358 /* Now, if insn does not accept our operands, put them into pseudos. */
1360 if (! (*insn_operand_predicate
[icode
][1]) (op0
, mode0
))
1361 op0
= copy_to_mode_reg (mode0
, op0
);
1363 if (! (*insn_operand_predicate
[icode
][0]) (temp
, GET_MODE (temp
))
1364 || (flag_force_mem
&& GET_CODE (temp
) == MEM
))
1365 temp
= gen_reg_rtx (GET_MODE (temp
));
1367 pat
= GEN_FCN (icode
) (temp
, op0
);
1369 if (GET_CODE (pat
) == SEQUENCE
&& code
!= UNKNOWN
)
1370 add_equal_note (pat
, temp
, code
, op0
, NULL_RTX
);
1375 emit_move_insn (target
, temp
);
1378 /* Emit code to perform a series of operations on a multi-word quantity, one
1381 Such a block is preceded by a CLOBBER of the output, consists of multiple
1382 insns, each setting one word of the output, and followed by a SET copying
1383 the output to itself.
1385 Each of the insns setting words of the output receives a REG_NO_CONFLICT
1386 note indicating that it doesn't conflict with the (also multi-word)
1387 inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
1390 INSNS is a block of code generated to perform the operation, not including
1391 the CLOBBER and final copy. All insns that compute intermediate values
1392 are first emitted, followed by the block as described above. Only
1393 INSNs are allowed in the block; no library calls or jumps may be
1396 TARGET, OP0, and OP1 are the output and inputs of the operations,
1397 respectively. OP1 may be zero for a unary operation.
1399 EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
1402 If TARGET is not a register, INSNS is simply emitted with no special
1405 The final insn emitted is returned. */
1408 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv
)
1414 rtx prev
, next
, first
, last
, insn
;
1416 if (GET_CODE (target
) != REG
|| reload_in_progress
)
1417 return emit_insns (insns
);
1419 /* First emit all insns that do not store into words of the output and remove
1420 these from the list. */
1421 for (insn
= insns
; insn
; insn
= next
)
1426 next
= NEXT_INSN (insn
);
1428 if (GET_CODE (insn
) != INSN
)
1431 if (GET_CODE (PATTERN (insn
)) == SET
)
1432 set
= PATTERN (insn
);
1433 else if (GET_CODE (PATTERN (insn
)) == PARALLEL
)
1435 for (i
= 0; i
< XVECLEN (PATTERN (insn
), 0); i
++)
1436 if (GET_CODE (XVECEXP (PATTERN (insn
), 0, i
)) == SET
)
1438 set
= XVECEXP (PATTERN (insn
), 0, i
);
1446 if (! reg_overlap_mentioned_p (target
, SET_DEST (set
)))
1448 if (PREV_INSN (insn
))
1449 NEXT_INSN (PREV_INSN (insn
)) = next
;
1454 PREV_INSN (next
) = PREV_INSN (insn
);
1460 prev
= get_last_insn ();
1462 /* Now write the CLOBBER of the output, followed by the setting of each
1463 of the words, followed by the final copy. */
1464 if (target
!= op0
&& target
!= op1
)
1465 emit_insn (gen_rtx (CLOBBER
, VOIDmode
, target
));
1467 for (insn
= insns
; insn
; insn
= next
)
1469 next
= NEXT_INSN (insn
);
1472 if (op1
&& GET_CODE (op1
) == REG
)
1473 REG_NOTES (insn
) = gen_rtx (EXPR_LIST
, REG_NO_CONFLICT
, op1
,
1476 if (op0
&& GET_CODE (op0
) == REG
)
1477 REG_NOTES (insn
) = gen_rtx (EXPR_LIST
, REG_NO_CONFLICT
, op0
,
1481 last
= emit_move_insn (target
, target
);
1483 REG_NOTES (last
) = gen_rtx (EXPR_LIST
, REG_EQUAL
, equiv
, REG_NOTES (last
));
1486 first
= get_insns ();
1488 first
= NEXT_INSN (prev
);
1490 /* Encapsulate the block so it gets manipulated as a unit. */
1491 REG_NOTES (first
) = gen_rtx (INSN_LIST
, REG_LIBCALL
, last
,
1493 REG_NOTES (last
) = gen_rtx (INSN_LIST
, REG_RETVAL
, first
, REG_NOTES (last
));
1498 /* Emit code to make a call to a constant function or a library call.
1500 INSNS is a list containing all insns emitted in the call.
1501 These insns leave the result in RESULT. Our block is to copy RESULT
1502 to TARGET, which is logically equivalent to EQUIV.
1504 We first emit any insns that set a pseudo on the assumption that these are
1505 loading constants into registers; doing so allows them to be safely cse'ed
1506 between blocks. Then we emit all the other insns in the block, followed by
1507 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
1508 note with an operand of EQUIV.
1510 Moving assignments to pseudos outside of the block is done to improve
1511 the generated code, but is not required to generate correct code,
1512 hence being unable to move an assignment is not grounds for not making
1513 a libcall block. There are two reasons why it is safe to leave these
1514 insns inside the block: First, we know that these pseudos cannot be
1515 used in generated RTL outside the block since they are created for
1516 temporary purposes within the block. Second, CSE will not record the
1517 values of anything set inside a libcall block, so we know they must
1518 be dead at the end of the block.
1520 Except for the first group of insns (the ones setting pseudos), the
1521 block is delimited by REG_RETVAL and REG_LIBCALL notes. */
1524 emit_libcall_block (insns
, target
, result
, equiv
)
1530 rtx prev
, next
, first
, last
, insn
;
1532 /* First emit all insns that set pseudos. Remove them from the list as
1533 we go. Avoid insns that set pseudo which were referenced in previous
1534 insns. These can be generated by move_by_pieces, for example,
1535 to update an address. */
1537 for (insn
= insns
; insn
; insn
= next
)
1539 rtx set
= single_set (insn
);
1541 next
= NEXT_INSN (insn
);
1543 if (set
!= 0 && GET_CODE (SET_DEST (set
)) == REG
1544 && REGNO (SET_DEST (set
)) >= FIRST_PSEUDO_REGISTER
1546 || (! reg_mentioned_p (SET_DEST (set
), PATTERN (insns
))
1547 && ! reg_used_between_p (SET_DEST (set
), insns
, insn
))))
1549 if (PREV_INSN (insn
))
1550 NEXT_INSN (PREV_INSN (insn
)) = next
;
1555 PREV_INSN (next
) = PREV_INSN (insn
);
1561 prev
= get_last_insn ();
1563 /* Write the remaining insns followed by the final copy. */
1565 for (insn
= insns
; insn
; insn
= next
)
1567 next
= NEXT_INSN (insn
);
1572 last
= emit_move_insn (target
, result
);
1573 REG_NOTES (last
) = gen_rtx (EXPR_LIST
, REG_EQUAL
, equiv
, REG_NOTES (last
));
1576 first
= get_insns ();
1578 first
= NEXT_INSN (prev
);
1580 /* Encapsulate the block so it gets manipulated as a unit. */
1581 REG_NOTES (first
) = gen_rtx (INSN_LIST
, REG_LIBCALL
, last
,
1583 REG_NOTES (last
) = gen_rtx (INSN_LIST
, REG_RETVAL
, first
, REG_NOTES (last
));
1586 /* Generate code to store zero in X. */
1592 emit_move_insn (x
, const0_rtx
);
1595 /* Generate code to store 1 in X
1596 assuming it contains zero beforehand. */
1599 emit_0_to_1_insn (x
)
1602 emit_move_insn (x
, const1_rtx
);
1605 /* Generate code to compare X with Y
1606 so that the condition codes are set.
1608 MODE is the mode of the inputs (in case they are const_int).
1609 UNSIGNEDP nonzero says that X and Y are unsigned;
1610 this matters if they need to be widened.
1612 If they have mode BLKmode, then SIZE specifies the size of both X and Y,
1613 and ALIGN specifies the known shared alignment of X and Y.
1615 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
1616 It is ignored for fixed-point and block comparisons;
1617 it is used only for floating-point comparisons. */
1620 emit_cmp_insn (x
, y
, comparison
, size
, mode
, unsignedp
, align
)
1622 enum rtx_code comparison
;
1624 enum machine_mode mode
;
1628 enum mode_class
class;
1629 enum machine_mode wider_mode
;
1631 class = GET_MODE_CLASS (mode
);
1633 /* They could both be VOIDmode if both args are immediate constants,
1634 but we should fold that at an earlier stage.
1635 With no special code here, this will call abort,
1636 reminding the programmer to implement such folding. */
1638 if (mode
!= BLKmode
&& flag_force_mem
)
1640 x
= force_not_mem (x
);
1641 y
= force_not_mem (y
);
1644 /* If we are inside an appropriately-short loop and one operand is an
1645 expensive constant, force it into a register. */
1646 if (CONSTANT_P (x
) && preserve_subexpressions_p () && rtx_cost (x
, COMPARE
) > 2)
1647 x
= force_reg (mode
, x
);
1649 if (CONSTANT_P (y
) && preserve_subexpressions_p () && rtx_cost (y
, COMPARE
) > 2)
1650 y
= force_reg (mode
, y
);
1652 /* Don't let both operands fail to indicate the mode. */
1653 if (GET_MODE (x
) == VOIDmode
&& GET_MODE (y
) == VOIDmode
)
1654 x
= force_reg (mode
, x
);
1656 /* Handle all BLKmode compares. */
1658 if (mode
== BLKmode
)
1661 x
= protect_from_queue (x
, 0);
1662 y
= protect_from_queue (y
, 0);
1666 #ifdef HAVE_cmpstrqi
1668 && GET_CODE (size
) == CONST_INT
1669 && INTVAL (size
) < (1 << GET_MODE_BITSIZE (QImode
)))
1671 enum machine_mode result_mode
1672 = insn_operand_mode
[(int) CODE_FOR_cmpstrqi
][0];
1673 rtx result
= gen_reg_rtx (result_mode
);
1674 emit_insn (gen_cmpstrqi (result
, x
, y
, size
, GEN_INT (align
)));
1675 emit_cmp_insn (result
, const0_rtx
, comparison
, NULL_RTX
,
1680 #ifdef HAVE_cmpstrhi
1682 && GET_CODE (size
) == CONST_INT
1683 && INTVAL (size
) < (1 << GET_MODE_BITSIZE (HImode
)))
1685 enum machine_mode result_mode
1686 = insn_operand_mode
[(int) CODE_FOR_cmpstrhi
][0];
1687 rtx result
= gen_reg_rtx (result_mode
);
1688 emit_insn (gen_cmpstrhi (result
, x
, y
, size
, GEN_INT (align
)));
1689 emit_cmp_insn (result
, const0_rtx
, comparison
, NULL_RTX
,
1694 #ifdef HAVE_cmpstrsi
1697 enum machine_mode result_mode
1698 = insn_operand_mode
[(int) CODE_FOR_cmpstrsi
][0];
1699 rtx result
= gen_reg_rtx (result_mode
);
1700 size
= protect_from_queue (size
, 0);
1701 emit_insn (gen_cmpstrsi (result
, x
, y
,
1702 convert_to_mode (SImode
, size
, 1),
1704 emit_cmp_insn (result
, const0_rtx
, comparison
, NULL_RTX
,
1710 #ifdef TARGET_MEM_FUNCTIONS
1711 emit_library_call (memcmp_libfunc
, 0,
1712 TYPE_MODE (integer_type_node
), 3,
1713 XEXP (x
, 0), Pmode
, XEXP (y
, 0), Pmode
,
1716 emit_library_call (bcmp_libfunc
, 0,
1717 TYPE_MODE (integer_type_node
), 3,
1718 XEXP (x
, 0), Pmode
, XEXP (y
, 0), Pmode
,
1721 emit_cmp_insn (hard_libcall_value (TYPE_MODE (integer_type_node
)),
1722 const0_rtx
, comparison
, NULL_RTX
,
1723 TYPE_MODE (integer_type_node
), 0, 0);
1728 /* Handle some compares against zero. */
1730 if (y
== CONST0_RTX (mode
)
1731 && tst_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1733 int icode
= (int) tst_optab
->handlers
[(int) mode
].insn_code
;
1736 x
= protect_from_queue (x
, 0);
1737 y
= protect_from_queue (y
, 0);
1739 /* Now, if insn does accept these operands, put them into pseudos. */
1740 if (! (*insn_operand_predicate
[icode
][0])
1741 (x
, insn_operand_mode
[icode
][0]))
1742 x
= copy_to_mode_reg (insn_operand_mode
[icode
][0], x
);
1744 emit_insn (GEN_FCN (icode
) (x
));
1748 /* Handle compares for which there is a directly suitable insn. */
1750 if (cmp_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1752 int icode
= (int) cmp_optab
->handlers
[(int) mode
].insn_code
;
1755 x
= protect_from_queue (x
, 0);
1756 y
= protect_from_queue (y
, 0);
1758 /* Now, if insn doesn't accept these operands, put them into pseudos. */
1759 if (! (*insn_operand_predicate
[icode
][0])
1760 (x
, insn_operand_mode
[icode
][0]))
1761 x
= copy_to_mode_reg (insn_operand_mode
[icode
][0], x
);
1763 if (! (*insn_operand_predicate
[icode
][1])
1764 (y
, insn_operand_mode
[icode
][1]))
1765 y
= copy_to_mode_reg (insn_operand_mode
[icode
][1], y
);
1767 emit_insn (GEN_FCN (icode
) (x
, y
));
1771 /* Try widening if we can find a direct insn that way. */
1773 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1775 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1776 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1778 if (cmp_optab
->handlers
[(int) wider_mode
].insn_code
1779 != CODE_FOR_nothing
)
1781 x
= protect_from_queue (x
, 0);
1782 y
= protect_from_queue (y
, 0);
1783 x
= convert_to_mode (wider_mode
, x
, unsignedp
);
1784 y
= convert_to_mode (wider_mode
, y
, unsignedp
);
1785 emit_cmp_insn (x
, y
, comparison
, NULL_RTX
,
1786 wider_mode
, unsignedp
, align
);
1792 /* Handle a lib call just for the mode we are using. */
1794 if (cmp_optab
->handlers
[(int) mode
].libfunc
1795 && class != MODE_FLOAT
)
1797 rtx libfunc
= cmp_optab
->handlers
[(int) mode
].libfunc
;
1798 /* If we want unsigned, and this mode has a distinct unsigned
1799 comparison routine, use that. */
1800 if (unsignedp
&& ucmp_optab
->handlers
[(int) mode
].libfunc
)
1801 libfunc
= ucmp_optab
->handlers
[(int) mode
].libfunc
;
1803 emit_library_call (libfunc
, 1,
1804 SImode
, 2, x
, mode
, y
, mode
);
1806 /* Integer comparison returns a result that must be compared against 1,
1807 so that even if we do an unsigned compare afterward,
1808 there is still a value that can represent the result "less than". */
1810 emit_cmp_insn (hard_libcall_value (SImode
), const1_rtx
,
1811 comparison
, NULL_RTX
, SImode
, unsignedp
, 0);
1815 if (class == MODE_FLOAT
)
1816 emit_float_lib_cmp (x
, y
, comparison
);
1822 /* Nonzero if a compare of mode MODE can be done straightforwardly
1823 (without splitting it into pieces). */
1826 can_compare_p (mode
)
1827 enum machine_mode mode
;
1831 if (cmp_optab
->handlers
[(int)mode
].insn_code
!= CODE_FOR_nothing
)
1833 mode
= GET_MODE_WIDER_MODE (mode
);
1834 } while (mode
!= VOIDmode
);
1839 /* Emit a library call comparison between floating point X and Y.
1840 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
1843 emit_float_lib_cmp (x
, y
, comparison
)
1845 enum rtx_code comparison
;
1847 enum machine_mode mode
= GET_MODE (x
);
1854 libfunc
= eqsf2_libfunc
;
1858 libfunc
= nesf2_libfunc
;
1862 libfunc
= gtsf2_libfunc
;
1866 libfunc
= gesf2_libfunc
;
1870 libfunc
= ltsf2_libfunc
;
1874 libfunc
= lesf2_libfunc
;
1877 else if (mode
== DFmode
)
1881 libfunc
= eqdf2_libfunc
;
1885 libfunc
= nedf2_libfunc
;
1889 libfunc
= gtdf2_libfunc
;
1893 libfunc
= gedf2_libfunc
;
1897 libfunc
= ltdf2_libfunc
;
1901 libfunc
= ledf2_libfunc
;
1904 else if (mode
== XFmode
)
1908 libfunc
= eqxf2_libfunc
;
1912 libfunc
= nexf2_libfunc
;
1916 libfunc
= gtxf2_libfunc
;
1920 libfunc
= gexf2_libfunc
;
1924 libfunc
= ltxf2_libfunc
;
1928 libfunc
= lexf2_libfunc
;
1931 else if (mode
== TFmode
)
1935 libfunc
= eqtf2_libfunc
;
1939 libfunc
= netf2_libfunc
;
1943 libfunc
= gttf2_libfunc
;
1947 libfunc
= getf2_libfunc
;
1951 libfunc
= lttf2_libfunc
;
1955 libfunc
= letf2_libfunc
;
1960 enum machine_mode wider_mode
;
1962 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1963 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1965 if ((cmp_optab
->handlers
[(int) wider_mode
].insn_code
1966 != CODE_FOR_nothing
)
1967 || (cmp_optab
->handlers
[(int) wider_mode
].libfunc
!= 0))
1969 x
= protect_from_queue (x
, 0);
1970 y
= protect_from_queue (y
, 0);
1971 x
= convert_to_mode (wider_mode
, x
, 0);
1972 y
= convert_to_mode (wider_mode
, y
, 0);
1973 emit_float_lib_cmp (x
, y
, comparison
);
1980 emit_library_call (libfunc
, 1,
1981 SImode
, 2, x
, mode
, y
, mode
);
1983 emit_cmp_insn (hard_libcall_value (SImode
), const0_rtx
, comparison
,
1984 NULL_RTX
, SImode
, 0, 0);
1987 /* Generate code to indirectly jump to a location given in the rtx LOC. */
1990 emit_indirect_jump (loc
)
1993 if (! ((*insn_operand_predicate
[(int)CODE_FOR_indirect_jump
][0])
1995 loc
= copy_to_mode_reg (insn_operand_mode
[(int)CODE_FOR_indirect_jump
][0],
1998 emit_jump_insn (gen_indirect_jump (loc
));
2002 /* These three functions generate an insn body and return it
2003 rather than emitting the insn.
2005 They do not protect from queued increments,
2006 because they may be used 1) in protect_from_queue itself
2007 and 2) in other passes where there is no queue. */
2009 /* Generate and return an insn body to add Y to X. */
2012 gen_add2_insn (x
, y
)
2015 int icode
= (int) add_optab
->handlers
[(int) GET_MODE (x
)].insn_code
;
2017 if (! (*insn_operand_predicate
[icode
][0]) (x
, insn_operand_mode
[icode
][0])
2018 || ! (*insn_operand_predicate
[icode
][1]) (x
, insn_operand_mode
[icode
][1])
2019 || ! (*insn_operand_predicate
[icode
][2]) (y
, insn_operand_mode
[icode
][2]))
2022 return (GEN_FCN (icode
) (x
, x
, y
));
2026 have_add2_insn (mode
)
2027 enum machine_mode mode
;
2029 return add_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
;
2032 /* Generate and return an insn body to subtract Y from X. */
2035 gen_sub2_insn (x
, y
)
2038 int icode
= (int) sub_optab
->handlers
[(int) GET_MODE (x
)].insn_code
;
2040 if (! (*insn_operand_predicate
[icode
][0]) (x
, insn_operand_mode
[icode
][0])
2041 || ! (*insn_operand_predicate
[icode
][1]) (x
, insn_operand_mode
[icode
][1])
2042 || ! (*insn_operand_predicate
[icode
][2]) (y
, insn_operand_mode
[icode
][2]))
2045 return (GEN_FCN (icode
) (x
, x
, y
));
2049 have_sub2_insn (mode
)
2050 enum machine_mode mode
;
2052 return sub_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
;
2055 /* Generate the body of an instruction to copy Y into X. */
2058 gen_move_insn (x
, y
)
2061 register enum machine_mode mode
= GET_MODE (x
);
2062 enum insn_code insn_code
;
2064 if (mode
== VOIDmode
)
2065 mode
= GET_MODE (y
);
2067 insn_code
= mov_optab
->handlers
[(int) mode
].insn_code
;
2069 /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
2070 find a mode to do it in. If we have a movcc, use it. Otherwise,
2071 find the MODE_INT mode of the same width. */
2073 if (insn_code
== CODE_FOR_nothing
)
2075 enum machine_mode tmode
= VOIDmode
;
2078 if (GET_MODE_CLASS (mode
) == MODE_CC
&& mode
!= CCmode
2079 && mov_optab
->handlers
[(int) CCmode
].insn_code
!= CODE_FOR_nothing
)
2081 else if (GET_MODE_CLASS (mode
) == MODE_CC
)
2082 for (tmode
= QImode
; tmode
!= VOIDmode
;
2083 tmode
= GET_MODE_WIDER_MODE (tmode
))
2084 if (GET_MODE_SIZE (tmode
) == GET_MODE_SIZE (mode
))
2087 if (tmode
== VOIDmode
)
2090 /* Get X and Y in TMODE. We can't use gen_lowpart here because it
2091 may call change_address which is not appropriate if we were
2092 called when a reload was in progress. We don't have to worry
2093 about changing the address since the size in bytes is supposed to
2094 be the same. Copy the MEM to change the mode and move any
2095 substitutions from the old MEM to the new one. */
2097 if (reload_in_progress
)
2099 x
= gen_lowpart_common (tmode
, x1
);
2100 if (x
== 0 && GET_CODE (x1
) == MEM
)
2102 x
= gen_rtx (MEM
, tmode
, XEXP (x1
, 0));
2103 RTX_UNCHANGING_P (x
) = RTX_UNCHANGING_P (x1
);
2104 MEM_IN_STRUCT_P (x
) = MEM_IN_STRUCT_P (x1
);
2105 MEM_VOLATILE_P (x
) = MEM_VOLATILE_P (x1
);
2106 copy_replacements (x1
, x
);
2109 y
= gen_lowpart_common (tmode
, y1
);
2110 if (y
== 0 && GET_CODE (y1
) == MEM
)
2112 y
= gen_rtx (MEM
, tmode
, XEXP (y1
, 0));
2113 RTX_UNCHANGING_P (y
) = RTX_UNCHANGING_P (y1
);
2114 MEM_IN_STRUCT_P (y
) = MEM_IN_STRUCT_P (y1
);
2115 MEM_VOLATILE_P (y
) = MEM_VOLATILE_P (y1
);
2116 copy_replacements (y1
, y
);
2121 x
= gen_lowpart (tmode
, x
);
2122 y
= gen_lowpart (tmode
, y
);
2125 insn_code
= mov_optab
->handlers
[(int) tmode
].insn_code
;
2128 return (GEN_FCN (insn_code
) (x
, y
));
2131 /* Tables of patterns for extending one integer mode to another. */
2132 static enum insn_code extendtab
[MAX_MACHINE_MODE
][MAX_MACHINE_MODE
][2];
2134 /* Return the insn code used to extend FROM_MODE to TO_MODE.
2135 UNSIGNEDP specifies zero-extension instead of sign-extension. If
2136 no such operation exists, CODE_FOR_nothing will be returned. */
2139 can_extend_p (to_mode
, from_mode
, unsignedp
)
2140 enum machine_mode to_mode
, from_mode
;
2143 return extendtab
[(int) to_mode
][(int) from_mode
][unsignedp
];
2146 /* Generate the body of an insn to extend Y (with mode MFROM)
2147 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
2150 gen_extend_insn (x
, y
, mto
, mfrom
, unsignedp
)
2152 enum machine_mode mto
, mfrom
;
2155 return (GEN_FCN (extendtab
[(int) mto
][(int) mfrom
][unsignedp
]) (x
, y
));
2163 for (p
= extendtab
[0][0];
2164 p
< extendtab
[0][0] + sizeof extendtab
/ sizeof extendtab
[0][0][0];
2166 *p
= CODE_FOR_nothing
;
2168 #ifdef HAVE_extendditi2
2169 if (HAVE_extendditi2
)
2170 extendtab
[(int) TImode
][(int) DImode
][0] = CODE_FOR_extendditi2
;
2172 #ifdef HAVE_extendsiti2
2173 if (HAVE_extendsiti2
)
2174 extendtab
[(int) TImode
][(int) SImode
][0] = CODE_FOR_extendsiti2
;
2176 #ifdef HAVE_extendhiti2
2177 if (HAVE_extendhiti2
)
2178 extendtab
[(int) TImode
][(int) HImode
][0] = CODE_FOR_extendhiti2
;
2180 #ifdef HAVE_extendqiti2
2181 if (HAVE_extendqiti2
)
2182 extendtab
[(int) TImode
][(int) QImode
][0] = CODE_FOR_extendqiti2
;
2184 #ifdef HAVE_extendsidi2
2185 if (HAVE_extendsidi2
)
2186 extendtab
[(int) DImode
][(int) SImode
][0] = CODE_FOR_extendsidi2
;
2188 #ifdef HAVE_extendhidi2
2189 if (HAVE_extendhidi2
)
2190 extendtab
[(int) DImode
][(int) HImode
][0] = CODE_FOR_extendhidi2
;
2192 #ifdef HAVE_extendqidi2
2193 if (HAVE_extendqidi2
)
2194 extendtab
[(int) DImode
][(int) QImode
][0] = CODE_FOR_extendqidi2
;
2196 #ifdef HAVE_extendhisi2
2197 if (HAVE_extendhisi2
)
2198 extendtab
[(int) SImode
][(int) HImode
][0] = CODE_FOR_extendhisi2
;
2200 #ifdef HAVE_extendqisi2
2201 if (HAVE_extendqisi2
)
2202 extendtab
[(int) SImode
][(int) QImode
][0] = CODE_FOR_extendqisi2
;
2204 #ifdef HAVE_extendqihi2
2205 if (HAVE_extendqihi2
)
2206 extendtab
[(int) HImode
][(int) QImode
][0] = CODE_FOR_extendqihi2
;
2209 #ifdef HAVE_zero_extendditi2
2210 if (HAVE_zero_extendsiti2
)
2211 extendtab
[(int) TImode
][(int) DImode
][1] = CODE_FOR_zero_extendditi2
;
2213 #ifdef HAVE_zero_extendsiti2
2214 if (HAVE_zero_extendsiti2
)
2215 extendtab
[(int) TImode
][(int) SImode
][1] = CODE_FOR_zero_extendsiti2
;
2217 #ifdef HAVE_zero_extendhiti2
2218 if (HAVE_zero_extendhiti2
)
2219 extendtab
[(int) TImode
][(int) HImode
][1] = CODE_FOR_zero_extendhiti2
;
2221 #ifdef HAVE_zero_extendqiti2
2222 if (HAVE_zero_extendqiti2
)
2223 extendtab
[(int) TImode
][(int) QImode
][1] = CODE_FOR_zero_extendqiti2
;
2225 #ifdef HAVE_zero_extendsidi2
2226 if (HAVE_zero_extendsidi2
)
2227 extendtab
[(int) DImode
][(int) SImode
][1] = CODE_FOR_zero_extendsidi2
;
2229 #ifdef HAVE_zero_extendhidi2
2230 if (HAVE_zero_extendhidi2
)
2231 extendtab
[(int) DImode
][(int) HImode
][1] = CODE_FOR_zero_extendhidi2
;
2233 #ifdef HAVE_zero_extendqidi2
2234 if (HAVE_zero_extendqidi2
)
2235 extendtab
[(int) DImode
][(int) QImode
][1] = CODE_FOR_zero_extendqidi2
;
2237 #ifdef HAVE_zero_extendhisi2
2238 if (HAVE_zero_extendhisi2
)
2239 extendtab
[(int) SImode
][(int) HImode
][1] = CODE_FOR_zero_extendhisi2
;
2241 #ifdef HAVE_zero_extendqisi2
2242 if (HAVE_zero_extendqisi2
)
2243 extendtab
[(int) SImode
][(int) QImode
][1] = CODE_FOR_zero_extendqisi2
;
2245 #ifdef HAVE_zero_extendqihi2
2246 if (HAVE_zero_extendqihi2
)
2247 extendtab
[(int) HImode
][(int) QImode
][1] = CODE_FOR_zero_extendqihi2
;
2251 /* can_fix_p and can_float_p say whether the target machine
2252 can directly convert a given fixed point type to
2253 a given floating point type, or vice versa.
2254 The returned value is the CODE_FOR_... value to use,
2255 or CODE_FOR_nothing if these modes cannot be directly converted. */
2257 static enum insn_code fixtab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
2258 static enum insn_code fixtrunctab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
2259 static enum insn_code floattab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
2261 /* *TRUNCP_PTR is set to 1 if it is necessary to output
2262 an explicit FTRUNC insn before the fix insn; otherwise 0. */
2264 static enum insn_code
2265 can_fix_p (fixmode
, fltmode
, unsignedp
, truncp_ptr
)
2266 enum machine_mode fltmode
, fixmode
;
2271 if (fixtrunctab
[(int) fltmode
][(int) fixmode
][unsignedp
] != CODE_FOR_nothing
)
2272 return fixtrunctab
[(int) fltmode
][(int) fixmode
][unsignedp
];
2274 if (ftrunc_optab
->handlers
[(int) fltmode
].insn_code
!= CODE_FOR_nothing
)
2277 return fixtab
[(int) fltmode
][(int) fixmode
][unsignedp
];
2279 return CODE_FOR_nothing
;
2282 static enum insn_code
2283 can_float_p (fltmode
, fixmode
, unsignedp
)
2284 enum machine_mode fixmode
, fltmode
;
2287 return floattab
[(int) fltmode
][(int) fixmode
][unsignedp
];
2294 for (p
= fixtab
[0][0];
2295 p
< fixtab
[0][0] + sizeof fixtab
/ sizeof (fixtab
[0][0][0]);
2297 *p
= CODE_FOR_nothing
;
2298 for (p
= fixtrunctab
[0][0];
2299 p
< fixtrunctab
[0][0] + sizeof fixtrunctab
/ sizeof (fixtrunctab
[0][0][0]);
2301 *p
= CODE_FOR_nothing
;
2303 #ifdef HAVE_fixsfqi2
2305 fixtab
[(int) SFmode
][(int) QImode
][0] = CODE_FOR_fixsfqi2
;
2307 #ifdef HAVE_fixsfhi2
2309 fixtab
[(int) SFmode
][(int) HImode
][0] = CODE_FOR_fixsfhi2
;
2311 #ifdef HAVE_fixsfsi2
2313 fixtab
[(int) SFmode
][(int) SImode
][0] = CODE_FOR_fixsfsi2
;
2315 #ifdef HAVE_fixsfdi2
2317 fixtab
[(int) SFmode
][(int) DImode
][0] = CODE_FOR_fixsfdi2
;
2320 #ifdef HAVE_fixdfqi2
2322 fixtab
[(int) DFmode
][(int) QImode
][0] = CODE_FOR_fixdfqi2
;
2324 #ifdef HAVE_fixdfhi2
2326 fixtab
[(int) DFmode
][(int) HImode
][0] = CODE_FOR_fixdfhi2
;
2328 #ifdef HAVE_fixdfsi2
2330 fixtab
[(int) DFmode
][(int) SImode
][0] = CODE_FOR_fixdfsi2
;
2332 #ifdef HAVE_fixdfdi2
2334 fixtab
[(int) DFmode
][(int) DImode
][0] = CODE_FOR_fixdfdi2
;
2336 #ifdef HAVE_fixdfti2
2338 fixtab
[(int) DFmode
][(int) TImode
][0] = CODE_FOR_fixdfti2
;
2341 #ifdef HAVE_fixxfqi2
2343 fixtab
[(int) XFmode
][(int) QImode
][0] = CODE_FOR_fixxfqi2
;
2345 #ifdef HAVE_fixxfhi2
2347 fixtab
[(int) XFmode
][(int) HImode
][0] = CODE_FOR_fixxfhi2
;
2349 #ifdef HAVE_fixxfsi2
2351 fixtab
[(int) XFmode
][(int) SImode
][0] = CODE_FOR_fixxfsi2
;
2353 #ifdef HAVE_fixxfdi2
2355 fixtab
[(int) XFmode
][(int) DImode
][0] = CODE_FOR_fixxfdi2
;
2357 #ifdef HAVE_fixxfti2
2359 fixtab
[(int) XFmode
][(int) TImode
][0] = CODE_FOR_fixxfti2
;
2362 #ifdef HAVE_fixtfqi2
2364 fixtab
[(int) TFmode
][(int) QImode
][0] = CODE_FOR_fixtfqi2
;
2366 #ifdef HAVE_fixtfhi2
2368 fixtab
[(int) TFmode
][(int) HImode
][0] = CODE_FOR_fixtfhi2
;
2370 #ifdef HAVE_fixtfsi2
2372 fixtab
[(int) TFmode
][(int) SImode
][0] = CODE_FOR_fixtfsi2
;
2374 #ifdef HAVE_fixtfdi2
2376 fixtab
[(int) TFmode
][(int) DImode
][0] = CODE_FOR_fixtfdi2
;
2378 #ifdef HAVE_fixtfti2
2380 fixtab
[(int) TFmode
][(int) TImode
][0] = CODE_FOR_fixtfti2
;
2383 #ifdef HAVE_fixunssfqi2
2384 if (HAVE_fixunssfqi2
)
2385 fixtab
[(int) SFmode
][(int) QImode
][1] = CODE_FOR_fixunssfqi2
;
2387 #ifdef HAVE_fixunssfhi2
2388 if (HAVE_fixunssfhi2
)
2389 fixtab
[(int) SFmode
][(int) HImode
][1] = CODE_FOR_fixunssfhi2
;
2391 #ifdef HAVE_fixunssfsi2
2392 if (HAVE_fixunssfsi2
)
2393 fixtab
[(int) SFmode
][(int) SImode
][1] = CODE_FOR_fixunssfsi2
;
2395 #ifdef HAVE_fixunssfdi2
2396 if (HAVE_fixunssfdi2
)
2397 fixtab
[(int) SFmode
][(int) DImode
][1] = CODE_FOR_fixunssfdi2
;
2400 #ifdef HAVE_fixunsdfqi2
2401 if (HAVE_fixunsdfqi2
)
2402 fixtab
[(int) DFmode
][(int) QImode
][1] = CODE_FOR_fixunsdfqi2
;
2404 #ifdef HAVE_fixunsdfhi2
2405 if (HAVE_fixunsdfhi2
)
2406 fixtab
[(int) DFmode
][(int) HImode
][1] = CODE_FOR_fixunsdfhi2
;
2408 #ifdef HAVE_fixunsdfsi2
2409 if (HAVE_fixunsdfsi2
)
2410 fixtab
[(int) DFmode
][(int) SImode
][1] = CODE_FOR_fixunsdfsi2
;
2412 #ifdef HAVE_fixunsdfdi2
2413 if (HAVE_fixunsdfdi2
)
2414 fixtab
[(int) DFmode
][(int) DImode
][1] = CODE_FOR_fixunsdfdi2
;
2416 #ifdef HAVE_fixunsdfti2
2417 if (HAVE_fixunsdfti2
)
2418 fixtab
[(int) DFmode
][(int) TImode
][1] = CODE_FOR_fixunsdfti2
;
2421 #ifdef HAVE_fixunsxfqi2
2422 if (HAVE_fixunsxfqi2
)
2423 fixtab
[(int) XFmode
][(int) QImode
][1] = CODE_FOR_fixunsxfqi2
;
2425 #ifdef HAVE_fixunsxfhi2
2426 if (HAVE_fixunsxfhi2
)
2427 fixtab
[(int) XFmode
][(int) HImode
][1] = CODE_FOR_fixunsxfhi2
;
2429 #ifdef HAVE_fixunsxfsi2
2430 if (HAVE_fixunsxfsi2
)
2431 fixtab
[(int) XFmode
][(int) SImode
][1] = CODE_FOR_fixunsxfsi2
;
2433 #ifdef HAVE_fixunsxfdi2
2434 if (HAVE_fixunsxfdi2
)
2435 fixtab
[(int) XFmode
][(int) DImode
][1] = CODE_FOR_fixunsxfdi2
;
2437 #ifdef HAVE_fixunsxfti2
2438 if (HAVE_fixunsxfti2
)
2439 fixtab
[(int) XFmode
][(int) TImode
][1] = CODE_FOR_fixunsxfti2
;
2442 #ifdef HAVE_fixunstfqi2
2443 if (HAVE_fixunstfqi2
)
2444 fixtab
[(int) TFmode
][(int) QImode
][1] = CODE_FOR_fixunstfqi2
;
2446 #ifdef HAVE_fixunstfhi2
2447 if (HAVE_fixunstfhi2
)
2448 fixtab
[(int) TFmode
][(int) HImode
][1] = CODE_FOR_fixunstfhi2
;
2450 #ifdef HAVE_fixunstfsi2
2451 if (HAVE_fixunstfsi2
)
2452 fixtab
[(int) TFmode
][(int) SImode
][1] = CODE_FOR_fixunstfsi2
;
2454 #ifdef HAVE_fixunstfdi2
2455 if (HAVE_fixunstfdi2
)
2456 fixtab
[(int) TFmode
][(int) DImode
][1] = CODE_FOR_fixunstfdi2
;
2458 #ifdef HAVE_fixunstfti2
2459 if (HAVE_fixunstfti2
)
2460 fixtab
[(int) TFmode
][(int) TImode
][1] = CODE_FOR_fixunstfti2
;
2463 #ifdef HAVE_fix_truncsfqi2
2464 if (HAVE_fix_truncsfqi2
)
2465 fixtrunctab
[(int) SFmode
][(int) QImode
][0] = CODE_FOR_fix_truncsfqi2
;
2467 #ifdef HAVE_fix_truncsfhi2
2468 if (HAVE_fix_truncsfhi2
)
2469 fixtrunctab
[(int) SFmode
][(int) HImode
][0] = CODE_FOR_fix_truncsfhi2
;
2471 #ifdef HAVE_fix_truncsfsi2
2472 if (HAVE_fix_truncsfsi2
)
2473 fixtrunctab
[(int) SFmode
][(int) SImode
][0] = CODE_FOR_fix_truncsfsi2
;
2475 #ifdef HAVE_fix_truncsfdi2
2476 if (HAVE_fix_truncsfdi2
)
2477 fixtrunctab
[(int) SFmode
][(int) DImode
][0] = CODE_FOR_fix_truncsfdi2
;
2480 #ifdef HAVE_fix_truncdfqi2
2481 if (HAVE_fix_truncdfsi2
)
2482 fixtrunctab
[(int) DFmode
][(int) QImode
][0] = CODE_FOR_fix_truncdfqi2
;
2484 #ifdef HAVE_fix_truncdfhi2
2485 if (HAVE_fix_truncdfhi2
)
2486 fixtrunctab
[(int) DFmode
][(int) HImode
][0] = CODE_FOR_fix_truncdfhi2
;
2488 #ifdef HAVE_fix_truncdfsi2
2489 if (HAVE_fix_truncdfsi2
)
2490 fixtrunctab
[(int) DFmode
][(int) SImode
][0] = CODE_FOR_fix_truncdfsi2
;
2492 #ifdef HAVE_fix_truncdfdi2
2493 if (HAVE_fix_truncdfdi2
)
2494 fixtrunctab
[(int) DFmode
][(int) DImode
][0] = CODE_FOR_fix_truncdfdi2
;
2496 #ifdef HAVE_fix_truncdfti2
2497 if (HAVE_fix_truncdfti2
)
2498 fixtrunctab
[(int) DFmode
][(int) TImode
][0] = CODE_FOR_fix_truncdfti2
;
2501 #ifdef HAVE_fix_truncxfqi2
2502 if (HAVE_fix_truncxfqi2
)
2503 fixtrunctab
[(int) XFmode
][(int) QImode
][0] = CODE_FOR_fix_truncxfqi2
;
2505 #ifdef HAVE_fix_truncxfhi2
2506 if (HAVE_fix_truncxfhi2
)
2507 fixtrunctab
[(int) XFmode
][(int) HImode
][0] = CODE_FOR_fix_truncxfhi2
;
2509 #ifdef HAVE_fix_truncxfsi2
2510 if (HAVE_fix_truncxfsi2
)
2511 fixtrunctab
[(int) XFmode
][(int) SImode
][0] = CODE_FOR_fix_truncxfsi2
;
2513 #ifdef HAVE_fix_truncxfdi2
2514 if (HAVE_fix_truncxfdi2
)
2515 fixtrunctab
[(int) XFmode
][(int) DImode
][0] = CODE_FOR_fix_truncxfdi2
;
2517 #ifdef HAVE_fix_truncxfti2
2518 if (HAVE_fix_truncxfti2
)
2519 fixtrunctab
[(int) XFmode
][(int) TImode
][0] = CODE_FOR_fix_truncxfti2
;
2522 #ifdef HAVE_fix_trunctfqi2
2523 if (HAVE_fix_trunctfqi2
)
2524 fixtrunctab
[(int) TFmode
][(int) QImode
][0] = CODE_FOR_fix_trunctfqi2
;
2526 #ifdef HAVE_fix_trunctfhi2
2527 if (HAVE_fix_trunctfhi2
)
2528 fixtrunctab
[(int) TFmode
][(int) HImode
][0] = CODE_FOR_fix_trunctfhi2
;
2530 #ifdef HAVE_fix_trunctfsi2
2531 if (HAVE_fix_trunctfsi2
)
2532 fixtrunctab
[(int) TFmode
][(int) SImode
][0] = CODE_FOR_fix_trunctfsi2
;
2534 #ifdef HAVE_fix_trunctfdi2
2535 if (HAVE_fix_trunctfdi2
)
2536 fixtrunctab
[(int) TFmode
][(int) DImode
][0] = CODE_FOR_fix_trunctfdi2
;
2538 #ifdef HAVE_fix_trunctfti2
2539 if (HAVE_fix_trunctfti2
)
2540 fixtrunctab
[(int) TFmode
][(int) TImode
][0] = CODE_FOR_fix_trunctfti2
;
2543 #ifdef HAVE_fixuns_truncsfqi2
2544 if (HAVE_fixuns_truncsfqi2
)
2545 fixtrunctab
[(int) SFmode
][(int) QImode
][1] = CODE_FOR_fixuns_truncsfqi2
;
2547 #ifdef HAVE_fixuns_truncsfhi2
2548 if (HAVE_fixuns_truncsfhi2
)
2549 fixtrunctab
[(int) SFmode
][(int) HImode
][1] = CODE_FOR_fixuns_truncsfhi2
;
2551 #ifdef HAVE_fixuns_truncsfsi2
2552 if (HAVE_fixuns_truncsfsi2
)
2553 fixtrunctab
[(int) SFmode
][(int) SImode
][1] = CODE_FOR_fixuns_truncsfsi2
;
2555 #ifdef HAVE_fixuns_truncsfdi2
2556 if (HAVE_fixuns_truncsfdi2
)
2557 fixtrunctab
[(int) SFmode
][(int) DImode
][1] = CODE_FOR_fixuns_truncsfdi2
;
2560 #ifdef HAVE_fixuns_truncdfqi2
2561 if (HAVE_fixuns_truncdfqi2
)
2562 fixtrunctab
[(int) DFmode
][(int) QImode
][1] = CODE_FOR_fixuns_truncdfqi2
;
2564 #ifdef HAVE_fixuns_truncdfhi2
2565 if (HAVE_fixuns_truncdfhi2
)
2566 fixtrunctab
[(int) DFmode
][(int) HImode
][1] = CODE_FOR_fixuns_truncdfhi2
;
2568 #ifdef HAVE_fixuns_truncdfsi2
2569 if (HAVE_fixuns_truncdfsi2
)
2570 fixtrunctab
[(int) DFmode
][(int) SImode
][1] = CODE_FOR_fixuns_truncdfsi2
;
2572 #ifdef HAVE_fixuns_truncdfdi2
2573 if (HAVE_fixuns_truncdfdi2
)
2574 fixtrunctab
[(int) DFmode
][(int) DImode
][1] = CODE_FOR_fixuns_truncdfdi2
;
2576 #ifdef HAVE_fixuns_truncdfti2
2577 if (HAVE_fixuns_truncdfti2
)
2578 fixtrunctab
[(int) DFmode
][(int) TImode
][1] = CODE_FOR_fixuns_truncdfti2
;
2581 #ifdef HAVE_fixuns_truncxfqi2
2582 if (HAVE_fixuns_truncxfqi2
)
2583 fixtrunctab
[(int) XFmode
][(int) QImode
][1] = CODE_FOR_fixuns_truncxfqi2
;
2585 #ifdef HAVE_fixuns_truncxfhi2
2586 if (HAVE_fixuns_truncxfhi2
)
2587 fixtrunctab
[(int) XFmode
][(int) HImode
][1] = CODE_FOR_fixuns_truncxfhi2
;
2589 #ifdef HAVE_fixuns_truncxfsi2
2590 if (HAVE_fixuns_truncxfsi2
)
2591 fixtrunctab
[(int) XFmode
][(int) SImode
][1] = CODE_FOR_fixuns_truncxfsi2
;
2593 #ifdef HAVE_fixuns_truncxfdi2
2594 if (HAVE_fixuns_truncxfdi2
)
2595 fixtrunctab
[(int) XFmode
][(int) DImode
][1] = CODE_FOR_fixuns_truncxfdi2
;
2597 #ifdef HAVE_fixuns_truncxfti2
2598 if (HAVE_fixuns_truncxfti2
)
2599 fixtrunctab
[(int) XFmode
][(int) TImode
][1] = CODE_FOR_fixuns_truncxfti2
;
2602 #ifdef HAVE_fixuns_trunctfqi2
2603 if (HAVE_fixuns_trunctfqi2
)
2604 fixtrunctab
[(int) TFmode
][(int) QImode
][1] = CODE_FOR_fixuns_trunctfqi2
;
2606 #ifdef HAVE_fixuns_trunctfhi2
2607 if (HAVE_fixuns_trunctfhi2
)
2608 fixtrunctab
[(int) TFmode
][(int) HImode
][1] = CODE_FOR_fixuns_trunctfhi2
;
2610 #ifdef HAVE_fixuns_trunctfsi2
2611 if (HAVE_fixuns_trunctfsi2
)
2612 fixtrunctab
[(int) TFmode
][(int) SImode
][1] = CODE_FOR_fixuns_trunctfsi2
;
2614 #ifdef HAVE_fixuns_trunctfdi2
2615 if (HAVE_fixuns_trunctfdi2
)
2616 fixtrunctab
[(int) TFmode
][(int) DImode
][1] = CODE_FOR_fixuns_trunctfdi2
;
2618 #ifdef HAVE_fixuns_trunctfti2
2619 if (HAVE_fixuns_trunctfti2
)
2620 fixtrunctab
[(int) TFmode
][(int) TImode
][1] = CODE_FOR_fixuns_trunctfti2
;
2623 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
2624 /* This flag says the same insns that convert to a signed fixnum
2625 also convert validly to an unsigned one. */
2629 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
2630 for (j
= 0; j
< NUM_MACHINE_MODES
; j
++)
2631 fixtrunctab
[i
][j
][1] = fixtrunctab
[i
][j
][0];
2640 for (p
= floattab
[0][0];
2641 p
< floattab
[0][0] + sizeof floattab
/ sizeof (floattab
[0][0][0]);
2643 *p
= CODE_FOR_nothing
;
2645 #ifdef HAVE_floatqisf2
2646 if (HAVE_floatqisf2
)
2647 floattab
[(int) SFmode
][(int) QImode
][0] = CODE_FOR_floatqisf2
;
2649 #ifdef HAVE_floathisf2
2650 if (HAVE_floathisf2
)
2651 floattab
[(int) SFmode
][(int) HImode
][0] = CODE_FOR_floathisf2
;
2653 #ifdef HAVE_floatsisf2
2654 if (HAVE_floatsisf2
)
2655 floattab
[(int) SFmode
][(int) SImode
][0] = CODE_FOR_floatsisf2
;
2657 #ifdef HAVE_floatdisf2
2658 if (HAVE_floatdisf2
)
2659 floattab
[(int) SFmode
][(int) DImode
][0] = CODE_FOR_floatdisf2
;
2661 #ifdef HAVE_floattisf2
2662 if (HAVE_floattisf2
)
2663 floattab
[(int) SFmode
][(int) TImode
][0] = CODE_FOR_floattisf2
;
2666 #ifdef HAVE_floatqidf2
2667 if (HAVE_floatqidf2
)
2668 floattab
[(int) DFmode
][(int) QImode
][0] = CODE_FOR_floatqidf2
;
2670 #ifdef HAVE_floathidf2
2671 if (HAVE_floathidf2
)
2672 floattab
[(int) DFmode
][(int) HImode
][0] = CODE_FOR_floathidf2
;
2674 #ifdef HAVE_floatsidf2
2675 if (HAVE_floatsidf2
)
2676 floattab
[(int) DFmode
][(int) SImode
][0] = CODE_FOR_floatsidf2
;
2678 #ifdef HAVE_floatdidf2
2679 if (HAVE_floatdidf2
)
2680 floattab
[(int) DFmode
][(int) DImode
][0] = CODE_FOR_floatdidf2
;
2682 #ifdef HAVE_floattidf2
2683 if (HAVE_floattidf2
)
2684 floattab
[(int) DFmode
][(int) TImode
][0] = CODE_FOR_floattidf2
;
2687 #ifdef HAVE_floatqixf2
2688 if (HAVE_floatqixf2
)
2689 floattab
[(int) XFmode
][(int) QImode
][0] = CODE_FOR_floatqixf2
;
2691 #ifdef HAVE_floathixf2
2692 if (HAVE_floathixf2
)
2693 floattab
[(int) XFmode
][(int) HImode
][0] = CODE_FOR_floathixf2
;
2695 #ifdef HAVE_floatsixf2
2696 if (HAVE_floatsixf2
)
2697 floattab
[(int) XFmode
][(int) SImode
][0] = CODE_FOR_floatsixf2
;
2699 #ifdef HAVE_floatdixf2
2700 if (HAVE_floatdixf2
)
2701 floattab
[(int) XFmode
][(int) DImode
][0] = CODE_FOR_floatdixf2
;
2703 #ifdef HAVE_floattixf2
2704 if (HAVE_floattixf2
)
2705 floattab
[(int) XFmode
][(int) TImode
][0] = CODE_FOR_floattixf2
;
2708 #ifdef HAVE_floatqitf2
2709 if (HAVE_floatqitf2
)
2710 floattab
[(int) TFmode
][(int) QImode
][0] = CODE_FOR_floatqitf2
;
2712 #ifdef HAVE_floathitf2
2713 if (HAVE_floathitf2
)
2714 floattab
[(int) TFmode
][(int) HImode
][0] = CODE_FOR_floathitf2
;
2716 #ifdef HAVE_floatsitf2
2717 if (HAVE_floatsitf2
)
2718 floattab
[(int) TFmode
][(int) SImode
][0] = CODE_FOR_floatsitf2
;
2720 #ifdef HAVE_floatditf2
2721 if (HAVE_floatditf2
)
2722 floattab
[(int) TFmode
][(int) DImode
][0] = CODE_FOR_floatditf2
;
2724 #ifdef HAVE_floattitf2
2725 if (HAVE_floattitf2
)
2726 floattab
[(int) TFmode
][(int) TImode
][0] = CODE_FOR_floattitf2
;
2729 #ifdef HAVE_floatunsqisf2
2730 if (HAVE_floatunsqisf2
)
2731 floattab
[(int) SFmode
][(int) QImode
][1] = CODE_FOR_floatunsqisf2
;
2733 #ifdef HAVE_floatunshisf2
2734 if (HAVE_floatunshisf2
)
2735 floattab
[(int) SFmode
][(int) HImode
][1] = CODE_FOR_floatunshisf2
;
2737 #ifdef HAVE_floatunssisf2
2738 if (HAVE_floatunssisf2
)
2739 floattab
[(int) SFmode
][(int) SImode
][1] = CODE_FOR_floatunssisf2
;
2741 #ifdef HAVE_floatunsdisf2
2742 if (HAVE_floatunsdisf2
)
2743 floattab
[(int) SFmode
][(int) DImode
][1] = CODE_FOR_floatunsdisf2
;
2745 #ifdef HAVE_floatunstisf2
2746 if (HAVE_floatunstisf2
)
2747 floattab
[(int) SFmode
][(int) TImode
][1] = CODE_FOR_floatunstisf2
;
2750 #ifdef HAVE_floatunsqidf2
2751 if (HAVE_floatunsqidf2
)
2752 floattab
[(int) DFmode
][(int) QImode
][1] = CODE_FOR_floatunsqidf2
;
2754 #ifdef HAVE_floatunshidf2
2755 if (HAVE_floatunshidf2
)
2756 floattab
[(int) DFmode
][(int) HImode
][1] = CODE_FOR_floatunshidf2
;
2758 #ifdef HAVE_floatunssidf2
2759 if (HAVE_floatunssidf2
)
2760 floattab
[(int) DFmode
][(int) SImode
][1] = CODE_FOR_floatunssidf2
;
2762 #ifdef HAVE_floatunsdidf2
2763 if (HAVE_floatunsdidf2
)
2764 floattab
[(int) DFmode
][(int) DImode
][1] = CODE_FOR_floatunsdidf2
;
2766 #ifdef HAVE_floatunstidf2
2767 if (HAVE_floatunstidf2
)
2768 floattab
[(int) DFmode
][(int) TImode
][1] = CODE_FOR_floatunstidf2
;
2771 #ifdef HAVE_floatunsqixf2
2772 if (HAVE_floatunsqixf2
)
2773 floattab
[(int) XFmode
][(int) QImode
][1] = CODE_FOR_floatunsqixf2
;
2775 #ifdef HAVE_floatunshixf2
2776 if (HAVE_floatunshixf2
)
2777 floattab
[(int) XFmode
][(int) HImode
][1] = CODE_FOR_floatunshixf2
;
2779 #ifdef HAVE_floatunssixf2
2780 if (HAVE_floatunssixf2
)
2781 floattab
[(int) XFmode
][(int) SImode
][1] = CODE_FOR_floatunssixf2
;
2783 #ifdef HAVE_floatunsdixf2
2784 if (HAVE_floatunsdixf2
)
2785 floattab
[(int) XFmode
][(int) DImode
][1] = CODE_FOR_floatunsdixf2
;
2787 #ifdef HAVE_floatunstixf2
2788 if (HAVE_floatunstixf2
)
2789 floattab
[(int) XFmode
][(int) TImode
][1] = CODE_FOR_floatunstixf2
;
2792 #ifdef HAVE_floatunsqitf2
2793 if (HAVE_floatunsqitf2
)
2794 floattab
[(int) TFmode
][(int) QImode
][1] = CODE_FOR_floatunsqitf2
;
2796 #ifdef HAVE_floatunshitf2
2797 if (HAVE_floatunshitf2
)
2798 floattab
[(int) TFmode
][(int) HImode
][1] = CODE_FOR_floatunshitf2
;
2800 #ifdef HAVE_floatunssitf2
2801 if (HAVE_floatunssitf2
)
2802 floattab
[(int) TFmode
][(int) SImode
][1] = CODE_FOR_floatunssitf2
;
2804 #ifdef HAVE_floatunsditf2
2805 if (HAVE_floatunsditf2
)
2806 floattab
[(int) TFmode
][(int) DImode
][1] = CODE_FOR_floatunsditf2
;
2808 #ifdef HAVE_floatunstitf2
2809 if (HAVE_floatunstitf2
)
2810 floattab
[(int) TFmode
][(int) TImode
][1] = CODE_FOR_floatunstitf2
;
2814 /* Generate code to convert FROM to floating point
2815 and store in TO. FROM must be fixed point and not VOIDmode.
2816 UNSIGNEDP nonzero means regard FROM as unsigned.
2817 Normally this is done by correcting the final value
2818 if it is negative. */
2821 expand_float (to
, from
, unsignedp
)
2825 enum insn_code icode
;
2826 register rtx target
= to
;
2827 enum machine_mode fmode
, imode
;
2829 /* Crash now, because we won't be able to decide which mode to use. */
2830 if (GET_MODE (from
) == VOIDmode
)
2833 /* Look for an insn to do the conversion. Do it in the specified
2834 modes if possible; otherwise convert either input, output or both to
2835 wider mode. If the integer mode is wider than the mode of FROM,
2836 we can do the conversion signed even if the input is unsigned. */
2838 for (imode
= GET_MODE (from
); imode
!= VOIDmode
;
2839 imode
= GET_MODE_WIDER_MODE (imode
))
2840 for (fmode
= GET_MODE (to
); fmode
!= VOIDmode
;
2841 fmode
= GET_MODE_WIDER_MODE (fmode
))
2843 int doing_unsigned
= unsignedp
;
2845 icode
= can_float_p (fmode
, imode
, unsignedp
);
2846 if (icode
== CODE_FOR_nothing
&& imode
!= GET_MODE (from
) && unsignedp
)
2847 icode
= can_float_p (fmode
, imode
, 0), doing_unsigned
= 0;
2849 if (icode
!= CODE_FOR_nothing
)
2851 to
= protect_from_queue (to
, 1);
2852 from
= protect_from_queue (from
, 0);
2854 if (imode
!= GET_MODE (from
))
2855 from
= convert_to_mode (imode
, from
, unsignedp
);
2857 if (fmode
!= GET_MODE (to
))
2858 target
= gen_reg_rtx (fmode
);
2860 emit_unop_insn (icode
, target
, from
,
2861 doing_unsigned
? UNSIGNED_FLOAT
: FLOAT
);
2864 convert_move (to
, target
, 0);
2869 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
2871 /* Unsigned integer, and no way to convert directly.
2872 Convert as signed, then conditionally adjust the result. */
2875 rtx label
= gen_label_rtx ();
2877 REAL_VALUE_TYPE offset
;
2881 to
= protect_from_queue (to
, 1);
2882 from
= protect_from_queue (from
, 0);
2885 from
= force_not_mem (from
);
2887 /* If we are about to do some arithmetic to correct for an
2888 unsigned operand, do it in a pseudo-register. */
2890 if (GET_CODE (to
) != REG
|| REGNO (to
) <= LAST_VIRTUAL_REGISTER
)
2891 target
= gen_reg_rtx (GET_MODE (to
));
2893 /* Convert as signed integer to floating. */
2894 expand_float (target
, from
, 0);
2896 /* If FROM is negative (and therefore TO is negative),
2897 correct its value by 2**bitwidth. */
2899 do_pending_stack_adjust ();
2900 emit_cmp_insn (from
, const0_rtx
, GE
, NULL_RTX
, GET_MODE (from
), 0, 0);
2901 emit_jump_insn (gen_bge (label
));
2902 /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
2903 Rather than setting up a dconst_dot_5, let's hope SCO
2905 offset
= REAL_VALUE_LDEXP (dconst1
, GET_MODE_BITSIZE (GET_MODE (from
)));
2906 temp
= expand_binop (GET_MODE (to
), add_optab
, target
,
2907 immed_real_const_1 (offset
, GET_MODE (to
)),
2908 target
, 0, OPTAB_LIB_WIDEN
);
2910 emit_move_insn (target
, temp
);
2911 do_pending_stack_adjust ();
2917 /* No hardware instruction available; call a library rotine to convert from
2918 SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */
2923 to
= protect_from_queue (to
, 1);
2924 from
= protect_from_queue (from
, 0);
2926 if (GET_MODE_SIZE (GET_MODE (from
)) < GET_MODE_SIZE (SImode
))
2927 from
= convert_to_mode (SImode
, from
, unsignedp
);
2930 from
= force_not_mem (from
);
2932 if (GET_MODE (to
) == SFmode
)
2934 if (GET_MODE (from
) == SImode
)
2935 libfcn
= floatsisf_libfunc
;
2936 else if (GET_MODE (from
) == DImode
)
2937 libfcn
= floatdisf_libfunc
;
2938 else if (GET_MODE (from
) == TImode
)
2939 libfcn
= floattisf_libfunc
;
2943 else if (GET_MODE (to
) == DFmode
)
2945 if (GET_MODE (from
) == SImode
)
2946 libfcn
= floatsidf_libfunc
;
2947 else if (GET_MODE (from
) == DImode
)
2948 libfcn
= floatdidf_libfunc
;
2949 else if (GET_MODE (from
) == TImode
)
2950 libfcn
= floattidf_libfunc
;
2954 else if (GET_MODE (to
) == XFmode
)
2956 if (GET_MODE (from
) == SImode
)
2957 libfcn
= floatsixf_libfunc
;
2958 else if (GET_MODE (from
) == DImode
)
2959 libfcn
= floatdixf_libfunc
;
2960 else if (GET_MODE (from
) == TImode
)
2961 libfcn
= floattixf_libfunc
;
2965 else if (GET_MODE (to
) == TFmode
)
2967 if (GET_MODE (from
) == SImode
)
2968 libfcn
= floatsitf_libfunc
;
2969 else if (GET_MODE (from
) == DImode
)
2970 libfcn
= floatditf_libfunc
;
2971 else if (GET_MODE (from
) == TImode
)
2972 libfcn
= floattitf_libfunc
;
2981 emit_library_call (libfcn
, 1, GET_MODE (to
), 1, from
, GET_MODE (from
));
2982 insns
= get_insns ();
2985 emit_libcall_block (insns
, target
, hard_libcall_value (GET_MODE (to
)),
2986 gen_rtx (FLOAT
, GET_MODE (to
), from
));
2989 /* Copy result to requested destination
2990 if we have been computing in a temp location. */
2994 if (GET_MODE (target
) == GET_MODE (to
))
2995 emit_move_insn (to
, target
);
2997 convert_move (to
, target
, 0);
3001 /* expand_fix: generate code to convert FROM to fixed point
3002 and store in TO. FROM must be floating point. */
3008 rtx temp
= gen_reg_rtx (GET_MODE (x
));
3009 return expand_unop (GET_MODE (x
), ftrunc_optab
, x
, temp
, 0);
3013 expand_fix (to
, from
, unsignedp
)
3014 register rtx to
, from
;
3017 enum insn_code icode
;
3018 register rtx target
= to
;
3019 enum machine_mode fmode
, imode
;
3023 /* We first try to find a pair of modes, one real and one integer, at
3024 least as wide as FROM and TO, respectively, in which we can open-code
3025 this conversion. If the integer mode is wider than the mode of TO,
3026 we can do the conversion either signed or unsigned. */
3028 for (imode
= GET_MODE (to
); imode
!= VOIDmode
;
3029 imode
= GET_MODE_WIDER_MODE (imode
))
3030 for (fmode
= GET_MODE (from
); fmode
!= VOIDmode
;
3031 fmode
= GET_MODE_WIDER_MODE (fmode
))
3033 int doing_unsigned
= unsignedp
;
3035 icode
= can_fix_p (imode
, fmode
, unsignedp
, &must_trunc
);
3036 if (icode
== CODE_FOR_nothing
&& imode
!= GET_MODE (to
) && unsignedp
)
3037 icode
= can_fix_p (imode
, fmode
, 0, &must_trunc
), doing_unsigned
= 0;
3039 if (icode
!= CODE_FOR_nothing
)
3041 to
= protect_from_queue (to
, 1);
3042 from
= protect_from_queue (from
, 0);
3044 if (fmode
!= GET_MODE (from
))
3045 from
= convert_to_mode (fmode
, from
, 0);
3048 from
= ftruncify (from
);
3050 if (imode
!= GET_MODE (to
))
3051 target
= gen_reg_rtx (imode
);
3053 emit_unop_insn (icode
, target
, from
,
3054 doing_unsigned
? UNSIGNED_FIX
: FIX
);
3056 convert_move (to
, target
, unsignedp
);
3061 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3062 /* For an unsigned conversion, there is one more way to do it.
3063 If we have a signed conversion, we generate code that compares
3064 the real value to the largest representable positive number. If if
3065 is smaller, the conversion is done normally. Otherwise, subtract
3066 one plus the highest signed number, convert, and add it back.
3068 We only need to check all real modes, since we know we didn't find
3069 anything with a wider integer mode. */
3071 if (unsignedp
&& GET_MODE_BITSIZE (GET_MODE (to
)) <= HOST_BITS_PER_WIDE_INT
)
3072 for (fmode
= GET_MODE (from
); fmode
!= VOIDmode
;
3073 fmode
= GET_MODE_WIDER_MODE (fmode
))
3074 /* Make sure we won't lose significant bits doing this. */
3075 if (GET_MODE_BITSIZE (fmode
) > GET_MODE_BITSIZE (GET_MODE (to
))
3076 && CODE_FOR_nothing
!= can_fix_p (GET_MODE (to
), fmode
, 0,
3079 int bitsize
= GET_MODE_BITSIZE (GET_MODE (to
));
3080 REAL_VALUE_TYPE offset
= REAL_VALUE_LDEXP (dconst1
, bitsize
- 1);
3081 rtx limit
= immed_real_const_1 (offset
, fmode
);
3082 rtx lab1
= gen_label_rtx ();
3083 rtx lab2
= gen_label_rtx ();
3087 to
= protect_from_queue (to
, 1);
3088 from
= protect_from_queue (from
, 0);
3091 from
= force_not_mem (from
);
3093 if (fmode
!= GET_MODE (from
))
3094 from
= convert_to_mode (fmode
, from
, 0);
3096 /* See if we need to do the subtraction. */
3097 do_pending_stack_adjust ();
3098 emit_cmp_insn (from
, limit
, GE
, NULL_RTX
, GET_MODE (from
), 0, 0);
3099 emit_jump_insn (gen_bge (lab1
));
3101 /* If not, do the signed "fix" and branch around fixup code. */
3102 expand_fix (to
, from
, 0);
3103 emit_jump_insn (gen_jump (lab2
));
3106 /* Otherwise, subtract 2**(N-1), convert to signed number,
3107 then add 2**(N-1). Do the addition using XOR since this
3108 will often generate better code. */
3110 target
= expand_binop (GET_MODE (from
), sub_optab
, from
, limit
,
3111 NULL_RTX
, 0, OPTAB_LIB_WIDEN
);
3112 expand_fix (to
, target
, 0);
3113 target
= expand_binop (GET_MODE (to
), xor_optab
, to
,
3114 GEN_INT ((HOST_WIDE_INT
) 1 << (bitsize
- 1)),
3115 to
, 1, OPTAB_LIB_WIDEN
);
3118 emit_move_insn (to
, target
);
3122 /* Make a place for a REG_NOTE and add it. */
3123 insn
= emit_move_insn (to
, to
);
3124 REG_NOTES (insn
) = gen_rtx (EXPR_LIST
, REG_EQUAL
,
3125 gen_rtx (UNSIGNED_FIX
, GET_MODE (to
),
3126 from
), REG_NOTES (insn
));
3132 /* We can't do it with an insn, so use a library call. But first ensure
3133 that the mode of TO is at least as wide as SImode, since those are the
3134 only library calls we know about. */
3136 if (GET_MODE_SIZE (GET_MODE (to
)) < GET_MODE_SIZE (SImode
))
3138 target
= gen_reg_rtx (SImode
);
3140 expand_fix (target
, from
, unsignedp
);
3142 else if (GET_MODE (from
) == SFmode
)
3144 if (GET_MODE (to
) == SImode
)
3145 libfcn
= unsignedp
? fixunssfsi_libfunc
: fixsfsi_libfunc
;
3146 else if (GET_MODE (to
) == DImode
)
3147 libfcn
= unsignedp
? fixunssfdi_libfunc
: fixsfdi_libfunc
;
3148 else if (GET_MODE (to
) == TImode
)
3149 libfcn
= unsignedp
? fixunssfti_libfunc
: fixsfti_libfunc
;
3153 else if (GET_MODE (from
) == DFmode
)
3155 if (GET_MODE (to
) == SImode
)
3156 libfcn
= unsignedp
? fixunsdfsi_libfunc
: fixdfsi_libfunc
;
3157 else if (GET_MODE (to
) == DImode
)
3158 libfcn
= unsignedp
? fixunsdfdi_libfunc
: fixdfdi_libfunc
;
3159 else if (GET_MODE (to
) == TImode
)
3160 libfcn
= unsignedp
? fixunsdfti_libfunc
: fixdfti_libfunc
;
3164 else if (GET_MODE (from
) == XFmode
)
3166 if (GET_MODE (to
) == SImode
)
3167 libfcn
= unsignedp
? fixunsxfsi_libfunc
: fixxfsi_libfunc
;
3168 else if (GET_MODE (to
) == DImode
)
3169 libfcn
= unsignedp
? fixunsxfdi_libfunc
: fixxfdi_libfunc
;
3170 else if (GET_MODE (to
) == TImode
)
3171 libfcn
= unsignedp
? fixunsxfti_libfunc
: fixxfti_libfunc
;
3175 else if (GET_MODE (from
) == TFmode
)
3177 if (GET_MODE (to
) == SImode
)
3178 libfcn
= unsignedp
? fixunstfsi_libfunc
: fixtfsi_libfunc
;
3179 else if (GET_MODE (to
) == DImode
)
3180 libfcn
= unsignedp
? fixunstfdi_libfunc
: fixtfdi_libfunc
;
3181 else if (GET_MODE (to
) == TImode
)
3182 libfcn
= unsignedp
? fixunstfti_libfunc
: fixtfti_libfunc
;
3193 to
= protect_from_queue (to
, 1);
3194 from
= protect_from_queue (from
, 0);
3197 from
= force_not_mem (from
);
3201 emit_library_call (libfcn
, 1, GET_MODE (to
), 1, from
, GET_MODE (from
));
3202 insns
= get_insns ();
3205 emit_libcall_block (insns
, target
, hard_libcall_value (GET_MODE (to
)),
3206 gen_rtx (unsignedp
? FIX
: UNSIGNED_FIX
,
3207 GET_MODE (to
), from
));
3210 if (GET_MODE (to
) == GET_MODE (target
))
3211 emit_move_insn (to
, target
);
3213 convert_move (to
, target
, 0);
3221 optab op
= (optab
) xmalloc (sizeof (struct optab
));
3223 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
3225 op
->handlers
[i
].insn_code
= CODE_FOR_nothing
;
3226 op
->handlers
[i
].libfunc
= 0;
3231 /* Initialize the libfunc fields of an entire group of entries in some
3232 optab. Each entry is set equal to a string consisting of a leading
3233 pair of underscores followed by a generic operation name followed by
3234 a mode name (downshifted to lower case) followed by a single character
3235 representing the number of operands for the given operation (which is
3236 usually one of the characters '2', '3', or '4').
3238 OPTABLE is the table in which libfunc fields are to be initialized.
3239 FIRST_MODE is the first machine mode index in the given optab to
3241 LAST_MODE is the last machine mode index in the given optab to
3243 OPNAME is the generic (string) name of the operation.
3244 SUFFIX is the character which specifies the number of operands for
3245 the given generic operation.
3249 init_libfuncs (optable
, first_mode
, last_mode
, opname
, suffix
)
3250 register optab optable
;
3251 register char *opname
;
3252 register enum machine_mode first_mode
;
3253 register enum machine_mode last_mode
;
3254 register char suffix
;
3256 register enum machine_mode mode
;
3257 register unsigned opname_len
= strlen (opname
);
3259 for (mode
= first_mode
; mode
<= last_mode
; mode
++)
3261 register char *mname
= mode_name
[(int) mode
];
3262 register unsigned mname_len
= strlen (mname
);
3263 register char *libfunc_name
3264 = (char *) xmalloc (2 + opname_len
+ mname_len
+ 1 + 1);
3271 for (q
= opname
; *q
; )
3273 for (q
= mname
; *q
; q
++)
3274 *p
++ = tolower (*q
);
3277 optable
->handlers
[(int) mode
].libfunc
3278 = gen_rtx (SYMBOL_REF
, Pmode
, libfunc_name
);
3282 /* Initialize the libfunc fields of an entire group of entries in some
3283 optab which correspond to all integer mode operations. The parameters
3284 have the same meaning as similarly named ones for the `init_libfuncs'
3285 routine. (See above). */
3288 init_integral_libfuncs (optable
, opname
, suffix
)
3289 register optab optable
;
3290 register char *opname
;
3291 register char suffix
;
3293 init_libfuncs (optable
, SImode
, TImode
, opname
, suffix
);
3296 /* Initialize the libfunc fields of an entire group of entries in some
3297 optab which correspond to all real mode operations. The parameters
3298 have the same meaning as similarly named ones for the `init_libfuncs'
3299 routine. (See above). */
3302 init_floating_libfuncs (optable
, opname
, suffix
)
3303 register optab optable
;
3304 register char *opname
;
3305 register char suffix
;
3307 init_libfuncs (optable
, SFmode
, TFmode
, opname
, suffix
);
3310 /* Call this once to initialize the contents of the optabs
3311 appropriately for the current target machine. */
3322 add_optab
= init_optab (PLUS
);
3323 sub_optab
= init_optab (MINUS
);
3324 smul_optab
= init_optab (MULT
);
3325 smul_widen_optab
= init_optab (UNKNOWN
);
3326 umul_widen_optab
= init_optab (UNKNOWN
);
3327 sdiv_optab
= init_optab (DIV
);
3328 sdivmod_optab
= init_optab (UNKNOWN
);
3329 udiv_optab
= init_optab (UDIV
);
3330 udivmod_optab
= init_optab (UNKNOWN
);
3331 smod_optab
= init_optab (MOD
);
3332 umod_optab
= init_optab (UMOD
);
3333 flodiv_optab
= init_optab (DIV
);
3334 ftrunc_optab
= init_optab (UNKNOWN
);
3335 and_optab
= init_optab (AND
);
3336 ior_optab
= init_optab (IOR
);
3337 xor_optab
= init_optab (XOR
);
3338 ashl_optab
= init_optab (ASHIFT
);
3339 ashr_optab
= init_optab (ASHIFTRT
);
3340 lshl_optab
= init_optab (LSHIFT
);
3341 lshr_optab
= init_optab (LSHIFTRT
);
3342 rotl_optab
= init_optab (ROTATE
);
3343 rotr_optab
= init_optab (ROTATERT
);
3344 smin_optab
= init_optab (SMIN
);
3345 smax_optab
= init_optab (SMAX
);
3346 umin_optab
= init_optab (UMIN
);
3347 umax_optab
= init_optab (UMAX
);
3348 mov_optab
= init_optab (UNKNOWN
);
3349 movstrict_optab
= init_optab (UNKNOWN
);
3350 cmp_optab
= init_optab (UNKNOWN
);
3351 ucmp_optab
= init_optab (UNKNOWN
);
3352 tst_optab
= init_optab (UNKNOWN
);
3353 neg_optab
= init_optab (NEG
);
3354 abs_optab
= init_optab (ABS
);
3355 one_cmpl_optab
= init_optab (NOT
);
3356 ffs_optab
= init_optab (FFS
);
3357 sqrt_optab
= init_optab (SQRT
);
3358 strlen_optab
= init_optab (UNKNOWN
);
3362 add_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_addqi3
;
3366 add_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_addhi3
;
3370 add_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_addpsi3
;
3374 add_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_addsi3
;
3378 add_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_adddi3
;
3382 add_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_addti3
;
3386 add_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_addsf3
;
3390 add_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_adddf3
;
3394 add_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_addxf3
;
3398 add_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_addtf3
;
3400 init_integral_libfuncs (add_optab
, "add", '3');
3401 init_floating_libfuncs (add_optab
, "add", '3');
3405 sub_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_subqi3
;
3409 sub_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_subhi3
;
3413 sub_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_subpsi3
;
3417 sub_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_subsi3
;
3421 sub_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_subdi3
;
3425 sub_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_subti3
;
3429 sub_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_subsf3
;
3433 sub_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_subdf3
;
3437 sub_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_subxf3
;
3441 sub_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_subtf3
;
3443 init_integral_libfuncs (sub_optab
, "sub", '3');
3444 init_floating_libfuncs (sub_optab
, "sub", '3');
3448 smul_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_mulqi3
;
3452 smul_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_mulhi3
;
3456 smul_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_mulpsi3
;
3460 smul_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_mulsi3
;
3464 smul_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_muldi3
;
3468 smul_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_multi3
;
3472 smul_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_mulsf3
;
3476 smul_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_muldf3
;
3480 smul_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_mulxf3
;
3484 smul_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_multf3
;
3486 init_integral_libfuncs (smul_optab
, "mul", '3');
3487 init_floating_libfuncs (smul_optab
, "mul", '3');
3489 #ifdef MULSI3_LIBCALL
3490 smul_optab
->handlers
[(int) SImode
].libfunc
3491 = gen_rtx (SYMBOL_REF
, Pmode
, MULSI3_LIBCALL
);
3493 #ifdef MULDI3_LIBCALL
3494 smul_optab
->handlers
[(int) DImode
].libfunc
3495 = gen_rtx (SYMBOL_REF
, Pmode
, MULDI3_LIBCALL
);
3497 #ifdef MULTI3_LIBCALL
3498 smul_optab
->handlers
[(int) TImode
].libfunc
3499 = gen_rtx (SYMBOL_REF
, Pmode
, MULTI3_LIBCALL
);
3502 #ifdef HAVE_mulqihi3
3504 smul_widen_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_mulqihi3
;
3506 #ifdef HAVE_mulhisi3
3508 smul_widen_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_mulhisi3
;
3510 #ifdef HAVE_mulsidi3
3512 smul_widen_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_mulsidi3
;
3514 #ifdef HAVE_mulditi3
3516 smul_widen_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_mulditi3
;
3519 #ifdef HAVE_umulqihi3
3521 umul_widen_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_umulqihi3
;
3523 #ifdef HAVE_umulhisi3
3525 umul_widen_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_umulhisi3
;
3527 #ifdef HAVE_umulsidi3
3529 umul_widen_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_umulsidi3
;
3531 #ifdef HAVE_umulditi3
3533 umul_widen_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_umulditi3
;
3538 sdiv_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_divqi3
;
3542 sdiv_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_divhi3
;
3546 sdiv_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_divpsi3
;
3550 sdiv_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_divsi3
;
3554 sdiv_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_divdi3
;
3558 sdiv_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_divti3
;
3560 init_integral_libfuncs (sdiv_optab
, "div", '3');
3562 #ifdef DIVSI3_LIBCALL
3563 sdiv_optab
->handlers
[(int) SImode
].libfunc
3564 = gen_rtx (SYMBOL_REF
, Pmode
, DIVSI3_LIBCALL
);
3566 #ifdef DIVDI3_LIBCALL
3567 sdiv_optab
->handlers
[(int) DImode
].libfunc
3568 = gen_rtx (SYMBOL_REF
, Pmode
, DIVDI3_LIBCALL
);
3570 #ifdef DIVTI3_LIBCALL
3571 sdiv_optab
->handlers
[(int) TImode
].libfunc
3572 = gen_rtx (SYMBOL_REF
, Pmode
, DIVTI3_LIBCALL
);
3577 udiv_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_udivqi3
;
3581 udiv_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_udivhi3
;
3583 #ifdef HAVE_udivpsi3
3585 udiv_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_udivpsi3
;
3589 udiv_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_udivsi3
;
3593 udiv_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_udivdi3
;
3597 udiv_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_udivti3
;
3599 init_integral_libfuncs (udiv_optab
, "udiv", '3');
3601 #ifdef UDIVSI3_LIBCALL
3602 udiv_optab
->handlers
[(int) SImode
].libfunc
3603 = gen_rtx (SYMBOL_REF
, Pmode
, UDIVSI3_LIBCALL
);
3605 #ifdef UDIVDI3_LIBCALL
3606 udiv_optab
->handlers
[(int) DImode
].libfunc
3607 = gen_rtx (SYMBOL_REF
, Pmode
, UDIVDI3_LIBCALL
);
3609 #ifdef UDIVTI3_LIBCALL
3610 udiv_optab
->handlers
[(int) TImode
].libfunc
3611 = gen_rtx (SYMBOL_REF
, Pmode
, UDIVTI3_LIBCALL
);
3614 #ifdef HAVE_divmodqi4
3616 sdivmod_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_divmodqi4
;
3618 #ifdef HAVE_divmodhi4
3620 sdivmod_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_divmodhi4
;
3622 #ifdef HAVE_divmodsi4
3624 sdivmod_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_divmodsi4
;
3626 #ifdef HAVE_divmoddi4
3628 sdivmod_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_divmoddi4
;
3630 #ifdef HAVE_divmodti4
3632 sdivmod_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_divmodti4
;
3634 init_integral_libfuncs (sdivmod_optab
, "divmod", '4');
3636 #ifdef HAVE_udivmodqi4
3637 if (HAVE_udivmodqi4
)
3638 udivmod_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_udivmodqi4
;
3640 #ifdef HAVE_udivmodhi4
3641 if (HAVE_udivmodhi4
)
3642 udivmod_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_udivmodhi4
;
3644 #ifdef HAVE_udivmodsi4
3645 if (HAVE_udivmodsi4
)
3646 udivmod_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_udivmodsi4
;
3648 #ifdef HAVE_udivmoddi4
3649 if (HAVE_udivmoddi4
)
3650 udivmod_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_udivmoddi4
;
3652 #ifdef HAVE_udivmodti4
3653 if (HAVE_udivmodti4
)
3654 udivmod_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_udivmodti4
;
3656 init_integral_libfuncs (udivmod_optab
, "udivmod", '4');
3660 smod_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_modqi3
;
3664 smod_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_modhi3
;
3668 smod_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_modpsi3
;
3672 smod_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_modsi3
;
3676 smod_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_moddi3
;
3680 smod_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_modti3
;
3682 init_integral_libfuncs (smod_optab
, "mod", '3');
3684 #ifdef MODSI3_LIBCALL
3685 smod_optab
->handlers
[(int) SImode
].libfunc
3686 = gen_rtx (SYMBOL_REF
, Pmode
, MODSI3_LIBCALL
);
3688 #ifdef MODDI3_LIBCALL
3689 smod_optab
->handlers
[(int) DImode
].libfunc
3690 = gen_rtx (SYMBOL_REF
, Pmode
, MODDI3_LIBCALL
);
3692 #ifdef MODTI3_LIBCALL
3693 smod_optab
->handlers
[(int) TImode
].libfunc
3694 = gen_rtx (SYMBOL_REF
, Pmode
, MODTI3_LIBCALL
);
3699 umod_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_umodqi3
;
3703 umod_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_umodhi3
;
3705 #ifdef HAVE_umodpsi3
3707 umod_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_umodpsi3
;
3711 umod_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_umodsi3
;
3715 umod_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_umoddi3
;
3719 umod_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_umodti3
;
3721 init_integral_libfuncs (umod_optab
, "umod", '3');
3723 #ifdef UMODSI3_LIBCALL
3724 umod_optab
->handlers
[(int) SImode
].libfunc
3725 = gen_rtx (SYMBOL_REF
, Pmode
, UMODSI3_LIBCALL
);
3727 #ifdef UMODDI3_LIBCALL
3728 umod_optab
->handlers
[(int) DImode
].libfunc
3729 = gen_rtx (SYMBOL_REF
, Pmode
, UMODDI3_LIBCALL
);
3731 #ifdef UMODTI3_LIBCALL
3732 umod_optab
->handlers
[(int) TImode
].libfunc
3733 = gen_rtx (SYMBOL_REF
, Pmode
, UMODTI3_LIBCALL
);
3738 flodiv_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_divsf3
;
3742 flodiv_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_divdf3
;
3746 flodiv_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_divxf3
;
3750 flodiv_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_divtf3
;
3752 init_floating_libfuncs (flodiv_optab
, "div", '3');
3754 #ifdef HAVE_ftruncsf2
3756 ftrunc_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_ftruncsf2
;
3758 #ifdef HAVE_ftruncdf2
3760 ftrunc_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_ftruncdf2
;
3762 #ifdef HAVE_ftruncxf2
3764 ftrunc_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_ftruncxf2
;
3766 #ifdef HAVE_ftrunctf2
3768 ftrunc_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_ftrunctf2
;
3770 init_floating_libfuncs (ftrunc_optab
, "ftrunc", '2');
3774 and_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_andqi3
;
3778 and_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_andhi3
;
3782 and_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_andpsi3
;
3786 and_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_andsi3
;
3790 and_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_anddi3
;
3794 and_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_andti3
;
3796 init_integral_libfuncs (and_optab
, "and", '3');
3800 ior_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_iorqi3
;
3804 ior_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_iorhi3
;
3808 ior_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_iorpsi3
;
3812 ior_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_iorsi3
;
3816 ior_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_iordi3
;
3820 ior_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_iorti3
;
3822 init_integral_libfuncs (ior_optab
, "ior", '3');
3826 xor_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_xorqi3
;
3830 xor_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_xorhi3
;
3834 xor_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_xorpsi3
;
3838 xor_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_xorsi3
;
3842 xor_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_xordi3
;
3846 xor_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_xorti3
;
3848 init_integral_libfuncs (xor_optab
, "xor", '3');
3852 ashl_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_ashlqi3
;
3856 ashl_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_ashlhi3
;
3858 #ifdef HAVE_ashlpsi3
3860 ashl_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_ashlpsi3
;
3864 ashl_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_ashlsi3
;
3868 ashl_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_ashldi3
;
3872 ashl_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_ashlti3
;
3874 init_integral_libfuncs (ashl_optab
, "ashl", '3');
3878 ashr_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_ashrqi3
;
3882 ashr_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_ashrhi3
;
3884 #ifdef HAVE_ashrpsi3
3886 ashr_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_ashrpsi3
;
3890 ashr_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_ashrsi3
;
3894 ashr_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_ashrdi3
;
3898 ashr_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_ashrti3
;
3900 init_integral_libfuncs (ashr_optab
, "ashr", '3');
3904 lshl_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_lshlqi3
;
3908 lshl_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_lshlhi3
;
3910 #ifdef HAVE_lshlpsi3
3912 lshl_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_lshlpsi3
;
3916 lshl_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_lshlsi3
;
3920 lshl_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_lshldi3
;
3924 lshl_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_lshlti3
;
3926 init_integral_libfuncs (lshl_optab
, "lshl", '3');
3930 lshr_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_lshrqi3
;
3934 lshr_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_lshrhi3
;
3936 #ifdef HAVE_lshrpsi3
3938 lshr_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_lshrpsi3
;
3942 lshr_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_lshrsi3
;
3946 lshr_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_lshrdi3
;
3950 lshr_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_lshrti3
;
3952 init_integral_libfuncs (lshr_optab
, "lshr", '3');
3956 rotl_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_rotlqi3
;
3960 rotl_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_rotlhi3
;
3962 #ifdef HAVE_rotlpsi3
3964 rotl_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_rotlpsi3
;
3968 rotl_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_rotlsi3
;
3972 rotl_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_rotldi3
;
3976 rotl_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_rotlti3
;
3978 init_integral_libfuncs (rotl_optab
, "rotl", '3');
3982 rotr_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_rotrqi3
;
3986 rotr_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_rotrhi3
;
3988 #ifdef HAVE_rotrpsi3
3990 rotr_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_rotrpsi3
;
3994 rotr_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_rotrsi3
;
3998 rotr_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_rotrdi3
;
4002 rotr_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_rotrti3
;
4004 init_integral_libfuncs (rotr_optab
, "rotr", '3');
4008 smin_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_sminqi3
;
4012 smin_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_sminhi3
;
4016 smin_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_sminsi3
;
4020 smin_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_smindi3
;
4024 smin_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_sminti3
;
4028 smin_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_minsf3
;
4032 smin_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_mindf3
;
4036 smin_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_minxf3
;
4040 smin_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_mintf3
;
4042 init_integral_libfuncs (smin_optab
, "min", '3');
4043 init_floating_libfuncs (smin_optab
, "min", '3');
4047 smax_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_smaxqi3
;
4051 smax_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_smaxhi3
;
4055 smax_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_smaxsi3
;
4059 smax_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_smaxdi3
;
4063 smax_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_smaxti3
;
4067 smax_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_maxsf3
;
4071 smax_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_maxdf3
;
4075 smax_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_maxxf3
;
4079 smax_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_maxtf3
;
4081 init_integral_libfuncs (smax_optab
, "max", '3');
4082 init_floating_libfuncs (smax_optab
, "max", '3');
4086 umin_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_uminqi3
;
4090 umin_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_uminhi3
;
4094 umin_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_uminsi3
;
4098 umin_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_umindi3
;
4102 umin_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_uminti3
;
4104 init_integral_libfuncs (umin_optab
, "umin", '3');
4108 umax_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_umaxqi3
;
4112 umax_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_umaxhi3
;
4116 umax_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_umaxsi3
;
4120 umax_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_umaxdi3
;
4124 umax_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_umaxti3
;
4126 init_integral_libfuncs (umax_optab
, "umax", '3');
4130 neg_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_negqi2
;
4134 neg_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_neghi2
;
4138 neg_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_negpsi2
;
4142 neg_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_negsi2
;
4146 neg_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_negdi2
;
4150 neg_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_negti2
;
4154 neg_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_negsf2
;
4158 neg_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_negdf2
;
4162 neg_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_negxf2
;
4166 neg_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_negtf2
;
4168 init_integral_libfuncs (neg_optab
, "neg", '2');
4169 init_floating_libfuncs (neg_optab
, "neg", '2');
4173 abs_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_absqi2
;
4177 abs_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_abshi2
;
4181 abs_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_abspsi2
;
4185 abs_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_abssi2
;
4189 abs_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_absdi2
;
4193 abs_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_absti2
;
4197 abs_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_abssf2
;
4201 abs_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_absdf2
;
4205 abs_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_absxf2
;
4209 abs_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_abstf2
;
4211 /* No library calls here! If there is no abs instruction,
4212 expand_expr will generate a conditional negation. */
4216 sqrt_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_sqrtqi2
;
4220 sqrt_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_sqrthi2
;
4222 #ifdef HAVE_sqrtpsi2
4224 sqrt_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_sqrtpsi2
;
4228 sqrt_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_sqrtsi2
;
4232 sqrt_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_sqrtdi2
;
4236 sqrt_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_sqrtti2
;
4240 sqrt_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_sqrtsf2
;
4244 sqrt_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_sqrtdf2
;
4248 sqrt_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_sqrttf2
;
4250 /* No library calls here! If there is no sqrt instruction expand_builtin
4251 should force the library call. */
4253 #ifdef HAVE_strlenqi
4255 strlen_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_strlenqi
;
4257 #ifdef HAVE_strlenhi
4259 strlen_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_strlenhi
;
4261 #ifdef HAVE_strlenpsi
4263 strlen_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_strlenpsi
;
4265 #ifdef HAVE_strlensi
4267 strlen_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_strlensi
;
4269 #ifdef HAVE_strlendi
4271 strlen_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_strlendi
;
4273 #ifdef HAVE_strlenti
4275 strlen_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_strlenti
;
4277 /* No library calls here! If there is no strlen instruction expand_builtin
4278 should force the library call. */
4280 #ifdef HAVE_one_cmplqi2
4281 if (HAVE_one_cmplqi2
)
4282 one_cmpl_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_one_cmplqi2
;
4284 #ifdef HAVE_one_cmplhi2
4285 if (HAVE_one_cmplhi2
)
4286 one_cmpl_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_one_cmplhi2
;
4288 #ifdef HAVE_one_cmplpsi2
4289 if (HAVE_one_cmplpsi2
)
4290 one_cmpl_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_one_cmplpsi2
;
4292 #ifdef HAVE_one_cmplsi2
4293 if (HAVE_one_cmplsi2
)
4294 one_cmpl_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_one_cmplsi2
;
4296 #ifdef HAVE_one_cmpldi2
4297 if (HAVE_one_cmpldi2
)
4298 one_cmpl_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_one_cmpldi2
;
4300 #ifdef HAVE_one_cmplti2
4301 if (HAVE_one_cmplti2
)
4302 one_cmpl_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_one_cmplti2
;
4304 init_integral_libfuncs (one_cmpl_optab
, "one_cmpl", '2');
4308 ffs_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_ffsqi2
;
4312 ffs_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_ffshi2
;
4316 ffs_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_ffspsi2
;
4320 ffs_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_ffssi2
;
4324 ffs_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_ffsdi2
;
4328 ffs_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_ffsti2
;
4330 init_integral_libfuncs (ffs_optab
, "ffs", '2');
4334 mov_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_movqi
;
4338 mov_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_movhi
;
4342 mov_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_movpsi
;
4346 mov_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_movsi
;
4350 mov_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_movdi
;
4354 mov_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_movti
;
4358 mov_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_movsf
;
4362 mov_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_movdf
;
4366 mov_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_movxf
;
4370 mov_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_movtf
;
4374 mov_optab
->handlers
[(int) CCmode
].insn_code
= CODE_FOR_movcc
;
4377 #ifdef EXTRA_CC_MODES
4381 #ifdef HAVE_movstrictqi
4382 if (HAVE_movstrictqi
)
4383 movstrict_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_movstrictqi
;
4385 #ifdef HAVE_movstricthi
4386 if (HAVE_movstricthi
)
4387 movstrict_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_movstricthi
;
4389 #ifdef HAVE_movstrictpsi
4390 if (HAVE_movstrictpsi
)
4391 movstrict_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_movstrictpsi
;
4393 #ifdef HAVE_movstrictsi
4394 if (HAVE_movstrictsi
)
4395 movstrict_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_movstrictsi
;
4397 #ifdef HAVE_movstrictdi
4398 if (HAVE_movstrictdi
)
4399 movstrict_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_movstrictdi
;
4401 #ifdef HAVE_movstrictti
4402 if (HAVE_movstrictti
)
4403 movstrict_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_movstrictti
;
4408 cmp_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_cmpqi
;
4412 cmp_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_cmphi
;
4416 cmp_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_cmppsi
;
4420 cmp_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_cmpsi
;
4424 cmp_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_cmpdi
;
4428 cmp_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_cmpti
;
4432 cmp_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_cmpsf
;
4436 cmp_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_cmpdf
;
4440 cmp_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_cmpxf
;
4444 cmp_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_cmptf
;
4446 /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
4447 init_integral_libfuncs (cmp_optab
, "cmp", '2');
4448 init_integral_libfuncs (ucmp_optab
, "ucmp", '2');
4449 init_floating_libfuncs (cmp_optab
, "cmp", '2');
4453 tst_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_tstqi
;
4457 tst_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_tsthi
;
4461 tst_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_tstpsi
;
4465 tst_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_tstsi
;
4469 tst_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_tstdi
;
4473 tst_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_tstti
;
4477 tst_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_tstsf
;
4481 tst_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_tstdf
;
4485 tst_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_tstxf
;
4489 tst_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_tsttf
;
4494 bcc_gen_fctn
[(int) EQ
] = gen_beq
;
4498 bcc_gen_fctn
[(int) NE
] = gen_bne
;
4502 bcc_gen_fctn
[(int) GT
] = gen_bgt
;
4506 bcc_gen_fctn
[(int) GE
] = gen_bge
;
4510 bcc_gen_fctn
[(int) GTU
] = gen_bgtu
;
4514 bcc_gen_fctn
[(int) GEU
] = gen_bgeu
;
4518 bcc_gen_fctn
[(int) LT
] = gen_blt
;
4522 bcc_gen_fctn
[(int) LE
] = gen_ble
;
4526 bcc_gen_fctn
[(int) LTU
] = gen_bltu
;
4530 bcc_gen_fctn
[(int) LEU
] = gen_bleu
;
4533 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
4534 setcc_gen_code
[i
] = CODE_FOR_nothing
;
4538 setcc_gen_code
[(int) EQ
] = CODE_FOR_seq
;
4542 setcc_gen_code
[(int) NE
] = CODE_FOR_sne
;
4546 setcc_gen_code
[(int) GT
] = CODE_FOR_sgt
;
4550 setcc_gen_code
[(int) GE
] = CODE_FOR_sge
;
4554 setcc_gen_code
[(int) GTU
] = CODE_FOR_sgtu
;
4558 setcc_gen_code
[(int) GEU
] = CODE_FOR_sgeu
;
4562 setcc_gen_code
[(int) LT
] = CODE_FOR_slt
;
4566 setcc_gen_code
[(int) LE
] = CODE_FOR_sle
;
4570 setcc_gen_code
[(int) LTU
] = CODE_FOR_sltu
;
4574 setcc_gen_code
[(int) LEU
] = CODE_FOR_sleu
;
4577 extendsfdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extendsfdf2");
4578 extendsfxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extendsfxf2");
4579 extendsftf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extendsftf2");
4580 extenddfxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extenddfxf2");
4581 extenddftf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extenddftf2");
4583 truncdfsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__truncdfsf2");
4584 truncxfsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__truncxfsf2");
4585 trunctfsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__trunctfsf2");
4586 truncxfdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__truncxfdf2");
4587 trunctfdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__trunctfdf2");
4589 memcpy_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "memcpy");
4590 bcopy_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "bcopy");
4591 memcmp_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "memcmp");
4592 bcmp_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "bcmp");
4593 memset_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "memset");
4594 bzero_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "bzero");
4596 eqsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqsf2");
4597 nesf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__nesf2");
4598 gtsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gtsf2");
4599 gesf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gesf2");
4600 ltsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ltsf2");
4601 lesf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__lesf2");
4603 eqdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqdf2");
4604 nedf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__nedf2");
4605 gtdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gtdf2");
4606 gedf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gedf2");
4607 ltdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ltdf2");
4608 ledf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ledf2");
4610 eqxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqxf2");
4611 nexf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__nexf2");
4612 gtxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gtxf2");
4613 gexf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gexf2");
4614 ltxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ltxf2");
4615 lexf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__lexf2");
4617 eqtf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqtf2");
4618 netf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__netf2");
4619 gttf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gttf2");
4620 getf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__getf2");
4621 lttf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__lttf2");
4622 letf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__letf2");
4624 floatsisf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatsisf");
4625 floatdisf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatdisf");
4626 floattisf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floattisf");
4628 floatsidf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatsidf");
4629 floatdidf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatdidf");
4630 floattidf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floattidf");
4632 floatsixf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatsixf");
4633 floatdixf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatdixf");
4634 floattixf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floattixf");
4636 floatsitf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatsitf");
4637 floatditf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatditf");
4638 floattitf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floattitf");
4640 fixsfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixsfsi");
4641 fixsfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixsfdi");
4642 fixsfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixsfti");
4644 fixdfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixdfsi");
4645 fixdfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixdfdi");
4646 fixdfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixdfti");
4648 fixxfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixxfsi");
4649 fixxfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixxfdi");
4650 fixxfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixxfti");
4652 fixtfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixtfsi");
4653 fixtfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixtfdi");
4654 fixtfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixtfti");
4656 fixunssfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunssfsi");
4657 fixunssfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunssfdi");
4658 fixunssfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunssfti");
4660 fixunsdfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsdfsi");
4661 fixunsdfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsdfdi");
4662 fixunsdfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsdfti");
4664 fixunsxfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsxfsi");
4665 fixunsxfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsxfdi");
4666 fixunsxfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsxfti");
4668 fixunstfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunstfsi");
4669 fixunstfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunstfdi");
4670 fixunstfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunstfti");
4675 /* SCO 3.2 apparently has a broken ldexp. */
4688 #endif /* BROKEN_LDEXP */