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
;
80 optab ucmp_optab
; /* Used only for libcalls for unsigned comparisons. */
85 /* SYMBOL_REF rtx's for the library functions that are called
86 implicitly and not via optabs. */
88 rtx extendsfdf2_libfunc
;
89 rtx extendsfxf2_libfunc
;
90 rtx extendsftf2_libfunc
;
91 rtx extenddfxf2_libfunc
;
92 rtx extenddftf2_libfunc
;
94 rtx truncdfsf2_libfunc
;
95 rtx truncxfsf2_libfunc
;
96 rtx trunctfsf2_libfunc
;
97 rtx truncxfdf2_libfunc
;
98 rtx trunctfdf2_libfunc
;
135 rtx floatsisf_libfunc
;
136 rtx floatdisf_libfunc
;
137 rtx floattisf_libfunc
;
139 rtx floatsidf_libfunc
;
140 rtx floatdidf_libfunc
;
141 rtx floattidf_libfunc
;
143 rtx floatsixf_libfunc
;
144 rtx floatdixf_libfunc
;
145 rtx floattixf_libfunc
;
147 rtx floatsitf_libfunc
;
148 rtx floatditf_libfunc
;
149 rtx floattitf_libfunc
;
167 rtx fixunssfsi_libfunc
;
168 rtx fixunssfdi_libfunc
;
169 rtx fixunssfti_libfunc
;
171 rtx fixunsdfsi_libfunc
;
172 rtx fixunsdfdi_libfunc
;
173 rtx fixunsdfti_libfunc
;
175 rtx fixunsxfsi_libfunc
;
176 rtx fixunsxfdi_libfunc
;
177 rtx fixunsxfti_libfunc
;
179 rtx fixunstfsi_libfunc
;
180 rtx fixunstfdi_libfunc
;
181 rtx fixunstfti_libfunc
;
183 /* from emit-rtl.c */
184 extern rtx
gen_highpart ();
186 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
187 gives the gen_function to make a branch to test that condition. */
189 rtxfun bcc_gen_fctn
[NUM_RTX_CODE
];
191 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
192 gives the insn code to make a store-condition insn
193 to test that condition. */
195 enum insn_code setcc_gen_code
[NUM_RTX_CODE
];
197 static void emit_float_lib_cmp ();
199 /* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
200 the result of operation CODE applied to OP0 (and OP1 if it is a binary
203 If the last insn does not set TARGET, don't do anything, but return 1.
205 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
206 don't add the REG_EQUAL note but return 0. Our caller can then try
207 again, ensuring that TARGET is not one of the operands. */
210 add_equal_note (seq
, target
, code
, op0
, op1
)
220 if ((GET_RTX_CLASS (code
) != '1' && GET_RTX_CLASS (code
) != '2'
221 && GET_RTX_CLASS (code
) != 'c' && GET_RTX_CLASS (code
) != '<')
222 || GET_CODE (seq
) != SEQUENCE
223 || (set
= single_set (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1))) == 0
224 || GET_CODE (target
) == ZERO_EXTRACT
225 || (! rtx_equal_p (SET_DEST (set
), target
)
226 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
228 && (GET_CODE (SET_DEST (set
)) != STRICT_LOW_PART
229 || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set
), 0)),
233 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
234 besides the last insn. */
235 if (reg_overlap_mentioned_p (target
, op0
)
236 || (op1
&& reg_overlap_mentioned_p (target
, op1
)))
237 for (i
= XVECLEN (seq
, 0) - 2; i
>= 0; i
--)
238 if (reg_set_p (target
, XVECEXP (seq
, 0, i
)))
241 if (GET_RTX_CLASS (code
) == '1')
242 note
= gen_rtx (code
, GET_MODE (target
), op0
);
244 note
= gen_rtx (code
, GET_MODE (target
), op0
, op1
);
246 REG_NOTES (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1))
247 = gen_rtx (EXPR_LIST
, REG_EQUAL
, note
,
248 REG_NOTES (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1)));
253 /* Generate code to perform an operation specified by BINOPTAB
254 on operands OP0 and OP1, with result having machine-mode MODE.
256 UNSIGNEDP is for the case where we have to widen the operands
257 to perform the operation. It says to use zero-extension.
259 If TARGET is nonzero, the value
260 is generated there, if it is convenient to do so.
261 In all cases an rtx is returned for the locus of the value;
262 this may or may not be TARGET. */
265 expand_binop (mode
, binoptab
, op0
, op1
, target
, unsignedp
, methods
)
266 enum machine_mode mode
;
271 enum optab_methods methods
;
273 enum mode_class
class;
274 enum machine_mode wider_mode
;
276 int commutative_op
= 0;
277 int shift_op
= (binoptab
->code
== ASHIFT
278 || binoptab
->code
== ASHIFTRT
279 || binoptab
->code
== LSHIFT
280 || binoptab
->code
== LSHIFTRT
281 || binoptab
->code
== ROTATE
282 || binoptab
->code
== ROTATERT
);
285 class = GET_MODE_CLASS (mode
);
287 op0
= protect_from_queue (op0
, 0);
288 op1
= protect_from_queue (op1
, 0);
290 target
= protect_from_queue (target
, 1);
294 op0
= force_not_mem (op0
);
295 op1
= force_not_mem (op1
);
298 /* If subtracting an integer constant, convert this into an addition of
299 the negated constant. */
301 if (binoptab
== sub_optab
&& GET_CODE (op1
) == CONST_INT
)
303 op1
= negate_rtx (mode
, op1
);
304 binoptab
= add_optab
;
307 /* If we are inside an appropriately-short loop and one operand is an
308 expensive constant, force it into a register. */
309 if (CONSTANT_P (op0
) && preserve_subexpressions_p ()
310 && rtx_cost (op0
, binoptab
->code
) > 2)
311 op0
= force_reg (mode
, op0
);
313 if (CONSTANT_P (op1
) && preserve_subexpressions_p ()
314 && rtx_cost (op1
, binoptab
->code
) > 2)
315 op1
= force_reg (shift_op
? word_mode
: mode
, op1
);
317 /* Record where to delete back to if we backtrack. */
318 last
= get_last_insn ();
320 /* If operation is commutative,
321 try to make the first operand a register.
322 Even better, try to make it the same as the target.
323 Also try to make the last operand a constant. */
324 if (GET_RTX_CLASS (binoptab
->code
) == 'c'
325 || binoptab
== smul_widen_optab
326 || binoptab
== umul_widen_optab
)
330 if (((target
== 0 || GET_CODE (target
) == REG
)
331 ? ((GET_CODE (op1
) == REG
332 && GET_CODE (op0
) != REG
)
334 : rtx_equal_p (op1
, target
))
335 || GET_CODE (op0
) == CONST_INT
)
343 /* If we can do it with a three-operand insn, do so. */
345 if (methods
!= OPTAB_MUST_WIDEN
346 && binoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
348 int icode
= (int) binoptab
->handlers
[(int) mode
].insn_code
;
349 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
350 enum machine_mode mode1
= insn_operand_mode
[icode
][2];
352 rtx xop0
= op0
, xop1
= op1
;
357 temp
= gen_reg_rtx (mode
);
359 /* If it is a commutative operator and the modes would match
360 if we would swap the operands, we can save the conversions. */
363 if (GET_MODE (op0
) != mode0
&& GET_MODE (op1
) != mode1
364 && GET_MODE (op0
) == mode1
&& GET_MODE (op1
) == mode0
)
368 tmp
= op0
; op0
= op1
; op1
= tmp
;
369 tmp
= xop0
; xop0
= xop1
; xop1
= tmp
;
373 /* In case the insn wants input operands in modes different from
374 the result, convert the operands. */
376 if (GET_MODE (op0
) != VOIDmode
377 && GET_MODE (op0
) != mode0
)
378 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
380 if (GET_MODE (xop1
) != VOIDmode
381 && GET_MODE (xop1
) != mode1
)
382 xop1
= convert_to_mode (mode1
, xop1
, unsignedp
);
384 /* Now, if insn's predicates don't allow our operands, put them into
387 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
388 xop0
= copy_to_mode_reg (mode0
, xop0
);
390 if (! (*insn_operand_predicate
[icode
][2]) (xop1
, mode1
))
391 xop1
= copy_to_mode_reg (mode1
, xop1
);
393 if (! (*insn_operand_predicate
[icode
][0]) (temp
, mode
))
394 temp
= gen_reg_rtx (mode
);
396 pat
= GEN_FCN (icode
) (temp
, xop0
, xop1
);
399 /* If PAT is a multi-insn sequence, try to add an appropriate
400 REG_EQUAL note to it. If we can't because TEMP conflicts with an
401 operand, call ourselves again, this time without a target. */
402 if (GET_CODE (pat
) == SEQUENCE
403 && ! add_equal_note (pat
, temp
, binoptab
->code
, xop0
, xop1
))
405 delete_insns_since (last
);
406 return expand_binop (mode
, binoptab
, op0
, op1
, NULL_RTX
,
414 delete_insns_since (last
);
417 /* If this is a multiply, see if we can do a widening operation that
418 takes operands of this mode and makes a wider mode. */
420 if (binoptab
== smul_optab
&& GET_MODE_WIDER_MODE (mode
) != VOIDmode
421 && (((unsignedp
? umul_widen_optab
: smul_widen_optab
)
422 ->handlers
[(int) GET_MODE_WIDER_MODE (mode
)].insn_code
)
423 != CODE_FOR_nothing
))
425 temp
= expand_binop (GET_MODE_WIDER_MODE (mode
),
426 unsignedp
? umul_widen_optab
: smul_widen_optab
,
427 op0
, op1
, 0, unsignedp
, OPTAB_DIRECT
);
429 if (GET_MODE_CLASS (mode
) == MODE_INT
)
430 return gen_lowpart (mode
, temp
);
432 return convert_to_mode (mode
, temp
, unsignedp
);
435 /* Look for a wider mode of the same class for which we think we
436 can open-code the operation. Check for a widening multiply at the
437 wider mode as well. */
439 if ((class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
440 && methods
!= OPTAB_DIRECT
&& methods
!= OPTAB_LIB
)
441 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
442 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
444 if (binoptab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
445 || (binoptab
== smul_optab
446 && GET_MODE_WIDER_MODE (wider_mode
) != VOIDmode
447 && (((unsignedp
? umul_widen_optab
: smul_widen_optab
)
448 ->handlers
[(int) GET_MODE_WIDER_MODE (wider_mode
)].insn_code
)
449 != CODE_FOR_nothing
)))
451 rtx xop0
= op0
, xop1
= op1
;
454 /* For certain integer operations, we need not actually extend
455 the narrow operands, as long as we will truncate
456 the results to the same narrowness. Don't do this when
457 WIDER_MODE is wider than a word since a paradoxical SUBREG
458 isn't valid for such modes. */
460 if ((binoptab
== ior_optab
|| binoptab
== and_optab
461 || binoptab
== xor_optab
462 || binoptab
== add_optab
|| binoptab
== sub_optab
463 || binoptab
== smul_optab
464 || binoptab
== ashl_optab
|| binoptab
== lshl_optab
)
466 && GET_MODE_SIZE (wider_mode
) <= UNITS_PER_WORD
)
469 /* If an operand is a constant integer, we might as well
470 convert it since that is more efficient than using a SUBREG,
471 unlike the case for other operands. Similarly for
472 SUBREGs that were made due to promoted objects. */
474 if (no_extend
&& GET_MODE (xop0
) != VOIDmode
475 && ! (GET_CODE (xop0
) == SUBREG
476 && SUBREG_PROMOTED_VAR_P (xop0
)))
477 xop0
= gen_rtx (SUBREG
, wider_mode
,
478 force_reg (GET_MODE (xop0
), xop0
), 0);
480 xop0
= convert_to_mode (wider_mode
, xop0
, unsignedp
);
482 if (no_extend
&& GET_MODE (xop1
) != VOIDmode
483 && ! (GET_CODE (xop1
) == SUBREG
484 && SUBREG_PROMOTED_VAR_P (xop1
)))
485 xop1
= gen_rtx (SUBREG
, wider_mode
,
486 force_reg (GET_MODE (xop1
), xop1
), 0);
488 xop1
= convert_to_mode (wider_mode
, xop1
, unsignedp
);
490 temp
= expand_binop (wider_mode
, binoptab
, xop0
, xop1
, NULL_RTX
,
491 unsignedp
, OPTAB_DIRECT
);
494 if (class != MODE_INT
)
497 target
= gen_reg_rtx (mode
);
498 convert_move (target
, temp
, 0);
502 return gen_lowpart (mode
, temp
);
505 delete_insns_since (last
);
509 /* These can be done a word at a time. */
510 if ((binoptab
== and_optab
|| binoptab
== ior_optab
|| binoptab
== xor_optab
)
512 && GET_MODE_SIZE (mode
) > UNITS_PER_WORD
513 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
519 /* If TARGET is the same as one of the operands, the REG_EQUAL note
520 won't be accurate, so use a new target. */
521 if (target
== 0 || target
== op0
|| target
== op1
)
522 target
= gen_reg_rtx (mode
);
526 /* Do the actual arithmetic. */
527 for (i
= 0; i
< GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
; i
++)
529 rtx target_piece
= operand_subword (target
, i
, 1, mode
);
530 rtx x
= expand_binop (word_mode
, binoptab
,
531 operand_subword_force (op0
, i
, mode
),
532 operand_subword_force (op1
, i
, mode
),
533 target_piece
, unsignedp
, methods
);
534 if (target_piece
!= x
)
535 emit_move_insn (target_piece
, x
);
538 insns
= get_insns ();
541 if (binoptab
->code
!= UNKNOWN
)
542 equiv_value
= gen_rtx (binoptab
->code
, mode
, op0
, op1
);
546 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv_value
);
550 /* These can be done a word at a time by propagating carries. */
551 if ((binoptab
== add_optab
|| binoptab
== sub_optab
)
553 && GET_MODE_SIZE (mode
) >= 2 * UNITS_PER_WORD
554 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
557 rtx carry_tmp
= gen_reg_rtx (word_mode
);
558 optab otheroptab
= binoptab
== add_optab
? sub_optab
: add_optab
;
559 int nwords
= GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
;
560 rtx carry_in
, carry_out
;
562 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
563 value is one of those, use it. Otherwise, use 1 since it is the
564 one easiest to get. */
565 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
566 int normalizep
= STORE_FLAG_VALUE
;
571 /* Prepare the operands. */
572 op0
= force_reg (mode
, op0
);
573 op1
= force_reg (mode
, op1
);
575 if (target
== 0 || GET_CODE (target
) != REG
576 || target
== op0
|| target
== op1
)
577 target
= gen_reg_rtx (mode
);
579 /* Do the actual arithmetic. */
580 for (i
= 0; i
< nwords
; i
++)
582 int index
= (WORDS_BIG_ENDIAN
? nwords
- i
- 1 : i
);
583 rtx target_piece
= operand_subword (target
, index
, 1, mode
);
584 rtx op0_piece
= operand_subword_force (op0
, index
, mode
);
585 rtx op1_piece
= operand_subword_force (op1
, index
, mode
);
588 /* Main add/subtract of the input operands. */
589 x
= expand_binop (word_mode
, binoptab
,
590 op0_piece
, op1_piece
,
591 target_piece
, unsignedp
, methods
);
597 /* Store carry from main add/subtract. */
598 carry_out
= gen_reg_rtx (word_mode
);
599 carry_out
= emit_store_flag (carry_out
,
600 binoptab
== add_optab
? LTU
: GTU
,
602 word_mode
, 1, normalizep
);
609 /* Add/subtract previous carry to main result. */
610 x
= expand_binop (word_mode
,
611 normalizep
== 1 ? binoptab
: otheroptab
,
613 target_piece
, 1, methods
);
614 if (target_piece
!= x
)
615 emit_move_insn (target_piece
, x
);
619 /* THIS CODE HAS NOT BEEN TESTED. */
620 /* Get out carry from adding/subtracting carry in. */
621 carry_tmp
= emit_store_flag (carry_tmp
,
622 binoptab
== add_optab
625 word_mode
, 1, normalizep
);
626 /* Logical-ior the two poss. carry together. */
627 carry_out
= expand_binop (word_mode
, ior_optab
,
628 carry_out
, carry_tmp
,
629 carry_out
, 0, methods
);
635 carry_in
= carry_out
;
638 if (i
== GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
)
642 temp
= emit_move_insn (target
, target
);
643 REG_NOTES (temp
) = gen_rtx (EXPR_LIST
, REG_EQUAL
,
644 gen_rtx (binoptab
->code
, mode
, op0
, op1
),
649 delete_insns_since (last
);
652 /* If we want to multiply two two-word values and have normal and widening
653 multiplies of single-word values, we can do this with three smaller
654 multiplications. Note that we do not make a REG_NO_CONFLICT block here
655 because we are not operating on one word at a time.
657 The multiplication proceeds as follows:
658 _______________________
659 [__op0_high_|__op0_low__]
660 _______________________
661 * [__op1_high_|__op1_low__]
662 _______________________________________________
663 _______________________
664 (1) [__op0_low__*__op1_low__]
665 _______________________
666 (2a) [__op0_low__*__op1_high_]
667 _______________________
668 (2b) [__op0_high_*__op1_low__]
669 _______________________
670 (3) [__op0_high_*__op1_high_]
673 This gives a 4-word result. Since we are only interested in the
674 lower 2 words, partial result (3) and the upper words of (2a) and
675 (2b) don't need to be calculated. Hence (2a) and (2b) can be
676 calculated using non-widening multiplication.
678 (1), however, needs to be calculated with an unsigned widening
679 multiplication. If this operation is not directly supported we
680 try using a signed widening multiplication and adjust the result.
681 This adjustment works as follows:
683 If both operands are positive then no adjustment is needed.
685 If the operands have different signs, for example op0_low < 0 and
686 op1_low >= 0, the instruction treats the most significant bit of
687 op0_low as a sign bit instead of a bit with significance
688 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
689 with 2**BITS_PER_WORD - op0_low, and two's complements the
690 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
693 Similarly, if both operands are negative, we need to add
694 (op0_low + op1_low) * 2**BITS_PER_WORD.
696 We use a trick to adjust quickly. We logically shift op0_low right
697 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
698 op0_high (op1_high) before it is used to calculate 2b (2a). If no
699 logical shift exists, we do an arithmetic right shift and subtract
702 if (binoptab
== smul_optab
704 && GET_MODE_SIZE (mode
) == 2 * UNITS_PER_WORD
705 && smul_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
706 && add_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
707 && ((umul_widen_optab
->handlers
[(int) mode
].insn_code
709 || (smul_widen_optab
->handlers
[(int) mode
].insn_code
710 != CODE_FOR_nothing
)))
712 int low
= (WORDS_BIG_ENDIAN
? 1 : 0);
713 int high
= (WORDS_BIG_ENDIAN
? 0 : 1);
714 rtx op0_high
= operand_subword_force (op0
, high
, mode
);
715 rtx op0_low
= operand_subword_force (op0
, low
, mode
);
716 rtx op1_high
= operand_subword_force (op1
, high
, mode
);
717 rtx op1_low
= operand_subword_force (op1
, low
, mode
);
722 /* If the target is the same as one of the inputs, don't use it. This
723 prevents problems with the REG_EQUAL note. */
724 if (target
== op0
|| target
== op1
)
727 /* Multiply the two lower words to get a double-word product.
728 If unsigned widening multiplication is available, use that;
729 otherwise use the signed form and compensate. */
731 if (umul_widen_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
733 product
= expand_binop (mode
, umul_widen_optab
, op0_low
, op1_low
,
734 target
, 1, OPTAB_DIRECT
);
736 /* If we didn't succeed, delete everything we did so far. */
738 delete_insns_since (last
);
740 op0_xhigh
= op0_high
, op1_xhigh
= op1_high
;
744 && smul_widen_optab
->handlers
[(int) mode
].insn_code
747 rtx wordm1
= GEN_INT (BITS_PER_WORD
- 1);
748 product
= expand_binop (mode
, smul_widen_optab
, op0_low
, op1_low
,
749 target
, 1, OPTAB_DIRECT
);
750 op0_xhigh
= expand_binop (word_mode
, lshr_optab
, op0_low
, wordm1
,
751 NULL_RTX
, 1, OPTAB_DIRECT
);
753 op0_xhigh
= expand_binop (word_mode
, add_optab
, op0_high
,
754 op0_xhigh
, op0_xhigh
, 0, OPTAB_DIRECT
);
757 op0_xhigh
= expand_binop (word_mode
, ashr_optab
, op0_low
, wordm1
,
758 NULL_RTX
, 0, OPTAB_DIRECT
);
760 op0_xhigh
= expand_binop (word_mode
, sub_optab
, op0_high
,
761 op0_xhigh
, op0_xhigh
, 0,
765 op1_xhigh
= expand_binop (word_mode
, lshr_optab
, op1_low
, wordm1
,
766 NULL_RTX
, 1, OPTAB_DIRECT
);
768 op1_xhigh
= expand_binop (word_mode
, add_optab
, op1_high
,
769 op1_xhigh
, op1_xhigh
, 0, OPTAB_DIRECT
);
772 op1_xhigh
= expand_binop (word_mode
, ashr_optab
, op1_low
, wordm1
,
773 NULL_RTX
, 0, OPTAB_DIRECT
);
775 op1_xhigh
= expand_binop (word_mode
, sub_optab
, op1_high
,
776 op1_xhigh
, op1_xhigh
, 0,
781 /* If we have been able to directly compute the product of the
782 low-order words of the operands and perform any required adjustments
783 of the operands, we proceed by trying two more multiplications
784 and then computing the appropriate sum.
786 We have checked above that the required addition is provided.
787 Full-word addition will normally always succeed, especially if
788 it is provided at all, so we don't worry about its failure. The
789 multiplication may well fail, however, so we do handle that. */
791 if (product
&& op0_xhigh
&& op1_xhigh
)
794 rtx product_high
= operand_subword (product
, high
, 1, mode
);
795 rtx temp
= expand_binop (word_mode
, binoptab
, op0_low
, op1_xhigh
,
796 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
= expand_binop (word_mode
, binoptab
, op1_low
, op0_xhigh
,
807 NULL_RTX
, 0, OPTAB_DIRECT
);
809 product_piece
= expand_binop (word_mode
, add_optab
, temp
,
810 product_high
, product_high
,
812 if (product_piece
!= product_high
)
813 emit_move_insn (product_high
, product_piece
);
815 temp
= emit_move_insn (product
, product
);
816 REG_NOTES (temp
) = gen_rtx (EXPR_LIST
, REG_EQUAL
,
817 gen_rtx (MULT
, mode
, op0
, op1
),
824 /* If we get here, we couldn't do it for some reason even though we
825 originally thought we could. Delete anything we've emitted in
828 delete_insns_since (last
);
831 /* We need to open-code the complex type operations: '+, -, * and /' */
833 /* At this point we allow operations between two similar complex
834 numbers, and also if one of the operands is not a complex number
835 but rather of MODE_FLOAT or MODE_INT. However, the caller
836 must make sure that the MODE of the non-complex operand matches
837 the SUBMODE of the complex operand. */
839 if (class == MODE_COMPLEX_FLOAT
|| class == MODE_COMPLEX_INT
)
851 /* Find the correct mode for the real and imaginary parts */
852 enum machine_mode submode
853 = mode_for_size (GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
,
854 class == MODE_COMPLEX_INT
? MODE_INT
: MODE_FLOAT
,
857 if (submode
== BLKmode
)
861 target
= gen_reg_rtx (mode
);
865 realr
= gen_realpart (submode
, target
);
866 imagr
= gen_imagpart (submode
, target
);
868 if (GET_MODE (op0
) == mode
)
870 real0
= gen_realpart (submode
, op0
);
871 imag0
= gen_imagpart (submode
, op0
);
876 if (GET_MODE (op1
) == mode
)
878 real1
= gen_realpart (submode
, op1
);
879 imag1
= gen_imagpart (submode
, op1
);
884 if (! real0
|| ! real1
|| ! (imag0
|| imag1
))
887 switch (binoptab
->code
)
891 res
= expand_binop (submode
, binoptab
, real0
, real1
,
892 realr
, unsignedp
, methods
);
894 emit_move_insn (realr
, res
);
897 res
= expand_binop (submode
, binoptab
, imag0
, imag1
,
898 imagr
, unsignedp
, methods
);
901 else if (binoptab
->code
== MINUS
)
902 res
= expand_unop (submode
, neg_optab
, imag1
, imagr
, unsignedp
);
907 emit_move_insn (imagr
, res
);
911 /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */
913 res
= expand_binop (submode
, binoptab
, real0
, real1
,
914 realr
, unsignedp
, methods
);
919 expand_binop (submode
, sub_optab
, res
,
920 expand_binop (submode
, binoptab
, imag0
, imag1
,
921 0, unsignedp
, methods
),
922 realr
, unsignedp
, methods
);
925 emit_move_insn (realr
, temp
);
927 res
= expand_binop (submode
, add_optab
,
928 expand_binop (submode
, binoptab
,
930 0, unsignedp
, methods
),
931 expand_binop (submode
, binoptab
,
933 0, unsignedp
, methods
),
934 imagr
, unsignedp
, methods
);
936 emit_move_insn (imagr
, res
);
941 emit_move_insn (realr
, res
);
944 res
= expand_binop (submode
, binoptab
,
945 real1
, imag0
, imagr
, unsignedp
, methods
);
947 res
= expand_binop (submode
, binoptab
,
948 real0
, imag1
, imagr
, unsignedp
, methods
);
950 emit_move_insn (imagr
, res
);
955 /* (c+id)/(a+ib) == ((c+id)*(a-ib))/(a*a+b*b) */
959 /* Simply divide the real and imaginary parts by `a' */
960 res
= expand_binop (submode
, binoptab
, real0
, real1
,
961 realr
, unsignedp
, methods
);
963 emit_move_insn (realr
, res
);
965 res
= expand_binop (submode
, binoptab
, imag0
, real1
,
966 imagr
, unsignedp
, methods
);
968 emit_move_insn (imagr
, res
);
970 else /* Divider is of complex type */
977 optab mulopt
= unsignedp
? umul_widen_optab
: smul_optab
;
979 /* Divider: a*a + b*b */
980 divider
= expand_binop (submode
, add_optab
,
981 expand_binop (submode
, mulopt
,
983 0, unsignedp
, methods
),
984 expand_binop (submode
, mulopt
,
986 0, unsignedp
, methods
),
987 0, unsignedp
, methods
);
989 if (! imag0
) /* ((c)(a-ib))/divider */
991 /* Calculate the divident */
992 real_t
= expand_binop (submode
, mulopt
, real0
, real1
,
993 0, unsignedp
, methods
);
996 = expand_unop (submode
, neg_optab
,
997 expand_binop (submode
, mulopt
, real0
, imag1
,
998 0, unsignedp
, methods
),
1001 else /* ((c+id)(a-ib))/divider */
1003 /* Calculate the divident */
1004 real_t
= expand_binop (submode
, add_optab
,
1005 expand_binop (submode
, mulopt
,
1007 0, unsignedp
, methods
),
1008 expand_binop (submode
, mulopt
,
1010 0, unsignedp
, methods
),
1011 0, unsignedp
, methods
);
1013 imag_t
= expand_binop (submode
, sub_optab
,
1014 expand_binop (submode
, mulopt
,
1016 0, unsignedp
, methods
),
1017 expand_binop (submode
, mulopt
,
1019 0, unsignedp
, methods
),
1020 0, unsignedp
, methods
);
1024 res
= expand_binop (submode
, binoptab
, real_t
, divider
,
1025 realr
, unsignedp
, methods
);
1027 emit_move_insn (realr
, res
);
1029 res
= expand_binop (submode
, binoptab
, imag_t
, divider
,
1030 imagr
, unsignedp
, methods
);
1032 emit_move_insn (imagr
, res
);
1043 if (binoptab
->code
!= UNKNOWN
)
1044 equiv_value
= gen_rtx (binoptab
->code
, mode
, op0
, op1
);
1048 emit_no_conflict_block (seq
, target
, op0
, op1
, equiv_value
);
1053 /* It can't be open-coded in this mode.
1054 Use a library call if one is available and caller says that's ok. */
1056 if (binoptab
->handlers
[(int) mode
].libfunc
1057 && (methods
== OPTAB_LIB
|| methods
== OPTAB_LIB_WIDEN
))
1060 rtx funexp
= binoptab
->handlers
[(int) mode
].libfunc
;
1062 enum machine_mode op1_mode
= mode
;
1068 op1_mode
= word_mode
;
1069 /* Specify unsigned here,
1070 since negative shift counts are meaningless. */
1071 op1x
= convert_to_mode (word_mode
, op1
, 1);
1074 /* Pass 1 for NO_QUEUE so we don't lose any increments
1075 if the libcall is cse'd or moved. */
1076 emit_library_call (binoptab
->handlers
[(int) mode
].libfunc
,
1077 1, mode
, 2, op0
, mode
, op1x
, op1_mode
);
1079 insns
= get_insns ();
1082 target
= gen_reg_rtx (mode
);
1083 emit_libcall_block (insns
, target
, hard_libcall_value (mode
),
1084 gen_rtx (binoptab
->code
, mode
, op0
, op1
));
1089 delete_insns_since (last
);
1091 /* It can't be done in this mode. Can we do it in a wider mode? */
1093 if (! (methods
== OPTAB_WIDEN
|| methods
== OPTAB_LIB_WIDEN
1094 || methods
== OPTAB_MUST_WIDEN
))
1095 return 0; /* Caller says, don't even try. */
1097 /* Compute the value of METHODS to pass to recursive calls.
1098 Don't allow widening to be tried recursively. */
1100 methods
= (methods
== OPTAB_LIB_WIDEN
? OPTAB_LIB
: OPTAB_DIRECT
);
1102 /* Look for a wider mode of the same class for which it appears we can do
1105 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1107 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1108 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1110 if ((binoptab
->handlers
[(int) wider_mode
].insn_code
1111 != CODE_FOR_nothing
)
1112 || (methods
== OPTAB_LIB
1113 && binoptab
->handlers
[(int) wider_mode
].libfunc
))
1115 rtx xop0
= op0
, xop1
= op1
;
1118 /* For certain integer operations, we need not actually extend
1119 the narrow operands, as long as we will truncate
1120 the results to the same narrowness. Don't do this when
1121 WIDER_MODE is wider than a word since a paradoxical SUBREG
1122 isn't valid for such modes. */
1124 if ((binoptab
== ior_optab
|| binoptab
== and_optab
1125 || binoptab
== xor_optab
1126 || binoptab
== add_optab
|| binoptab
== sub_optab
1127 || binoptab
== smul_optab
1128 || binoptab
== ashl_optab
|| binoptab
== lshl_optab
)
1129 && class == MODE_INT
1130 && GET_MODE_SIZE (wider_mode
) <= UNITS_PER_WORD
)
1133 /* If an operand is a constant integer, we might as well
1134 convert it since that is more efficient than using a SUBREG,
1135 unlike the case for other operands. Similarly for
1136 SUBREGs that were made due to promoted objects.*/
1138 if (no_extend
&& GET_MODE (xop0
) != VOIDmode
1139 && ! (GET_CODE (xop0
) == SUBREG
1140 && SUBREG_PROMOTED_VAR_P (xop0
)))
1141 xop0
= gen_rtx (SUBREG
, wider_mode
,
1142 force_reg (GET_MODE (xop0
), xop0
), 0);
1144 xop0
= convert_to_mode (wider_mode
, xop0
, unsignedp
);
1146 if (no_extend
&& GET_MODE (xop1
) != VOIDmode
1147 && ! (GET_CODE (xop1
) == SUBREG
1148 && SUBREG_PROMOTED_VAR_P (xop1
)))
1149 xop1
= gen_rtx (SUBREG
, wider_mode
,
1150 force_reg (GET_MODE (xop1
), xop1
), 0);
1152 xop1
= convert_to_mode (wider_mode
, xop1
, unsignedp
);
1154 temp
= expand_binop (wider_mode
, binoptab
, xop0
, xop1
, NULL_RTX
,
1155 unsignedp
, methods
);
1158 if (class != MODE_INT
)
1161 target
= gen_reg_rtx (mode
);
1162 convert_move (target
, temp
, 0);
1166 return gen_lowpart (mode
, temp
);
1169 delete_insns_since (last
);
1177 /* Expand a binary operator which has both signed and unsigned forms.
1178 UOPTAB is the optab for unsigned operations, and SOPTAB is for
1181 If we widen unsigned operands, we may use a signed wider operation instead
1182 of an unsigned wider operation, since the result would be the same. */
1185 sign_expand_binop (mode
, uoptab
, soptab
, op0
, op1
, target
, unsignedp
, methods
)
1186 enum machine_mode mode
;
1187 optab uoptab
, soptab
;
1188 rtx op0
, op1
, target
;
1190 enum optab_methods methods
;
1193 optab direct_optab
= unsignedp
? uoptab
: soptab
;
1194 struct optab wide_soptab
;
1196 /* Do it without widening, if possible. */
1197 temp
= expand_binop (mode
, direct_optab
, op0
, op1
, target
,
1198 unsignedp
, OPTAB_DIRECT
);
1199 if (temp
|| methods
== OPTAB_DIRECT
)
1202 /* Try widening to a signed int. Make a fake signed optab that
1203 hides any signed insn for direct use. */
1204 wide_soptab
= *soptab
;
1205 wide_soptab
.handlers
[(int) mode
].insn_code
= CODE_FOR_nothing
;
1206 wide_soptab
.handlers
[(int) mode
].libfunc
= 0;
1208 temp
= expand_binop (mode
, &wide_soptab
, op0
, op1
, target
,
1209 unsignedp
, OPTAB_WIDEN
);
1211 /* For unsigned operands, try widening to an unsigned int. */
1212 if (temp
== 0 && unsignedp
)
1213 temp
= expand_binop (mode
, uoptab
, op0
, op1
, target
,
1214 unsignedp
, OPTAB_WIDEN
);
1215 if (temp
|| methods
== OPTAB_WIDEN
)
1218 /* Use the right width lib call if that exists. */
1219 temp
= expand_binop (mode
, direct_optab
, op0
, op1
, target
, unsignedp
, OPTAB_LIB
);
1220 if (temp
|| methods
== OPTAB_LIB
)
1223 /* Must widen and use a lib call, use either signed or unsigned. */
1224 temp
= expand_binop (mode
, &wide_soptab
, op0
, op1
, target
,
1225 unsignedp
, methods
);
1229 return expand_binop (mode
, uoptab
, op0
, op1
, target
,
1230 unsignedp
, methods
);
1234 /* Generate code to perform an operation specified by BINOPTAB
1235 on operands OP0 and OP1, with two results to TARG1 and TARG2.
1236 We assume that the order of the operands for the instruction
1237 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
1238 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
1240 Either TARG0 or TARG1 may be zero, but what that means is that
1241 that result is not actually wanted. We will generate it into
1242 a dummy pseudo-reg and discard it. They may not both be zero.
1244 Returns 1 if this operation can be performed; 0 if not. */
1247 expand_twoval_binop (binoptab
, op0
, op1
, targ0
, targ1
, unsignedp
)
1253 enum machine_mode mode
= GET_MODE (targ0
? targ0
: targ1
);
1254 enum mode_class
class;
1255 enum machine_mode wider_mode
;
1258 class = GET_MODE_CLASS (mode
);
1260 op0
= protect_from_queue (op0
, 0);
1261 op1
= protect_from_queue (op1
, 0);
1265 op0
= force_not_mem (op0
);
1266 op1
= force_not_mem (op1
);
1269 /* If we are inside an appropriately-short loop and one operand is an
1270 expensive constant, force it into a register. */
1271 if (CONSTANT_P (op0
) && preserve_subexpressions_p ()
1272 && rtx_cost (op0
, binoptab
->code
) > 2)
1273 op0
= force_reg (mode
, op0
);
1275 if (CONSTANT_P (op1
) && preserve_subexpressions_p ()
1276 && rtx_cost (op1
, binoptab
->code
) > 2)
1277 op1
= force_reg (mode
, op1
);
1280 targ0
= protect_from_queue (targ0
, 1);
1282 targ0
= gen_reg_rtx (mode
);
1284 targ1
= protect_from_queue (targ1
, 1);
1286 targ1
= gen_reg_rtx (mode
);
1288 /* Record where to go back to if we fail. */
1289 last
= get_last_insn ();
1291 if (binoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1293 int icode
= (int) binoptab
->handlers
[(int) mode
].insn_code
;
1294 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
1295 enum machine_mode mode1
= insn_operand_mode
[icode
][2];
1297 rtx xop0
= op0
, xop1
= op1
;
1299 /* In case this insn wants input operands in modes different from the
1300 result, convert the operands. */
1301 if (GET_MODE (op0
) != VOIDmode
&& GET_MODE (op0
) != mode0
)
1302 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
1304 if (GET_MODE (op1
) != VOIDmode
&& GET_MODE (op1
) != mode1
)
1305 xop1
= convert_to_mode (mode1
, xop1
, unsignedp
);
1307 /* Now, if insn doesn't accept these operands, put them into pseudos. */
1308 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
1309 xop0
= copy_to_mode_reg (mode0
, xop0
);
1311 if (! (*insn_operand_predicate
[icode
][2]) (xop1
, mode1
))
1312 xop1
= copy_to_mode_reg (mode1
, xop1
);
1314 /* We could handle this, but we should always be called with a pseudo
1315 for our targets and all insns should take them as outputs. */
1316 if (! (*insn_operand_predicate
[icode
][0]) (targ0
, mode
)
1317 || ! (*insn_operand_predicate
[icode
][3]) (targ1
, mode
))
1320 pat
= GEN_FCN (icode
) (targ0
, xop0
, xop1
, targ1
);
1327 delete_insns_since (last
);
1330 /* It can't be done in this mode. Can we do it in a wider mode? */
1332 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1334 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1335 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1337 if (binoptab
->handlers
[(int) wider_mode
].insn_code
1338 != CODE_FOR_nothing
)
1340 register rtx t0
= gen_reg_rtx (wider_mode
);
1341 register rtx t1
= gen_reg_rtx (wider_mode
);
1343 if (expand_twoval_binop (binoptab
,
1344 convert_to_mode (wider_mode
, op0
,
1346 convert_to_mode (wider_mode
, op1
,
1350 convert_move (targ0
, t0
, unsignedp
);
1351 convert_move (targ1
, t1
, unsignedp
);
1355 delete_insns_since (last
);
1363 /* Generate code to perform an operation specified by UNOPTAB
1364 on operand OP0, with result having machine-mode MODE.
1366 UNSIGNEDP is for the case where we have to widen the operands
1367 to perform the operation. It says to use zero-extension.
1369 If TARGET is nonzero, the value
1370 is generated there, if it is convenient to do so.
1371 In all cases an rtx is returned for the locus of the value;
1372 this may or may not be TARGET. */
1375 expand_unop (mode
, unoptab
, op0
, target
, unsignedp
)
1376 enum machine_mode mode
;
1382 enum mode_class
class;
1383 enum machine_mode wider_mode
;
1385 rtx last
= get_last_insn ();
1388 class = GET_MODE_CLASS (mode
);
1390 op0
= protect_from_queue (op0
, 0);
1394 op0
= force_not_mem (op0
);
1398 target
= protect_from_queue (target
, 1);
1400 if (unoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1402 int icode
= (int) unoptab
->handlers
[(int) mode
].insn_code
;
1403 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
1409 temp
= gen_reg_rtx (mode
);
1411 if (GET_MODE (xop0
) != VOIDmode
1412 && GET_MODE (xop0
) != mode0
)
1413 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
1415 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
1417 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
1418 xop0
= copy_to_mode_reg (mode0
, xop0
);
1420 if (! (*insn_operand_predicate
[icode
][0]) (temp
, mode
))
1421 temp
= gen_reg_rtx (mode
);
1423 pat
= GEN_FCN (icode
) (temp
, xop0
);
1426 if (GET_CODE (pat
) == SEQUENCE
1427 && ! add_equal_note (pat
, temp
, unoptab
->code
, xop0
, NULL_RTX
))
1429 delete_insns_since (last
);
1430 return expand_unop (mode
, unoptab
, op0
, NULL_RTX
, unsignedp
);
1438 delete_insns_since (last
);
1441 /* It can't be done in this mode. Can we open-code it in a wider mode? */
1443 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1444 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1445 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1447 if (unoptab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
)
1451 /* For certain operations, we need not actually extend
1452 the narrow operand, as long as we will truncate the
1453 results to the same narrowness. But it is faster to
1454 convert a SUBREG due to mode promotion. */
1456 if ((unoptab
== neg_optab
|| unoptab
== one_cmpl_optab
)
1457 && GET_MODE_SIZE (wider_mode
) <= UNITS_PER_WORD
1458 && class == MODE_INT
1459 && ! (GET_CODE (xop0
) == SUBREG
1460 && SUBREG_PROMOTED_VAR_P (xop0
)))
1461 xop0
= gen_rtx (SUBREG
, wider_mode
, force_reg (mode
, xop0
), 0);
1463 xop0
= convert_to_mode (wider_mode
, xop0
, unsignedp
);
1465 temp
= expand_unop (wider_mode
, unoptab
, xop0
, NULL_RTX
,
1470 if (class != MODE_INT
)
1473 target
= gen_reg_rtx (mode
);
1474 convert_move (target
, temp
, 0);
1478 return gen_lowpart (mode
, temp
);
1481 delete_insns_since (last
);
1485 /* These can be done a word at a time. */
1486 if (unoptab
== one_cmpl_optab
1487 && class == MODE_INT
1488 && GET_MODE_SIZE (mode
) > UNITS_PER_WORD
1489 && unoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
1494 if (target
== 0 || target
== op0
)
1495 target
= gen_reg_rtx (mode
);
1499 /* Do the actual arithmetic. */
1500 for (i
= 0; i
< GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
; i
++)
1502 rtx target_piece
= operand_subword (target
, i
, 1, mode
);
1503 rtx x
= expand_unop (word_mode
, unoptab
,
1504 operand_subword_force (op0
, i
, mode
),
1505 target_piece
, unsignedp
);
1506 if (target_piece
!= x
)
1507 emit_move_insn (target_piece
, x
);
1510 insns
= get_insns ();
1513 emit_no_conflict_block (insns
, target
, op0
, NULL_RTX
,
1514 gen_rtx (unoptab
->code
, mode
, op0
));
1518 /* Open-code the complex negation operation. */
1519 else if (unoptab
== neg_optab
1520 && (class == MODE_COMPLEX_FLOAT
|| class == MODE_COMPLEX_INT
))
1526 /* Find the correct mode for the real and imaginary parts */
1527 enum machine_mode submode
1528 = mode_for_size (GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
,
1529 class == MODE_COMPLEX_INT
? MODE_INT
: MODE_FLOAT
,
1532 if (submode
== BLKmode
)
1536 target
= gen_reg_rtx (mode
);
1540 target_piece
= gen_imagpart (submode
, target
);
1541 x
= expand_unop (submode
, unoptab
,
1542 gen_imagpart (submode
, op0
),
1543 target_piece
, unsignedp
);
1544 if (target_piece
!= x
)
1545 emit_move_insn (target_piece
, x
);
1547 target_piece
= gen_realpart (submode
, target
);
1548 x
= expand_unop (submode
, unoptab
,
1549 gen_realpart (submode
, op0
),
1550 target_piece
, unsignedp
);
1551 if (target_piece
!= x
)
1552 emit_move_insn (target_piece
, x
);
1554 seq
= gen_sequence ();
1557 emit_no_conflict_block (seq
, target
, op0
, 0,
1558 gen_rtx (unoptab
->code
, mode
, op0
));
1562 /* Now try a library call in this mode. */
1563 if (unoptab
->handlers
[(int) mode
].libfunc
)
1566 rtx funexp
= unoptab
->handlers
[(int) mode
].libfunc
;
1570 /* Pass 1 for NO_QUEUE so we don't lose any increments
1571 if the libcall is cse'd or moved. */
1572 emit_library_call (unoptab
->handlers
[(int) mode
].libfunc
,
1573 1, mode
, 1, op0
, mode
);
1574 insns
= get_insns ();
1577 target
= gen_reg_rtx (mode
);
1578 emit_libcall_block (insns
, target
, hard_libcall_value (mode
),
1579 gen_rtx (unoptab
->code
, mode
, op0
));
1584 /* It can't be done in this mode. Can we do it in a wider mode? */
1586 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1588 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1589 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1591 if ((unoptab
->handlers
[(int) wider_mode
].insn_code
1592 != CODE_FOR_nothing
)
1593 || unoptab
->handlers
[(int) wider_mode
].libfunc
)
1597 /* For certain operations, we need not actually extend
1598 the narrow operand, as long as we will truncate the
1599 results to the same narrowness. */
1601 if ((unoptab
== neg_optab
|| unoptab
== one_cmpl_optab
)
1602 && GET_MODE_SIZE (wider_mode
) <= UNITS_PER_WORD
1603 && class == MODE_INT
1604 && ! (GET_CODE (xop0
) == SUBREG
1605 && SUBREG_PROMOTED_VAR_P (xop0
)))
1606 xop0
= gen_rtx (SUBREG
, wider_mode
, force_reg (mode
, xop0
), 0);
1608 xop0
= convert_to_mode (wider_mode
, xop0
, unsignedp
);
1610 temp
= expand_unop (wider_mode
, unoptab
, xop0
, NULL_RTX
,
1615 if (class != MODE_INT
)
1618 target
= gen_reg_rtx (mode
);
1619 convert_move (target
, temp
, 0);
1623 return gen_lowpart (mode
, temp
);
1626 delete_insns_since (last
);
1634 /* Emit code to compute the absolute value of OP0, with result to
1635 TARGET if convenient. (TARGET may be 0.) The return value says
1636 where the result actually is to be found.
1638 MODE is the mode of the operand; the mode of the result is
1639 different but can be deduced from MODE.
1641 UNSIGNEDP is relevant for complex integer modes. */
1644 expand_complex_abs (mode
, op0
, target
, unsignedp
)
1645 enum machine_mode mode
;
1650 enum mode_class
class = GET_MODE_CLASS (mode
);
1651 enum machine_mode wider_mode
;
1653 rtx last
= get_last_insn ();
1656 /* Find the correct mode for the real and imaginary parts. */
1657 enum machine_mode submode
1658 = mode_for_size (GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
,
1659 class == MODE_COMPLEX_INT
? MODE_INT
: MODE_FLOAT
,
1662 if (submode
== BLKmode
)
1665 op0
= protect_from_queue (op0
, 0);
1669 op0
= force_not_mem (op0
);
1673 target
= protect_from_queue (target
, 1);
1675 if (abs_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1677 int icode
= (int) abs_optab
->handlers
[(int) mode
].insn_code
;
1678 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
1684 temp
= gen_reg_rtx (submode
);
1686 if (GET_MODE (xop0
) != VOIDmode
1687 && GET_MODE (xop0
) != mode0
)
1688 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
1690 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
1692 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
1693 xop0
= copy_to_mode_reg (mode0
, xop0
);
1695 if (! (*insn_operand_predicate
[icode
][0]) (temp
, submode
))
1696 temp
= gen_reg_rtx (submode
);
1698 pat
= GEN_FCN (icode
) (temp
, xop0
);
1701 if (GET_CODE (pat
) == SEQUENCE
1702 && ! add_equal_note (pat
, temp
, abs_optab
->code
, xop0
, NULL_RTX
))
1704 delete_insns_since (last
);
1705 return expand_unop (mode
, abs_optab
, op0
, NULL_RTX
, unsignedp
);
1713 delete_insns_since (last
);
1716 /* It can't be done in this mode. Can we open-code it in a wider mode? */
1718 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1719 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1721 if (abs_optab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
)
1725 xop0
= convert_to_mode (wider_mode
, xop0
, unsignedp
);
1726 temp
= expand_complex_abs (wider_mode
, xop0
, NULL_RTX
, unsignedp
);
1730 if (class != MODE_COMPLEX_INT
)
1733 target
= gen_reg_rtx (submode
);
1734 convert_move (target
, temp
, 0);
1738 return gen_lowpart (submode
, temp
);
1741 delete_insns_since (last
);
1745 /* Open-code the complex absolute-value operation
1746 if we can open-code sqrt. Otherwise it's not worth while. */
1747 if (sqrt_optab
->handlers
[(int) submode
].insn_code
!= CODE_FOR_nothing
)
1749 rtx real
, imag
, total
;
1751 real
= gen_realpart (submode
, op0
);
1752 imag
= gen_imagpart (submode
, op0
);
1753 /* Square both parts. */
1754 real
= expand_mult (mode
, real
, real
, NULL_RTX
, 0);
1755 imag
= expand_mult (mode
, imag
, imag
, NULL_RTX
, 0);
1756 /* Sum the parts. */
1757 total
= expand_binop (submode
, add_optab
, real
, imag
, 0,
1758 0, OPTAB_LIB_WIDEN
);
1759 /* Get sqrt in TARGET. Set TARGET to where the result is. */
1760 target
= expand_unop (submode
, sqrt_optab
, total
, target
, 0);
1762 delete_insns_since (last
);
1767 /* Now try a library call in this mode. */
1768 if (abs_optab
->handlers
[(int) mode
].libfunc
)
1771 rtx funexp
= abs_optab
->handlers
[(int) mode
].libfunc
;
1775 /* Pass 1 for NO_QUEUE so we don't lose any increments
1776 if the libcall is cse'd or moved. */
1777 emit_library_call (abs_optab
->handlers
[(int) mode
].libfunc
,
1778 1, mode
, 1, op0
, mode
);
1779 insns
= get_insns ();
1782 target
= gen_reg_rtx (submode
);
1783 emit_libcall_block (insns
, target
, hard_libcall_value (submode
),
1784 gen_rtx (abs_optab
->code
, mode
, op0
));
1789 /* It can't be done in this mode. Can we do it in a wider mode? */
1791 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1792 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1794 if ((abs_optab
->handlers
[(int) wider_mode
].insn_code
1795 != CODE_FOR_nothing
)
1796 || abs_optab
->handlers
[(int) wider_mode
].libfunc
)
1800 xop0
= convert_to_mode (wider_mode
, xop0
, unsignedp
);
1802 temp
= expand_complex_abs (wider_mode
, xop0
, NULL_RTX
, unsignedp
);
1806 if (class != MODE_COMPLEX_INT
)
1809 target
= gen_reg_rtx (submode
);
1810 convert_move (target
, temp
, 0);
1814 return gen_lowpart (submode
, temp
);
1817 delete_insns_since (last
);
1824 /* Generate an instruction whose insn-code is INSN_CODE,
1825 with two operands: an output TARGET and an input OP0.
1826 TARGET *must* be nonzero, and the output is always stored there.
1827 CODE is an rtx code such that (CODE OP0) is an rtx that describes
1828 the value that is stored into TARGET. */
1831 emit_unop_insn (icode
, target
, op0
, code
)
1838 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
1841 temp
= target
= protect_from_queue (target
, 1);
1843 op0
= protect_from_queue (op0
, 0);
1846 op0
= force_not_mem (op0
);
1848 /* Now, if insn does not accept our operands, put them into pseudos. */
1850 if (! (*insn_operand_predicate
[icode
][1]) (op0
, mode0
))
1851 op0
= copy_to_mode_reg (mode0
, op0
);
1853 if (! (*insn_operand_predicate
[icode
][0]) (temp
, GET_MODE (temp
))
1854 || (flag_force_mem
&& GET_CODE (temp
) == MEM
))
1855 temp
= gen_reg_rtx (GET_MODE (temp
));
1857 pat
= GEN_FCN (icode
) (temp
, op0
);
1859 if (GET_CODE (pat
) == SEQUENCE
&& code
!= UNKNOWN
)
1860 add_equal_note (pat
, temp
, code
, op0
, NULL_RTX
);
1865 emit_move_insn (target
, temp
);
1868 /* Emit code to perform a series of operations on a multi-word quantity, one
1871 Such a block is preceded by a CLOBBER of the output, consists of multiple
1872 insns, each setting one word of the output, and followed by a SET copying
1873 the output to itself.
1875 Each of the insns setting words of the output receives a REG_NO_CONFLICT
1876 note indicating that it doesn't conflict with the (also multi-word)
1877 inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
1880 INSNS is a block of code generated to perform the operation, not including
1881 the CLOBBER and final copy. All insns that compute intermediate values
1882 are first emitted, followed by the block as described above. Only
1883 INSNs are allowed in the block; no library calls or jumps may be
1886 TARGET, OP0, and OP1 are the output and inputs of the operations,
1887 respectively. OP1 may be zero for a unary operation.
1889 EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
1892 If TARGET is not a register, INSNS is simply emitted with no special
1895 The final insn emitted is returned. */
1898 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv
)
1904 rtx prev
, next
, first
, last
, insn
;
1906 if (GET_CODE (target
) != REG
|| reload_in_progress
)
1907 return emit_insns (insns
);
1909 /* First emit all insns that do not store into words of the output and remove
1910 these from the list. */
1911 for (insn
= insns
; insn
; insn
= next
)
1916 next
= NEXT_INSN (insn
);
1918 if (GET_CODE (insn
) != INSN
)
1921 if (GET_CODE (PATTERN (insn
)) == SET
)
1922 set
= PATTERN (insn
);
1923 else if (GET_CODE (PATTERN (insn
)) == PARALLEL
)
1925 for (i
= 0; i
< XVECLEN (PATTERN (insn
), 0); i
++)
1926 if (GET_CODE (XVECEXP (PATTERN (insn
), 0, i
)) == SET
)
1928 set
= XVECEXP (PATTERN (insn
), 0, i
);
1936 if (! reg_overlap_mentioned_p (target
, SET_DEST (set
)))
1938 if (PREV_INSN (insn
))
1939 NEXT_INSN (PREV_INSN (insn
)) = next
;
1944 PREV_INSN (next
) = PREV_INSN (insn
);
1950 prev
= get_last_insn ();
1952 /* Now write the CLOBBER of the output, followed by the setting of each
1953 of the words, followed by the final copy. */
1954 if (target
!= op0
&& target
!= op1
)
1955 emit_insn (gen_rtx (CLOBBER
, VOIDmode
, target
));
1957 for (insn
= insns
; insn
; insn
= next
)
1959 next
= NEXT_INSN (insn
);
1962 if (op1
&& GET_CODE (op1
) == REG
)
1963 REG_NOTES (insn
) = gen_rtx (EXPR_LIST
, REG_NO_CONFLICT
, op1
,
1966 if (op0
&& GET_CODE (op0
) == REG
)
1967 REG_NOTES (insn
) = gen_rtx (EXPR_LIST
, REG_NO_CONFLICT
, op0
,
1971 last
= emit_move_insn (target
, target
);
1973 REG_NOTES (last
) = gen_rtx (EXPR_LIST
, REG_EQUAL
, equiv
, REG_NOTES (last
));
1976 first
= get_insns ();
1978 first
= NEXT_INSN (prev
);
1980 /* Encapsulate the block so it gets manipulated as a unit. */
1981 REG_NOTES (first
) = gen_rtx (INSN_LIST
, REG_LIBCALL
, last
,
1983 REG_NOTES (last
) = gen_rtx (INSN_LIST
, REG_RETVAL
, first
, REG_NOTES (last
));
1988 /* Emit code to make a call to a constant function or a library call.
1990 INSNS is a list containing all insns emitted in the call.
1991 These insns leave the result in RESULT. Our block is to copy RESULT
1992 to TARGET, which is logically equivalent to EQUIV.
1994 We first emit any insns that set a pseudo on the assumption that these are
1995 loading constants into registers; doing so allows them to be safely cse'ed
1996 between blocks. Then we emit all the other insns in the block, followed by
1997 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
1998 note with an operand of EQUIV.
2000 Moving assignments to pseudos outside of the block is done to improve
2001 the generated code, but is not required to generate correct code,
2002 hence being unable to move an assignment is not grounds for not making
2003 a libcall block. There are two reasons why it is safe to leave these
2004 insns inside the block: First, we know that these pseudos cannot be
2005 used in generated RTL outside the block since they are created for
2006 temporary purposes within the block. Second, CSE will not record the
2007 values of anything set inside a libcall block, so we know they must
2008 be dead at the end of the block.
2010 Except for the first group of insns (the ones setting pseudos), the
2011 block is delimited by REG_RETVAL and REG_LIBCALL notes. */
2014 emit_libcall_block (insns
, target
, result
, equiv
)
2020 rtx prev
, next
, first
, last
, insn
;
2022 /* First emit all insns that set pseudos. Remove them from the list as
2023 we go. Avoid insns that set pseudo which were referenced in previous
2024 insns. These can be generated by move_by_pieces, for example,
2025 to update an address. */
2027 for (insn
= insns
; insn
; insn
= next
)
2029 rtx set
= single_set (insn
);
2031 next
= NEXT_INSN (insn
);
2033 if (set
!= 0 && GET_CODE (SET_DEST (set
)) == REG
2034 && REGNO (SET_DEST (set
)) >= FIRST_PSEUDO_REGISTER
2036 || (! reg_mentioned_p (SET_DEST (set
), PATTERN (insns
))
2037 && ! reg_used_between_p (SET_DEST (set
), insns
, insn
))))
2039 if (PREV_INSN (insn
))
2040 NEXT_INSN (PREV_INSN (insn
)) = next
;
2045 PREV_INSN (next
) = PREV_INSN (insn
);
2051 prev
= get_last_insn ();
2053 /* Write the remaining insns followed by the final copy. */
2055 for (insn
= insns
; insn
; insn
= next
)
2057 next
= NEXT_INSN (insn
);
2062 last
= emit_move_insn (target
, result
);
2063 REG_NOTES (last
) = gen_rtx (EXPR_LIST
, REG_EQUAL
, equiv
, REG_NOTES (last
));
2066 first
= get_insns ();
2068 first
= NEXT_INSN (prev
);
2070 /* Encapsulate the block so it gets manipulated as a unit. */
2071 REG_NOTES (first
) = gen_rtx (INSN_LIST
, REG_LIBCALL
, last
,
2073 REG_NOTES (last
) = gen_rtx (INSN_LIST
, REG_RETVAL
, first
, REG_NOTES (last
));
2076 /* Generate code to store zero in X. */
2082 emit_move_insn (x
, const0_rtx
);
2085 /* Generate code to store 1 in X
2086 assuming it contains zero beforehand. */
2089 emit_0_to_1_insn (x
)
2092 emit_move_insn (x
, const1_rtx
);
2095 /* Generate code to compare X with Y
2096 so that the condition codes are set.
2098 MODE is the mode of the inputs (in case they are const_int).
2099 UNSIGNEDP nonzero says that X and Y are unsigned;
2100 this matters if they need to be widened.
2102 If they have mode BLKmode, then SIZE specifies the size of both X and Y,
2103 and ALIGN specifies the known shared alignment of X and Y.
2105 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
2106 It is ignored for fixed-point and block comparisons;
2107 it is used only for floating-point comparisons. */
2110 emit_cmp_insn (x
, y
, comparison
, size
, mode
, unsignedp
, align
)
2112 enum rtx_code comparison
;
2114 enum machine_mode mode
;
2118 enum mode_class
class;
2119 enum machine_mode wider_mode
;
2121 class = GET_MODE_CLASS (mode
);
2123 /* They could both be VOIDmode if both args are immediate constants,
2124 but we should fold that at an earlier stage.
2125 With no special code here, this will call abort,
2126 reminding the programmer to implement such folding. */
2128 if (mode
!= BLKmode
&& flag_force_mem
)
2130 x
= force_not_mem (x
);
2131 y
= force_not_mem (y
);
2134 /* If we are inside an appropriately-short loop and one operand is an
2135 expensive constant, force it into a register. */
2136 if (CONSTANT_P (x
) && preserve_subexpressions_p () && rtx_cost (x
, COMPARE
) > 2)
2137 x
= force_reg (mode
, x
);
2139 if (CONSTANT_P (y
) && preserve_subexpressions_p () && rtx_cost (y
, COMPARE
) > 2)
2140 y
= force_reg (mode
, y
);
2142 /* Don't let both operands fail to indicate the mode. */
2143 if (GET_MODE (x
) == VOIDmode
&& GET_MODE (y
) == VOIDmode
)
2144 x
= force_reg (mode
, x
);
2146 /* Handle all BLKmode compares. */
2148 if (mode
== BLKmode
)
2151 x
= protect_from_queue (x
, 0);
2152 y
= protect_from_queue (y
, 0);
2156 #ifdef HAVE_cmpstrqi
2158 && GET_CODE (size
) == CONST_INT
2159 && INTVAL (size
) < (1 << GET_MODE_BITSIZE (QImode
)))
2161 enum machine_mode result_mode
2162 = insn_operand_mode
[(int) CODE_FOR_cmpstrqi
][0];
2163 rtx result
= gen_reg_rtx (result_mode
);
2164 emit_insn (gen_cmpstrqi (result
, x
, y
, size
, GEN_INT (align
)));
2165 emit_cmp_insn (result
, const0_rtx
, comparison
, NULL_RTX
,
2170 #ifdef HAVE_cmpstrhi
2172 && GET_CODE (size
) == CONST_INT
2173 && INTVAL (size
) < (1 << GET_MODE_BITSIZE (HImode
)))
2175 enum machine_mode result_mode
2176 = insn_operand_mode
[(int) CODE_FOR_cmpstrhi
][0];
2177 rtx result
= gen_reg_rtx (result_mode
);
2178 emit_insn (gen_cmpstrhi (result
, x
, y
, size
, GEN_INT (align
)));
2179 emit_cmp_insn (result
, const0_rtx
, comparison
, NULL_RTX
,
2184 #ifdef HAVE_cmpstrsi
2187 enum machine_mode result_mode
2188 = insn_operand_mode
[(int) CODE_FOR_cmpstrsi
][0];
2189 rtx result
= gen_reg_rtx (result_mode
);
2190 size
= protect_from_queue (size
, 0);
2191 emit_insn (gen_cmpstrsi (result
, x
, y
,
2192 convert_to_mode (SImode
, size
, 1),
2194 emit_cmp_insn (result
, const0_rtx
, comparison
, NULL_RTX
,
2200 #ifdef TARGET_MEM_FUNCTIONS
2201 emit_library_call (memcmp_libfunc
, 0,
2202 TYPE_MODE (integer_type_node
), 3,
2203 XEXP (x
, 0), Pmode
, XEXP (y
, 0), Pmode
,
2206 emit_library_call (bcmp_libfunc
, 0,
2207 TYPE_MODE (integer_type_node
), 3,
2208 XEXP (x
, 0), Pmode
, XEXP (y
, 0), Pmode
,
2211 emit_cmp_insn (hard_libcall_value (TYPE_MODE (integer_type_node
)),
2212 const0_rtx
, comparison
, NULL_RTX
,
2213 TYPE_MODE (integer_type_node
), 0, 0);
2218 /* Handle some compares against zero. */
2220 if (y
== CONST0_RTX (mode
)
2221 && tst_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
2223 int icode
= (int) tst_optab
->handlers
[(int) mode
].insn_code
;
2226 x
= protect_from_queue (x
, 0);
2227 y
= protect_from_queue (y
, 0);
2229 /* Now, if insn does accept these operands, put them into pseudos. */
2230 if (! (*insn_operand_predicate
[icode
][0])
2231 (x
, insn_operand_mode
[icode
][0]))
2232 x
= copy_to_mode_reg (insn_operand_mode
[icode
][0], x
);
2234 emit_insn (GEN_FCN (icode
) (x
));
2238 /* Handle compares for which there is a directly suitable insn. */
2240 if (cmp_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
2242 int icode
= (int) cmp_optab
->handlers
[(int) mode
].insn_code
;
2245 x
= protect_from_queue (x
, 0);
2246 y
= protect_from_queue (y
, 0);
2248 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2249 if (! (*insn_operand_predicate
[icode
][0])
2250 (x
, insn_operand_mode
[icode
][0]))
2251 x
= copy_to_mode_reg (insn_operand_mode
[icode
][0], x
);
2253 if (! (*insn_operand_predicate
[icode
][1])
2254 (y
, insn_operand_mode
[icode
][1]))
2255 y
= copy_to_mode_reg (insn_operand_mode
[icode
][1], y
);
2257 emit_insn (GEN_FCN (icode
) (x
, y
));
2261 /* Try widening if we can find a direct insn that way. */
2263 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
2265 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2266 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2268 if (cmp_optab
->handlers
[(int) wider_mode
].insn_code
2269 != CODE_FOR_nothing
)
2271 x
= protect_from_queue (x
, 0);
2272 y
= protect_from_queue (y
, 0);
2273 x
= convert_to_mode (wider_mode
, x
, unsignedp
);
2274 y
= convert_to_mode (wider_mode
, y
, unsignedp
);
2275 emit_cmp_insn (x
, y
, comparison
, NULL_RTX
,
2276 wider_mode
, unsignedp
, align
);
2282 /* Handle a lib call just for the mode we are using. */
2284 if (cmp_optab
->handlers
[(int) mode
].libfunc
2285 && class != MODE_FLOAT
)
2287 rtx libfunc
= cmp_optab
->handlers
[(int) mode
].libfunc
;
2288 /* If we want unsigned, and this mode has a distinct unsigned
2289 comparison routine, use that. */
2290 if (unsignedp
&& ucmp_optab
->handlers
[(int) mode
].libfunc
)
2291 libfunc
= ucmp_optab
->handlers
[(int) mode
].libfunc
;
2293 emit_library_call (libfunc
, 1,
2294 SImode
, 2, x
, mode
, y
, mode
);
2296 /* Integer comparison returns a result that must be compared against 1,
2297 so that even if we do an unsigned compare afterward,
2298 there is still a value that can represent the result "less than". */
2300 emit_cmp_insn (hard_libcall_value (SImode
), const1_rtx
,
2301 comparison
, NULL_RTX
, SImode
, unsignedp
, 0);
2305 if (class == MODE_FLOAT
)
2306 emit_float_lib_cmp (x
, y
, comparison
);
2312 /* Nonzero if a compare of mode MODE can be done straightforwardly
2313 (without splitting it into pieces). */
2316 can_compare_p (mode
)
2317 enum machine_mode mode
;
2321 if (cmp_optab
->handlers
[(int)mode
].insn_code
!= CODE_FOR_nothing
)
2323 mode
= GET_MODE_WIDER_MODE (mode
);
2324 } while (mode
!= VOIDmode
);
2329 /* Emit a library call comparison between floating point X and Y.
2330 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
2333 emit_float_lib_cmp (x
, y
, comparison
)
2335 enum rtx_code comparison
;
2337 enum machine_mode mode
= GET_MODE (x
);
2344 libfunc
= eqsf2_libfunc
;
2348 libfunc
= nesf2_libfunc
;
2352 libfunc
= gtsf2_libfunc
;
2356 libfunc
= gesf2_libfunc
;
2360 libfunc
= ltsf2_libfunc
;
2364 libfunc
= lesf2_libfunc
;
2367 else if (mode
== DFmode
)
2371 libfunc
= eqdf2_libfunc
;
2375 libfunc
= nedf2_libfunc
;
2379 libfunc
= gtdf2_libfunc
;
2383 libfunc
= gedf2_libfunc
;
2387 libfunc
= ltdf2_libfunc
;
2391 libfunc
= ledf2_libfunc
;
2394 else if (mode
== XFmode
)
2398 libfunc
= eqxf2_libfunc
;
2402 libfunc
= nexf2_libfunc
;
2406 libfunc
= gtxf2_libfunc
;
2410 libfunc
= gexf2_libfunc
;
2414 libfunc
= ltxf2_libfunc
;
2418 libfunc
= lexf2_libfunc
;
2421 else if (mode
== TFmode
)
2425 libfunc
= eqtf2_libfunc
;
2429 libfunc
= netf2_libfunc
;
2433 libfunc
= gttf2_libfunc
;
2437 libfunc
= getf2_libfunc
;
2441 libfunc
= lttf2_libfunc
;
2445 libfunc
= letf2_libfunc
;
2450 enum machine_mode wider_mode
;
2452 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2453 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2455 if ((cmp_optab
->handlers
[(int) wider_mode
].insn_code
2456 != CODE_FOR_nothing
)
2457 || (cmp_optab
->handlers
[(int) wider_mode
].libfunc
!= 0))
2459 x
= protect_from_queue (x
, 0);
2460 y
= protect_from_queue (y
, 0);
2461 x
= convert_to_mode (wider_mode
, x
, 0);
2462 y
= convert_to_mode (wider_mode
, y
, 0);
2463 emit_float_lib_cmp (x
, y
, comparison
);
2470 emit_library_call (libfunc
, 1,
2471 SImode
, 2, x
, mode
, y
, mode
);
2473 emit_cmp_insn (hard_libcall_value (SImode
), const0_rtx
, comparison
,
2474 NULL_RTX
, SImode
, 0, 0);
2477 /* Generate code to indirectly jump to a location given in the rtx LOC. */
2480 emit_indirect_jump (loc
)
2483 if (! ((*insn_operand_predicate
[(int)CODE_FOR_indirect_jump
][0])
2485 loc
= copy_to_mode_reg (insn_operand_mode
[(int)CODE_FOR_indirect_jump
][0],
2488 emit_jump_insn (gen_indirect_jump (loc
));
2492 /* These three functions generate an insn body and return it
2493 rather than emitting the insn.
2495 They do not protect from queued increments,
2496 because they may be used 1) in protect_from_queue itself
2497 and 2) in other passes where there is no queue. */
2499 /* Generate and return an insn body to add Y to X. */
2502 gen_add2_insn (x
, y
)
2505 int icode
= (int) add_optab
->handlers
[(int) GET_MODE (x
)].insn_code
;
2507 if (! (*insn_operand_predicate
[icode
][0]) (x
, insn_operand_mode
[icode
][0])
2508 || ! (*insn_operand_predicate
[icode
][1]) (x
, insn_operand_mode
[icode
][1])
2509 || ! (*insn_operand_predicate
[icode
][2]) (y
, insn_operand_mode
[icode
][2]))
2512 return (GEN_FCN (icode
) (x
, x
, y
));
2516 have_add2_insn (mode
)
2517 enum machine_mode mode
;
2519 return add_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
;
2522 /* Generate and return an insn body to subtract Y from X. */
2525 gen_sub2_insn (x
, y
)
2528 int icode
= (int) sub_optab
->handlers
[(int) GET_MODE (x
)].insn_code
;
2530 if (! (*insn_operand_predicate
[icode
][0]) (x
, insn_operand_mode
[icode
][0])
2531 || ! (*insn_operand_predicate
[icode
][1]) (x
, insn_operand_mode
[icode
][1])
2532 || ! (*insn_operand_predicate
[icode
][2]) (y
, insn_operand_mode
[icode
][2]))
2535 return (GEN_FCN (icode
) (x
, x
, y
));
2539 have_sub2_insn (mode
)
2540 enum machine_mode mode
;
2542 return sub_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
;
2545 /* Generate the body of an instruction to copy Y into X. */
2548 gen_move_insn (x
, y
)
2551 register enum machine_mode mode
= GET_MODE (x
);
2552 enum insn_code insn_code
;
2554 if (mode
== VOIDmode
)
2555 mode
= GET_MODE (y
);
2557 insn_code
= mov_optab
->handlers
[(int) mode
].insn_code
;
2559 /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
2560 find a mode to do it in. If we have a movcc, use it. Otherwise,
2561 find the MODE_INT mode of the same width. */
2563 if (insn_code
== CODE_FOR_nothing
)
2565 enum machine_mode tmode
= VOIDmode
;
2568 if (GET_MODE_CLASS (mode
) == MODE_CC
&& mode
!= CCmode
2569 && mov_optab
->handlers
[(int) CCmode
].insn_code
!= CODE_FOR_nothing
)
2571 else if (GET_MODE_CLASS (mode
) == MODE_CC
)
2572 for (tmode
= QImode
; tmode
!= VOIDmode
;
2573 tmode
= GET_MODE_WIDER_MODE (tmode
))
2574 if (GET_MODE_SIZE (tmode
) == GET_MODE_SIZE (mode
))
2577 if (tmode
== VOIDmode
)
2580 /* Get X and Y in TMODE. We can't use gen_lowpart here because it
2581 may call change_address which is not appropriate if we were
2582 called when a reload was in progress. We don't have to worry
2583 about changing the address since the size in bytes is supposed to
2584 be the same. Copy the MEM to change the mode and move any
2585 substitutions from the old MEM to the new one. */
2587 if (reload_in_progress
)
2589 x
= gen_lowpart_common (tmode
, x1
);
2590 if (x
== 0 && GET_CODE (x1
) == MEM
)
2592 x
= gen_rtx (MEM
, tmode
, XEXP (x1
, 0));
2593 RTX_UNCHANGING_P (x
) = RTX_UNCHANGING_P (x1
);
2594 MEM_IN_STRUCT_P (x
) = MEM_IN_STRUCT_P (x1
);
2595 MEM_VOLATILE_P (x
) = MEM_VOLATILE_P (x1
);
2596 copy_replacements (x1
, x
);
2599 y
= gen_lowpart_common (tmode
, y1
);
2600 if (y
== 0 && GET_CODE (y1
) == MEM
)
2602 y
= gen_rtx (MEM
, tmode
, XEXP (y1
, 0));
2603 RTX_UNCHANGING_P (y
) = RTX_UNCHANGING_P (y1
);
2604 MEM_IN_STRUCT_P (y
) = MEM_IN_STRUCT_P (y1
);
2605 MEM_VOLATILE_P (y
) = MEM_VOLATILE_P (y1
);
2606 copy_replacements (y1
, y
);
2611 x
= gen_lowpart (tmode
, x
);
2612 y
= gen_lowpart (tmode
, y
);
2615 insn_code
= mov_optab
->handlers
[(int) tmode
].insn_code
;
2618 return (GEN_FCN (insn_code
) (x
, y
));
2621 /* Tables of patterns for extending one integer mode to another. */
2622 static enum insn_code extendtab
[MAX_MACHINE_MODE
][MAX_MACHINE_MODE
][2];
2624 /* Return the insn code used to extend FROM_MODE to TO_MODE.
2625 UNSIGNEDP specifies zero-extension instead of sign-extension. If
2626 no such operation exists, CODE_FOR_nothing will be returned. */
2629 can_extend_p (to_mode
, from_mode
, unsignedp
)
2630 enum machine_mode to_mode
, from_mode
;
2633 return extendtab
[(int) to_mode
][(int) from_mode
][unsignedp
];
2636 /* Generate the body of an insn to extend Y (with mode MFROM)
2637 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
2640 gen_extend_insn (x
, y
, mto
, mfrom
, unsignedp
)
2642 enum machine_mode mto
, mfrom
;
2645 return (GEN_FCN (extendtab
[(int) mto
][(int) mfrom
][unsignedp
]) (x
, y
));
2653 for (p
= extendtab
[0][0];
2654 p
< extendtab
[0][0] + sizeof extendtab
/ sizeof extendtab
[0][0][0];
2656 *p
= CODE_FOR_nothing
;
2658 #ifdef HAVE_extendditi2
2659 if (HAVE_extendditi2
)
2660 extendtab
[(int) TImode
][(int) DImode
][0] = CODE_FOR_extendditi2
;
2662 #ifdef HAVE_extendsiti2
2663 if (HAVE_extendsiti2
)
2664 extendtab
[(int) TImode
][(int) SImode
][0] = CODE_FOR_extendsiti2
;
2666 #ifdef HAVE_extendhiti2
2667 if (HAVE_extendhiti2
)
2668 extendtab
[(int) TImode
][(int) HImode
][0] = CODE_FOR_extendhiti2
;
2670 #ifdef HAVE_extendqiti2
2671 if (HAVE_extendqiti2
)
2672 extendtab
[(int) TImode
][(int) QImode
][0] = CODE_FOR_extendqiti2
;
2674 #ifdef HAVE_extendsidi2
2675 if (HAVE_extendsidi2
)
2676 extendtab
[(int) DImode
][(int) SImode
][0] = CODE_FOR_extendsidi2
;
2678 #ifdef HAVE_extendhidi2
2679 if (HAVE_extendhidi2
)
2680 extendtab
[(int) DImode
][(int) HImode
][0] = CODE_FOR_extendhidi2
;
2682 #ifdef HAVE_extendqidi2
2683 if (HAVE_extendqidi2
)
2684 extendtab
[(int) DImode
][(int) QImode
][0] = CODE_FOR_extendqidi2
;
2686 #ifdef HAVE_extendhisi2
2687 if (HAVE_extendhisi2
)
2688 extendtab
[(int) SImode
][(int) HImode
][0] = CODE_FOR_extendhisi2
;
2690 #ifdef HAVE_extendqisi2
2691 if (HAVE_extendqisi2
)
2692 extendtab
[(int) SImode
][(int) QImode
][0] = CODE_FOR_extendqisi2
;
2694 #ifdef HAVE_extendqihi2
2695 if (HAVE_extendqihi2
)
2696 extendtab
[(int) HImode
][(int) QImode
][0] = CODE_FOR_extendqihi2
;
2699 #ifdef HAVE_zero_extendditi2
2700 if (HAVE_zero_extendsiti2
)
2701 extendtab
[(int) TImode
][(int) DImode
][1] = CODE_FOR_zero_extendditi2
;
2703 #ifdef HAVE_zero_extendsiti2
2704 if (HAVE_zero_extendsiti2
)
2705 extendtab
[(int) TImode
][(int) SImode
][1] = CODE_FOR_zero_extendsiti2
;
2707 #ifdef HAVE_zero_extendhiti2
2708 if (HAVE_zero_extendhiti2
)
2709 extendtab
[(int) TImode
][(int) HImode
][1] = CODE_FOR_zero_extendhiti2
;
2711 #ifdef HAVE_zero_extendqiti2
2712 if (HAVE_zero_extendqiti2
)
2713 extendtab
[(int) TImode
][(int) QImode
][1] = CODE_FOR_zero_extendqiti2
;
2715 #ifdef HAVE_zero_extendsidi2
2716 if (HAVE_zero_extendsidi2
)
2717 extendtab
[(int) DImode
][(int) SImode
][1] = CODE_FOR_zero_extendsidi2
;
2719 #ifdef HAVE_zero_extendhidi2
2720 if (HAVE_zero_extendhidi2
)
2721 extendtab
[(int) DImode
][(int) HImode
][1] = CODE_FOR_zero_extendhidi2
;
2723 #ifdef HAVE_zero_extendqidi2
2724 if (HAVE_zero_extendqidi2
)
2725 extendtab
[(int) DImode
][(int) QImode
][1] = CODE_FOR_zero_extendqidi2
;
2727 #ifdef HAVE_zero_extendhisi2
2728 if (HAVE_zero_extendhisi2
)
2729 extendtab
[(int) SImode
][(int) HImode
][1] = CODE_FOR_zero_extendhisi2
;
2731 #ifdef HAVE_zero_extendqisi2
2732 if (HAVE_zero_extendqisi2
)
2733 extendtab
[(int) SImode
][(int) QImode
][1] = CODE_FOR_zero_extendqisi2
;
2735 #ifdef HAVE_zero_extendqihi2
2736 if (HAVE_zero_extendqihi2
)
2737 extendtab
[(int) HImode
][(int) QImode
][1] = CODE_FOR_zero_extendqihi2
;
2741 /* can_fix_p and can_float_p say whether the target machine
2742 can directly convert a given fixed point type to
2743 a given floating point type, or vice versa.
2744 The returned value is the CODE_FOR_... value to use,
2745 or CODE_FOR_nothing if these modes cannot be directly converted. */
2747 static enum insn_code fixtab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
2748 static enum insn_code fixtrunctab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
2749 static enum insn_code floattab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
2751 /* *TRUNCP_PTR is set to 1 if it is necessary to output
2752 an explicit FTRUNC insn before the fix insn; otherwise 0. */
2754 static enum insn_code
2755 can_fix_p (fixmode
, fltmode
, unsignedp
, truncp_ptr
)
2756 enum machine_mode fltmode
, fixmode
;
2761 if (fixtrunctab
[(int) fltmode
][(int) fixmode
][unsignedp
] != CODE_FOR_nothing
)
2762 return fixtrunctab
[(int) fltmode
][(int) fixmode
][unsignedp
];
2764 if (ftrunc_optab
->handlers
[(int) fltmode
].insn_code
!= CODE_FOR_nothing
)
2767 return fixtab
[(int) fltmode
][(int) fixmode
][unsignedp
];
2769 return CODE_FOR_nothing
;
2772 static enum insn_code
2773 can_float_p (fltmode
, fixmode
, unsignedp
)
2774 enum machine_mode fixmode
, fltmode
;
2777 return floattab
[(int) fltmode
][(int) fixmode
][unsignedp
];
2784 for (p
= fixtab
[0][0];
2785 p
< fixtab
[0][0] + sizeof fixtab
/ sizeof (fixtab
[0][0][0]);
2787 *p
= CODE_FOR_nothing
;
2788 for (p
= fixtrunctab
[0][0];
2789 p
< fixtrunctab
[0][0] + sizeof fixtrunctab
/ sizeof (fixtrunctab
[0][0][0]);
2791 *p
= CODE_FOR_nothing
;
2793 #ifdef HAVE_fixsfqi2
2795 fixtab
[(int) SFmode
][(int) QImode
][0] = CODE_FOR_fixsfqi2
;
2797 #ifdef HAVE_fixsfhi2
2799 fixtab
[(int) SFmode
][(int) HImode
][0] = CODE_FOR_fixsfhi2
;
2801 #ifdef HAVE_fixsfsi2
2803 fixtab
[(int) SFmode
][(int) SImode
][0] = CODE_FOR_fixsfsi2
;
2805 #ifdef HAVE_fixsfdi2
2807 fixtab
[(int) SFmode
][(int) DImode
][0] = CODE_FOR_fixsfdi2
;
2810 #ifdef HAVE_fixdfqi2
2812 fixtab
[(int) DFmode
][(int) QImode
][0] = CODE_FOR_fixdfqi2
;
2814 #ifdef HAVE_fixdfhi2
2816 fixtab
[(int) DFmode
][(int) HImode
][0] = CODE_FOR_fixdfhi2
;
2818 #ifdef HAVE_fixdfsi2
2820 fixtab
[(int) DFmode
][(int) SImode
][0] = CODE_FOR_fixdfsi2
;
2822 #ifdef HAVE_fixdfdi2
2824 fixtab
[(int) DFmode
][(int) DImode
][0] = CODE_FOR_fixdfdi2
;
2826 #ifdef HAVE_fixdfti2
2828 fixtab
[(int) DFmode
][(int) TImode
][0] = CODE_FOR_fixdfti2
;
2831 #ifdef HAVE_fixxfqi2
2833 fixtab
[(int) XFmode
][(int) QImode
][0] = CODE_FOR_fixxfqi2
;
2835 #ifdef HAVE_fixxfhi2
2837 fixtab
[(int) XFmode
][(int) HImode
][0] = CODE_FOR_fixxfhi2
;
2839 #ifdef HAVE_fixxfsi2
2841 fixtab
[(int) XFmode
][(int) SImode
][0] = CODE_FOR_fixxfsi2
;
2843 #ifdef HAVE_fixxfdi2
2845 fixtab
[(int) XFmode
][(int) DImode
][0] = CODE_FOR_fixxfdi2
;
2847 #ifdef HAVE_fixxfti2
2849 fixtab
[(int) XFmode
][(int) TImode
][0] = CODE_FOR_fixxfti2
;
2852 #ifdef HAVE_fixtfqi2
2854 fixtab
[(int) TFmode
][(int) QImode
][0] = CODE_FOR_fixtfqi2
;
2856 #ifdef HAVE_fixtfhi2
2858 fixtab
[(int) TFmode
][(int) HImode
][0] = CODE_FOR_fixtfhi2
;
2860 #ifdef HAVE_fixtfsi2
2862 fixtab
[(int) TFmode
][(int) SImode
][0] = CODE_FOR_fixtfsi2
;
2864 #ifdef HAVE_fixtfdi2
2866 fixtab
[(int) TFmode
][(int) DImode
][0] = CODE_FOR_fixtfdi2
;
2868 #ifdef HAVE_fixtfti2
2870 fixtab
[(int) TFmode
][(int) TImode
][0] = CODE_FOR_fixtfti2
;
2873 #ifdef HAVE_fixunssfqi2
2874 if (HAVE_fixunssfqi2
)
2875 fixtab
[(int) SFmode
][(int) QImode
][1] = CODE_FOR_fixunssfqi2
;
2877 #ifdef HAVE_fixunssfhi2
2878 if (HAVE_fixunssfhi2
)
2879 fixtab
[(int) SFmode
][(int) HImode
][1] = CODE_FOR_fixunssfhi2
;
2881 #ifdef HAVE_fixunssfsi2
2882 if (HAVE_fixunssfsi2
)
2883 fixtab
[(int) SFmode
][(int) SImode
][1] = CODE_FOR_fixunssfsi2
;
2885 #ifdef HAVE_fixunssfdi2
2886 if (HAVE_fixunssfdi2
)
2887 fixtab
[(int) SFmode
][(int) DImode
][1] = CODE_FOR_fixunssfdi2
;
2890 #ifdef HAVE_fixunsdfqi2
2891 if (HAVE_fixunsdfqi2
)
2892 fixtab
[(int) DFmode
][(int) QImode
][1] = CODE_FOR_fixunsdfqi2
;
2894 #ifdef HAVE_fixunsdfhi2
2895 if (HAVE_fixunsdfhi2
)
2896 fixtab
[(int) DFmode
][(int) HImode
][1] = CODE_FOR_fixunsdfhi2
;
2898 #ifdef HAVE_fixunsdfsi2
2899 if (HAVE_fixunsdfsi2
)
2900 fixtab
[(int) DFmode
][(int) SImode
][1] = CODE_FOR_fixunsdfsi2
;
2902 #ifdef HAVE_fixunsdfdi2
2903 if (HAVE_fixunsdfdi2
)
2904 fixtab
[(int) DFmode
][(int) DImode
][1] = CODE_FOR_fixunsdfdi2
;
2906 #ifdef HAVE_fixunsdfti2
2907 if (HAVE_fixunsdfti2
)
2908 fixtab
[(int) DFmode
][(int) TImode
][1] = CODE_FOR_fixunsdfti2
;
2911 #ifdef HAVE_fixunsxfqi2
2912 if (HAVE_fixunsxfqi2
)
2913 fixtab
[(int) XFmode
][(int) QImode
][1] = CODE_FOR_fixunsxfqi2
;
2915 #ifdef HAVE_fixunsxfhi2
2916 if (HAVE_fixunsxfhi2
)
2917 fixtab
[(int) XFmode
][(int) HImode
][1] = CODE_FOR_fixunsxfhi2
;
2919 #ifdef HAVE_fixunsxfsi2
2920 if (HAVE_fixunsxfsi2
)
2921 fixtab
[(int) XFmode
][(int) SImode
][1] = CODE_FOR_fixunsxfsi2
;
2923 #ifdef HAVE_fixunsxfdi2
2924 if (HAVE_fixunsxfdi2
)
2925 fixtab
[(int) XFmode
][(int) DImode
][1] = CODE_FOR_fixunsxfdi2
;
2927 #ifdef HAVE_fixunsxfti2
2928 if (HAVE_fixunsxfti2
)
2929 fixtab
[(int) XFmode
][(int) TImode
][1] = CODE_FOR_fixunsxfti2
;
2932 #ifdef HAVE_fixunstfqi2
2933 if (HAVE_fixunstfqi2
)
2934 fixtab
[(int) TFmode
][(int) QImode
][1] = CODE_FOR_fixunstfqi2
;
2936 #ifdef HAVE_fixunstfhi2
2937 if (HAVE_fixunstfhi2
)
2938 fixtab
[(int) TFmode
][(int) HImode
][1] = CODE_FOR_fixunstfhi2
;
2940 #ifdef HAVE_fixunstfsi2
2941 if (HAVE_fixunstfsi2
)
2942 fixtab
[(int) TFmode
][(int) SImode
][1] = CODE_FOR_fixunstfsi2
;
2944 #ifdef HAVE_fixunstfdi2
2945 if (HAVE_fixunstfdi2
)
2946 fixtab
[(int) TFmode
][(int) DImode
][1] = CODE_FOR_fixunstfdi2
;
2948 #ifdef HAVE_fixunstfti2
2949 if (HAVE_fixunstfti2
)
2950 fixtab
[(int) TFmode
][(int) TImode
][1] = CODE_FOR_fixunstfti2
;
2953 #ifdef HAVE_fix_truncsfqi2
2954 if (HAVE_fix_truncsfqi2
)
2955 fixtrunctab
[(int) SFmode
][(int) QImode
][0] = CODE_FOR_fix_truncsfqi2
;
2957 #ifdef HAVE_fix_truncsfhi2
2958 if (HAVE_fix_truncsfhi2
)
2959 fixtrunctab
[(int) SFmode
][(int) HImode
][0] = CODE_FOR_fix_truncsfhi2
;
2961 #ifdef HAVE_fix_truncsfsi2
2962 if (HAVE_fix_truncsfsi2
)
2963 fixtrunctab
[(int) SFmode
][(int) SImode
][0] = CODE_FOR_fix_truncsfsi2
;
2965 #ifdef HAVE_fix_truncsfdi2
2966 if (HAVE_fix_truncsfdi2
)
2967 fixtrunctab
[(int) SFmode
][(int) DImode
][0] = CODE_FOR_fix_truncsfdi2
;
2970 #ifdef HAVE_fix_truncdfqi2
2971 if (HAVE_fix_truncdfqi2
)
2972 fixtrunctab
[(int) DFmode
][(int) QImode
][0] = CODE_FOR_fix_truncdfqi2
;
2974 #ifdef HAVE_fix_truncdfhi2
2975 if (HAVE_fix_truncdfhi2
)
2976 fixtrunctab
[(int) DFmode
][(int) HImode
][0] = CODE_FOR_fix_truncdfhi2
;
2978 #ifdef HAVE_fix_truncdfsi2
2979 if (HAVE_fix_truncdfsi2
)
2980 fixtrunctab
[(int) DFmode
][(int) SImode
][0] = CODE_FOR_fix_truncdfsi2
;
2982 #ifdef HAVE_fix_truncdfdi2
2983 if (HAVE_fix_truncdfdi2
)
2984 fixtrunctab
[(int) DFmode
][(int) DImode
][0] = CODE_FOR_fix_truncdfdi2
;
2986 #ifdef HAVE_fix_truncdfti2
2987 if (HAVE_fix_truncdfti2
)
2988 fixtrunctab
[(int) DFmode
][(int) TImode
][0] = CODE_FOR_fix_truncdfti2
;
2991 #ifdef HAVE_fix_truncxfqi2
2992 if (HAVE_fix_truncxfqi2
)
2993 fixtrunctab
[(int) XFmode
][(int) QImode
][0] = CODE_FOR_fix_truncxfqi2
;
2995 #ifdef HAVE_fix_truncxfhi2
2996 if (HAVE_fix_truncxfhi2
)
2997 fixtrunctab
[(int) XFmode
][(int) HImode
][0] = CODE_FOR_fix_truncxfhi2
;
2999 #ifdef HAVE_fix_truncxfsi2
3000 if (HAVE_fix_truncxfsi2
)
3001 fixtrunctab
[(int) XFmode
][(int) SImode
][0] = CODE_FOR_fix_truncxfsi2
;
3003 #ifdef HAVE_fix_truncxfdi2
3004 if (HAVE_fix_truncxfdi2
)
3005 fixtrunctab
[(int) XFmode
][(int) DImode
][0] = CODE_FOR_fix_truncxfdi2
;
3007 #ifdef HAVE_fix_truncxfti2
3008 if (HAVE_fix_truncxfti2
)
3009 fixtrunctab
[(int) XFmode
][(int) TImode
][0] = CODE_FOR_fix_truncxfti2
;
3012 #ifdef HAVE_fix_trunctfqi2
3013 if (HAVE_fix_trunctfqi2
)
3014 fixtrunctab
[(int) TFmode
][(int) QImode
][0] = CODE_FOR_fix_trunctfqi2
;
3016 #ifdef HAVE_fix_trunctfhi2
3017 if (HAVE_fix_trunctfhi2
)
3018 fixtrunctab
[(int) TFmode
][(int) HImode
][0] = CODE_FOR_fix_trunctfhi2
;
3020 #ifdef HAVE_fix_trunctfsi2
3021 if (HAVE_fix_trunctfsi2
)
3022 fixtrunctab
[(int) TFmode
][(int) SImode
][0] = CODE_FOR_fix_trunctfsi2
;
3024 #ifdef HAVE_fix_trunctfdi2
3025 if (HAVE_fix_trunctfdi2
)
3026 fixtrunctab
[(int) TFmode
][(int) DImode
][0] = CODE_FOR_fix_trunctfdi2
;
3028 #ifdef HAVE_fix_trunctfti2
3029 if (HAVE_fix_trunctfti2
)
3030 fixtrunctab
[(int) TFmode
][(int) TImode
][0] = CODE_FOR_fix_trunctfti2
;
3033 #ifdef HAVE_fixuns_truncsfqi2
3034 if (HAVE_fixuns_truncsfqi2
)
3035 fixtrunctab
[(int) SFmode
][(int) QImode
][1] = CODE_FOR_fixuns_truncsfqi2
;
3037 #ifdef HAVE_fixuns_truncsfhi2
3038 if (HAVE_fixuns_truncsfhi2
)
3039 fixtrunctab
[(int) SFmode
][(int) HImode
][1] = CODE_FOR_fixuns_truncsfhi2
;
3041 #ifdef HAVE_fixuns_truncsfsi2
3042 if (HAVE_fixuns_truncsfsi2
)
3043 fixtrunctab
[(int) SFmode
][(int) SImode
][1] = CODE_FOR_fixuns_truncsfsi2
;
3045 #ifdef HAVE_fixuns_truncsfdi2
3046 if (HAVE_fixuns_truncsfdi2
)
3047 fixtrunctab
[(int) SFmode
][(int) DImode
][1] = CODE_FOR_fixuns_truncsfdi2
;
3050 #ifdef HAVE_fixuns_truncdfqi2
3051 if (HAVE_fixuns_truncdfqi2
)
3052 fixtrunctab
[(int) DFmode
][(int) QImode
][1] = CODE_FOR_fixuns_truncdfqi2
;
3054 #ifdef HAVE_fixuns_truncdfhi2
3055 if (HAVE_fixuns_truncdfhi2
)
3056 fixtrunctab
[(int) DFmode
][(int) HImode
][1] = CODE_FOR_fixuns_truncdfhi2
;
3058 #ifdef HAVE_fixuns_truncdfsi2
3059 if (HAVE_fixuns_truncdfsi2
)
3060 fixtrunctab
[(int) DFmode
][(int) SImode
][1] = CODE_FOR_fixuns_truncdfsi2
;
3062 #ifdef HAVE_fixuns_truncdfdi2
3063 if (HAVE_fixuns_truncdfdi2
)
3064 fixtrunctab
[(int) DFmode
][(int) DImode
][1] = CODE_FOR_fixuns_truncdfdi2
;
3066 #ifdef HAVE_fixuns_truncdfti2
3067 if (HAVE_fixuns_truncdfti2
)
3068 fixtrunctab
[(int) DFmode
][(int) TImode
][1] = CODE_FOR_fixuns_truncdfti2
;
3071 #ifdef HAVE_fixuns_truncxfqi2
3072 if (HAVE_fixuns_truncxfqi2
)
3073 fixtrunctab
[(int) XFmode
][(int) QImode
][1] = CODE_FOR_fixuns_truncxfqi2
;
3075 #ifdef HAVE_fixuns_truncxfhi2
3076 if (HAVE_fixuns_truncxfhi2
)
3077 fixtrunctab
[(int) XFmode
][(int) HImode
][1] = CODE_FOR_fixuns_truncxfhi2
;
3079 #ifdef HAVE_fixuns_truncxfsi2
3080 if (HAVE_fixuns_truncxfsi2
)
3081 fixtrunctab
[(int) XFmode
][(int) SImode
][1] = CODE_FOR_fixuns_truncxfsi2
;
3083 #ifdef HAVE_fixuns_truncxfdi2
3084 if (HAVE_fixuns_truncxfdi2
)
3085 fixtrunctab
[(int) XFmode
][(int) DImode
][1] = CODE_FOR_fixuns_truncxfdi2
;
3087 #ifdef HAVE_fixuns_truncxfti2
3088 if (HAVE_fixuns_truncxfti2
)
3089 fixtrunctab
[(int) XFmode
][(int) TImode
][1] = CODE_FOR_fixuns_truncxfti2
;
3092 #ifdef HAVE_fixuns_trunctfqi2
3093 if (HAVE_fixuns_trunctfqi2
)
3094 fixtrunctab
[(int) TFmode
][(int) QImode
][1] = CODE_FOR_fixuns_trunctfqi2
;
3096 #ifdef HAVE_fixuns_trunctfhi2
3097 if (HAVE_fixuns_trunctfhi2
)
3098 fixtrunctab
[(int) TFmode
][(int) HImode
][1] = CODE_FOR_fixuns_trunctfhi2
;
3100 #ifdef HAVE_fixuns_trunctfsi2
3101 if (HAVE_fixuns_trunctfsi2
)
3102 fixtrunctab
[(int) TFmode
][(int) SImode
][1] = CODE_FOR_fixuns_trunctfsi2
;
3104 #ifdef HAVE_fixuns_trunctfdi2
3105 if (HAVE_fixuns_trunctfdi2
)
3106 fixtrunctab
[(int) TFmode
][(int) DImode
][1] = CODE_FOR_fixuns_trunctfdi2
;
3108 #ifdef HAVE_fixuns_trunctfti2
3109 if (HAVE_fixuns_trunctfti2
)
3110 fixtrunctab
[(int) TFmode
][(int) TImode
][1] = CODE_FOR_fixuns_trunctfti2
;
3113 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
3114 /* This flag says the same insns that convert to a signed fixnum
3115 also convert validly to an unsigned one. */
3119 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
3120 for (j
= 0; j
< NUM_MACHINE_MODES
; j
++)
3121 fixtrunctab
[i
][j
][1] = fixtrunctab
[i
][j
][0];
3130 for (p
= floattab
[0][0];
3131 p
< floattab
[0][0] + sizeof floattab
/ sizeof (floattab
[0][0][0]);
3133 *p
= CODE_FOR_nothing
;
3135 #ifdef HAVE_floatqisf2
3136 if (HAVE_floatqisf2
)
3137 floattab
[(int) SFmode
][(int) QImode
][0] = CODE_FOR_floatqisf2
;
3139 #ifdef HAVE_floathisf2
3140 if (HAVE_floathisf2
)
3141 floattab
[(int) SFmode
][(int) HImode
][0] = CODE_FOR_floathisf2
;
3143 #ifdef HAVE_floatsisf2
3144 if (HAVE_floatsisf2
)
3145 floattab
[(int) SFmode
][(int) SImode
][0] = CODE_FOR_floatsisf2
;
3147 #ifdef HAVE_floatdisf2
3148 if (HAVE_floatdisf2
)
3149 floattab
[(int) SFmode
][(int) DImode
][0] = CODE_FOR_floatdisf2
;
3151 #ifdef HAVE_floattisf2
3152 if (HAVE_floattisf2
)
3153 floattab
[(int) SFmode
][(int) TImode
][0] = CODE_FOR_floattisf2
;
3156 #ifdef HAVE_floatqidf2
3157 if (HAVE_floatqidf2
)
3158 floattab
[(int) DFmode
][(int) QImode
][0] = CODE_FOR_floatqidf2
;
3160 #ifdef HAVE_floathidf2
3161 if (HAVE_floathidf2
)
3162 floattab
[(int) DFmode
][(int) HImode
][0] = CODE_FOR_floathidf2
;
3164 #ifdef HAVE_floatsidf2
3165 if (HAVE_floatsidf2
)
3166 floattab
[(int) DFmode
][(int) SImode
][0] = CODE_FOR_floatsidf2
;
3168 #ifdef HAVE_floatdidf2
3169 if (HAVE_floatdidf2
)
3170 floattab
[(int) DFmode
][(int) DImode
][0] = CODE_FOR_floatdidf2
;
3172 #ifdef HAVE_floattidf2
3173 if (HAVE_floattidf2
)
3174 floattab
[(int) DFmode
][(int) TImode
][0] = CODE_FOR_floattidf2
;
3177 #ifdef HAVE_floatqixf2
3178 if (HAVE_floatqixf2
)
3179 floattab
[(int) XFmode
][(int) QImode
][0] = CODE_FOR_floatqixf2
;
3181 #ifdef HAVE_floathixf2
3182 if (HAVE_floathixf2
)
3183 floattab
[(int) XFmode
][(int) HImode
][0] = CODE_FOR_floathixf2
;
3185 #ifdef HAVE_floatsixf2
3186 if (HAVE_floatsixf2
)
3187 floattab
[(int) XFmode
][(int) SImode
][0] = CODE_FOR_floatsixf2
;
3189 #ifdef HAVE_floatdixf2
3190 if (HAVE_floatdixf2
)
3191 floattab
[(int) XFmode
][(int) DImode
][0] = CODE_FOR_floatdixf2
;
3193 #ifdef HAVE_floattixf2
3194 if (HAVE_floattixf2
)
3195 floattab
[(int) XFmode
][(int) TImode
][0] = CODE_FOR_floattixf2
;
3198 #ifdef HAVE_floatqitf2
3199 if (HAVE_floatqitf2
)
3200 floattab
[(int) TFmode
][(int) QImode
][0] = CODE_FOR_floatqitf2
;
3202 #ifdef HAVE_floathitf2
3203 if (HAVE_floathitf2
)
3204 floattab
[(int) TFmode
][(int) HImode
][0] = CODE_FOR_floathitf2
;
3206 #ifdef HAVE_floatsitf2
3207 if (HAVE_floatsitf2
)
3208 floattab
[(int) TFmode
][(int) SImode
][0] = CODE_FOR_floatsitf2
;
3210 #ifdef HAVE_floatditf2
3211 if (HAVE_floatditf2
)
3212 floattab
[(int) TFmode
][(int) DImode
][0] = CODE_FOR_floatditf2
;
3214 #ifdef HAVE_floattitf2
3215 if (HAVE_floattitf2
)
3216 floattab
[(int) TFmode
][(int) TImode
][0] = CODE_FOR_floattitf2
;
3219 #ifdef HAVE_floatunsqisf2
3220 if (HAVE_floatunsqisf2
)
3221 floattab
[(int) SFmode
][(int) QImode
][1] = CODE_FOR_floatunsqisf2
;
3223 #ifdef HAVE_floatunshisf2
3224 if (HAVE_floatunshisf2
)
3225 floattab
[(int) SFmode
][(int) HImode
][1] = CODE_FOR_floatunshisf2
;
3227 #ifdef HAVE_floatunssisf2
3228 if (HAVE_floatunssisf2
)
3229 floattab
[(int) SFmode
][(int) SImode
][1] = CODE_FOR_floatunssisf2
;
3231 #ifdef HAVE_floatunsdisf2
3232 if (HAVE_floatunsdisf2
)
3233 floattab
[(int) SFmode
][(int) DImode
][1] = CODE_FOR_floatunsdisf2
;
3235 #ifdef HAVE_floatunstisf2
3236 if (HAVE_floatunstisf2
)
3237 floattab
[(int) SFmode
][(int) TImode
][1] = CODE_FOR_floatunstisf2
;
3240 #ifdef HAVE_floatunsqidf2
3241 if (HAVE_floatunsqidf2
)
3242 floattab
[(int) DFmode
][(int) QImode
][1] = CODE_FOR_floatunsqidf2
;
3244 #ifdef HAVE_floatunshidf2
3245 if (HAVE_floatunshidf2
)
3246 floattab
[(int) DFmode
][(int) HImode
][1] = CODE_FOR_floatunshidf2
;
3248 #ifdef HAVE_floatunssidf2
3249 if (HAVE_floatunssidf2
)
3250 floattab
[(int) DFmode
][(int) SImode
][1] = CODE_FOR_floatunssidf2
;
3252 #ifdef HAVE_floatunsdidf2
3253 if (HAVE_floatunsdidf2
)
3254 floattab
[(int) DFmode
][(int) DImode
][1] = CODE_FOR_floatunsdidf2
;
3256 #ifdef HAVE_floatunstidf2
3257 if (HAVE_floatunstidf2
)
3258 floattab
[(int) DFmode
][(int) TImode
][1] = CODE_FOR_floatunstidf2
;
3261 #ifdef HAVE_floatunsqixf2
3262 if (HAVE_floatunsqixf2
)
3263 floattab
[(int) XFmode
][(int) QImode
][1] = CODE_FOR_floatunsqixf2
;
3265 #ifdef HAVE_floatunshixf2
3266 if (HAVE_floatunshixf2
)
3267 floattab
[(int) XFmode
][(int) HImode
][1] = CODE_FOR_floatunshixf2
;
3269 #ifdef HAVE_floatunssixf2
3270 if (HAVE_floatunssixf2
)
3271 floattab
[(int) XFmode
][(int) SImode
][1] = CODE_FOR_floatunssixf2
;
3273 #ifdef HAVE_floatunsdixf2
3274 if (HAVE_floatunsdixf2
)
3275 floattab
[(int) XFmode
][(int) DImode
][1] = CODE_FOR_floatunsdixf2
;
3277 #ifdef HAVE_floatunstixf2
3278 if (HAVE_floatunstixf2
)
3279 floattab
[(int) XFmode
][(int) TImode
][1] = CODE_FOR_floatunstixf2
;
3282 #ifdef HAVE_floatunsqitf2
3283 if (HAVE_floatunsqitf2
)
3284 floattab
[(int) TFmode
][(int) QImode
][1] = CODE_FOR_floatunsqitf2
;
3286 #ifdef HAVE_floatunshitf2
3287 if (HAVE_floatunshitf2
)
3288 floattab
[(int) TFmode
][(int) HImode
][1] = CODE_FOR_floatunshitf2
;
3290 #ifdef HAVE_floatunssitf2
3291 if (HAVE_floatunssitf2
)
3292 floattab
[(int) TFmode
][(int) SImode
][1] = CODE_FOR_floatunssitf2
;
3294 #ifdef HAVE_floatunsditf2
3295 if (HAVE_floatunsditf2
)
3296 floattab
[(int) TFmode
][(int) DImode
][1] = CODE_FOR_floatunsditf2
;
3298 #ifdef HAVE_floatunstitf2
3299 if (HAVE_floatunstitf2
)
3300 floattab
[(int) TFmode
][(int) TImode
][1] = CODE_FOR_floatunstitf2
;
3304 /* Generate code to convert FROM to floating point
3305 and store in TO. FROM must be fixed point and not VOIDmode.
3306 UNSIGNEDP nonzero means regard FROM as unsigned.
3307 Normally this is done by correcting the final value
3308 if it is negative. */
3311 expand_float (to
, from
, unsignedp
)
3315 enum insn_code icode
;
3316 register rtx target
= to
;
3317 enum machine_mode fmode
, imode
;
3319 /* Crash now, because we won't be able to decide which mode to use. */
3320 if (GET_MODE (from
) == VOIDmode
)
3323 /* Look for an insn to do the conversion. Do it in the specified
3324 modes if possible; otherwise convert either input, output or both to
3325 wider mode. If the integer mode is wider than the mode of FROM,
3326 we can do the conversion signed even if the input is unsigned. */
3328 for (imode
= GET_MODE (from
); imode
!= VOIDmode
;
3329 imode
= GET_MODE_WIDER_MODE (imode
))
3330 for (fmode
= GET_MODE (to
); fmode
!= VOIDmode
;
3331 fmode
= GET_MODE_WIDER_MODE (fmode
))
3333 int doing_unsigned
= unsignedp
;
3335 icode
= can_float_p (fmode
, imode
, unsignedp
);
3336 if (icode
== CODE_FOR_nothing
&& imode
!= GET_MODE (from
) && unsignedp
)
3337 icode
= can_float_p (fmode
, imode
, 0), doing_unsigned
= 0;
3339 if (icode
!= CODE_FOR_nothing
)
3341 to
= protect_from_queue (to
, 1);
3342 from
= protect_from_queue (from
, 0);
3344 if (imode
!= GET_MODE (from
))
3345 from
= convert_to_mode (imode
, from
, unsignedp
);
3347 if (fmode
!= GET_MODE (to
))
3348 target
= gen_reg_rtx (fmode
);
3350 emit_unop_insn (icode
, target
, from
,
3351 doing_unsigned
? UNSIGNED_FLOAT
: FLOAT
);
3354 convert_move (to
, target
, 0);
3359 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3361 /* Unsigned integer, and no way to convert directly.
3362 Convert as signed, then conditionally adjust the result. */
3365 rtx label
= gen_label_rtx ();
3367 REAL_VALUE_TYPE offset
;
3371 to
= protect_from_queue (to
, 1);
3372 from
= protect_from_queue (from
, 0);
3375 from
= force_not_mem (from
);
3377 /* If we are about to do some arithmetic to correct for an
3378 unsigned operand, do it in a pseudo-register. */
3380 if (GET_CODE (to
) != REG
|| REGNO (to
) <= LAST_VIRTUAL_REGISTER
)
3381 target
= gen_reg_rtx (GET_MODE (to
));
3383 /* Convert as signed integer to floating. */
3384 expand_float (target
, from
, 0);
3386 /* If FROM is negative (and therefore TO is negative),
3387 correct its value by 2**bitwidth. */
3389 do_pending_stack_adjust ();
3390 emit_cmp_insn (from
, const0_rtx
, GE
, NULL_RTX
, GET_MODE (from
), 0, 0);
3391 emit_jump_insn (gen_bge (label
));
3392 /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
3393 Rather than setting up a dconst_dot_5, let's hope SCO
3395 offset
= REAL_VALUE_LDEXP (dconst1
, GET_MODE_BITSIZE (GET_MODE (from
)));
3396 temp
= expand_binop (GET_MODE (to
), add_optab
, target
,
3397 immed_real_const_1 (offset
, GET_MODE (to
)),
3398 target
, 0, OPTAB_LIB_WIDEN
);
3400 emit_move_insn (target
, temp
);
3401 do_pending_stack_adjust ();
3407 /* No hardware instruction available; call a library rotine to convert from
3408 SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */
3413 to
= protect_from_queue (to
, 1);
3414 from
= protect_from_queue (from
, 0);
3416 if (GET_MODE_SIZE (GET_MODE (from
)) < GET_MODE_SIZE (SImode
))
3417 from
= convert_to_mode (SImode
, from
, unsignedp
);
3420 from
= force_not_mem (from
);
3422 if (GET_MODE (to
) == SFmode
)
3424 if (GET_MODE (from
) == SImode
)
3425 libfcn
= floatsisf_libfunc
;
3426 else if (GET_MODE (from
) == DImode
)
3427 libfcn
= floatdisf_libfunc
;
3428 else if (GET_MODE (from
) == TImode
)
3429 libfcn
= floattisf_libfunc
;
3433 else if (GET_MODE (to
) == DFmode
)
3435 if (GET_MODE (from
) == SImode
)
3436 libfcn
= floatsidf_libfunc
;
3437 else if (GET_MODE (from
) == DImode
)
3438 libfcn
= floatdidf_libfunc
;
3439 else if (GET_MODE (from
) == TImode
)
3440 libfcn
= floattidf_libfunc
;
3444 else if (GET_MODE (to
) == XFmode
)
3446 if (GET_MODE (from
) == SImode
)
3447 libfcn
= floatsixf_libfunc
;
3448 else if (GET_MODE (from
) == DImode
)
3449 libfcn
= floatdixf_libfunc
;
3450 else if (GET_MODE (from
) == TImode
)
3451 libfcn
= floattixf_libfunc
;
3455 else if (GET_MODE (to
) == TFmode
)
3457 if (GET_MODE (from
) == SImode
)
3458 libfcn
= floatsitf_libfunc
;
3459 else if (GET_MODE (from
) == DImode
)
3460 libfcn
= floatditf_libfunc
;
3461 else if (GET_MODE (from
) == TImode
)
3462 libfcn
= floattitf_libfunc
;
3471 emit_library_call (libfcn
, 1, GET_MODE (to
), 1, from
, GET_MODE (from
));
3472 insns
= get_insns ();
3475 emit_libcall_block (insns
, target
, hard_libcall_value (GET_MODE (to
)),
3476 gen_rtx (FLOAT
, GET_MODE (to
), from
));
3479 /* Copy result to requested destination
3480 if we have been computing in a temp location. */
3484 if (GET_MODE (target
) == GET_MODE (to
))
3485 emit_move_insn (to
, target
);
3487 convert_move (to
, target
, 0);
3491 /* expand_fix: generate code to convert FROM to fixed point
3492 and store in TO. FROM must be floating point. */
3498 rtx temp
= gen_reg_rtx (GET_MODE (x
));
3499 return expand_unop (GET_MODE (x
), ftrunc_optab
, x
, temp
, 0);
3503 expand_fix (to
, from
, unsignedp
)
3504 register rtx to
, from
;
3507 enum insn_code icode
;
3508 register rtx target
= to
;
3509 enum machine_mode fmode
, imode
;
3513 /* We first try to find a pair of modes, one real and one integer, at
3514 least as wide as FROM and TO, respectively, in which we can open-code
3515 this conversion. If the integer mode is wider than the mode of TO,
3516 we can do the conversion either signed or unsigned. */
3518 for (imode
= GET_MODE (to
); imode
!= VOIDmode
;
3519 imode
= GET_MODE_WIDER_MODE (imode
))
3520 for (fmode
= GET_MODE (from
); fmode
!= VOIDmode
;
3521 fmode
= GET_MODE_WIDER_MODE (fmode
))
3523 int doing_unsigned
= unsignedp
;
3525 icode
= can_fix_p (imode
, fmode
, unsignedp
, &must_trunc
);
3526 if (icode
== CODE_FOR_nothing
&& imode
!= GET_MODE (to
) && unsignedp
)
3527 icode
= can_fix_p (imode
, fmode
, 0, &must_trunc
), doing_unsigned
= 0;
3529 if (icode
!= CODE_FOR_nothing
)
3531 to
= protect_from_queue (to
, 1);
3532 from
= protect_from_queue (from
, 0);
3534 if (fmode
!= GET_MODE (from
))
3535 from
= convert_to_mode (fmode
, from
, 0);
3538 from
= ftruncify (from
);
3540 if (imode
!= GET_MODE (to
))
3541 target
= gen_reg_rtx (imode
);
3543 emit_unop_insn (icode
, target
, from
,
3544 doing_unsigned
? UNSIGNED_FIX
: FIX
);
3546 convert_move (to
, target
, unsignedp
);
3551 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3552 /* For an unsigned conversion, there is one more way to do it.
3553 If we have a signed conversion, we generate code that compares
3554 the real value to the largest representable positive number. If if
3555 is smaller, the conversion is done normally. Otherwise, subtract
3556 one plus the highest signed number, convert, and add it back.
3558 We only need to check all real modes, since we know we didn't find
3559 anything with a wider integer mode. */
3561 if (unsignedp
&& GET_MODE_BITSIZE (GET_MODE (to
)) <= HOST_BITS_PER_WIDE_INT
)
3562 for (fmode
= GET_MODE (from
); fmode
!= VOIDmode
;
3563 fmode
= GET_MODE_WIDER_MODE (fmode
))
3564 /* Make sure we won't lose significant bits doing this. */
3565 if (GET_MODE_BITSIZE (fmode
) > GET_MODE_BITSIZE (GET_MODE (to
))
3566 && CODE_FOR_nothing
!= can_fix_p (GET_MODE (to
), fmode
, 0,
3569 int bitsize
= GET_MODE_BITSIZE (GET_MODE (to
));
3570 REAL_VALUE_TYPE offset
= REAL_VALUE_LDEXP (dconst1
, bitsize
- 1);
3571 rtx limit
= immed_real_const_1 (offset
, fmode
);
3572 rtx lab1
= gen_label_rtx ();
3573 rtx lab2
= gen_label_rtx ();
3577 to
= protect_from_queue (to
, 1);
3578 from
= protect_from_queue (from
, 0);
3581 from
= force_not_mem (from
);
3583 if (fmode
!= GET_MODE (from
))
3584 from
= convert_to_mode (fmode
, from
, 0);
3586 /* See if we need to do the subtraction. */
3587 do_pending_stack_adjust ();
3588 emit_cmp_insn (from
, limit
, GE
, NULL_RTX
, GET_MODE (from
), 0, 0);
3589 emit_jump_insn (gen_bge (lab1
));
3591 /* If not, do the signed "fix" and branch around fixup code. */
3592 expand_fix (to
, from
, 0);
3593 emit_jump_insn (gen_jump (lab2
));
3596 /* Otherwise, subtract 2**(N-1), convert to signed number,
3597 then add 2**(N-1). Do the addition using XOR since this
3598 will often generate better code. */
3600 target
= expand_binop (GET_MODE (from
), sub_optab
, from
, limit
,
3601 NULL_RTX
, 0, OPTAB_LIB_WIDEN
);
3602 expand_fix (to
, target
, 0);
3603 target
= expand_binop (GET_MODE (to
), xor_optab
, to
,
3604 GEN_INT ((HOST_WIDE_INT
) 1 << (bitsize
- 1)),
3605 to
, 1, OPTAB_LIB_WIDEN
);
3608 emit_move_insn (to
, target
);
3612 /* Make a place for a REG_NOTE and add it. */
3613 insn
= emit_move_insn (to
, to
);
3614 REG_NOTES (insn
) = gen_rtx (EXPR_LIST
, REG_EQUAL
,
3615 gen_rtx (UNSIGNED_FIX
, GET_MODE (to
),
3616 from
), REG_NOTES (insn
));
3622 /* We can't do it with an insn, so use a library call. But first ensure
3623 that the mode of TO is at least as wide as SImode, since those are the
3624 only library calls we know about. */
3626 if (GET_MODE_SIZE (GET_MODE (to
)) < GET_MODE_SIZE (SImode
))
3628 target
= gen_reg_rtx (SImode
);
3630 expand_fix (target
, from
, unsignedp
);
3632 else if (GET_MODE (from
) == SFmode
)
3634 if (GET_MODE (to
) == SImode
)
3635 libfcn
= unsignedp
? fixunssfsi_libfunc
: fixsfsi_libfunc
;
3636 else if (GET_MODE (to
) == DImode
)
3637 libfcn
= unsignedp
? fixunssfdi_libfunc
: fixsfdi_libfunc
;
3638 else if (GET_MODE (to
) == TImode
)
3639 libfcn
= unsignedp
? fixunssfti_libfunc
: fixsfti_libfunc
;
3643 else if (GET_MODE (from
) == DFmode
)
3645 if (GET_MODE (to
) == SImode
)
3646 libfcn
= unsignedp
? fixunsdfsi_libfunc
: fixdfsi_libfunc
;
3647 else if (GET_MODE (to
) == DImode
)
3648 libfcn
= unsignedp
? fixunsdfdi_libfunc
: fixdfdi_libfunc
;
3649 else if (GET_MODE (to
) == TImode
)
3650 libfcn
= unsignedp
? fixunsdfti_libfunc
: fixdfti_libfunc
;
3654 else if (GET_MODE (from
) == XFmode
)
3656 if (GET_MODE (to
) == SImode
)
3657 libfcn
= unsignedp
? fixunsxfsi_libfunc
: fixxfsi_libfunc
;
3658 else if (GET_MODE (to
) == DImode
)
3659 libfcn
= unsignedp
? fixunsxfdi_libfunc
: fixxfdi_libfunc
;
3660 else if (GET_MODE (to
) == TImode
)
3661 libfcn
= unsignedp
? fixunsxfti_libfunc
: fixxfti_libfunc
;
3665 else if (GET_MODE (from
) == TFmode
)
3667 if (GET_MODE (to
) == SImode
)
3668 libfcn
= unsignedp
? fixunstfsi_libfunc
: fixtfsi_libfunc
;
3669 else if (GET_MODE (to
) == DImode
)
3670 libfcn
= unsignedp
? fixunstfdi_libfunc
: fixtfdi_libfunc
;
3671 else if (GET_MODE (to
) == TImode
)
3672 libfcn
= unsignedp
? fixunstfti_libfunc
: fixtfti_libfunc
;
3683 to
= protect_from_queue (to
, 1);
3684 from
= protect_from_queue (from
, 0);
3687 from
= force_not_mem (from
);
3691 emit_library_call (libfcn
, 1, GET_MODE (to
), 1, from
, GET_MODE (from
));
3692 insns
= get_insns ();
3695 emit_libcall_block (insns
, target
, hard_libcall_value (GET_MODE (to
)),
3696 gen_rtx (unsignedp
? FIX
: UNSIGNED_FIX
,
3697 GET_MODE (to
), from
));
3700 if (GET_MODE (to
) == GET_MODE (target
))
3701 emit_move_insn (to
, target
);
3703 convert_move (to
, target
, 0);
3711 optab op
= (optab
) xmalloc (sizeof (struct optab
));
3713 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
3715 op
->handlers
[i
].insn_code
= CODE_FOR_nothing
;
3716 op
->handlers
[i
].libfunc
= 0;
3721 /* Initialize the libfunc fields of an entire group of entries in some
3722 optab. Each entry is set equal to a string consisting of a leading
3723 pair of underscores followed by a generic operation name followed by
3724 a mode name (downshifted to lower case) followed by a single character
3725 representing the number of operands for the given operation (which is
3726 usually one of the characters '2', '3', or '4').
3728 OPTABLE is the table in which libfunc fields are to be initialized.
3729 FIRST_MODE is the first machine mode index in the given optab to
3731 LAST_MODE is the last machine mode index in the given optab to
3733 OPNAME is the generic (string) name of the operation.
3734 SUFFIX is the character which specifies the number of operands for
3735 the given generic operation.
3739 init_libfuncs (optable
, first_mode
, last_mode
, opname
, suffix
)
3740 register optab optable
;
3741 register char *opname
;
3742 register enum machine_mode first_mode
;
3743 register enum machine_mode last_mode
;
3744 register char suffix
;
3746 register enum machine_mode mode
;
3747 register unsigned opname_len
= strlen (opname
);
3749 for (mode
= first_mode
; mode
<= last_mode
; mode
++)
3751 register char *mname
= mode_name
[(int) mode
];
3752 register unsigned mname_len
= strlen (mname
);
3753 register char *libfunc_name
3754 = (char *) xmalloc (2 + opname_len
+ mname_len
+ 1 + 1);
3761 for (q
= opname
; *q
; )
3763 for (q
= mname
; *q
; q
++)
3764 *p
++ = tolower (*q
);
3767 optable
->handlers
[(int) mode
].libfunc
3768 = gen_rtx (SYMBOL_REF
, Pmode
, libfunc_name
);
3772 /* Initialize the libfunc fields of an entire group of entries in some
3773 optab which correspond to all integer mode operations. The parameters
3774 have the same meaning as similarly named ones for the `init_libfuncs'
3775 routine. (See above). */
3778 init_integral_libfuncs (optable
, opname
, suffix
)
3779 register optab optable
;
3780 register char *opname
;
3781 register char suffix
;
3783 init_libfuncs (optable
, SImode
, TImode
, opname
, suffix
);
3786 /* Initialize the libfunc fields of an entire group of entries in some
3787 optab which correspond to all real mode operations. The parameters
3788 have the same meaning as similarly named ones for the `init_libfuncs'
3789 routine. (See above). */
3792 init_floating_libfuncs (optable
, opname
, suffix
)
3793 register optab optable
;
3794 register char *opname
;
3795 register char suffix
;
3797 init_libfuncs (optable
, SFmode
, TFmode
, opname
, suffix
);
3800 /* Initialize the libfunc fields of an entire group of entries in some
3801 optab which correspond to all complex floating modes. The parameters
3802 have the same meaning as similarly named ones for the `init_libfuncs'
3803 routine. (See above). */
3806 init_complex_libfuncs (optable
, opname
, suffix
)
3807 register optab optable
;
3808 register char *opname
;
3809 register char suffix
;
3811 init_libfuncs (optable
, SCmode
, TCmode
, opname
, suffix
);
3814 /* Call this once to initialize the contents of the optabs
3815 appropriately for the current target machine. */
3826 add_optab
= init_optab (PLUS
);
3827 sub_optab
= init_optab (MINUS
);
3828 smul_optab
= init_optab (MULT
);
3829 smul_widen_optab
= init_optab (UNKNOWN
);
3830 umul_widen_optab
= init_optab (UNKNOWN
);
3831 sdiv_optab
= init_optab (DIV
);
3832 sdivmod_optab
= init_optab (UNKNOWN
);
3833 udiv_optab
= init_optab (UDIV
);
3834 udivmod_optab
= init_optab (UNKNOWN
);
3835 smod_optab
= init_optab (MOD
);
3836 umod_optab
= init_optab (UMOD
);
3837 flodiv_optab
= init_optab (DIV
);
3838 ftrunc_optab
= init_optab (UNKNOWN
);
3839 and_optab
= init_optab (AND
);
3840 ior_optab
= init_optab (IOR
);
3841 xor_optab
= init_optab (XOR
);
3842 ashl_optab
= init_optab (ASHIFT
);
3843 ashr_optab
= init_optab (ASHIFTRT
);
3844 lshl_optab
= init_optab (LSHIFT
);
3845 lshr_optab
= init_optab (LSHIFTRT
);
3846 rotl_optab
= init_optab (ROTATE
);
3847 rotr_optab
= init_optab (ROTATERT
);
3848 smin_optab
= init_optab (SMIN
);
3849 smax_optab
= init_optab (SMAX
);
3850 umin_optab
= init_optab (UMIN
);
3851 umax_optab
= init_optab (UMAX
);
3852 mov_optab
= init_optab (UNKNOWN
);
3853 movstrict_optab
= init_optab (UNKNOWN
);
3854 cmp_optab
= init_optab (UNKNOWN
);
3855 ucmp_optab
= init_optab (UNKNOWN
);
3856 tst_optab
= init_optab (UNKNOWN
);
3857 neg_optab
= init_optab (NEG
);
3858 abs_optab
= init_optab (ABS
);
3859 one_cmpl_optab
= init_optab (NOT
);
3860 ffs_optab
= init_optab (FFS
);
3861 sqrt_optab
= init_optab (SQRT
);
3862 sin_optab
= init_optab (UNKNOWN
);
3863 cos_optab
= init_optab (UNKNOWN
);
3864 strlen_optab
= init_optab (UNKNOWN
);
3868 add_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_addqi3
;
3872 add_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_addhi3
;
3876 add_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_addpsi3
;
3880 add_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_addsi3
;
3884 add_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_adddi3
;
3888 add_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_addti3
;
3892 add_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_addsf3
;
3896 add_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_adddf3
;
3900 add_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_addxf3
;
3904 add_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_addtf3
;
3906 init_integral_libfuncs (add_optab
, "add", '3');
3907 init_floating_libfuncs (add_optab
, "add", '3');
3911 sub_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_subqi3
;
3915 sub_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_subhi3
;
3919 sub_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_subpsi3
;
3923 sub_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_subsi3
;
3927 sub_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_subdi3
;
3931 sub_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_subti3
;
3935 sub_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_subsf3
;
3939 sub_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_subdf3
;
3943 sub_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_subxf3
;
3947 sub_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_subtf3
;
3949 init_integral_libfuncs (sub_optab
, "sub", '3');
3950 init_floating_libfuncs (sub_optab
, "sub", '3');
3954 smul_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_mulqi3
;
3958 smul_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_mulhi3
;
3962 smul_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_mulpsi3
;
3966 smul_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_mulsi3
;
3970 smul_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_muldi3
;
3974 smul_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_multi3
;
3978 smul_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_mulsf3
;
3982 smul_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_muldf3
;
3986 smul_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_mulxf3
;
3990 smul_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_multf3
;
3992 init_integral_libfuncs (smul_optab
, "mul", '3');
3993 init_floating_libfuncs (smul_optab
, "mul", '3');
3995 #ifdef MULSI3_LIBCALL
3996 smul_optab
->handlers
[(int) SImode
].libfunc
3997 = gen_rtx (SYMBOL_REF
, Pmode
, MULSI3_LIBCALL
);
3999 #ifdef MULDI3_LIBCALL
4000 smul_optab
->handlers
[(int) DImode
].libfunc
4001 = gen_rtx (SYMBOL_REF
, Pmode
, MULDI3_LIBCALL
);
4003 #ifdef MULTI3_LIBCALL
4004 smul_optab
->handlers
[(int) TImode
].libfunc
4005 = gen_rtx (SYMBOL_REF
, Pmode
, MULTI3_LIBCALL
);
4008 #ifdef HAVE_mulqihi3
4010 smul_widen_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_mulqihi3
;
4012 #ifdef HAVE_mulhisi3
4014 smul_widen_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_mulhisi3
;
4016 #ifdef HAVE_mulsidi3
4018 smul_widen_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_mulsidi3
;
4020 #ifdef HAVE_mulditi3
4022 smul_widen_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_mulditi3
;
4025 #ifdef HAVE_umulqihi3
4027 umul_widen_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_umulqihi3
;
4029 #ifdef HAVE_umulhisi3
4031 umul_widen_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_umulhisi3
;
4033 #ifdef HAVE_umulsidi3
4035 umul_widen_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_umulsidi3
;
4037 #ifdef HAVE_umulditi3
4039 umul_widen_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_umulditi3
;
4044 sdiv_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_divqi3
;
4048 sdiv_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_divhi3
;
4052 sdiv_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_divpsi3
;
4056 sdiv_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_divsi3
;
4060 sdiv_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_divdi3
;
4064 sdiv_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_divti3
;
4066 init_integral_libfuncs (sdiv_optab
, "div", '3');
4068 #ifdef DIVSI3_LIBCALL
4069 sdiv_optab
->handlers
[(int) SImode
].libfunc
4070 = gen_rtx (SYMBOL_REF
, Pmode
, DIVSI3_LIBCALL
);
4072 #ifdef DIVDI3_LIBCALL
4073 sdiv_optab
->handlers
[(int) DImode
].libfunc
4074 = gen_rtx (SYMBOL_REF
, Pmode
, DIVDI3_LIBCALL
);
4076 #ifdef DIVTI3_LIBCALL
4077 sdiv_optab
->handlers
[(int) TImode
].libfunc
4078 = gen_rtx (SYMBOL_REF
, Pmode
, DIVTI3_LIBCALL
);
4083 udiv_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_udivqi3
;
4087 udiv_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_udivhi3
;
4089 #ifdef HAVE_udivpsi3
4091 udiv_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_udivpsi3
;
4095 udiv_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_udivsi3
;
4099 udiv_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_udivdi3
;
4103 udiv_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_udivti3
;
4105 init_integral_libfuncs (udiv_optab
, "udiv", '3');
4107 #ifdef UDIVSI3_LIBCALL
4108 udiv_optab
->handlers
[(int) SImode
].libfunc
4109 = gen_rtx (SYMBOL_REF
, Pmode
, UDIVSI3_LIBCALL
);
4111 #ifdef UDIVDI3_LIBCALL
4112 udiv_optab
->handlers
[(int) DImode
].libfunc
4113 = gen_rtx (SYMBOL_REF
, Pmode
, UDIVDI3_LIBCALL
);
4115 #ifdef UDIVTI3_LIBCALL
4116 udiv_optab
->handlers
[(int) TImode
].libfunc
4117 = gen_rtx (SYMBOL_REF
, Pmode
, UDIVTI3_LIBCALL
);
4120 #ifdef HAVE_divmodqi4
4122 sdivmod_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_divmodqi4
;
4124 #ifdef HAVE_divmodhi4
4126 sdivmod_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_divmodhi4
;
4128 #ifdef HAVE_divmodsi4
4130 sdivmod_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_divmodsi4
;
4132 #ifdef HAVE_divmoddi4
4134 sdivmod_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_divmoddi4
;
4136 #ifdef HAVE_divmodti4
4138 sdivmod_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_divmodti4
;
4140 init_integral_libfuncs (sdivmod_optab
, "divmod", '4');
4142 #ifdef HAVE_udivmodqi4
4143 if (HAVE_udivmodqi4
)
4144 udivmod_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_udivmodqi4
;
4146 #ifdef HAVE_udivmodhi4
4147 if (HAVE_udivmodhi4
)
4148 udivmod_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_udivmodhi4
;
4150 #ifdef HAVE_udivmodsi4
4151 if (HAVE_udivmodsi4
)
4152 udivmod_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_udivmodsi4
;
4154 #ifdef HAVE_udivmoddi4
4155 if (HAVE_udivmoddi4
)
4156 udivmod_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_udivmoddi4
;
4158 #ifdef HAVE_udivmodti4
4159 if (HAVE_udivmodti4
)
4160 udivmod_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_udivmodti4
;
4162 init_integral_libfuncs (udivmod_optab
, "udivmod", '4');
4166 smod_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_modqi3
;
4170 smod_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_modhi3
;
4174 smod_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_modpsi3
;
4178 smod_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_modsi3
;
4182 smod_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_moddi3
;
4186 smod_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_modti3
;
4188 init_integral_libfuncs (smod_optab
, "mod", '3');
4190 #ifdef MODSI3_LIBCALL
4191 smod_optab
->handlers
[(int) SImode
].libfunc
4192 = gen_rtx (SYMBOL_REF
, Pmode
, MODSI3_LIBCALL
);
4194 #ifdef MODDI3_LIBCALL
4195 smod_optab
->handlers
[(int) DImode
].libfunc
4196 = gen_rtx (SYMBOL_REF
, Pmode
, MODDI3_LIBCALL
);
4198 #ifdef MODTI3_LIBCALL
4199 smod_optab
->handlers
[(int) TImode
].libfunc
4200 = gen_rtx (SYMBOL_REF
, Pmode
, MODTI3_LIBCALL
);
4205 umod_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_umodqi3
;
4209 umod_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_umodhi3
;
4211 #ifdef HAVE_umodpsi3
4213 umod_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_umodpsi3
;
4217 umod_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_umodsi3
;
4221 umod_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_umoddi3
;
4225 umod_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_umodti3
;
4227 init_integral_libfuncs (umod_optab
, "umod", '3');
4229 #ifdef UMODSI3_LIBCALL
4230 umod_optab
->handlers
[(int) SImode
].libfunc
4231 = gen_rtx (SYMBOL_REF
, Pmode
, UMODSI3_LIBCALL
);
4233 #ifdef UMODDI3_LIBCALL
4234 umod_optab
->handlers
[(int) DImode
].libfunc
4235 = gen_rtx (SYMBOL_REF
, Pmode
, UMODDI3_LIBCALL
);
4237 #ifdef UMODTI3_LIBCALL
4238 umod_optab
->handlers
[(int) TImode
].libfunc
4239 = gen_rtx (SYMBOL_REF
, Pmode
, UMODTI3_LIBCALL
);
4244 flodiv_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_divsf3
;
4248 flodiv_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_divdf3
;
4252 flodiv_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_divxf3
;
4256 flodiv_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_divtf3
;
4258 init_floating_libfuncs (flodiv_optab
, "div", '3');
4260 #ifdef HAVE_ftruncsf2
4262 ftrunc_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_ftruncsf2
;
4264 #ifdef HAVE_ftruncdf2
4266 ftrunc_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_ftruncdf2
;
4268 #ifdef HAVE_ftruncxf2
4270 ftrunc_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_ftruncxf2
;
4272 #ifdef HAVE_ftrunctf2
4274 ftrunc_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_ftrunctf2
;
4276 init_floating_libfuncs (ftrunc_optab
, "ftrunc", '2');
4280 and_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_andqi3
;
4284 and_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_andhi3
;
4288 and_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_andpsi3
;
4292 and_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_andsi3
;
4296 and_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_anddi3
;
4300 and_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_andti3
;
4302 init_integral_libfuncs (and_optab
, "and", '3');
4306 ior_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_iorqi3
;
4310 ior_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_iorhi3
;
4314 ior_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_iorpsi3
;
4318 ior_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_iorsi3
;
4322 ior_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_iordi3
;
4326 ior_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_iorti3
;
4328 init_integral_libfuncs (ior_optab
, "ior", '3');
4332 xor_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_xorqi3
;
4336 xor_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_xorhi3
;
4340 xor_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_xorpsi3
;
4344 xor_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_xorsi3
;
4348 xor_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_xordi3
;
4352 xor_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_xorti3
;
4354 init_integral_libfuncs (xor_optab
, "xor", '3');
4358 ashl_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_ashlqi3
;
4362 ashl_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_ashlhi3
;
4364 #ifdef HAVE_ashlpsi3
4366 ashl_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_ashlpsi3
;
4370 ashl_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_ashlsi3
;
4374 ashl_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_ashldi3
;
4378 ashl_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_ashlti3
;
4380 init_integral_libfuncs (ashl_optab
, "ashl", '3');
4384 ashr_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_ashrqi3
;
4388 ashr_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_ashrhi3
;
4390 #ifdef HAVE_ashrpsi3
4392 ashr_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_ashrpsi3
;
4396 ashr_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_ashrsi3
;
4400 ashr_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_ashrdi3
;
4404 ashr_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_ashrti3
;
4406 init_integral_libfuncs (ashr_optab
, "ashr", '3');
4410 lshl_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_lshlqi3
;
4414 lshl_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_lshlhi3
;
4416 #ifdef HAVE_lshlpsi3
4418 lshl_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_lshlpsi3
;
4422 lshl_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_lshlsi3
;
4426 lshl_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_lshldi3
;
4430 lshl_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_lshlti3
;
4432 init_integral_libfuncs (lshl_optab
, "lshl", '3');
4436 lshr_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_lshrqi3
;
4440 lshr_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_lshrhi3
;
4442 #ifdef HAVE_lshrpsi3
4444 lshr_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_lshrpsi3
;
4448 lshr_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_lshrsi3
;
4452 lshr_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_lshrdi3
;
4456 lshr_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_lshrti3
;
4458 init_integral_libfuncs (lshr_optab
, "lshr", '3');
4462 rotl_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_rotlqi3
;
4466 rotl_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_rotlhi3
;
4468 #ifdef HAVE_rotlpsi3
4470 rotl_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_rotlpsi3
;
4474 rotl_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_rotlsi3
;
4478 rotl_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_rotldi3
;
4482 rotl_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_rotlti3
;
4484 init_integral_libfuncs (rotl_optab
, "rotl", '3');
4488 rotr_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_rotrqi3
;
4492 rotr_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_rotrhi3
;
4494 #ifdef HAVE_rotrpsi3
4496 rotr_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_rotrpsi3
;
4500 rotr_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_rotrsi3
;
4504 rotr_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_rotrdi3
;
4508 rotr_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_rotrti3
;
4510 init_integral_libfuncs (rotr_optab
, "rotr", '3');
4514 smin_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_sminqi3
;
4518 smin_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_sminhi3
;
4522 smin_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_sminsi3
;
4526 smin_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_smindi3
;
4530 smin_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_sminti3
;
4534 smin_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_minsf3
;
4538 smin_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_mindf3
;
4542 smin_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_minxf3
;
4546 smin_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_mintf3
;
4548 init_integral_libfuncs (smin_optab
, "min", '3');
4549 init_floating_libfuncs (smin_optab
, "min", '3');
4553 smax_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_smaxqi3
;
4557 smax_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_smaxhi3
;
4561 smax_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_smaxsi3
;
4565 smax_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_smaxdi3
;
4569 smax_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_smaxti3
;
4573 smax_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_maxsf3
;
4577 smax_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_maxdf3
;
4581 smax_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_maxxf3
;
4585 smax_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_maxtf3
;
4587 init_integral_libfuncs (smax_optab
, "max", '3');
4588 init_floating_libfuncs (smax_optab
, "max", '3');
4592 umin_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_uminqi3
;
4596 umin_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_uminhi3
;
4600 umin_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_uminsi3
;
4604 umin_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_umindi3
;
4608 umin_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_uminti3
;
4610 init_integral_libfuncs (umin_optab
, "umin", '3');
4614 umax_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_umaxqi3
;
4618 umax_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_umaxhi3
;
4622 umax_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_umaxsi3
;
4626 umax_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_umaxdi3
;
4630 umax_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_umaxti3
;
4632 init_integral_libfuncs (umax_optab
, "umax", '3');
4636 neg_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_negqi2
;
4640 neg_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_neghi2
;
4644 neg_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_negpsi2
;
4648 neg_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_negsi2
;
4652 neg_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_negdi2
;
4656 neg_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_negti2
;
4660 neg_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_negsf2
;
4664 neg_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_negdf2
;
4668 neg_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_negxf2
;
4672 neg_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_negtf2
;
4674 init_integral_libfuncs (neg_optab
, "neg", '2');
4675 init_floating_libfuncs (neg_optab
, "neg", '2');
4679 abs_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_absqi2
;
4683 abs_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_abshi2
;
4687 abs_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_abspsi2
;
4691 abs_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_abssi2
;
4695 abs_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_absdi2
;
4699 abs_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_absti2
;
4703 abs_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_abssf2
;
4707 abs_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_absdf2
;
4711 abs_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_absxf2
;
4715 abs_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_abstf2
;
4718 /* Use cabs for DC complex abs, since systems generally have cabs.
4719 Don't define any libcall for SCmode, so that cabs will be used. */
4720 abs_optab
->handlers
[(int) DCmode
].libfunc
4721 = gen_rtx (SYMBOL_REF
, Pmode
, "cabs");
4725 sqrt_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_sqrtqi2
;
4729 sqrt_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_sqrthi2
;
4731 #ifdef HAVE_sqrtpsi2
4733 sqrt_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_sqrtpsi2
;
4737 sqrt_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_sqrtsi2
;
4741 sqrt_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_sqrtdi2
;
4745 sqrt_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_sqrtti2
;
4749 sqrt_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_sqrtsf2
;
4753 sqrt_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_sqrtdf2
;
4757 sqrt_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_sqrttf2
;
4759 /* No library calls here! If there is no sqrt instruction expand_builtin
4760 should force the library call. */
4764 sin_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_sinsf2
;
4768 sin_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_sindf2
;
4772 sin_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_sintf2
;
4774 /* No library calls here! If there is no sin instruction expand_builtin
4775 should force the library call. */
4779 cos_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_cossf2
;
4783 cos_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_cosdf2
;
4787 cos_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_costf2
;
4789 /* No library calls here! If there is no cos instruction expand_builtin
4790 should force the library call. */
4792 #ifdef HAVE_strlenqi
4794 strlen_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_strlenqi
;
4796 #ifdef HAVE_strlenhi
4798 strlen_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_strlenhi
;
4800 #ifdef HAVE_strlenpsi
4802 strlen_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_strlenpsi
;
4804 #ifdef HAVE_strlensi
4806 strlen_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_strlensi
;
4808 #ifdef HAVE_strlendi
4810 strlen_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_strlendi
;
4812 #ifdef HAVE_strlenti
4814 strlen_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_strlenti
;
4816 /* No library calls here! If there is no strlen instruction expand_builtin
4817 should force the library call. */
4819 #ifdef HAVE_one_cmplqi2
4820 if (HAVE_one_cmplqi2
)
4821 one_cmpl_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_one_cmplqi2
;
4823 #ifdef HAVE_one_cmplhi2
4824 if (HAVE_one_cmplhi2
)
4825 one_cmpl_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_one_cmplhi2
;
4827 #ifdef HAVE_one_cmplpsi2
4828 if (HAVE_one_cmplpsi2
)
4829 one_cmpl_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_one_cmplpsi2
;
4831 #ifdef HAVE_one_cmplsi2
4832 if (HAVE_one_cmplsi2
)
4833 one_cmpl_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_one_cmplsi2
;
4835 #ifdef HAVE_one_cmpldi2
4836 if (HAVE_one_cmpldi2
)
4837 one_cmpl_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_one_cmpldi2
;
4839 #ifdef HAVE_one_cmplti2
4840 if (HAVE_one_cmplti2
)
4841 one_cmpl_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_one_cmplti2
;
4843 init_integral_libfuncs (one_cmpl_optab
, "one_cmpl", '2');
4847 ffs_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_ffsqi2
;
4851 ffs_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_ffshi2
;
4855 ffs_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_ffspsi2
;
4859 ffs_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_ffssi2
;
4863 ffs_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_ffsdi2
;
4867 ffs_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_ffsti2
;
4869 init_integral_libfuncs (ffs_optab
, "ffs", '2');
4873 mov_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_movqi
;
4877 mov_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_movhi
;
4881 mov_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_movpsi
;
4885 mov_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_movsi
;
4889 mov_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_movdi
;
4893 mov_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_movti
;
4897 mov_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_movsf
;
4901 mov_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_movdf
;
4905 mov_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_movxf
;
4909 mov_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_movtf
;
4913 mov_optab
->handlers
[(int) CCmode
].insn_code
= CODE_FOR_movcc
;
4916 #ifdef EXTRA_CC_MODES
4920 #ifdef HAVE_movstrictqi
4921 if (HAVE_movstrictqi
)
4922 movstrict_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_movstrictqi
;
4924 #ifdef HAVE_movstricthi
4925 if (HAVE_movstricthi
)
4926 movstrict_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_movstricthi
;
4928 #ifdef HAVE_movstrictpsi
4929 if (HAVE_movstrictpsi
)
4930 movstrict_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_movstrictpsi
;
4932 #ifdef HAVE_movstrictsi
4933 if (HAVE_movstrictsi
)
4934 movstrict_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_movstrictsi
;
4936 #ifdef HAVE_movstrictdi
4937 if (HAVE_movstrictdi
)
4938 movstrict_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_movstrictdi
;
4940 #ifdef HAVE_movstrictti
4941 if (HAVE_movstrictti
)
4942 movstrict_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_movstrictti
;
4947 cmp_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_cmpqi
;
4951 cmp_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_cmphi
;
4955 cmp_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_cmppsi
;
4959 cmp_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_cmpsi
;
4963 cmp_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_cmpdi
;
4967 cmp_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_cmpti
;
4971 cmp_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_cmpsf
;
4975 cmp_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_cmpdf
;
4979 cmp_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_cmpxf
;
4983 cmp_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_cmptf
;
4985 /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
4986 init_integral_libfuncs (cmp_optab
, "cmp", '2');
4987 init_integral_libfuncs (ucmp_optab
, "ucmp", '2');
4988 init_floating_libfuncs (cmp_optab
, "cmp", '2');
4992 tst_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_tstqi
;
4996 tst_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_tsthi
;
5000 tst_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_tstpsi
;
5004 tst_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_tstsi
;
5008 tst_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_tstdi
;
5012 tst_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_tstti
;
5016 tst_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_tstsf
;
5020 tst_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_tstdf
;
5024 tst_optab
->handlers
[(int) XFmode
].insn_code
= CODE_FOR_tstxf
;
5028 tst_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_tsttf
;
5033 bcc_gen_fctn
[(int) EQ
] = gen_beq
;
5037 bcc_gen_fctn
[(int) NE
] = gen_bne
;
5041 bcc_gen_fctn
[(int) GT
] = gen_bgt
;
5045 bcc_gen_fctn
[(int) GE
] = gen_bge
;
5049 bcc_gen_fctn
[(int) GTU
] = gen_bgtu
;
5053 bcc_gen_fctn
[(int) GEU
] = gen_bgeu
;
5057 bcc_gen_fctn
[(int) LT
] = gen_blt
;
5061 bcc_gen_fctn
[(int) LE
] = gen_ble
;
5065 bcc_gen_fctn
[(int) LTU
] = gen_bltu
;
5069 bcc_gen_fctn
[(int) LEU
] = gen_bleu
;
5072 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
5073 setcc_gen_code
[i
] = CODE_FOR_nothing
;
5077 setcc_gen_code
[(int) EQ
] = CODE_FOR_seq
;
5081 setcc_gen_code
[(int) NE
] = CODE_FOR_sne
;
5085 setcc_gen_code
[(int) GT
] = CODE_FOR_sgt
;
5089 setcc_gen_code
[(int) GE
] = CODE_FOR_sge
;
5093 setcc_gen_code
[(int) GTU
] = CODE_FOR_sgtu
;
5097 setcc_gen_code
[(int) GEU
] = CODE_FOR_sgeu
;
5101 setcc_gen_code
[(int) LT
] = CODE_FOR_slt
;
5105 setcc_gen_code
[(int) LE
] = CODE_FOR_sle
;
5109 setcc_gen_code
[(int) LTU
] = CODE_FOR_sltu
;
5113 setcc_gen_code
[(int) LEU
] = CODE_FOR_sleu
;
5116 extendsfdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extendsfdf2");
5117 extendsfxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extendsfxf2");
5118 extendsftf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extendsftf2");
5119 extenddfxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extenddfxf2");
5120 extenddftf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extenddftf2");
5122 truncdfsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__truncdfsf2");
5123 truncxfsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__truncxfsf2");
5124 trunctfsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__trunctfsf2");
5125 truncxfdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__truncxfdf2");
5126 trunctfdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__trunctfdf2");
5128 memcpy_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "memcpy");
5129 bcopy_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "bcopy");
5130 memcmp_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "memcmp");
5131 bcmp_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gcc_bcmp");
5132 memset_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "memset");
5133 bzero_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "bzero");
5135 eqsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqsf2");
5136 nesf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__nesf2");
5137 gtsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gtsf2");
5138 gesf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gesf2");
5139 ltsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ltsf2");
5140 lesf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__lesf2");
5142 eqdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqdf2");
5143 nedf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__nedf2");
5144 gtdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gtdf2");
5145 gedf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gedf2");
5146 ltdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ltdf2");
5147 ledf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ledf2");
5149 eqxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqxf2");
5150 nexf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__nexf2");
5151 gtxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gtxf2");
5152 gexf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gexf2");
5153 ltxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ltxf2");
5154 lexf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__lexf2");
5156 eqtf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqtf2");
5157 netf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__netf2");
5158 gttf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gttf2");
5159 getf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__getf2");
5160 lttf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__lttf2");
5161 letf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__letf2");
5163 floatsisf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatsisf");
5164 floatdisf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatdisf");
5165 floattisf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floattisf");
5167 floatsidf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatsidf");
5168 floatdidf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatdidf");
5169 floattidf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floattidf");
5171 floatsixf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatsixf");
5172 floatdixf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatdixf");
5173 floattixf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floattixf");
5175 floatsitf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatsitf");
5176 floatditf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatditf");
5177 floattitf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floattitf");
5179 fixsfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixsfsi");
5180 fixsfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixsfdi");
5181 fixsfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixsfti");
5183 fixdfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixdfsi");
5184 fixdfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixdfdi");
5185 fixdfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixdfti");
5187 fixxfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixxfsi");
5188 fixxfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixxfdi");
5189 fixxfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixxfti");
5191 fixtfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixtfsi");
5192 fixtfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixtfdi");
5193 fixtfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixtfti");
5195 fixunssfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunssfsi");
5196 fixunssfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunssfdi");
5197 fixunssfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunssfti");
5199 fixunsdfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsdfsi");
5200 fixunsdfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsdfdi");
5201 fixunsdfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsdfti");
5203 fixunsxfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsxfsi");
5204 fixunsxfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsxfdi");
5205 fixunsxfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsxfti");
5207 fixunstfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunstfsi");
5208 fixunstfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunstfdi");
5209 fixunstfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunstfti");
5214 /* SCO 3.2 apparently has a broken ldexp. */
5227 #endif /* BROKEN_LDEXP */