]>
gcc.gnu.org Git - gcc.git/blob - gcc/optabs.c
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"
33 /* Each optab contains info on how this target machine
34 can perform a particular operation
35 for all sizes and kinds of operands.
37 The operation to be performed is often specified
38 by passing one of these optabs as an argument.
40 See expr.h for documentation of these optabs. */
45 optab smul_widen_optab
;
46 optab umul_widen_optab
;
70 optab movstrict_optab
;
81 optab ucmp_optab
; /* Used only for libcalls for unsigned comparisons. */
86 /* Tables of patterns for extending one integer mode to another. */
87 enum insn_code extendtab
[MAX_MACHINE_MODE
][MAX_MACHINE_MODE
][2];
89 /* Tables of patterns for converting between fixed and floating point. */
90 enum insn_code fixtab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
91 enum insn_code fixtrunctab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
92 enum insn_code floattab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
94 /* SYMBOL_REF rtx's for the library functions that are called
95 implicitly and not via optabs. */
97 rtx extendsfdf2_libfunc
;
98 rtx extendsfxf2_libfunc
;
99 rtx extendsftf2_libfunc
;
100 rtx extenddfxf2_libfunc
;
101 rtx extenddftf2_libfunc
;
103 rtx truncdfsf2_libfunc
;
104 rtx truncxfsf2_libfunc
;
105 rtx trunctfsf2_libfunc
;
106 rtx truncxfdf2_libfunc
;
107 rtx trunctfdf2_libfunc
;
144 rtx floatsisf_libfunc
;
145 rtx floatdisf_libfunc
;
146 rtx floattisf_libfunc
;
148 rtx floatsidf_libfunc
;
149 rtx floatdidf_libfunc
;
150 rtx floattidf_libfunc
;
152 rtx floatsixf_libfunc
;
153 rtx floatdixf_libfunc
;
154 rtx floattixf_libfunc
;
156 rtx floatsitf_libfunc
;
157 rtx floatditf_libfunc
;
158 rtx floattitf_libfunc
;
176 rtx fixunssfsi_libfunc
;
177 rtx fixunssfdi_libfunc
;
178 rtx fixunssfti_libfunc
;
180 rtx fixunsdfsi_libfunc
;
181 rtx fixunsdfdi_libfunc
;
182 rtx fixunsdfti_libfunc
;
184 rtx fixunsxfsi_libfunc
;
185 rtx fixunsxfdi_libfunc
;
186 rtx fixunsxfti_libfunc
;
188 rtx fixunstfsi_libfunc
;
189 rtx fixunstfdi_libfunc
;
190 rtx fixunstfti_libfunc
;
192 /* from emit-rtl.c */
193 extern rtx
gen_highpart ();
195 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
196 gives the gen_function to make a branch to test that condition. */
198 rtxfun bcc_gen_fctn
[NUM_RTX_CODE
];
200 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
201 gives the insn code to make a store-condition insn
202 to test that condition. */
204 enum insn_code setcc_gen_code
[NUM_RTX_CODE
];
206 static int add_equal_note
PROTO((rtx
, rtx
, enum rtx_code
, rtx
, rtx
));
207 static void emit_float_lib_cmp
PROTO((rtx
, rtx
, enum rtx_code
));
208 static enum insn_code can_fix_p
PROTO((enum machine_mode
, enum machine_mode
,
210 static enum insn_code can_float_p
PROTO((enum machine_mode
, enum machine_mode
,
212 static rtx ftruncify
PROTO((rtx
));
213 static optab init_optab
PROTO((enum rtx_code
));
214 static void init_libfuncs
PROTO((optab
, int, int, char *, int));
215 static void init_integral_libfuncs
PROTO((optab
, char *, int));
216 static void init_floating_libfuncs
PROTO((optab
, char *, int));
217 static void init_complex_libfuncs
PROTO((optab
, char *, int));
219 /* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
220 the result of operation CODE applied to OP0 (and OP1 if it is a binary
223 If the last insn does not set TARGET, don't do anything, but return 1.
225 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
226 don't add the REG_EQUAL note but return 0. Our caller can then try
227 again, ensuring that TARGET is not one of the operands. */
230 add_equal_note (seq
, target
, code
, op0
, op1
)
240 if ((GET_RTX_CLASS (code
) != '1' && GET_RTX_CLASS (code
) != '2'
241 && GET_RTX_CLASS (code
) != 'c' && GET_RTX_CLASS (code
) != '<')
242 || GET_CODE (seq
) != SEQUENCE
243 || (set
= single_set (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1))) == 0
244 || GET_CODE (target
) == ZERO_EXTRACT
245 || (! rtx_equal_p (SET_DEST (set
), target
)
246 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
248 && (GET_CODE (SET_DEST (set
)) != STRICT_LOW_PART
249 || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set
), 0)),
253 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
254 besides the last insn. */
255 if (reg_overlap_mentioned_p (target
, op0
)
256 || (op1
&& reg_overlap_mentioned_p (target
, op1
)))
257 for (i
= XVECLEN (seq
, 0) - 2; i
>= 0; i
--)
258 if (reg_set_p (target
, XVECEXP (seq
, 0, i
)))
261 if (GET_RTX_CLASS (code
) == '1')
262 note
= gen_rtx (code
, GET_MODE (target
), op0
);
264 note
= gen_rtx (code
, GET_MODE (target
), op0
, op1
);
266 REG_NOTES (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1))
267 = gen_rtx (EXPR_LIST
, REG_EQUAL
, note
,
268 REG_NOTES (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1)));
273 /* Generate code to perform an operation specified by BINOPTAB
274 on operands OP0 and OP1, with result having machine-mode MODE.
276 UNSIGNEDP is for the case where we have to widen the operands
277 to perform the operation. It says to use zero-extension.
279 If TARGET is nonzero, the value
280 is generated there, if it is convenient to do so.
281 In all cases an rtx is returned for the locus of the value;
282 this may or may not be TARGET. */
285 expand_binop (mode
, binoptab
, op0
, op1
, target
, unsignedp
, methods
)
286 enum machine_mode mode
;
291 enum optab_methods methods
;
293 enum mode_class
class;
294 enum machine_mode wider_mode
;
296 int commutative_op
= 0;
297 int shift_op
= (binoptab
->code
== ASHIFT
298 || binoptab
->code
== ASHIFTRT
299 || binoptab
->code
== LSHIFT
300 || binoptab
->code
== LSHIFTRT
301 || binoptab
->code
== ROTATE
302 || binoptab
->code
== ROTATERT
);
303 rtx entry_last
= get_last_insn ();
306 class = GET_MODE_CLASS (mode
);
308 op0
= protect_from_queue (op0
, 0);
309 op1
= protect_from_queue (op1
, 0);
311 target
= protect_from_queue (target
, 1);
315 op0
= force_not_mem (op0
);
316 op1
= force_not_mem (op1
);
319 /* If subtracting an integer constant, convert this into an addition of
320 the negated constant. */
322 if (binoptab
== sub_optab
&& GET_CODE (op1
) == CONST_INT
)
324 op1
= negate_rtx (mode
, op1
);
325 binoptab
= add_optab
;
328 /* If we are inside an appropriately-short loop and one operand is an
329 expensive constant, force it into a register. */
330 if (CONSTANT_P (op0
) && preserve_subexpressions_p ()
331 && rtx_cost (op0
, binoptab
->code
) > 2)
332 op0
= force_reg (mode
, op0
);
334 if (CONSTANT_P (op1
) && preserve_subexpressions_p ()
335 && rtx_cost (op1
, binoptab
->code
) > 2)
336 op1
= force_reg (shift_op
? word_mode
: mode
, op1
);
338 /* Record where to delete back to if we backtrack. */
339 last
= get_last_insn ();
341 /* If operation is commutative,
342 try to make the first operand a register.
343 Even better, try to make it the same as the target.
344 Also try to make the last operand a constant. */
345 if (GET_RTX_CLASS (binoptab
->code
) == 'c'
346 || binoptab
== smul_widen_optab
347 || binoptab
== umul_widen_optab
)
351 if (((target
== 0 || GET_CODE (target
) == REG
)
352 ? ((GET_CODE (op1
) == REG
353 && GET_CODE (op0
) != REG
)
355 : rtx_equal_p (op1
, target
))
356 || GET_CODE (op0
) == CONST_INT
)
364 /* If we can do it with a three-operand insn, do so. */
366 if (methods
!= OPTAB_MUST_WIDEN
367 && binoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
369 int icode
= (int) binoptab
->handlers
[(int) mode
].insn_code
;
370 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
371 enum machine_mode mode1
= insn_operand_mode
[icode
][2];
373 rtx xop0
= op0
, xop1
= op1
;
378 temp
= gen_reg_rtx (mode
);
380 /* If it is a commutative operator and the modes would match
381 if we would swap the operands, we can save the conversions. */
384 if (GET_MODE (op0
) != mode0
&& GET_MODE (op1
) != mode1
385 && GET_MODE (op0
) == mode1
&& GET_MODE (op1
) == mode0
)
389 tmp
= op0
; op0
= op1
; op1
= tmp
;
390 tmp
= xop0
; xop0
= xop1
; xop1
= tmp
;
394 /* In case the insn wants input operands in modes different from
395 the result, convert the operands. */
397 if (GET_MODE (op0
) != VOIDmode
398 && GET_MODE (op0
) != mode0
)
399 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
401 if (GET_MODE (xop1
) != VOIDmode
402 && GET_MODE (xop1
) != mode1
)
403 xop1
= convert_to_mode (mode1
, xop1
, unsignedp
);
405 /* Now, if insn's predicates don't allow our operands, put them into
408 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
409 xop0
= copy_to_mode_reg (mode0
, xop0
);
411 if (! (*insn_operand_predicate
[icode
][2]) (xop1
, mode1
))
412 xop1
= copy_to_mode_reg (mode1
, xop1
);
414 if (! (*insn_operand_predicate
[icode
][0]) (temp
, mode
))
415 temp
= gen_reg_rtx (mode
);
417 pat
= GEN_FCN (icode
) (temp
, xop0
, xop1
);
420 /* If PAT is a multi-insn sequence, try to add an appropriate
421 REG_EQUAL note to it. If we can't because TEMP conflicts with an
422 operand, call ourselves again, this time without a target. */
423 if (GET_CODE (pat
) == SEQUENCE
424 && ! add_equal_note (pat
, temp
, binoptab
->code
, xop0
, xop1
))
426 delete_insns_since (last
);
427 return expand_binop (mode
, binoptab
, op0
, op1
, NULL_RTX
,
435 delete_insns_since (last
);
438 /* If this is a multiply, see if we can do a widening operation that
439 takes operands of this mode and makes a wider mode. */
441 if (binoptab
== smul_optab
&& GET_MODE_WIDER_MODE (mode
) != VOIDmode
442 && (((unsignedp
? umul_widen_optab
: smul_widen_optab
)
443 ->handlers
[(int) GET_MODE_WIDER_MODE (mode
)].insn_code
)
444 != CODE_FOR_nothing
))
446 temp
= expand_binop (GET_MODE_WIDER_MODE (mode
),
447 unsignedp
? umul_widen_optab
: smul_widen_optab
,
448 op0
, op1
, 0, unsignedp
, OPTAB_DIRECT
);
450 if (GET_MODE_CLASS (mode
) == MODE_INT
)
451 return gen_lowpart (mode
, temp
);
453 return convert_to_mode (mode
, temp
, unsignedp
);
456 /* Look for a wider mode of the same class for which we think we
457 can open-code the operation. Check for a widening multiply at the
458 wider mode as well. */
460 if ((class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
461 && methods
!= OPTAB_DIRECT
&& methods
!= OPTAB_LIB
)
462 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
463 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
465 if (binoptab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
466 || (binoptab
== smul_optab
467 && GET_MODE_WIDER_MODE (wider_mode
) != VOIDmode
468 && (((unsignedp
? umul_widen_optab
: smul_widen_optab
)
469 ->handlers
[(int) GET_MODE_WIDER_MODE (wider_mode
)].insn_code
)
470 != CODE_FOR_nothing
)))
472 rtx xop0
= op0
, xop1
= op1
;
475 /* For certain integer operations, we need not actually extend
476 the narrow operands, as long as we will truncate
477 the results to the same narrowness. Don't do this when
478 WIDER_MODE is wider than a word since a paradoxical SUBREG
479 isn't valid for such modes. */
481 if ((binoptab
== ior_optab
|| binoptab
== and_optab
482 || binoptab
== xor_optab
483 || binoptab
== add_optab
|| binoptab
== sub_optab
484 || binoptab
== smul_optab
485 || binoptab
== ashl_optab
|| binoptab
== lshl_optab
)
487 && GET_MODE_SIZE (wider_mode
) <= UNITS_PER_WORD
)
490 /* If an operand is a constant integer, we might as well
491 convert it since that is more efficient than using a SUBREG,
492 unlike the case for other operands. Similarly for
493 SUBREGs that were made due to promoted objects. */
495 if (no_extend
&& GET_MODE (xop0
) != VOIDmode
496 && ! (GET_CODE (xop0
) == SUBREG
497 && SUBREG_PROMOTED_VAR_P (xop0
)))
498 xop0
= gen_rtx (SUBREG
, wider_mode
,
499 force_reg (GET_MODE (xop0
), xop0
), 0);
501 xop0
= convert_to_mode (wider_mode
, xop0
, unsignedp
);
503 if (no_extend
&& GET_MODE (xop1
) != VOIDmode
504 && ! (GET_CODE (xop1
) == SUBREG
505 && SUBREG_PROMOTED_VAR_P (xop1
)))
506 xop1
= gen_rtx (SUBREG
, wider_mode
,
507 force_reg (GET_MODE (xop1
), xop1
), 0);
509 xop1
= convert_to_mode (wider_mode
, xop1
, unsignedp
);
511 temp
= expand_binop (wider_mode
, binoptab
, xop0
, xop1
, NULL_RTX
,
512 unsignedp
, OPTAB_DIRECT
);
515 if (class != MODE_INT
)
518 target
= gen_reg_rtx (mode
);
519 convert_move (target
, temp
, 0);
523 return gen_lowpart (mode
, temp
);
526 delete_insns_since (last
);
530 /* These can be done a word at a time. */
531 if ((binoptab
== and_optab
|| binoptab
== ior_optab
|| binoptab
== xor_optab
)
533 && GET_MODE_SIZE (mode
) > UNITS_PER_WORD
534 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
540 /* If TARGET is the same as one of the operands, the REG_EQUAL note
541 won't be accurate, so use a new target. */
542 if (target
== 0 || target
== op0
|| target
== op1
)
543 target
= gen_reg_rtx (mode
);
547 /* Do the actual arithmetic. */
548 for (i
= 0; i
< GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
; i
++)
550 rtx target_piece
= operand_subword (target
, i
, 1, mode
);
551 rtx x
= expand_binop (word_mode
, binoptab
,
552 operand_subword_force (op0
, i
, mode
),
553 operand_subword_force (op1
, i
, mode
),
554 target_piece
, unsignedp
, methods
);
555 if (target_piece
!= x
)
556 emit_move_insn (target_piece
, x
);
559 insns
= get_insns ();
562 if (binoptab
->code
!= UNKNOWN
)
563 equiv_value
= gen_rtx (binoptab
->code
, mode
, op0
, op1
);
567 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv_value
);
571 /* These can be done a word at a time by propagating carries. */
572 if ((binoptab
== add_optab
|| binoptab
== sub_optab
)
574 && GET_MODE_SIZE (mode
) >= 2 * UNITS_PER_WORD
575 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
578 rtx carry_tmp
= gen_reg_rtx (word_mode
);
579 optab otheroptab
= binoptab
== add_optab
? sub_optab
: add_optab
;
580 int nwords
= GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
;
581 rtx carry_in
, carry_out
;
584 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
585 value is one of those, use it. Otherwise, use 1 since it is the
586 one easiest to get. */
587 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
588 int normalizep
= STORE_FLAG_VALUE
;
593 /* Prepare the operands. */
594 xop0
= force_reg (mode
, op0
);
595 xop1
= force_reg (mode
, op1
);
597 if (target
== 0 || GET_CODE (target
) != REG
598 || target
== xop0
|| target
== xop1
)
599 target
= gen_reg_rtx (mode
);
601 /* Indicate for flow that the entire target reg is being set. */
602 if (GET_CODE (target
) == REG
)
603 emit_insn (gen_rtx (CLOBBER
, VOIDmode
, target
));
605 /* Do the actual arithmetic. */
606 for (i
= 0; i
< nwords
; i
++)
608 int index
= (WORDS_BIG_ENDIAN
? nwords
- i
- 1 : i
);
609 rtx target_piece
= operand_subword (target
, index
, 1, mode
);
610 rtx op0_piece
= operand_subword_force (xop0
, index
, mode
);
611 rtx op1_piece
= operand_subword_force (xop1
, index
, mode
);
614 /* Main add/subtract of the input operands. */
615 x
= expand_binop (word_mode
, binoptab
,
616 op0_piece
, op1_piece
,
617 target_piece
, unsignedp
, methods
);
623 /* Store carry from main add/subtract. */
624 carry_out
= gen_reg_rtx (word_mode
);
625 carry_out
= emit_store_flag (carry_out
,
626 binoptab
== add_optab
? LTU
: GTU
,
628 word_mode
, 1, normalizep
);
635 /* Add/subtract previous carry to main result. */
636 x
= expand_binop (word_mode
,
637 normalizep
== 1 ? binoptab
: otheroptab
,
639 target_piece
, 1, methods
);
640 if (target_piece
!= x
)
641 emit_move_insn (target_piece
, x
);
645 /* THIS CODE HAS NOT BEEN TESTED. */
646 /* Get out carry from adding/subtracting carry in. */
647 carry_tmp
= emit_store_flag (carry_tmp
,
648 binoptab
== add_optab
651 word_mode
, 1, normalizep
);
652 /* Logical-ior the two poss. carry together. */
653 carry_out
= expand_binop (word_mode
, ior_optab
,
654 carry_out
, carry_tmp
,
655 carry_out
, 0, methods
);
661 carry_in
= carry_out
;
664 if (i
== GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
)
668 temp
= emit_move_insn (target
, target
);
669 REG_NOTES (temp
) = gen_rtx (EXPR_LIST
, REG_EQUAL
,
670 gen_rtx (binoptab
->code
, mode
, xop0
, xop1
),
675 delete_insns_since (last
);
678 /* If we want to multiply two two-word values and have normal and widening
679 multiplies of single-word values, we can do this with three smaller
680 multiplications. Note that we do not make a REG_NO_CONFLICT block here
681 because we are not operating on one word at a time.
683 The multiplication proceeds as follows:
684 _______________________
685 [__op0_high_|__op0_low__]
686 _______________________
687 * [__op1_high_|__op1_low__]
688 _______________________________________________
689 _______________________
690 (1) [__op0_low__*__op1_low__]
691 _______________________
692 (2a) [__op0_low__*__op1_high_]
693 _______________________
694 (2b) [__op0_high_*__op1_low__]
695 _______________________
696 (3) [__op0_high_*__op1_high_]
699 This gives a 4-word result. Since we are only interested in the
700 lower 2 words, partial result (3) and the upper words of (2a) and
701 (2b) don't need to be calculated. Hence (2a) and (2b) can be
702 calculated using non-widening multiplication.
704 (1), however, needs to be calculated with an unsigned widening
705 multiplication. If this operation is not directly supported we
706 try using a signed widening multiplication and adjust the result.
707 This adjustment works as follows:
709 If both operands are positive then no adjustment is needed.
711 If the operands have different signs, for example op0_low < 0 and
712 op1_low >= 0, the instruction treats the most significant bit of
713 op0_low as a sign bit instead of a bit with significance
714 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
715 with 2**BITS_PER_WORD - op0_low, and two's complements the
716 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
719 Similarly, if both operands are negative, we need to add
720 (op0_low + op1_low) * 2**BITS_PER_WORD.
722 We use a trick to adjust quickly. We logically shift op0_low right
723 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
724 op0_high (op1_high) before it is used to calculate 2b (2a). If no
725 logical shift exists, we do an arithmetic right shift and subtract
728 if (binoptab
== smul_optab
730 && GET_MODE_SIZE (mode
) == 2 * UNITS_PER_WORD
731 && smul_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
732 && add_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
733 && ((umul_widen_optab
->handlers
[(int) mode
].insn_code
735 || (smul_widen_optab
->handlers
[(int) mode
].insn_code
736 != CODE_FOR_nothing
)))
738 int low
= (WORDS_BIG_ENDIAN
? 1 : 0);
739 int high
= (WORDS_BIG_ENDIAN
? 0 : 1);
740 rtx op0_high
= operand_subword_force (op0
, high
, mode
);
741 rtx op0_low
= operand_subword_force (op0
, low
, mode
);
742 rtx op1_high
= operand_subword_force (op1
, high
, mode
);
743 rtx op1_low
= operand_subword_force (op1
, low
, mode
);
748 /* If the target is the same as one of the inputs, don't use it. This
749 prevents problems with the REG_EQUAL note. */
750 if (target
== op0
|| target
== op1
)
753 /* Multiply the two lower words to get a double-word product.
754 If unsigned widening multiplication is available, use that;
755 otherwise use the signed form and compensate. */
757 if (umul_widen_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
759 product
= expand_binop (mode
, umul_widen_optab
, op0_low
, op1_low
,
760 target
, 1, OPTAB_DIRECT
);
762 /* If we didn't succeed, delete everything we did so far. */
764 delete_insns_since (last
);
766 op0_xhigh
= op0_high
, op1_xhigh
= op1_high
;
770 && smul_widen_optab
->handlers
[(int) mode
].insn_code
773 rtx wordm1
= GEN_INT (BITS_PER_WORD
- 1);
774 product
= expand_binop (mode
, smul_widen_optab
, op0_low
, op1_low
,
775 target
, 1, OPTAB_DIRECT
);
776 op0_xhigh
= expand_binop (word_mode
, lshr_optab
, op0_low
, wordm1
,
777 NULL_RTX
, 1, OPTAB_DIRECT
);
779 op0_xhigh
= expand_binop (word_mode
, add_optab
, op0_high
,
780 op0_xhigh
, op0_xhigh
, 0, OPTAB_DIRECT
);
783 op0_xhigh
= expand_binop (word_mode
, ashr_optab
, op0_low
, wordm1
,
784 NULL_RTX
, 0, OPTAB_DIRECT
);
786 op0_xhigh
= expand_binop (word_mode
, sub_optab
, op0_high
,
787 op0_xhigh
, op0_xhigh
, 0,
791 op1_xhigh
= expand_binop (word_mode
, lshr_optab
, op1_low
, wordm1
,
792 NULL_RTX
, 1, OPTAB_DIRECT
);
794 op1_xhigh
= expand_binop (word_mode
, add_optab
, op1_high
,
795 op1_xhigh
, op1_xhigh
, 0, OPTAB_DIRECT
);
798 op1_xhigh
= expand_binop (word_mode
, ashr_optab
, op1_low
, wordm1
,
799 NULL_RTX
, 0, OPTAB_DIRECT
);
801 op1_xhigh
= expand_binop (word_mode
, sub_optab
, op1_high
,
802 op1_xhigh
, op1_xhigh
, 0,
807 /* If we have been able to directly compute the product of the
808 low-order words of the operands and perform any required adjustments
809 of the operands, we proceed by trying two more multiplications
810 and then computing the appropriate sum.
812 We have checked above that the required addition is provided.
813 Full-word addition will normally always succeed, especially if
814 it is provided at all, so we don't worry about its failure. The
815 multiplication may well fail, however, so we do handle that. */
817 if (product
&& op0_xhigh
&& op1_xhigh
)
820 rtx product_high
= operand_subword (product
, high
, 1, mode
);
821 rtx temp
= expand_binop (word_mode
, binoptab
, op0_low
, op1_xhigh
,
822 NULL_RTX
, 0, OPTAB_DIRECT
);
826 product_piece
= expand_binop (word_mode
, add_optab
, temp
,
827 product_high
, product_high
,
829 if (product_piece
!= product_high
)
830 emit_move_insn (product_high
, product_piece
);
832 temp
= expand_binop (word_mode
, binoptab
, op1_low
, op0_xhigh
,
833 NULL_RTX
, 0, OPTAB_DIRECT
);
835 product_piece
= expand_binop (word_mode
, add_optab
, temp
,
836 product_high
, product_high
,
838 if (product_piece
!= product_high
)
839 emit_move_insn (product_high
, product_piece
);
841 temp
= emit_move_insn (product
, product
);
842 REG_NOTES (temp
) = gen_rtx (EXPR_LIST
, REG_EQUAL
,
843 gen_rtx (MULT
, mode
, op0
, op1
),
850 /* If we get here, we couldn't do it for some reason even though we
851 originally thought we could. Delete anything we've emitted in
854 delete_insns_since (last
);
857 /* We need to open-code the complex type operations: '+, -, * and /' */
859 /* At this point we allow operations between two similar complex
860 numbers, and also if one of the operands is not a complex number
861 but rather of MODE_FLOAT or MODE_INT. However, the caller
862 must make sure that the MODE of the non-complex operand matches
863 the SUBMODE of the complex operand. */
865 if (class == MODE_COMPLEX_FLOAT
|| class == MODE_COMPLEX_INT
)
877 /* Find the correct mode for the real and imaginary parts */
878 enum machine_mode submode
879 = mode_for_size (GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
,
880 class == MODE_COMPLEX_INT
? MODE_INT
: MODE_FLOAT
,
883 if (submode
== BLKmode
)
887 target
= gen_reg_rtx (mode
);
891 realr
= gen_realpart (submode
, target
);
892 imagr
= gen_imagpart (submode
, target
);
894 if (GET_MODE (op0
) == mode
)
896 real0
= gen_realpart (submode
, op0
);
897 imag0
= gen_imagpart (submode
, op0
);
902 if (GET_MODE (op1
) == mode
)
904 real1
= gen_realpart (submode
, op1
);
905 imag1
= gen_imagpart (submode
, op1
);
910 if (! real0
|| ! real1
|| ! (imag0
|| imag1
))
913 switch (binoptab
->code
)
916 /* (a+ib) + (c+id) = (a+c) + i(b+d) */
918 /* (a+ib) - (c+id) = (a-c) + i(b-d) */
919 res
= expand_binop (submode
, binoptab
, real0
, real1
,
920 realr
, unsignedp
, methods
);
922 emit_move_insn (realr
, res
);
925 res
= expand_binop (submode
, binoptab
, imag0
, imag1
,
926 imagr
, unsignedp
, methods
);
929 else if (binoptab
->code
== MINUS
)
930 res
= expand_unop (submode
, neg_optab
, imag1
, imagr
, unsignedp
);
935 emit_move_insn (imagr
, res
);
939 /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */
943 /* Don't fetch these from memory more than once. */
944 real0
= force_reg (submode
, real0
);
945 real1
= force_reg (submode
, real1
);
946 imag0
= force_reg (submode
, imag0
);
947 imag1
= force_reg (submode
, imag1
);
949 res
= expand_binop (submode
, sub_optab
,
950 expand_binop (submode
, binoptab
, real0
,
951 real1
, 0, unsignedp
, methods
),
952 expand_binop (submode
, binoptab
, imag0
,
953 imag1
, 0, unsignedp
, methods
),
954 realr
, unsignedp
, methods
);
957 emit_move_insn (realr
, res
);
959 res
= expand_binop (submode
, add_optab
,
960 expand_binop (submode
, binoptab
,
962 0, unsignedp
, methods
),
963 expand_binop (submode
, binoptab
,
965 0, unsignedp
, methods
),
966 imagr
, unsignedp
, methods
);
968 emit_move_insn (imagr
, res
);
972 /* Don't fetch these from memory more than once. */
973 real0
= force_reg (submode
, real0
);
974 real1
= force_reg (submode
, real1
);
976 res
= expand_binop (submode
, binoptab
, real0
, real1
,
977 realr
, unsignedp
, methods
);
979 emit_move_insn (realr
, res
);
982 res
= expand_binop (submode
, binoptab
,
983 real1
, imag0
, imagr
, unsignedp
, methods
);
985 res
= expand_binop (submode
, binoptab
,
986 real0
, imag1
, imagr
, unsignedp
, methods
);
988 emit_move_insn (imagr
, res
);
993 /* (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) */
996 { /* (a+ib) / (c+i0) = (a/c) + i(b/c) */
998 /* Don't fetch these from memory more than once. */
999 real1
= force_reg (submode
, real1
);
1001 /* Simply divide the real and imaginary parts by `c' */
1002 res
= expand_binop (submode
, binoptab
, real0
, real1
,
1003 realr
, unsignedp
, methods
);
1005 emit_move_insn (realr
, res
);
1007 res
= expand_binop (submode
, binoptab
, imag0
, real1
,
1008 imagr
, unsignedp
, methods
);
1010 emit_move_insn (imagr
, res
);
1012 else /* Divisor is of complex type */
1019 optab mulopt
= unsignedp
? umul_widen_optab
: smul_optab
;
1021 /* Don't fetch these from memory more than once. */
1022 real0
= force_reg (submode
, real0
);
1023 real1
= force_reg (submode
, real1
);
1025 imag0
= force_reg (submode
, imag0
);
1026 imag1
= force_reg (submode
, imag1
);
1028 /* Divisor: c*c + d*d */
1029 divisor
= expand_binop (submode
, add_optab
,
1030 expand_binop (submode
, mulopt
,
1032 0, unsignedp
, methods
),
1033 expand_binop (submode
, mulopt
,
1035 0, unsignedp
, methods
),
1036 0, unsignedp
, methods
);
1038 if (! imag0
) /* ((a)(c-id))/divisor */
1039 { /* (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)) */
1040 /* Calculate the dividend */
1041 real_t
= expand_binop (submode
, mulopt
, real0
, real1
,
1042 0, unsignedp
, methods
);
1045 = expand_unop (submode
, neg_optab
,
1046 expand_binop (submode
, mulopt
, real0
, imag1
,
1047 0, unsignedp
, methods
),
1050 else /* ((a+ib)(c-id))/divider */
1052 /* Calculate the dividend */
1053 real_t
= expand_binop (submode
, add_optab
,
1054 expand_binop (submode
, mulopt
,
1056 0, unsignedp
, methods
),
1057 expand_binop (submode
, mulopt
,
1059 0, unsignedp
, methods
),
1060 0, unsignedp
, methods
);
1062 imag_t
= expand_binop (submode
, sub_optab
,
1063 expand_binop (submode
, mulopt
,
1065 0, unsignedp
, methods
),
1066 expand_binop (submode
, mulopt
,
1068 0, unsignedp
, methods
),
1069 0, unsignedp
, methods
);
1073 res
= expand_binop (submode
, binoptab
, real_t
, divisor
,
1074 realr
, unsignedp
, methods
);
1076 emit_move_insn (realr
, res
);
1078 res
= expand_binop (submode
, binoptab
, imag_t
, divisor
,
1079 imagr
, unsignedp
, methods
);
1081 emit_move_insn (imagr
, res
);
1092 if (binoptab
->code
!= UNKNOWN
)
1093 equiv_value
= gen_rtx (binoptab
->code
, mode
, op0
, op1
);
1097 emit_no_conflict_block (seq
, target
, op0
, op1
, equiv_value
);
1102 /* It can't be open-coded in this mode.
1103 Use a library call if one is available and caller says that's ok. */
1105 if (binoptab
->handlers
[(int) mode
].libfunc
1106 && (methods
== OPTAB_LIB
|| methods
== OPTAB_LIB_WIDEN
))
1109 rtx funexp
= binoptab
->handlers
[(int) mode
].libfunc
;
1111 enum machine_mode op1_mode
= mode
;
1117 op1_mode
= word_mode
;
1118 /* Specify unsigned here,
1119 since negative shift counts are meaningless. */
1120 op1x
= convert_to_mode (word_mode
, op1
, 1);
1123 /* Pass 1 for NO_QUEUE so we don't lose any increments
1124 if the libcall is cse'd or moved. */
1125 emit_library_call (binoptab
->handlers
[(int) mode
].libfunc
,
1126 1, mode
, 2, op0
, mode
, op1x
, op1_mode
);
1128 insns
= get_insns ();
1131 target
= gen_reg_rtx (mode
);
1132 emit_libcall_block (insns
, target
, hard_libcall_value (mode
),
1133 gen_rtx (binoptab
->code
, mode
, op0
, op1
));
1138 delete_insns_since (last
);
1140 /* It can't be done in this mode. Can we do it in a wider mode? */
1142 if (! (methods
== OPTAB_WIDEN
|| methods
== OPTAB_LIB_WIDEN
1143 || methods
== OPTAB_MUST_WIDEN
))
1145 /* Caller says, don't even try. */
1146 delete_insns_since (entry_last
);
1150 /* Compute the value of METHODS to pass to recursive calls.
1151 Don't allow widening to be tried recursively. */
1153 methods
= (methods
== OPTAB_LIB_WIDEN
? OPTAB_LIB
: OPTAB_DIRECT
);
1155 /* Look for a wider mode of the same class for which it appears we can do
1158 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1160 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1161 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1163 if ((binoptab
->handlers
[(int) wider_mode
].insn_code
1164 != CODE_FOR_nothing
)
1165 || (methods
== OPTAB_LIB
1166 && binoptab
->handlers
[(int) wider_mode
].libfunc
))
1168 rtx xop0
= op0
, xop1
= op1
;
1171 /* For certain integer operations, we need not actually extend
1172 the narrow operands, as long as we will truncate
1173 the results to the same narrowness. Don't do this when
1174 WIDER_MODE is wider than a word since a paradoxical SUBREG
1175 isn't valid for such modes. */
1177 if ((binoptab
== ior_optab
|| binoptab
== and_optab
1178 || binoptab
== xor_optab
1179 || binoptab
== add_optab
|| binoptab
== sub_optab
1180 || binoptab
== smul_optab
1181 || binoptab
== ashl_optab
|| binoptab
== lshl_optab
)
1182 && class == MODE_INT
1183 && GET_MODE_SIZE (wider_mode
) <= UNITS_PER_WORD
)
1186 /* If an operand is a constant integer, we might as well
1187 convert it since that is more efficient than using a SUBREG,
1188 unlike the case for other operands. Similarly for
1189 SUBREGs that were made due to promoted objects.*/
1191 if (no_extend
&& GET_MODE (xop0
) != VOIDmode
1192 && ! (GET_CODE (xop0
) == SUBREG
1193 && SUBREG_PROMOTED_VAR_P (xop0
)))
1194 xop0
= gen_rtx (SUBREG
, wider_mode
,
1195 force_reg (GET_MODE (xop0
), xop0
), 0);
1197 xop0
= convert_to_mode (wider_mode
, xop0
, unsignedp
);
1199 if (no_extend
&& GET_MODE (xop1
) != VOIDmode
1200 && ! (GET_CODE (xop1
) == SUBREG
1201 && SUBREG_PROMOTED_VAR_P (xop1
)))
1202 xop1
= gen_rtx (SUBREG
, wider_mode
,
1203 force_reg (GET_MODE (xop1
), xop1
), 0);
1205 xop1
= convert_to_mode (wider_mode
, xop1
, unsignedp
);
1207 temp
= expand_binop (wider_mode
, binoptab
, xop0
, xop1
, NULL_RTX
,
1208 unsignedp
, methods
);
1211 if (class != MODE_INT
)
1214 target
= gen_reg_rtx (mode
);
1215 convert_move (target
, temp
, 0);
1219 return gen_lowpart (mode
, temp
);
1222 delete_insns_since (last
);
1227 delete_insns_since (entry_last
);
1231 /* Expand a binary operator which has both signed and unsigned forms.
1232 UOPTAB is the optab for unsigned operations, and SOPTAB is for
1235 If we widen unsigned operands, we may use a signed wider operation instead
1236 of an unsigned wider operation, since the result would be the same. */
1239 sign_expand_binop (mode
, uoptab
, soptab
, op0
, op1
, target
, unsignedp
, methods
)
1240 enum machine_mode mode
;
1241 optab uoptab
, soptab
;
1242 rtx op0
, op1
, target
;
1244 enum optab_methods methods
;
1247 optab direct_optab
= unsignedp
? uoptab
: soptab
;
1248 struct optab wide_soptab
;
1250 /* Do it without widening, if possible. */
1251 temp
= expand_binop (mode
, direct_optab
, op0
, op1
, target
,
1252 unsignedp
, OPTAB_DIRECT
);
1253 if (temp
|| methods
== OPTAB_DIRECT
)
1256 /* Try widening to a signed int. Make a fake signed optab that
1257 hides any signed insn for direct use. */
1258 wide_soptab
= *soptab
;
1259 wide_soptab
.handlers
[(int) mode
].insn_code
= CODE_FOR_nothing
;
1260 wide_soptab
.handlers
[(int) mode
].libfunc
= 0;
1262 temp
= expand_binop (mode
, &wide_soptab
, op0
, op1
, target
,
1263 unsignedp
, OPTAB_WIDEN
);
1265 /* For unsigned operands, try widening to an unsigned int. */
1266 if (temp
== 0 && unsignedp
)
1267 temp
= expand_binop (mode
, uoptab
, op0
, op1
, target
,
1268 unsignedp
, OPTAB_WIDEN
);
1269 if (temp
|| methods
== OPTAB_WIDEN
)
1272 /* Use the right width lib call if that exists. */
1273 temp
= expand_binop (mode
, direct_optab
, op0
, op1
, target
, unsignedp
, OPTAB_LIB
);
1274 if (temp
|| methods
== OPTAB_LIB
)
1277 /* Must widen and use a lib call, use either signed or unsigned. */
1278 temp
= expand_binop (mode
, &wide_soptab
, op0
, op1
, target
,
1279 unsignedp
, methods
);
1283 return expand_binop (mode
, uoptab
, op0
, op1
, target
,
1284 unsignedp
, methods
);
1288 /* Generate code to perform an operation specified by BINOPTAB
1289 on operands OP0 and OP1, with two results to TARG1 and TARG2.
1290 We assume that the order of the operands for the instruction
1291 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
1292 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
1294 Either TARG0 or TARG1 may be zero, but what that means is that
1295 that result is not actually wanted. We will generate it into
1296 a dummy pseudo-reg and discard it. They may not both be zero.
1298 Returns 1 if this operation can be performed; 0 if not. */
1301 expand_twoval_binop (binoptab
, op0
, op1
, targ0
, targ1
, unsignedp
)
1307 enum machine_mode mode
= GET_MODE (targ0
? targ0
: targ1
);
1308 enum mode_class
class;
1309 enum machine_mode wider_mode
;
1310 rtx entry_last
= get_last_insn ();
1313 class = GET_MODE_CLASS (mode
);
1315 op0
= protect_from_queue (op0
, 0);
1316 op1
= protect_from_queue (op1
, 0);
1320 op0
= force_not_mem (op0
);
1321 op1
= force_not_mem (op1
);
1324 /* If we are inside an appropriately-short loop and one operand is an
1325 expensive constant, force it into a register. */
1326 if (CONSTANT_P (op0
) && preserve_subexpressions_p ()
1327 && rtx_cost (op0
, binoptab
->code
) > 2)
1328 op0
= force_reg (mode
, op0
);
1330 if (CONSTANT_P (op1
) && preserve_subexpressions_p ()
1331 && rtx_cost (op1
, binoptab
->code
) > 2)
1332 op1
= force_reg (mode
, op1
);
1335 targ0
= protect_from_queue (targ0
, 1);
1337 targ0
= gen_reg_rtx (mode
);
1339 targ1
= protect_from_queue (targ1
, 1);
1341 targ1
= gen_reg_rtx (mode
);
1343 /* Record where to go back to if we fail. */
1344 last
= get_last_insn ();
1346 if (binoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1348 int icode
= (int) binoptab
->handlers
[(int) mode
].insn_code
;
1349 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
1350 enum machine_mode mode1
= insn_operand_mode
[icode
][2];
1352 rtx xop0
= op0
, xop1
= op1
;
1354 /* In case this insn wants input operands in modes different from the
1355 result, convert the operands. */
1356 if (GET_MODE (op0
) != VOIDmode
&& GET_MODE (op0
) != mode0
)
1357 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
1359 if (GET_MODE (op1
) != VOIDmode
&& GET_MODE (op1
) != mode1
)
1360 xop1
= convert_to_mode (mode1
, xop1
, unsignedp
);
1362 /* Now, if insn doesn't accept these operands, put them into pseudos. */
1363 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
1364 xop0
= copy_to_mode_reg (mode0
, xop0
);
1366 if (! (*insn_operand_predicate
[icode
][2]) (xop1
, mode1
))
1367 xop1
= copy_to_mode_reg (mode1
, xop1
);
1369 /* We could handle this, but we should always be called with a pseudo
1370 for our targets and all insns should take them as outputs. */
1371 if (! (*insn_operand_predicate
[icode
][0]) (targ0
, mode
)
1372 || ! (*insn_operand_predicate
[icode
][3]) (targ1
, mode
))
1375 pat
= GEN_FCN (icode
) (targ0
, xop0
, xop1
, targ1
);
1382 delete_insns_since (last
);
1385 /* It can't be done in this mode. Can we do it in a wider mode? */
1387 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1389 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1390 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1392 if (binoptab
->handlers
[(int) wider_mode
].insn_code
1393 != CODE_FOR_nothing
)
1395 register rtx t0
= gen_reg_rtx (wider_mode
);
1396 register rtx t1
= gen_reg_rtx (wider_mode
);
1398 if (expand_twoval_binop (binoptab
,
1399 convert_to_mode (wider_mode
, op0
,
1401 convert_to_mode (wider_mode
, op1
,
1405 convert_move (targ0
, t0
, unsignedp
);
1406 convert_move (targ1
, t1
, unsignedp
);
1410 delete_insns_since (last
);
1415 delete_insns_since (entry_last
);
1419 /* Generate code to perform an operation specified by UNOPTAB
1420 on operand OP0, with result having machine-mode MODE.
1422 UNSIGNEDP is for the case where we have to widen the operands
1423 to perform the operation. It says to use zero-extension.
1425 If TARGET is nonzero, the value
1426 is generated there, if it is convenient to do so.
1427 In all cases an rtx is returned for the locus of the value;
1428 this may or may not be TARGET. */
1431 expand_unop (mode
, unoptab
, op0
, target
, unsignedp
)
1432 enum machine_mode mode
;
1438 enum mode_class
class;
1439 enum machine_mode wider_mode
;
1441 rtx last
= get_last_insn ();
1444 class = GET_MODE_CLASS (mode
);
1446 op0
= protect_from_queue (op0
, 0);
1450 op0
= force_not_mem (op0
);
1454 target
= protect_from_queue (target
, 1);
1456 if (unoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1458 int icode
= (int) unoptab
->handlers
[(int) mode
].insn_code
;
1459 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
1465 temp
= gen_reg_rtx (mode
);
1467 if (GET_MODE (xop0
) != VOIDmode
1468 && GET_MODE (xop0
) != mode0
)
1469 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
1471 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
1473 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
1474 xop0
= copy_to_mode_reg (mode0
, xop0
);
1476 if (! (*insn_operand_predicate
[icode
][0]) (temp
, mode
))
1477 temp
= gen_reg_rtx (mode
);
1479 pat
= GEN_FCN (icode
) (temp
, xop0
);
1482 if (GET_CODE (pat
) == SEQUENCE
1483 && ! add_equal_note (pat
, temp
, unoptab
->code
, xop0
, NULL_RTX
))
1485 delete_insns_since (last
);
1486 return expand_unop (mode
, unoptab
, op0
, NULL_RTX
, unsignedp
);
1494 delete_insns_since (last
);
1497 /* It can't be done in this mode. Can we open-code it in a wider mode? */
1499 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1500 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1501 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1503 if (unoptab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
)
1507 /* For certain operations, we need not actually extend
1508 the narrow operand, as long as we will truncate the
1509 results to the same narrowness. But it is faster to
1510 convert a SUBREG due to mode promotion. */
1512 if ((unoptab
== neg_optab
|| unoptab
== one_cmpl_optab
)
1513 && GET_MODE_SIZE (wider_mode
) <= UNITS_PER_WORD
1514 && class == MODE_INT
1515 && ! (GET_CODE (xop0
) == SUBREG
1516 && SUBREG_PROMOTED_VAR_P (xop0
)))
1517 xop0
= gen_rtx (SUBREG
, wider_mode
, force_reg (mode
, xop0
), 0);
1519 xop0
= convert_to_mode (wider_mode
, xop0
, unsignedp
);
1521 temp
= expand_unop (wider_mode
, unoptab
, xop0
, NULL_RTX
,
1526 if (class != MODE_INT
)
1529 target
= gen_reg_rtx (mode
);
1530 convert_move (target
, temp
, 0);
1534 return gen_lowpart (mode
, temp
);
1537 delete_insns_since (last
);
1541 /* These can be done a word at a time. */
1542 if (unoptab
== one_cmpl_optab
1543 && class == MODE_INT
1544 && GET_MODE_SIZE (mode
) > UNITS_PER_WORD
1545 && unoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
1550 if (target
== 0 || target
== op0
)
1551 target
= gen_reg_rtx (mode
);
1555 /* Do the actual arithmetic. */
1556 for (i
= 0; i
< GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
; i
++)
1558 rtx target_piece
= operand_subword (target
, i
, 1, mode
);
1559 rtx x
= expand_unop (word_mode
, unoptab
,
1560 operand_subword_force (op0
, i
, mode
),
1561 target_piece
, unsignedp
);
1562 if (target_piece
!= x
)
1563 emit_move_insn (target_piece
, x
);
1566 insns
= get_insns ();
1569 emit_no_conflict_block (insns
, target
, op0
, NULL_RTX
,
1570 gen_rtx (unoptab
->code
, mode
, op0
));
1574 /* Open-code the complex negation operation. */
1575 else if (unoptab
== neg_optab
1576 && (class == MODE_COMPLEX_FLOAT
|| class == MODE_COMPLEX_INT
))
1582 /* Find the correct mode for the real and imaginary parts */
1583 enum machine_mode submode
1584 = mode_for_size (GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
,
1585 class == MODE_COMPLEX_INT
? MODE_INT
: MODE_FLOAT
,
1588 if (submode
== BLKmode
)
1592 target
= gen_reg_rtx (mode
);
1596 target_piece
= gen_imagpart (submode
, target
);
1597 x
= expand_unop (submode
, unoptab
,
1598 gen_imagpart (submode
, op0
),
1599 target_piece
, unsignedp
);
1600 if (target_piece
!= x
)
1601 emit_move_insn (target_piece
, x
);
1603 target_piece
= gen_realpart (submode
, target
);
1604 x
= expand_unop (submode
, unoptab
,
1605 gen_realpart (submode
, op0
),
1606 target_piece
, unsignedp
);
1607 if (target_piece
!= x
)
1608 emit_move_insn (target_piece
, x
);
1613 emit_no_conflict_block (seq
, target
, op0
, 0,
1614 gen_rtx (unoptab
->code
, mode
, op0
));
1618 /* Now try a library call in this mode. */
1619 if (unoptab
->handlers
[(int) mode
].libfunc
)
1622 rtx funexp
= unoptab
->handlers
[(int) mode
].libfunc
;
1626 /* Pass 1 for NO_QUEUE so we don't lose any increments
1627 if the libcall is cse'd or moved. */
1628 emit_library_call (unoptab
->handlers
[(int) mode
].libfunc
,
1629 1, mode
, 1, op0
, mode
);
1630 insns
= get_insns ();
1633 target
= gen_reg_rtx (mode
);
1634 emit_libcall_block (insns
, target
, hard_libcall_value (mode
),
1635 gen_rtx (unoptab
->code
, mode
, op0
));
1640 /* It can't be done in this mode. Can we do it in a wider mode? */
1642 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1644 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1645 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1647 if ((unoptab
->handlers
[(int) wider_mode
].insn_code
1648 != CODE_FOR_nothing
)
1649 || unoptab
->handlers
[(int) wider_mode
].libfunc
)
1653 /* For certain operations, we need not actually extend
1654 the narrow operand, as long as we will truncate the
1655 results to the same narrowness. */
1657 if ((unoptab
== neg_optab
|| unoptab
== one_cmpl_optab
)
1658 && GET_MODE_SIZE (wider_mode
) <= UNITS_PER_WORD
1659 && class == MODE_INT
1660 && ! (GET_CODE (xop0
) == SUBREG
1661 && SUBREG_PROMOTED_VAR_P (xop0
)))
1662 xop0
= gen_rtx (SUBREG
, wider_mode
, force_reg (mode
, xop0
), 0);
1664 xop0
= convert_to_mode (wider_mode
, xop0
, unsignedp
);
1666 temp
= expand_unop (wider_mode
, unoptab
, xop0
, NULL_RTX
,
1671 if (class != MODE_INT
)
1674 target
= gen_reg_rtx (mode
);
1675 convert_move (target
, temp
, 0);
1679 return gen_lowpart (mode
, temp
);
1682 delete_insns_since (last
);
1690 /* Emit code to compute the absolute value of OP0, with result to
1691 TARGET if convenient. (TARGET may be 0.) The return value says
1692 where the result actually is to be found.
1694 MODE is the mode of the operand; the mode of the result is
1695 different but can be deduced from MODE.
1697 UNSIGNEDP is relevant for complex integer modes. */
1700 expand_complex_abs (mode
, op0
, target
, unsignedp
)
1701 enum machine_mode mode
;
1706 enum mode_class
class = GET_MODE_CLASS (mode
);
1707 enum machine_mode wider_mode
;
1709 rtx entry_last
= get_last_insn ();
1713 /* Find the correct mode for the real and imaginary parts. */
1714 enum machine_mode submode
1715 = mode_for_size (GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
,
1716 class == MODE_COMPLEX_INT
? MODE_INT
: MODE_FLOAT
,
1719 if (submode
== BLKmode
)
1722 op0
= protect_from_queue (op0
, 0);
1726 op0
= force_not_mem (op0
);
1729 last
= get_last_insn ();
1732 target
= protect_from_queue (target
, 1);
1734 if (abs_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1736 int icode
= (int) abs_optab
->handlers
[(int) mode
].insn_code
;
1737 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
1743 temp
= gen_reg_rtx (submode
);
1745 if (GET_MODE (xop0
) != VOIDmode
1746 && GET_MODE (xop0
) != mode0
)
1747 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
1749 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
1751 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
1752 xop0
= copy_to_mode_reg (mode0
, xop0
);
1754 if (! (*insn_operand_predicate
[icode
][0]) (temp
, submode
))
1755 temp
= gen_reg_rtx (submode
);
1757 pat
= GEN_FCN (icode
) (temp
, xop0
);
1760 if (GET_CODE (pat
) == SEQUENCE
1761 && ! add_equal_note (pat
, temp
, abs_optab
->code
, xop0
, NULL_RTX
))
1763 delete_insns_since (last
);
1764 return expand_unop (mode
, abs_optab
, op0
, NULL_RTX
, unsignedp
);
1772 delete_insns_since (last
);
1775 /* It can't be done in this mode. Can we open-code it in a wider mode? */
1777 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1778 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1780 if (abs_optab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
)
1784 xop0
= convert_to_mode (wider_mode
, xop0
, unsignedp
);
1785 temp
= expand_complex_abs (wider_mode
, xop0
, NULL_RTX
, unsignedp
);
1789 if (class != MODE_COMPLEX_INT
)
1792 target
= gen_reg_rtx (submode
);
1793 convert_move (target
, temp
, 0);
1797 return gen_lowpart (submode
, temp
);
1800 delete_insns_since (last
);
1804 /* Open-code the complex absolute-value operation
1805 if we can open-code sqrt. Otherwise it's not worth while. */
1806 if (sqrt_optab
->handlers
[(int) submode
].insn_code
!= CODE_FOR_nothing
)
1808 rtx real
, imag
, total
;
1810 real
= gen_realpart (submode
, op0
);
1811 imag
= gen_imagpart (submode
, op0
);
1812 /* Square both parts. */
1813 real
= expand_mult (mode
, real
, real
, NULL_RTX
, 0);
1814 imag
= expand_mult (mode
, imag
, imag
, NULL_RTX
, 0);
1815 /* Sum the parts. */
1816 total
= expand_binop (submode
, add_optab
, real
, imag
, 0,
1817 0, OPTAB_LIB_WIDEN
);
1818 /* Get sqrt in TARGET. Set TARGET to where the result is. */
1819 target
= expand_unop (submode
, sqrt_optab
, total
, target
, 0);
1821 delete_insns_since (last
);
1826 /* Now try a library call in this mode. */
1827 if (abs_optab
->handlers
[(int) mode
].libfunc
)
1830 rtx funexp
= abs_optab
->handlers
[(int) mode
].libfunc
;
1834 /* Pass 1 for NO_QUEUE so we don't lose any increments
1835 if the libcall is cse'd or moved. */
1836 emit_library_call (abs_optab
->handlers
[(int) mode
].libfunc
,
1837 1, mode
, 1, op0
, mode
);
1838 insns
= get_insns ();
1841 target
= gen_reg_rtx (submode
);
1842 emit_libcall_block (insns
, target
, hard_libcall_value (submode
),
1843 gen_rtx (abs_optab
->code
, mode
, op0
));
1848 /* It can't be done in this mode. Can we do it in a wider mode? */
1850 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1851 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1853 if ((abs_optab
->handlers
[(int) wider_mode
].insn_code
1854 != CODE_FOR_nothing
)
1855 || abs_optab
->handlers
[(int) wider_mode
].libfunc
)
1859 xop0
= convert_to_mode (wider_mode
, xop0
, unsignedp
);
1861 temp
= expand_complex_abs (wider_mode
, xop0
, NULL_RTX
, unsignedp
);
1865 if (class != MODE_COMPLEX_INT
)
1868 target
= gen_reg_rtx (submode
);
1869 convert_move (target
, temp
, 0);
1873 return gen_lowpart (submode
, temp
);
1876 delete_insns_since (last
);
1880 delete_insns_since (entry_last
);
1884 /* Generate an instruction whose insn-code is INSN_CODE,
1885 with two operands: an output TARGET and an input OP0.
1886 TARGET *must* be nonzero, and the output is always stored there.
1887 CODE is an rtx code such that (CODE OP0) is an rtx that describes
1888 the value that is stored into TARGET. */
1891 emit_unop_insn (icode
, target
, op0
, code
)
1898 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
1901 temp
= target
= protect_from_queue (target
, 1);
1903 op0
= protect_from_queue (op0
, 0);
1906 op0
= force_not_mem (op0
);
1908 /* Now, if insn does not accept our operands, put them into pseudos. */
1910 if (! (*insn_operand_predicate
[icode
][1]) (op0
, mode0
))
1911 op0
= copy_to_mode_reg (mode0
, op0
);
1913 if (! (*insn_operand_predicate
[icode
][0]) (temp
, GET_MODE (temp
))
1914 || (flag_force_mem
&& GET_CODE (temp
) == MEM
))
1915 temp
= gen_reg_rtx (GET_MODE (temp
));
1917 pat
= GEN_FCN (icode
) (temp
, op0
);
1919 if (GET_CODE (pat
) == SEQUENCE
&& code
!= UNKNOWN
)
1920 add_equal_note (pat
, temp
, code
, op0
, NULL_RTX
);
1925 emit_move_insn (target
, temp
);
1928 /* Emit code to perform a series of operations on a multi-word quantity, one
1931 Such a block is preceded by a CLOBBER of the output, consists of multiple
1932 insns, each setting one word of the output, and followed by a SET copying
1933 the output to itself.
1935 Each of the insns setting words of the output receives a REG_NO_CONFLICT
1936 note indicating that it doesn't conflict with the (also multi-word)
1937 inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
1940 INSNS is a block of code generated to perform the operation, not including
1941 the CLOBBER and final copy. All insns that compute intermediate values
1942 are first emitted, followed by the block as described above. Only
1943 INSNs are allowed in the block; no library calls or jumps may be
1946 TARGET, OP0, and OP1 are the output and inputs of the operations,
1947 respectively. OP1 may be zero for a unary operation.
1949 EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
1952 If TARGET is not a register, INSNS is simply emitted with no special
1955 The final insn emitted is returned. */
1958 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv
)
1964 rtx prev
, next
, first
, last
, insn
;
1966 if (GET_CODE (target
) != REG
|| reload_in_progress
)
1967 return emit_insns (insns
);
1969 /* First emit all insns that do not store into words of the output and remove
1970 these from the list. */
1971 for (insn
= insns
; insn
; insn
= next
)
1976 next
= NEXT_INSN (insn
);
1978 if (GET_CODE (insn
) != INSN
)
1981 if (GET_CODE (PATTERN (insn
)) == SET
)
1982 set
= PATTERN (insn
);
1983 else if (GET_CODE (PATTERN (insn
)) == PARALLEL
)
1985 for (i
= 0; i
< XVECLEN (PATTERN (insn
), 0); i
++)
1986 if (GET_CODE (XVECEXP (PATTERN (insn
), 0, i
)) == SET
)
1988 set
= XVECEXP (PATTERN (insn
), 0, i
);
1996 if (! reg_overlap_mentioned_p (target
, SET_DEST (set
)))
1998 if (PREV_INSN (insn
))
1999 NEXT_INSN (PREV_INSN (insn
)) = next
;
2004 PREV_INSN (next
) = PREV_INSN (insn
);
2010 prev
= get_last_insn ();
2012 /* Now write the CLOBBER of the output, followed by the setting of each
2013 of the words, followed by the final copy. */
2014 if (target
!= op0
&& target
!= op1
)
2015 emit_insn (gen_rtx (CLOBBER
, VOIDmode
, target
));
2017 for (insn
= insns
; insn
; insn
= next
)
2019 next
= NEXT_INSN (insn
);
2022 if (op1
&& GET_CODE (op1
) == REG
)
2023 REG_NOTES (insn
) = gen_rtx (EXPR_LIST
, REG_NO_CONFLICT
, op1
,
2026 if (op0
&& GET_CODE (op0
) == REG
)
2027 REG_NOTES (insn
) = gen_rtx (EXPR_LIST
, REG_NO_CONFLICT
, op0
,
2031 if (mov_optab
->handlers
[(int) GET_MODE (target
)].insn_code
2032 != CODE_FOR_nothing
)
2034 last
= emit_move_insn (target
, target
);
2037 = gen_rtx (EXPR_LIST
, REG_EQUAL
, equiv
, REG_NOTES (last
));
2040 last
= get_last_insn ();
2043 first
= get_insns ();
2045 first
= NEXT_INSN (prev
);
2047 /* Encapsulate the block so it gets manipulated as a unit. */
2048 REG_NOTES (first
) = gen_rtx (INSN_LIST
, REG_LIBCALL
, last
,
2050 REG_NOTES (last
) = gen_rtx (INSN_LIST
, REG_RETVAL
, first
, REG_NOTES (last
));
2055 /* Emit code to make a call to a constant function or a library call.
2057 INSNS is a list containing all insns emitted in the call.
2058 These insns leave the result in RESULT. Our block is to copy RESULT
2059 to TARGET, which is logically equivalent to EQUIV.
2061 We first emit any insns that set a pseudo on the assumption that these are
2062 loading constants into registers; doing so allows them to be safely cse'ed
2063 between blocks. Then we emit all the other insns in the block, followed by
2064 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
2065 note with an operand of EQUIV.
2067 Moving assignments to pseudos outside of the block is done to improve
2068 the generated code, but is not required to generate correct code,
2069 hence being unable to move an assignment is not grounds for not making
2070 a libcall block. There are two reasons why it is safe to leave these
2071 insns inside the block: First, we know that these pseudos cannot be
2072 used in generated RTL outside the block since they are created for
2073 temporary purposes within the block. Second, CSE will not record the
2074 values of anything set inside a libcall block, so we know they must
2075 be dead at the end of the block.
2077 Except for the first group of insns (the ones setting pseudos), the
2078 block is delimited by REG_RETVAL and REG_LIBCALL notes. */
2081 emit_libcall_block (insns
, target
, result
, equiv
)
2087 rtx prev
, next
, first
, last
, insn
;
2089 /* First emit all insns that set pseudos. Remove them from the list as
2090 we go. Avoid insns that set pseudo which were referenced in previous
2091 insns. These can be generated by move_by_pieces, for example,
2092 to update an address. */
2094 for (insn
= insns
; insn
; insn
= next
)
2096 rtx set
= single_set (insn
);
2098 next
= NEXT_INSN (insn
);
2100 if (set
!= 0 && GET_CODE (SET_DEST (set
)) == REG
2101 && REGNO (SET_DEST (set
)) >= FIRST_PSEUDO_REGISTER
2103 || (! reg_mentioned_p (SET_DEST (set
), PATTERN (insns
))
2104 && ! reg_used_between_p (SET_DEST (set
), insns
, insn
))))
2106 if (PREV_INSN (insn
))
2107 NEXT_INSN (PREV_INSN (insn
)) = next
;
2112 PREV_INSN (next
) = PREV_INSN (insn
);
2118 prev
= get_last_insn ();
2120 /* Write the remaining insns followed by the final copy. */
2122 for (insn
= insns
; insn
; insn
= next
)
2124 next
= NEXT_INSN (insn
);
2129 last
= emit_move_insn (target
, result
);
2130 REG_NOTES (last
) = gen_rtx (EXPR_LIST
, REG_EQUAL
, equiv
, REG_NOTES (last
));
2133 first
= get_insns ();
2135 first
= NEXT_INSN (prev
);
2137 /* Encapsulate the block so it gets manipulated as a unit. */
2138 REG_NOTES (first
) = gen_rtx (INSN_LIST
, REG_LIBCALL
, last
,
2140 REG_NOTES (last
) = gen_rtx (INSN_LIST
, REG_RETVAL
, first
, REG_NOTES (last
));
2143 /* Generate code to store zero in X. */
2149 emit_move_insn (x
, const0_rtx
);
2152 /* Generate code to store 1 in X
2153 assuming it contains zero beforehand. */
2156 emit_0_to_1_insn (x
)
2159 emit_move_insn (x
, const1_rtx
);
2162 /* Generate code to compare X with Y
2163 so that the condition codes are set.
2165 MODE is the mode of the inputs (in case they are const_int).
2166 UNSIGNEDP nonzero says that X and Y are unsigned;
2167 this matters if they need to be widened.
2169 If they have mode BLKmode, then SIZE specifies the size of both X and Y,
2170 and ALIGN specifies the known shared alignment of X and Y.
2172 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
2173 It is ignored for fixed-point and block comparisons;
2174 it is used only for floating-point comparisons. */
2177 emit_cmp_insn (x
, y
, comparison
, size
, mode
, unsignedp
, align
)
2179 enum rtx_code comparison
;
2181 enum machine_mode mode
;
2185 enum mode_class
class;
2186 enum machine_mode wider_mode
;
2188 class = GET_MODE_CLASS (mode
);
2190 /* They could both be VOIDmode if both args are immediate constants,
2191 but we should fold that at an earlier stage.
2192 With no special code here, this will call abort,
2193 reminding the programmer to implement such folding. */
2195 if (mode
!= BLKmode
&& flag_force_mem
)
2197 x
= force_not_mem (x
);
2198 y
= force_not_mem (y
);
2201 /* If we are inside an appropriately-short loop and one operand is an
2202 expensive constant, force it into a register. */
2203 if (CONSTANT_P (x
) && preserve_subexpressions_p () && rtx_cost (x
, COMPARE
) > 2)
2204 x
= force_reg (mode
, x
);
2206 if (CONSTANT_P (y
) && preserve_subexpressions_p () && rtx_cost (y
, COMPARE
) > 2)
2207 y
= force_reg (mode
, y
);
2209 /* Don't let both operands fail to indicate the mode. */
2210 if (GET_MODE (x
) == VOIDmode
&& GET_MODE (y
) == VOIDmode
)
2211 x
= force_reg (mode
, x
);
2213 /* Handle all BLKmode compares. */
2215 if (mode
== BLKmode
)
2218 x
= protect_from_queue (x
, 0);
2219 y
= protect_from_queue (y
, 0);
2223 #ifdef HAVE_cmpstrqi
2225 && GET_CODE (size
) == CONST_INT
2226 && INTVAL (size
) < (1 << GET_MODE_BITSIZE (QImode
)))
2228 enum machine_mode result_mode
2229 = insn_operand_mode
[(int) CODE_FOR_cmpstrqi
][0];
2230 rtx result
= gen_reg_rtx (result_mode
);
2231 emit_insn (gen_cmpstrqi (result
, x
, y
, size
, GEN_INT (align
)));
2232 emit_cmp_insn (result
, const0_rtx
, comparison
, NULL_RTX
,
2237 #ifdef HAVE_cmpstrhi
2239 && GET_CODE (size
) == CONST_INT
2240 && INTVAL (size
) < (1 << GET_MODE_BITSIZE (HImode
)))
2242 enum machine_mode result_mode
2243 = insn_operand_mode
[(int) CODE_FOR_cmpstrhi
][0];
2244 rtx result
= gen_reg_rtx (result_mode
);
2245 emit_insn (gen_cmpstrhi (result
, x
, y
, size
, GEN_INT (align
)));
2246 emit_cmp_insn (result
, const0_rtx
, comparison
, NULL_RTX
,
2251 #ifdef HAVE_cmpstrsi
2254 enum machine_mode result_mode
2255 = insn_operand_mode
[(int) CODE_FOR_cmpstrsi
][0];
2256 rtx result
= gen_reg_rtx (result_mode
);
2257 size
= protect_from_queue (size
, 0);
2258 emit_insn (gen_cmpstrsi (result
, x
, y
,
2259 convert_to_mode (SImode
, size
, 1),
2261 emit_cmp_insn (result
, const0_rtx
, comparison
, NULL_RTX
,
2267 #ifdef TARGET_MEM_FUNCTIONS
2268 emit_library_call (memcmp_libfunc
, 0,
2269 TYPE_MODE (integer_type_node
), 3,
2270 XEXP (x
, 0), Pmode
, XEXP (y
, 0), Pmode
,
2273 emit_library_call (bcmp_libfunc
, 0,
2274 TYPE_MODE (integer_type_node
), 3,
2275 XEXP (x
, 0), Pmode
, XEXP (y
, 0), Pmode
,
2278 emit_cmp_insn (hard_libcall_value (TYPE_MODE (integer_type_node
)),
2279 const0_rtx
, comparison
, NULL_RTX
,
2280 TYPE_MODE (integer_type_node
), 0, 0);
2285 /* Handle some compares against zero. */
2287 if (y
== CONST0_RTX (mode
)
2288 && tst_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
2290 int icode
= (int) tst_optab
->handlers
[(int) mode
].insn_code
;
2293 x
= protect_from_queue (x
, 0);
2294 y
= protect_from_queue (y
, 0);
2296 /* Now, if insn does accept these operands, put them into pseudos. */
2297 if (! (*insn_operand_predicate
[icode
][0])
2298 (x
, insn_operand_mode
[icode
][0]))
2299 x
= copy_to_mode_reg (insn_operand_mode
[icode
][0], x
);
2301 emit_insn (GEN_FCN (icode
) (x
));
2305 /* Handle compares for which there is a directly suitable insn. */
2307 if (cmp_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
2309 int icode
= (int) cmp_optab
->handlers
[(int) mode
].insn_code
;
2312 x
= protect_from_queue (x
, 0);
2313 y
= protect_from_queue (y
, 0);
2315 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2316 if (! (*insn_operand_predicate
[icode
][0])
2317 (x
, insn_operand_mode
[icode
][0]))
2318 x
= copy_to_mode_reg (insn_operand_mode
[icode
][0], x
);
2320 if (! (*insn_operand_predicate
[icode
][1])
2321 (y
, insn_operand_mode
[icode
][1]))
2322 y
= copy_to_mode_reg (insn_operand_mode
[icode
][1], y
);
2324 emit_insn (GEN_FCN (icode
) (x
, y
));
2328 /* Try widening if we can find a direct insn that way. */
2330 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
2332 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2333 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2335 if (cmp_optab
->handlers
[(int) wider_mode
].insn_code
2336 != CODE_FOR_nothing
)
2338 x
= protect_from_queue (x
, 0);
2339 y
= protect_from_queue (y
, 0);
2340 x
= convert_to_mode (wider_mode
, x
, unsignedp
);
2341 y
= convert_to_mode (wider_mode
, y
, unsignedp
);
2342 emit_cmp_insn (x
, y
, comparison
, NULL_RTX
,
2343 wider_mode
, unsignedp
, align
);
2349 /* Handle a lib call just for the mode we are using. */
2351 if (cmp_optab
->handlers
[(int) mode
].libfunc
2352 && class != MODE_FLOAT
)
2354 rtx libfunc
= cmp_optab
->handlers
[(int) mode
].libfunc
;
2355 /* If we want unsigned, and this mode has a distinct unsigned
2356 comparison routine, use that. */
2357 if (unsignedp
&& ucmp_optab
->handlers
[(int) mode
].libfunc
)
2358 libfunc
= ucmp_optab
->handlers
[(int) mode
].libfunc
;
2360 emit_library_call (libfunc
, 1,
2361 word_mode
, 2, x
, mode
, y
, mode
);
2363 /* Integer comparison returns a result that must be compared against 1,
2364 so that even if we do an unsigned compare afterward,
2365 there is still a value that can represent the result "less than". */
2367 emit_cmp_insn (hard_libcall_value (word_mode
), const1_rtx
,
2368 comparison
, NULL_RTX
, word_mode
, unsignedp
, 0);
2372 if (class == MODE_FLOAT
)
2373 emit_float_lib_cmp (x
, y
, comparison
);
2379 /* Nonzero if a compare of mode MODE can be done straightforwardly
2380 (without splitting it into pieces). */
2383 can_compare_p (mode
)
2384 enum machine_mode mode
;
2388 if (cmp_optab
->handlers
[(int)mode
].insn_code
!= CODE_FOR_nothing
)
2390 mode
= GET_MODE_WIDER_MODE (mode
);
2391 } while (mode
!= VOIDmode
);
2396 /* Emit a library call comparison between floating point X and Y.
2397 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
2400 emit_float_lib_cmp (x
, y
, comparison
)
2402 enum rtx_code comparison
;
2404 enum machine_mode mode
= GET_MODE (x
);
2411 libfunc
= eqsf2_libfunc
;
2415 libfunc
= nesf2_libfunc
;
2419 libfunc
= gtsf2_libfunc
;
2423 libfunc
= gesf2_libfunc
;
2427 libfunc
= ltsf2_libfunc
;
2431 libfunc
= lesf2_libfunc
;
2434 else if (mode
== DFmode
)
2438 libfunc
= eqdf2_libfunc
;
2442 libfunc
= nedf2_libfunc
;
2446 libfunc
= gtdf2_libfunc
;
2450 libfunc
= gedf2_libfunc
;
2454 libfunc
= ltdf2_libfunc
;
2458 libfunc
= ledf2_libfunc
;
2461 else if (mode
== XFmode
)
2465 libfunc
= eqxf2_libfunc
;
2469 libfunc
= nexf2_libfunc
;
2473 libfunc
= gtxf2_libfunc
;
2477 libfunc
= gexf2_libfunc
;
2481 libfunc
= ltxf2_libfunc
;
2485 libfunc
= lexf2_libfunc
;
2488 else if (mode
== TFmode
)
2492 libfunc
= eqtf2_libfunc
;
2496 libfunc
= netf2_libfunc
;
2500 libfunc
= gttf2_libfunc
;
2504 libfunc
= getf2_libfunc
;
2508 libfunc
= lttf2_libfunc
;
2512 libfunc
= letf2_libfunc
;
2517 enum machine_mode wider_mode
;
2519 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2520 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2522 if ((cmp_optab
->handlers
[(int) wider_mode
].insn_code
2523 != CODE_FOR_nothing
)
2524 || (cmp_optab
->handlers
[(int) wider_mode
].libfunc
!= 0))
2526 x
= protect_from_queue (x
, 0);
2527 y
= protect_from_queue (y
, 0);
2528 x
= convert_to_mode (wider_mode
, x
, 0);
2529 y
= convert_to_mode (wider_mode
, y
, 0);
2530 emit_float_lib_cmp (x
, y
, comparison
);
2537 emit_library_call (libfunc
, 1,
2538 word_mode
, 2, x
, mode
, y
, mode
);
2540 emit_cmp_insn (hard_libcall_value (word_mode
), const0_rtx
, comparison
,
2541 NULL_RTX
, word_mode
, 0, 0);
2544 /* Generate code to indirectly jump to a location given in the rtx LOC. */
2547 emit_indirect_jump (loc
)
2550 if (! ((*insn_operand_predicate
[(int)CODE_FOR_indirect_jump
][0])
2552 loc
= copy_to_mode_reg (Pmode
, loc
);
2554 emit_jump_insn (gen_indirect_jump (loc
));
2558 /* These three functions generate an insn body and return it
2559 rather than emitting the insn.
2561 They do not protect from queued increments,
2562 because they may be used 1) in protect_from_queue itself
2563 and 2) in other passes where there is no queue. */
2565 /* Generate and return an insn body to add Y to X. */
2568 gen_add2_insn (x
, y
)
2571 int icode
= (int) add_optab
->handlers
[(int) GET_MODE (x
)].insn_code
;
2573 if (! (*insn_operand_predicate
[icode
][0]) (x
, insn_operand_mode
[icode
][0])
2574 || ! (*insn_operand_predicate
[icode
][1]) (x
, insn_operand_mode
[icode
][1])
2575 || ! (*insn_operand_predicate
[icode
][2]) (y
, insn_operand_mode
[icode
][2]))
2578 return (GEN_FCN (icode
) (x
, x
, y
));
2582 have_add2_insn (mode
)
2583 enum machine_mode mode
;
2585 return add_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
;
2588 /* Generate and return an insn body to subtract Y from X. */
2591 gen_sub2_insn (x
, y
)
2594 int icode
= (int) sub_optab
->handlers
[(int) GET_MODE (x
)].insn_code
;
2596 if (! (*insn_operand_predicate
[icode
][0]) (x
, insn_operand_mode
[icode
][0])
2597 || ! (*insn_operand_predicate
[icode
][1]) (x
, insn_operand_mode
[icode
][1])
2598 || ! (*insn_operand_predicate
[icode
][2]) (y
, insn_operand_mode
[icode
][2]))
2601 return (GEN_FCN (icode
) (x
, x
, y
));
2605 have_sub2_insn (mode
)
2606 enum machine_mode mode
;
2608 return sub_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
;
2611 /* Generate the body of an instruction to copy Y into X.
2612 It may be a SEQUENCE, if one insn isn't enough. */
2615 gen_move_insn (x
, y
)
2618 register enum machine_mode mode
= GET_MODE (x
);
2619 enum insn_code insn_code
;
2622 if (mode
== VOIDmode
)
2623 mode
= GET_MODE (y
);
2625 insn_code
= mov_optab
->handlers
[(int) mode
].insn_code
;
2627 /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
2628 find a mode to do it in. If we have a movcc, use it. Otherwise,
2629 find the MODE_INT mode of the same width. */
2631 if (GET_MODE_CLASS (mode
) == MODE_CC
&& insn_code
== CODE_FOR_nothing
)
2633 enum machine_mode tmode
= VOIDmode
;
2637 && mov_optab
->handlers
[(int) CCmode
].insn_code
!= CODE_FOR_nothing
)
2640 for (tmode
= QImode
; tmode
!= VOIDmode
;
2641 tmode
= GET_MODE_WIDER_MODE (tmode
))
2642 if (GET_MODE_SIZE (tmode
) == GET_MODE_SIZE (mode
))
2645 if (tmode
== VOIDmode
)
2648 /* Get X and Y in TMODE. We can't use gen_lowpart here because it
2649 may call change_address which is not appropriate if we were
2650 called when a reload was in progress. We don't have to worry
2651 about changing the address since the size in bytes is supposed to
2652 be the same. Copy the MEM to change the mode and move any
2653 substitutions from the old MEM to the new one. */
2655 if (reload_in_progress
)
2657 x
= gen_lowpart_common (tmode
, x1
);
2658 if (x
== 0 && GET_CODE (x1
) == MEM
)
2660 x
= gen_rtx (MEM
, tmode
, XEXP (x1
, 0));
2661 RTX_UNCHANGING_P (x
) = RTX_UNCHANGING_P (x1
);
2662 MEM_IN_STRUCT_P (x
) = MEM_IN_STRUCT_P (x1
);
2663 MEM_VOLATILE_P (x
) = MEM_VOLATILE_P (x1
);
2664 copy_replacements (x1
, x
);
2667 y
= gen_lowpart_common (tmode
, y1
);
2668 if (y
== 0 && GET_CODE (y1
) == MEM
)
2670 y
= gen_rtx (MEM
, tmode
, XEXP (y1
, 0));
2671 RTX_UNCHANGING_P (y
) = RTX_UNCHANGING_P (y1
);
2672 MEM_IN_STRUCT_P (y
) = MEM_IN_STRUCT_P (y1
);
2673 MEM_VOLATILE_P (y
) = MEM_VOLATILE_P (y1
);
2674 copy_replacements (y1
, y
);
2679 x
= gen_lowpart (tmode
, x
);
2680 y
= gen_lowpart (tmode
, y
);
2683 insn_code
= mov_optab
->handlers
[(int) tmode
].insn_code
;
2684 return (GEN_FCN (insn_code
) (x
, y
));
2688 emit_move_insn_1 (x
, y
);
2689 seq
= gen_sequence ();
2694 /* Return the insn code used to extend FROM_MODE to TO_MODE.
2695 UNSIGNEDP specifies zero-extension instead of sign-extension. If
2696 no such operation exists, CODE_FOR_nothing will be returned. */
2699 can_extend_p (to_mode
, from_mode
, unsignedp
)
2700 enum machine_mode to_mode
, from_mode
;
2703 return extendtab
[(int) to_mode
][(int) from_mode
][unsignedp
];
2706 /* Generate the body of an insn to extend Y (with mode MFROM)
2707 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
2710 gen_extend_insn (x
, y
, mto
, mfrom
, unsignedp
)
2712 enum machine_mode mto
, mfrom
;
2715 return (GEN_FCN (extendtab
[(int) mto
][(int) mfrom
][unsignedp
]) (x
, y
));
2718 /* can_fix_p and can_float_p say whether the target machine
2719 can directly convert a given fixed point type to
2720 a given floating point type, or vice versa.
2721 The returned value is the CODE_FOR_... value to use,
2722 or CODE_FOR_nothing if these modes cannot be directly converted.
2724 *TRUNCP_PTR is set to 1 if it is necessary to output
2725 an explicit FTRUNC insn before the fix insn; otherwise 0. */
2727 static enum insn_code
2728 can_fix_p (fixmode
, fltmode
, unsignedp
, truncp_ptr
)
2729 enum machine_mode fltmode
, fixmode
;
2734 if (fixtrunctab
[(int) fltmode
][(int) fixmode
][unsignedp
] != CODE_FOR_nothing
)
2735 return fixtrunctab
[(int) fltmode
][(int) fixmode
][unsignedp
];
2737 if (ftrunc_optab
->handlers
[(int) fltmode
].insn_code
!= CODE_FOR_nothing
)
2740 return fixtab
[(int) fltmode
][(int) fixmode
][unsignedp
];
2742 return CODE_FOR_nothing
;
2745 static enum insn_code
2746 can_float_p (fltmode
, fixmode
, unsignedp
)
2747 enum machine_mode fixmode
, fltmode
;
2750 return floattab
[(int) fltmode
][(int) fixmode
][unsignedp
];
2753 /* Generate code to convert FROM to floating point
2754 and store in TO. FROM must be fixed point and not VOIDmode.
2755 UNSIGNEDP nonzero means regard FROM as unsigned.
2756 Normally this is done by correcting the final value
2757 if it is negative. */
2760 expand_float (to
, from
, unsignedp
)
2764 enum insn_code icode
;
2765 register rtx target
= to
;
2766 enum machine_mode fmode
, imode
;
2768 /* Crash now, because we won't be able to decide which mode to use. */
2769 if (GET_MODE (from
) == VOIDmode
)
2772 /* Look for an insn to do the conversion. Do it in the specified
2773 modes if possible; otherwise convert either input, output or both to
2774 wider mode. If the integer mode is wider than the mode of FROM,
2775 we can do the conversion signed even if the input is unsigned. */
2777 for (imode
= GET_MODE (from
); imode
!= VOIDmode
;
2778 imode
= GET_MODE_WIDER_MODE (imode
))
2779 for (fmode
= GET_MODE (to
); fmode
!= VOIDmode
;
2780 fmode
= GET_MODE_WIDER_MODE (fmode
))
2782 int doing_unsigned
= unsignedp
;
2784 icode
= can_float_p (fmode
, imode
, unsignedp
);
2785 if (icode
== CODE_FOR_nothing
&& imode
!= GET_MODE (from
) && unsignedp
)
2786 icode
= can_float_p (fmode
, imode
, 0), doing_unsigned
= 0;
2788 if (icode
!= CODE_FOR_nothing
)
2790 to
= protect_from_queue (to
, 1);
2791 from
= protect_from_queue (from
, 0);
2793 if (imode
!= GET_MODE (from
))
2794 from
= convert_to_mode (imode
, from
, unsignedp
);
2796 if (fmode
!= GET_MODE (to
))
2797 target
= gen_reg_rtx (fmode
);
2799 emit_unop_insn (icode
, target
, from
,
2800 doing_unsigned
? UNSIGNED_FLOAT
: FLOAT
);
2803 convert_move (to
, target
, 0);
2808 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
2810 /* Unsigned integer, and no way to convert directly.
2811 Convert as signed, then conditionally adjust the result. */
2814 rtx label
= gen_label_rtx ();
2816 REAL_VALUE_TYPE offset
;
2820 to
= protect_from_queue (to
, 1);
2821 from
= protect_from_queue (from
, 0);
2824 from
= force_not_mem (from
);
2826 /* Look for a usable floating mode FMODE wider than the source and at
2827 least as wide as the target. Using FMODE will avoid rounding woes
2828 with unsigned values greater than the signed maximum value. */
2829 for (fmode
= GET_MODE (to
); fmode
!= VOIDmode
;
2830 fmode
= GET_MODE_WIDER_MODE (fmode
))
2831 if (GET_MODE_BITSIZE (GET_MODE (from
)) < GET_MODE_BITSIZE (fmode
)
2832 && can_float_p (fmode
, GET_MODE (from
), 0) != CODE_FOR_nothing
)
2834 if (fmode
== VOIDmode
)
2836 /* There is no such mode. Pretend the target is wide enough.
2837 This may cause rounding problems, unfortunately. */
2838 fmode
= GET_MODE (to
);
2841 /* If we are about to do some arithmetic to correct for an
2842 unsigned operand, do it in a pseudo-register. */
2844 if (GET_MODE (to
) != fmode
2845 || GET_CODE (to
) != REG
|| REGNO (to
) <= LAST_VIRTUAL_REGISTER
)
2846 target
= gen_reg_rtx (fmode
);
2848 /* Convert as signed integer to floating. */
2849 expand_float (target
, from
, 0);
2851 /* If FROM is negative (and therefore TO is negative),
2852 correct its value by 2**bitwidth. */
2854 do_pending_stack_adjust ();
2855 emit_cmp_insn (from
, const0_rtx
, GE
, NULL_RTX
, GET_MODE (from
), 0, 0);
2856 emit_jump_insn (gen_bge (label
));
2857 /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
2858 Rather than setting up a dconst_dot_5, let's hope SCO
2860 offset
= REAL_VALUE_LDEXP (dconst1
, GET_MODE_BITSIZE (GET_MODE (from
)));
2861 temp
= expand_binop (fmode
, add_optab
, target
,
2862 immed_real_const_1 (offset
, fmode
),
2863 target
, 0, OPTAB_LIB_WIDEN
);
2865 emit_move_insn (target
, temp
);
2866 do_pending_stack_adjust ();
2872 /* No hardware instruction available; call a library rotine to convert from
2873 SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */
2878 to
= protect_from_queue (to
, 1);
2879 from
= protect_from_queue (from
, 0);
2881 if (GET_MODE_SIZE (GET_MODE (from
)) < GET_MODE_SIZE (SImode
))
2882 from
= convert_to_mode (SImode
, from
, unsignedp
);
2885 from
= force_not_mem (from
);
2887 if (GET_MODE (to
) == SFmode
)
2889 if (GET_MODE (from
) == SImode
)
2890 libfcn
= floatsisf_libfunc
;
2891 else if (GET_MODE (from
) == DImode
)
2892 libfcn
= floatdisf_libfunc
;
2893 else if (GET_MODE (from
) == TImode
)
2894 libfcn
= floattisf_libfunc
;
2898 else if (GET_MODE (to
) == DFmode
)
2900 if (GET_MODE (from
) == SImode
)
2901 libfcn
= floatsidf_libfunc
;
2902 else if (GET_MODE (from
) == DImode
)
2903 libfcn
= floatdidf_libfunc
;
2904 else if (GET_MODE (from
) == TImode
)
2905 libfcn
= floattidf_libfunc
;
2909 else if (GET_MODE (to
) == XFmode
)
2911 if (GET_MODE (from
) == SImode
)
2912 libfcn
= floatsixf_libfunc
;
2913 else if (GET_MODE (from
) == DImode
)
2914 libfcn
= floatdixf_libfunc
;
2915 else if (GET_MODE (from
) == TImode
)
2916 libfcn
= floattixf_libfunc
;
2920 else if (GET_MODE (to
) == TFmode
)
2922 if (GET_MODE (from
) == SImode
)
2923 libfcn
= floatsitf_libfunc
;
2924 else if (GET_MODE (from
) == DImode
)
2925 libfcn
= floatditf_libfunc
;
2926 else if (GET_MODE (from
) == TImode
)
2927 libfcn
= floattitf_libfunc
;
2936 emit_library_call (libfcn
, 1, GET_MODE (to
), 1, from
, GET_MODE (from
));
2937 insns
= get_insns ();
2940 emit_libcall_block (insns
, target
, hard_libcall_value (GET_MODE (to
)),
2941 gen_rtx (FLOAT
, GET_MODE (to
), from
));
2944 /* Copy result to requested destination
2945 if we have been computing in a temp location. */
2949 if (GET_MODE (target
) == GET_MODE (to
))
2950 emit_move_insn (to
, target
);
2952 convert_move (to
, target
, 0);
2956 /* expand_fix: generate code to convert FROM to fixed point
2957 and store in TO. FROM must be floating point. */
2963 rtx temp
= gen_reg_rtx (GET_MODE (x
));
2964 return expand_unop (GET_MODE (x
), ftrunc_optab
, x
, temp
, 0);
2968 expand_fix (to
, from
, unsignedp
)
2969 register rtx to
, from
;
2972 enum insn_code icode
;
2973 register rtx target
= to
;
2974 enum machine_mode fmode
, imode
;
2978 /* We first try to find a pair of modes, one real and one integer, at
2979 least as wide as FROM and TO, respectively, in which we can open-code
2980 this conversion. If the integer mode is wider than the mode of TO,
2981 we can do the conversion either signed or unsigned. */
2983 for (imode
= GET_MODE (to
); imode
!= VOIDmode
;
2984 imode
= GET_MODE_WIDER_MODE (imode
))
2985 for (fmode
= GET_MODE (from
); fmode
!= VOIDmode
;
2986 fmode
= GET_MODE_WIDER_MODE (fmode
))
2988 int doing_unsigned
= unsignedp
;
2990 icode
= can_fix_p (imode
, fmode
, unsignedp
, &must_trunc
);
2991 if (icode
== CODE_FOR_nothing
&& imode
!= GET_MODE (to
) && unsignedp
)
2992 icode
= can_fix_p (imode
, fmode
, 0, &must_trunc
), doing_unsigned
= 0;
2994 if (icode
!= CODE_FOR_nothing
)
2996 to
= protect_from_queue (to
, 1);
2997 from
= protect_from_queue (from
, 0);
2999 if (fmode
!= GET_MODE (from
))
3000 from
= convert_to_mode (fmode
, from
, 0);
3003 from
= ftruncify (from
);
3005 if (imode
!= GET_MODE (to
))
3006 target
= gen_reg_rtx (imode
);
3008 emit_unop_insn (icode
, target
, from
,
3009 doing_unsigned
? UNSIGNED_FIX
: FIX
);
3011 convert_move (to
, target
, unsignedp
);
3016 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3017 /* For an unsigned conversion, there is one more way to do it.
3018 If we have a signed conversion, we generate code that compares
3019 the real value to the largest representable positive number. If if
3020 is smaller, the conversion is done normally. Otherwise, subtract
3021 one plus the highest signed number, convert, and add it back.
3023 We only need to check all real modes, since we know we didn't find
3024 anything with a wider integer mode. */
3026 if (unsignedp
&& GET_MODE_BITSIZE (GET_MODE (to
)) <= HOST_BITS_PER_WIDE_INT
)
3027 for (fmode
= GET_MODE (from
); fmode
!= VOIDmode
;
3028 fmode
= GET_MODE_WIDER_MODE (fmode
))
3029 /* Make sure we won't lose significant bits doing this. */
3030 if (GET_MODE_BITSIZE (fmode
) > GET_MODE_BITSIZE (GET_MODE (to
))
3031 && CODE_FOR_nothing
!= can_fix_p (GET_MODE (to
), fmode
, 0,
3035 REAL_VALUE_TYPE offset
;
3036 rtx limit
, lab1
, lab2
, insn
;
3038 bitsize
= GET_MODE_BITSIZE (GET_MODE (to
));
3039 offset
= REAL_VALUE_LDEXP (dconst1
, bitsize
- 1);
3040 limit
= immed_real_const_1 (offset
, fmode
);
3041 lab1
= gen_label_rtx ();
3042 lab2
= gen_label_rtx ();
3045 to
= protect_from_queue (to
, 1);
3046 from
= protect_from_queue (from
, 0);
3049 from
= force_not_mem (from
);
3051 if (fmode
!= GET_MODE (from
))
3052 from
= convert_to_mode (fmode
, from
, 0);
3054 /* See if we need to do the subtraction. */
3055 do_pending_stack_adjust ();
3056 emit_cmp_insn (from
, limit
, GE
, NULL_RTX
, GET_MODE (from
), 0, 0);
3057 emit_jump_insn (gen_bge (lab1
));
3059 /* If not, do the signed "fix" and branch around fixup code. */
3060 expand_fix (to
, from
, 0);
3061 emit_jump_insn (gen_jump (lab2
));
3064 /* Otherwise, subtract 2**(N-1), convert to signed number,
3065 then add 2**(N-1). Do the addition using XOR since this
3066 will often generate better code. */
3068 target
= expand_binop (GET_MODE (from
), sub_optab
, from
, limit
,
3069 NULL_RTX
, 0, OPTAB_LIB_WIDEN
);
3070 expand_fix (to
, target
, 0);
3071 target
= expand_binop (GET_MODE (to
), xor_optab
, to
,
3072 GEN_INT ((HOST_WIDE_INT
) 1 << (bitsize
- 1)),
3073 to
, 1, OPTAB_LIB_WIDEN
);
3076 emit_move_insn (to
, target
);
3080 /* Make a place for a REG_NOTE and add it. */
3081 insn
= emit_move_insn (to
, to
);
3082 REG_NOTES (insn
) = gen_rtx (EXPR_LIST
, REG_EQUAL
,
3083 gen_rtx (UNSIGNED_FIX
, GET_MODE (to
),
3084 from
), REG_NOTES (insn
));
3090 /* We can't do it with an insn, so use a library call. But first ensure
3091 that the mode of TO is at least as wide as SImode, since those are the
3092 only library calls we know about. */
3094 if (GET_MODE_SIZE (GET_MODE (to
)) < GET_MODE_SIZE (SImode
))
3096 target
= gen_reg_rtx (SImode
);
3098 expand_fix (target
, from
, unsignedp
);
3100 else if (GET_MODE (from
) == SFmode
)
3102 if (GET_MODE (to
) == SImode
)
3103 libfcn
= unsignedp
? fixunssfsi_libfunc
: fixsfsi_libfunc
;
3104 else if (GET_MODE (to
) == DImode
)
3105 libfcn
= unsignedp
? fixunssfdi_libfunc
: fixsfdi_libfunc
;
3106 else if (GET_MODE (to
) == TImode
)
3107 libfcn
= unsignedp
? fixunssfti_libfunc
: fixsfti_libfunc
;
3111 else if (GET_MODE (from
) == DFmode
)
3113 if (GET_MODE (to
) == SImode
)
3114 libfcn
= unsignedp
? fixunsdfsi_libfunc
: fixdfsi_libfunc
;
3115 else if (GET_MODE (to
) == DImode
)
3116 libfcn
= unsignedp
? fixunsdfdi_libfunc
: fixdfdi_libfunc
;
3117 else if (GET_MODE (to
) == TImode
)
3118 libfcn
= unsignedp
? fixunsdfti_libfunc
: fixdfti_libfunc
;
3122 else if (GET_MODE (from
) == XFmode
)
3124 if (GET_MODE (to
) == SImode
)
3125 libfcn
= unsignedp
? fixunsxfsi_libfunc
: fixxfsi_libfunc
;
3126 else if (GET_MODE (to
) == DImode
)
3127 libfcn
= unsignedp
? fixunsxfdi_libfunc
: fixxfdi_libfunc
;
3128 else if (GET_MODE (to
) == TImode
)
3129 libfcn
= unsignedp
? fixunsxfti_libfunc
: fixxfti_libfunc
;
3133 else if (GET_MODE (from
) == TFmode
)
3135 if (GET_MODE (to
) == SImode
)
3136 libfcn
= unsignedp
? fixunstfsi_libfunc
: fixtfsi_libfunc
;
3137 else if (GET_MODE (to
) == DImode
)
3138 libfcn
= unsignedp
? fixunstfdi_libfunc
: fixtfdi_libfunc
;
3139 else if (GET_MODE (to
) == TImode
)
3140 libfcn
= unsignedp
? fixunstfti_libfunc
: fixtfti_libfunc
;
3151 to
= protect_from_queue (to
, 1);
3152 from
= protect_from_queue (from
, 0);
3155 from
= force_not_mem (from
);
3159 emit_library_call (libfcn
, 1, GET_MODE (to
), 1, from
, GET_MODE (from
));
3160 insns
= get_insns ();
3163 emit_libcall_block (insns
, target
, hard_libcall_value (GET_MODE (to
)),
3164 gen_rtx (unsignedp
? FIX
: UNSIGNED_FIX
,
3165 GET_MODE (to
), from
));
3168 if (GET_MODE (to
) == GET_MODE (target
))
3169 emit_move_insn (to
, target
);
3171 convert_move (to
, target
, 0);
3179 optab op
= (optab
) xmalloc (sizeof (struct optab
));
3181 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
3183 op
->handlers
[i
].insn_code
= CODE_FOR_nothing
;
3184 op
->handlers
[i
].libfunc
= 0;
3189 /* Initialize the libfunc fields of an entire group of entries in some
3190 optab. Each entry is set equal to a string consisting of a leading
3191 pair of underscores followed by a generic operation name followed by
3192 a mode name (downshifted to lower case) followed by a single character
3193 representing the number of operands for the given operation (which is
3194 usually one of the characters '2', '3', or '4').
3196 OPTABLE is the table in which libfunc fields are to be initialized.
3197 FIRST_MODE is the first machine mode index in the given optab to
3199 LAST_MODE is the last machine mode index in the given optab to
3201 OPNAME is the generic (string) name of the operation.
3202 SUFFIX is the character which specifies the number of operands for
3203 the given generic operation.
3207 init_libfuncs (optable
, first_mode
, last_mode
, opname
, suffix
)
3208 register optab optable
;
3209 register int first_mode
;
3210 register int last_mode
;
3211 register char *opname
;
3212 register char suffix
;
3215 register unsigned opname_len
= strlen (opname
);
3217 for (mode
= first_mode
; (int) mode
<= (int) last_mode
;
3218 mode
= (enum machine_mode
) ((int) mode
+ 1))
3220 register char *mname
= mode_name
[(int) mode
];
3221 register unsigned mname_len
= strlen (mname
);
3222 register char *libfunc_name
3223 = (char *) xmalloc (2 + opname_len
+ mname_len
+ 1 + 1);
3230 for (q
= opname
; *q
; )
3232 for (q
= mname
; *q
; q
++)
3233 *p
++ = tolower (*q
);
3236 optable
->handlers
[(int) mode
].libfunc
3237 = gen_rtx (SYMBOL_REF
, Pmode
, libfunc_name
);
3241 /* Initialize the libfunc fields of an entire group of entries in some
3242 optab which correspond to all integer mode operations. The parameters
3243 have the same meaning as similarly named ones for the `init_libfuncs'
3244 routine. (See above). */
3247 init_integral_libfuncs (optable
, opname
, suffix
)
3248 register optab optable
;
3249 register char *opname
;
3250 register char suffix
;
3252 init_libfuncs (optable
, SImode
, TImode
, opname
, suffix
);
3255 /* Initialize the libfunc fields of an entire group of entries in some
3256 optab which correspond to all real mode operations. The parameters
3257 have the same meaning as similarly named ones for the `init_libfuncs'
3258 routine. (See above). */
3261 init_floating_libfuncs (optable
, opname
, suffix
)
3262 register optab optable
;
3263 register char *opname
;
3264 register char suffix
;
3266 init_libfuncs (optable
, SFmode
, TFmode
, opname
, suffix
);
3269 /* Initialize the libfunc fields of an entire group of entries in some
3270 optab which correspond to all complex floating modes. The parameters
3271 have the same meaning as similarly named ones for the `init_libfuncs'
3272 routine. (See above). */
3275 init_complex_libfuncs (optable
, opname
, suffix
)
3276 register optab optable
;
3277 register char *opname
;
3278 register char suffix
;
3280 init_libfuncs (optable
, SCmode
, TCmode
, opname
, suffix
);
3283 /* Call this once to initialize the contents of the optabs
3284 appropriately for the current target machine. */
3292 /* Start by initializing all tables to contain CODE_FOR_nothing. */
3294 for (p
= fixtab
[0][0];
3295 p
< fixtab
[0][0] + sizeof fixtab
/ sizeof (fixtab
[0][0][0]);
3297 *p
= CODE_FOR_nothing
;
3299 for (p
= fixtrunctab
[0][0];
3300 p
< fixtrunctab
[0][0] + sizeof fixtrunctab
/ sizeof (fixtrunctab
[0][0][0]);
3302 *p
= CODE_FOR_nothing
;
3304 for (p
= floattab
[0][0];
3305 p
< floattab
[0][0] + sizeof floattab
/ sizeof (floattab
[0][0][0]);
3307 *p
= CODE_FOR_nothing
;
3309 for (p
= extendtab
[0][0];
3310 p
< extendtab
[0][0] + sizeof extendtab
/ sizeof extendtab
[0][0][0];
3312 *p
= CODE_FOR_nothing
;
3314 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
3315 setcc_gen_code
[i
] = CODE_FOR_nothing
;
3317 add_optab
= init_optab (PLUS
);
3318 sub_optab
= init_optab (MINUS
);
3319 smul_optab
= init_optab (MULT
);
3320 smul_widen_optab
= init_optab (UNKNOWN
);
3321 umul_widen_optab
= init_optab (UNKNOWN
);
3322 sdiv_optab
= init_optab (DIV
);
3323 sdivmod_optab
= init_optab (UNKNOWN
);
3324 udiv_optab
= init_optab (UDIV
);
3325 udivmod_optab
= init_optab (UNKNOWN
);
3326 smod_optab
= init_optab (MOD
);
3327 umod_optab
= init_optab (UMOD
);
3328 flodiv_optab
= init_optab (DIV
);
3329 ftrunc_optab
= init_optab (UNKNOWN
);
3330 and_optab
= init_optab (AND
);
3331 ior_optab
= init_optab (IOR
);
3332 xor_optab
= init_optab (XOR
);
3333 ashl_optab
= init_optab (ASHIFT
);
3334 ashr_optab
= init_optab (ASHIFTRT
);
3335 lshl_optab
= init_optab (LSHIFT
);
3336 lshr_optab
= init_optab (LSHIFTRT
);
3337 rotl_optab
= init_optab (ROTATE
);
3338 rotr_optab
= init_optab (ROTATERT
);
3339 smin_optab
= init_optab (SMIN
);
3340 smax_optab
= init_optab (SMAX
);
3341 umin_optab
= init_optab (UMIN
);
3342 umax_optab
= init_optab (UMAX
);
3343 mov_optab
= init_optab (UNKNOWN
);
3344 movstrict_optab
= init_optab (UNKNOWN
);
3345 cmp_optab
= init_optab (UNKNOWN
);
3346 ucmp_optab
= init_optab (UNKNOWN
);
3347 tst_optab
= init_optab (UNKNOWN
);
3348 neg_optab
= init_optab (NEG
);
3349 abs_optab
= init_optab (ABS
);
3350 one_cmpl_optab
= init_optab (NOT
);
3351 ffs_optab
= init_optab (FFS
);
3352 sqrt_optab
= init_optab (SQRT
);
3353 sin_optab
= init_optab (UNKNOWN
);
3354 cos_optab
= init_optab (UNKNOWN
);
3355 strlen_optab
= init_optab (UNKNOWN
);
3357 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
3359 movstr_optab
[i
] = CODE_FOR_nothing
;
3361 #ifdef HAVE_SECONDARY_RELOADS
3362 reload_in_optab
[i
] = reload_out_optab
[i
] = CODE_FOR_nothing
;
3366 /* Fill in the optabs with the insns we support. */
3369 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
3370 /* This flag says the same insns that convert to a signed fixnum
3371 also convert validly to an unsigned one. */
3372 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
3373 for (j
= 0; j
< NUM_MACHINE_MODES
; j
++)
3374 fixtrunctab
[i
][j
][1] = fixtrunctab
[i
][j
][0];
3377 #ifdef EXTRA_CC_MODES
3381 /* Initialize the optabs with the names of the library functions. */
3382 init_integral_libfuncs (add_optab
, "add", '3');
3383 init_floating_libfuncs (add_optab
, "add", '3');
3384 init_integral_libfuncs (sub_optab
, "sub", '3');
3385 init_floating_libfuncs (sub_optab
, "sub", '3');
3386 init_integral_libfuncs (smul_optab
, "mul", '3');
3387 init_floating_libfuncs (smul_optab
, "mul", '3');
3388 init_integral_libfuncs (sdiv_optab
, "div", '3');
3389 init_integral_libfuncs (udiv_optab
, "udiv", '3');
3390 init_integral_libfuncs (sdivmod_optab
, "divmod", '4');
3391 init_integral_libfuncs (udivmod_optab
, "udivmod", '4');
3392 init_integral_libfuncs (smod_optab
, "mod", '3');
3393 init_integral_libfuncs (umod_optab
, "umod", '3');
3394 init_floating_libfuncs (flodiv_optab
, "div", '3');
3395 init_floating_libfuncs (ftrunc_optab
, "ftrunc", '2');
3396 init_integral_libfuncs (and_optab
, "and", '3');
3397 init_integral_libfuncs (ior_optab
, "ior", '3');
3398 init_integral_libfuncs (xor_optab
, "xor", '3');
3399 init_integral_libfuncs (ashl_optab
, "ashl", '3');
3400 init_integral_libfuncs (ashr_optab
, "ashr", '3');
3401 init_integral_libfuncs (lshl_optab
, "lshl", '3');
3402 init_integral_libfuncs (lshr_optab
, "lshr", '3');
3403 init_integral_libfuncs (rotl_optab
, "rotl", '3');
3404 init_integral_libfuncs (rotr_optab
, "rotr", '3');
3405 init_integral_libfuncs (smin_optab
, "min", '3');
3406 init_floating_libfuncs (smin_optab
, "min", '3');
3407 init_integral_libfuncs (smax_optab
, "max", '3');
3408 init_floating_libfuncs (smax_optab
, "max", '3');
3409 init_integral_libfuncs (umin_optab
, "umin", '3');
3410 init_integral_libfuncs (umax_optab
, "umax", '3');
3411 init_integral_libfuncs (neg_optab
, "neg", '2');
3412 init_floating_libfuncs (neg_optab
, "neg", '2');
3413 init_integral_libfuncs (one_cmpl_optab
, "one_cmpl", '2');
3414 init_integral_libfuncs (ffs_optab
, "ffs", '2');
3416 /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
3417 init_integral_libfuncs (cmp_optab
, "cmp", '2');
3418 init_integral_libfuncs (ucmp_optab
, "ucmp", '2');
3419 init_floating_libfuncs (cmp_optab
, "cmp", '2');
3421 #ifdef MULSI3_LIBCALL
3422 smul_optab
->handlers
[(int) SImode
].libfunc
3423 = gen_rtx (SYMBOL_REF
, Pmode
, MULSI3_LIBCALL
);
3425 #ifdef MULDI3_LIBCALL
3426 smul_optab
->handlers
[(int) DImode
].libfunc
3427 = gen_rtx (SYMBOL_REF
, Pmode
, MULDI3_LIBCALL
);
3429 #ifdef MULTI3_LIBCALL
3430 smul_optab
->handlers
[(int) TImode
].libfunc
3431 = gen_rtx (SYMBOL_REF
, Pmode
, MULTI3_LIBCALL
);
3434 #ifdef DIVSI3_LIBCALL
3435 sdiv_optab
->handlers
[(int) SImode
].libfunc
3436 = gen_rtx (SYMBOL_REF
, Pmode
, DIVSI3_LIBCALL
);
3438 #ifdef DIVDI3_LIBCALL
3439 sdiv_optab
->handlers
[(int) DImode
].libfunc
3440 = gen_rtx (SYMBOL_REF
, Pmode
, DIVDI3_LIBCALL
);
3442 #ifdef DIVTI3_LIBCALL
3443 sdiv_optab
->handlers
[(int) TImode
].libfunc
3444 = gen_rtx (SYMBOL_REF
, Pmode
, DIVTI3_LIBCALL
);
3447 #ifdef UDIVSI3_LIBCALL
3448 udiv_optab
->handlers
[(int) SImode
].libfunc
3449 = gen_rtx (SYMBOL_REF
, Pmode
, UDIVSI3_LIBCALL
);
3451 #ifdef UDIVDI3_LIBCALL
3452 udiv_optab
->handlers
[(int) DImode
].libfunc
3453 = gen_rtx (SYMBOL_REF
, Pmode
, UDIVDI3_LIBCALL
);
3455 #ifdef UDIVTI3_LIBCALL
3456 udiv_optab
->handlers
[(int) TImode
].libfunc
3457 = gen_rtx (SYMBOL_REF
, Pmode
, UDIVTI3_LIBCALL
);
3461 #ifdef MODSI3_LIBCALL
3462 smod_optab
->handlers
[(int) SImode
].libfunc
3463 = gen_rtx (SYMBOL_REF
, Pmode
, MODSI3_LIBCALL
);
3465 #ifdef MODDI3_LIBCALL
3466 smod_optab
->handlers
[(int) DImode
].libfunc
3467 = gen_rtx (SYMBOL_REF
, Pmode
, MODDI3_LIBCALL
);
3469 #ifdef MODTI3_LIBCALL
3470 smod_optab
->handlers
[(int) TImode
].libfunc
3471 = gen_rtx (SYMBOL_REF
, Pmode
, MODTI3_LIBCALL
);
3475 #ifdef UMODSI3_LIBCALL
3476 umod_optab
->handlers
[(int) SImode
].libfunc
3477 = gen_rtx (SYMBOL_REF
, Pmode
, UMODSI3_LIBCALL
);
3479 #ifdef UMODDI3_LIBCALL
3480 umod_optab
->handlers
[(int) DImode
].libfunc
3481 = gen_rtx (SYMBOL_REF
, Pmode
, UMODDI3_LIBCALL
);
3483 #ifdef UMODTI3_LIBCALL
3484 umod_optab
->handlers
[(int) TImode
].libfunc
3485 = gen_rtx (SYMBOL_REF
, Pmode
, UMODTI3_LIBCALL
);
3488 /* Use cabs for DC complex abs, since systems generally have cabs.
3489 Don't define any libcall for SCmode, so that cabs will be used. */
3490 abs_optab
->handlers
[(int) DCmode
].libfunc
3491 = gen_rtx (SYMBOL_REF
, Pmode
, "cabs");
3493 ffs_optab
->handlers
[(int) mode_for_size (BITS_PER_WORD
, MODE_INT
, 0)] .libfunc
3494 = gen_rtx (SYMBOL_REF
, Pmode
, "ffs");
3496 extendsfdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extendsfdf2");
3497 extendsfxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extendsfxf2");
3498 extendsftf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extendsftf2");
3499 extenddfxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extenddfxf2");
3500 extenddftf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extenddftf2");
3502 truncdfsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__truncdfsf2");
3503 truncxfsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__truncxfsf2");
3504 trunctfsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__trunctfsf2");
3505 truncxfdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__truncxfdf2");
3506 trunctfdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__trunctfdf2");
3508 memcpy_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "memcpy");
3509 bcopy_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "bcopy");
3510 memcmp_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "memcmp");
3511 bcmp_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gcc_bcmp");
3512 memset_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "memset");
3513 bzero_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "bzero");
3515 eqsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqsf2");
3516 nesf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__nesf2");
3517 gtsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gtsf2");
3518 gesf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gesf2");
3519 ltsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ltsf2");
3520 lesf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__lesf2");
3522 eqdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqdf2");
3523 nedf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__nedf2");
3524 gtdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gtdf2");
3525 gedf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gedf2");
3526 ltdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ltdf2");
3527 ledf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ledf2");
3529 eqxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqxf2");
3530 nexf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__nexf2");
3531 gtxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gtxf2");
3532 gexf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gexf2");
3533 ltxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ltxf2");
3534 lexf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__lexf2");
3536 eqtf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqtf2");
3537 netf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__netf2");
3538 gttf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gttf2");
3539 getf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__getf2");
3540 lttf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__lttf2");
3541 letf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__letf2");
3543 floatsisf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatsisf");
3544 floatdisf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatdisf");
3545 floattisf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floattisf");
3547 floatsidf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatsidf");
3548 floatdidf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatdidf");
3549 floattidf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floattidf");
3551 floatsixf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatsixf");
3552 floatdixf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatdixf");
3553 floattixf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floattixf");
3555 floatsitf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatsitf");
3556 floatditf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatditf");
3557 floattitf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floattitf");
3559 fixsfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixsfsi");
3560 fixsfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixsfdi");
3561 fixsfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixsfti");
3563 fixdfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixdfsi");
3564 fixdfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixdfdi");
3565 fixdfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixdfti");
3567 fixxfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixxfsi");
3568 fixxfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixxfdi");
3569 fixxfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixxfti");
3571 fixtfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixtfsi");
3572 fixtfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixtfdi");
3573 fixtfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixtfti");
3575 fixunssfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunssfsi");
3576 fixunssfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunssfdi");
3577 fixunssfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunssfti");
3579 fixunsdfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsdfsi");
3580 fixunsdfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsdfdi");
3581 fixunsdfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsdfti");
3583 fixunsxfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsxfsi");
3584 fixunsxfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsxfdi");
3585 fixunsxfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsxfti");
3587 fixunstfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunstfsi");
3588 fixunstfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunstfdi");
3589 fixunstfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunstfti");
3594 /* SCO 3.2 apparently has a broken ldexp. */
3607 #endif /* BROKEN_LDEXP */
This page took 0.20315 seconds and 6 git commands to generate.