1 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2 Copyright (C) 1987, 88, 92-98, 1999 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, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
25 /* Include insn-config.h before expr.h so that HAVE_conditional_move
26 is properly defined. */
27 #include "insn-config.h"
31 #include "insn-flags.h"
32 #include "insn-codes.h"
37 /* Each optab contains info on how this target machine
38 can perform a particular operation
39 for all sizes and kinds of operands.
41 The operation to be performed is often specified
42 by passing one of these optabs as an argument.
44 See expr.h for documentation of these optabs. */
49 optab smul_highpart_optab
;
50 optab umul_highpart_optab
;
51 optab smul_widen_optab
;
52 optab umul_widen_optab
;
75 optab movstrict_optab
;
86 optab ucmp_optab
; /* Used only for libcalls for unsigned comparisons. */
91 /* Tables of patterns for extending one integer mode to another. */
92 enum insn_code extendtab
[MAX_MACHINE_MODE
][MAX_MACHINE_MODE
][2];
94 /* Tables of patterns for converting between fixed and floating point. */
95 enum insn_code fixtab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
96 enum insn_code fixtrunctab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
97 enum insn_code floattab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
99 /* Contains the optab used for each rtx code. */
100 optab code_to_optab
[NUM_RTX_CODE
+ 1];
102 /* SYMBOL_REF rtx's for the library functions that are called
103 implicitly and not via optabs. */
105 rtx extendsfdf2_libfunc
;
106 rtx extendsfxf2_libfunc
;
107 rtx extendsftf2_libfunc
;
108 rtx extenddfxf2_libfunc
;
109 rtx extenddftf2_libfunc
;
111 rtx truncdfsf2_libfunc
;
112 rtx truncxfsf2_libfunc
;
113 rtx trunctfsf2_libfunc
;
114 rtx truncxfdf2_libfunc
;
115 rtx trunctfdf2_libfunc
;
127 rtx sjpopnthrow_libfunc
;
128 rtx terminate_libfunc
;
131 rtx eh_rtime_match_libfunc
;
168 rtx floatsisf_libfunc
;
169 rtx floatdisf_libfunc
;
170 rtx floattisf_libfunc
;
172 rtx floatsidf_libfunc
;
173 rtx floatdidf_libfunc
;
174 rtx floattidf_libfunc
;
176 rtx floatsixf_libfunc
;
177 rtx floatdixf_libfunc
;
178 rtx floattixf_libfunc
;
180 rtx floatsitf_libfunc
;
181 rtx floatditf_libfunc
;
182 rtx floattitf_libfunc
;
200 rtx fixunssfsi_libfunc
;
201 rtx fixunssfdi_libfunc
;
202 rtx fixunssfti_libfunc
;
204 rtx fixunsdfsi_libfunc
;
205 rtx fixunsdfdi_libfunc
;
206 rtx fixunsdfti_libfunc
;
208 rtx fixunsxfsi_libfunc
;
209 rtx fixunsxfdi_libfunc
;
210 rtx fixunsxfti_libfunc
;
212 rtx fixunstfsi_libfunc
;
213 rtx fixunstfdi_libfunc
;
214 rtx fixunstfti_libfunc
;
216 rtx chkr_check_addr_libfunc
;
217 rtx chkr_set_right_libfunc
;
218 rtx chkr_copy_bitmap_libfunc
;
219 rtx chkr_check_exec_libfunc
;
220 rtx chkr_check_str_libfunc
;
222 rtx profile_function_entry_libfunc
;
223 rtx profile_function_exit_libfunc
;
225 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
226 gives the gen_function to make a branch to test that condition. */
228 rtxfun bcc_gen_fctn
[NUM_RTX_CODE
];
230 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
231 gives the insn code to make a store-condition insn
232 to test that condition. */
234 enum insn_code setcc_gen_code
[NUM_RTX_CODE
];
236 #ifdef HAVE_conditional_move
237 /* Indexed by the machine mode, gives the insn code to make a conditional
238 move insn. This is not indexed by the rtx-code like bcc_gen_fctn and
239 setcc_gen_code to cut down on the number of named patterns. Consider a day
240 when a lot more rtx codes are conditional (eg: for the ARM). */
242 enum insn_code movcc_gen_code
[NUM_MACHINE_MODES
];
245 static int add_equal_note
PROTO((rtx
, rtx
, enum rtx_code
, rtx
, rtx
));
246 static rtx widen_operand
PROTO((rtx
, enum machine_mode
,
247 enum machine_mode
, int, int));
248 static enum insn_code can_fix_p
PROTO((enum machine_mode
, enum machine_mode
,
250 static enum insn_code can_float_p
PROTO((enum machine_mode
, enum machine_mode
,
252 static rtx ftruncify
PROTO((rtx
));
253 static optab init_optab
PROTO((enum rtx_code
));
254 static void init_libfuncs
PROTO((optab
, int, int, const char *, int));
255 static void init_integral_libfuncs
PROTO((optab
, const char *, int));
256 static void init_floating_libfuncs
PROTO((optab
, const char *, int));
257 #ifdef HAVE_conditional_trap
258 static void init_traps
PROTO((void));
261 /* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
262 the result of operation CODE applied to OP0 (and OP1 if it is a binary
265 If the last insn does not set TARGET, don't do anything, but return 1.
267 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
268 don't add the REG_EQUAL note but return 0. Our caller can then try
269 again, ensuring that TARGET is not one of the operands. */
272 add_equal_note (seq
, target
, code
, op0
, op1
)
282 if ((GET_RTX_CLASS (code
) != '1' && GET_RTX_CLASS (code
) != '2'
283 && GET_RTX_CLASS (code
) != 'c' && GET_RTX_CLASS (code
) != '<')
284 || GET_CODE (seq
) != SEQUENCE
285 || (set
= single_set (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1))) == 0
286 || GET_CODE (target
) == ZERO_EXTRACT
287 || (! rtx_equal_p (SET_DEST (set
), target
)
288 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
290 && (GET_CODE (SET_DEST (set
)) != STRICT_LOW_PART
291 || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set
), 0)),
295 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
296 besides the last insn. */
297 if (reg_overlap_mentioned_p (target
, op0
)
298 || (op1
&& reg_overlap_mentioned_p (target
, op1
)))
299 for (i
= XVECLEN (seq
, 0) - 2; i
>= 0; i
--)
300 if (reg_set_p (target
, XVECEXP (seq
, 0, i
)))
303 if (GET_RTX_CLASS (code
) == '1')
304 note
= gen_rtx_fmt_e (code
, GET_MODE (target
), copy_rtx (op0
));
306 note
= gen_rtx_fmt_ee (code
, GET_MODE (target
), copy_rtx (op0
), copy_rtx (op1
));
308 set_unique_reg_note (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1), REG_EQUAL
, note
);
313 /* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP
314 says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need
315 not actually do a sign-extend or zero-extend, but can leave the
316 higher-order bits of the result rtx undefined, for example, in the case
317 of logical operations, but not right shifts. */
320 widen_operand (op
, mode
, oldmode
, unsignedp
, no_extend
)
322 enum machine_mode mode
, oldmode
;
328 /* If we must extend do so. If OP is either a constant or a SUBREG
329 for a promoted object, also extend since it will be more efficient to
332 || GET_MODE (op
) == VOIDmode
333 || (GET_CODE (op
) == SUBREG
&& SUBREG_PROMOTED_VAR_P (op
)))
334 return convert_modes (mode
, oldmode
, op
, unsignedp
);
336 /* If MODE is no wider than a single word, we return a paradoxical
338 if (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
)
339 return gen_rtx_SUBREG (mode
, force_reg (GET_MODE (op
), op
), 0);
341 /* Otherwise, get an object of MODE, clobber it, and set the low-order
344 result
= gen_reg_rtx (mode
);
345 emit_insn (gen_rtx_CLOBBER (VOIDmode
, result
));
346 emit_move_insn (gen_lowpart (GET_MODE (op
), result
), op
);
350 /* Generate code to perform an operation specified by BINOPTAB
351 on operands OP0 and OP1, with result having machine-mode MODE.
353 UNSIGNEDP is for the case where we have to widen the operands
354 to perform the operation. It says to use zero-extension.
356 If TARGET is nonzero, the value
357 is generated there, if it is convenient to do so.
358 In all cases an rtx is returned for the locus of the value;
359 this may or may not be TARGET. */
362 expand_binop (mode
, binoptab
, op0
, op1
, target
, unsignedp
, methods
)
363 enum machine_mode mode
;
368 enum optab_methods methods
;
370 enum optab_methods next_methods
371 = (methods
== OPTAB_LIB
|| methods
== OPTAB_LIB_WIDEN
372 ? OPTAB_WIDEN
: methods
);
373 enum mode_class
class;
374 enum machine_mode wider_mode
;
376 int commutative_op
= 0;
377 int shift_op
= (binoptab
->code
== ASHIFT
378 || binoptab
->code
== ASHIFTRT
379 || binoptab
->code
== LSHIFTRT
380 || binoptab
->code
== ROTATE
381 || binoptab
->code
== ROTATERT
);
382 rtx entry_last
= get_last_insn ();
385 class = GET_MODE_CLASS (mode
);
387 op0
= protect_from_queue (op0
, 0);
388 op1
= protect_from_queue (op1
, 0);
390 target
= protect_from_queue (target
, 1);
394 op0
= force_not_mem (op0
);
395 op1
= force_not_mem (op1
);
398 /* If subtracting an integer constant, convert this into an addition of
399 the negated constant. */
401 if (binoptab
== sub_optab
&& GET_CODE (op1
) == CONST_INT
)
403 op1
= negate_rtx (mode
, op1
);
404 binoptab
= add_optab
;
407 /* If we are inside an appropriately-short loop and one operand is an
408 expensive constant, force it into a register. */
409 if (CONSTANT_P (op0
) && preserve_subexpressions_p ()
410 && rtx_cost (op0
, binoptab
->code
) > 2)
411 op0
= force_reg (mode
, op0
);
413 if (CONSTANT_P (op1
) && preserve_subexpressions_p ()
414 && ! shift_op
&& rtx_cost (op1
, binoptab
->code
) > 2)
415 op1
= force_reg (mode
, op1
);
417 /* Record where to delete back to if we backtrack. */
418 last
= get_last_insn ();
420 /* If operation is commutative,
421 try to make the first operand a register.
422 Even better, try to make it the same as the target.
423 Also try to make the last operand a constant. */
424 if (GET_RTX_CLASS (binoptab
->code
) == 'c'
425 || binoptab
== smul_widen_optab
426 || binoptab
== umul_widen_optab
427 || binoptab
== smul_highpart_optab
428 || binoptab
== umul_highpart_optab
)
432 if (((target
== 0 || GET_CODE (target
) == REG
)
433 ? ((GET_CODE (op1
) == REG
434 && GET_CODE (op0
) != REG
)
436 : rtx_equal_p (op1
, target
))
437 || GET_CODE (op0
) == CONST_INT
)
445 /* If we can do it with a three-operand insn, do so. */
447 if (methods
!= OPTAB_MUST_WIDEN
448 && binoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
450 int icode
= (int) binoptab
->handlers
[(int) mode
].insn_code
;
451 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
452 enum machine_mode mode1
= insn_operand_mode
[icode
][2];
454 rtx xop0
= op0
, xop1
= op1
;
459 temp
= gen_reg_rtx (mode
);
461 /* If it is a commutative operator and the modes would match
462 if we would swap the operands, we can save the conversions. */
465 if (GET_MODE (op0
) != mode0
&& GET_MODE (op1
) != mode1
466 && GET_MODE (op0
) == mode1
&& GET_MODE (op1
) == mode0
)
470 tmp
= op0
; op0
= op1
; op1
= tmp
;
471 tmp
= xop0
; xop0
= xop1
; xop1
= tmp
;
475 /* In case the insn wants input operands in modes different from
476 the result, convert the operands. */
478 if (GET_MODE (op0
) != VOIDmode
479 && GET_MODE (op0
) != mode0
480 && mode0
!= VOIDmode
)
481 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
483 if (GET_MODE (xop1
) != VOIDmode
484 && GET_MODE (xop1
) != mode1
485 && mode1
!= VOIDmode
)
486 xop1
= convert_to_mode (mode1
, xop1
, unsignedp
);
488 /* Now, if insn's predicates don't allow our operands, put them into
491 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
)
492 && mode0
!= VOIDmode
)
493 xop0
= copy_to_mode_reg (mode0
, xop0
);
495 if (! (*insn_operand_predicate
[icode
][2]) (xop1
, mode1
)
496 && mode1
!= VOIDmode
)
497 xop1
= copy_to_mode_reg (mode1
, xop1
);
499 if (! (*insn_operand_predicate
[icode
][0]) (temp
, mode
))
500 temp
= gen_reg_rtx (mode
);
502 pat
= GEN_FCN (icode
) (temp
, xop0
, xop1
);
505 /* If PAT is a multi-insn sequence, try to add an appropriate
506 REG_EQUAL note to it. If we can't because TEMP conflicts with an
507 operand, call ourselves again, this time without a target. */
508 if (GET_CODE (pat
) == SEQUENCE
509 && ! add_equal_note (pat
, temp
, binoptab
->code
, xop0
, xop1
))
511 delete_insns_since (last
);
512 return expand_binop (mode
, binoptab
, op0
, op1
, NULL_RTX
,
520 delete_insns_since (last
);
523 /* If this is a multiply, see if we can do a widening operation that
524 takes operands of this mode and makes a wider mode. */
526 if (binoptab
== smul_optab
&& GET_MODE_WIDER_MODE (mode
) != VOIDmode
527 && (((unsignedp
? umul_widen_optab
: smul_widen_optab
)
528 ->handlers
[(int) GET_MODE_WIDER_MODE (mode
)].insn_code
)
529 != CODE_FOR_nothing
))
531 temp
= expand_binop (GET_MODE_WIDER_MODE (mode
),
532 unsignedp
? umul_widen_optab
: smul_widen_optab
,
533 op0
, op1
, NULL_RTX
, unsignedp
, OPTAB_DIRECT
);
537 if (GET_MODE_CLASS (mode
) == MODE_INT
)
538 return gen_lowpart (mode
, temp
);
540 return convert_to_mode (mode
, temp
, unsignedp
);
544 /* Look for a wider mode of the same class for which we think we
545 can open-code the operation. Check for a widening multiply at the
546 wider mode as well. */
548 if ((class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
549 && methods
!= OPTAB_DIRECT
&& methods
!= OPTAB_LIB
)
550 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
551 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
553 if (binoptab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
554 || (binoptab
== smul_optab
555 && GET_MODE_WIDER_MODE (wider_mode
) != VOIDmode
556 && (((unsignedp
? umul_widen_optab
: smul_widen_optab
)
557 ->handlers
[(int) GET_MODE_WIDER_MODE (wider_mode
)].insn_code
)
558 != CODE_FOR_nothing
)))
560 rtx xop0
= op0
, xop1
= op1
;
563 /* For certain integer operations, we need not actually extend
564 the narrow operands, as long as we will truncate
565 the results to the same narrowness. */
567 if ((binoptab
== ior_optab
|| binoptab
== and_optab
568 || binoptab
== xor_optab
569 || binoptab
== add_optab
|| binoptab
== sub_optab
570 || binoptab
== smul_optab
|| binoptab
== ashl_optab
)
571 && class == MODE_INT
)
574 xop0
= widen_operand (xop0
, wider_mode
, mode
, unsignedp
, no_extend
);
576 /* The second operand of a shift must always be extended. */
577 xop1
= widen_operand (xop1
, wider_mode
, mode
, unsignedp
,
578 no_extend
&& binoptab
!= ashl_optab
);
580 temp
= expand_binop (wider_mode
, binoptab
, xop0
, xop1
, NULL_RTX
,
581 unsignedp
, OPTAB_DIRECT
);
584 if (class != MODE_INT
)
587 target
= gen_reg_rtx (mode
);
588 convert_move (target
, temp
, 0);
592 return gen_lowpart (mode
, temp
);
595 delete_insns_since (last
);
599 /* These can be done a word at a time. */
600 if ((binoptab
== and_optab
|| binoptab
== ior_optab
|| binoptab
== xor_optab
)
602 && GET_MODE_SIZE (mode
) > UNITS_PER_WORD
603 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
609 /* If TARGET is the same as one of the operands, the REG_EQUAL note
610 won't be accurate, so use a new target. */
611 if (target
== 0 || target
== op0
|| target
== op1
)
612 target
= gen_reg_rtx (mode
);
616 /* Do the actual arithmetic. */
617 for (i
= 0; i
< GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
; i
++)
619 rtx target_piece
= operand_subword (target
, i
, 1, mode
);
620 rtx x
= expand_binop (word_mode
, binoptab
,
621 operand_subword_force (op0
, i
, mode
),
622 operand_subword_force (op1
, i
, mode
),
623 target_piece
, unsignedp
, next_methods
);
628 if (target_piece
!= x
)
629 emit_move_insn (target_piece
, x
);
632 insns
= get_insns ();
635 if (i
== GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
)
637 if (binoptab
->code
!= UNKNOWN
)
639 = gen_rtx_fmt_ee (binoptab
->code
, mode
,
640 copy_rtx (op0
), copy_rtx (op1
));
644 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv_value
);
649 /* Synthesize double word shifts from single word shifts. */
650 if ((binoptab
== lshr_optab
|| binoptab
== ashl_optab
651 || binoptab
== ashr_optab
)
653 && GET_CODE (op1
) == CONST_INT
654 && GET_MODE_SIZE (mode
) == 2 * UNITS_PER_WORD
655 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
656 && ashl_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
657 && lshr_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
659 rtx insns
, inter
, equiv_value
;
660 rtx into_target
, outof_target
;
661 rtx into_input
, outof_input
;
662 int shift_count
, left_shift
, outof_word
;
664 /* If TARGET is the same as one of the operands, the REG_EQUAL note
665 won't be accurate, so use a new target. */
666 if (target
== 0 || target
== op0
|| target
== op1
)
667 target
= gen_reg_rtx (mode
);
671 shift_count
= INTVAL (op1
);
673 /* OUTOF_* is the word we are shifting bits away from, and
674 INTO_* is the word that we are shifting bits towards, thus
675 they differ depending on the direction of the shift and
678 left_shift
= binoptab
== ashl_optab
;
679 outof_word
= left_shift
^ ! WORDS_BIG_ENDIAN
;
681 outof_target
= operand_subword (target
, outof_word
, 1, mode
);
682 into_target
= operand_subword (target
, 1 - outof_word
, 1, mode
);
684 outof_input
= operand_subword_force (op0
, outof_word
, mode
);
685 into_input
= operand_subword_force (op0
, 1 - outof_word
, mode
);
687 if (shift_count
>= BITS_PER_WORD
)
689 inter
= expand_binop (word_mode
, binoptab
,
691 GEN_INT (shift_count
- BITS_PER_WORD
),
692 into_target
, unsignedp
, next_methods
);
694 if (inter
!= 0 && inter
!= into_target
)
695 emit_move_insn (into_target
, inter
);
697 /* For a signed right shift, we must fill the word we are shifting
698 out of with copies of the sign bit. Otherwise it is zeroed. */
699 if (inter
!= 0 && binoptab
!= ashr_optab
)
700 inter
= CONST0_RTX (word_mode
);
702 inter
= expand_binop (word_mode
, binoptab
,
704 GEN_INT (BITS_PER_WORD
- 1),
705 outof_target
, unsignedp
, next_methods
);
707 if (inter
!= 0 && inter
!= outof_target
)
708 emit_move_insn (outof_target
, inter
);
713 optab reverse_unsigned_shift
, unsigned_shift
;
715 /* For a shift of less then BITS_PER_WORD, to compute the carry,
716 we must do a logical shift in the opposite direction of the
719 reverse_unsigned_shift
= (left_shift
? lshr_optab
: ashl_optab
);
721 /* For a shift of less than BITS_PER_WORD, to compute the word
722 shifted towards, we need to unsigned shift the orig value of
725 unsigned_shift
= (left_shift
? ashl_optab
: lshr_optab
);
727 carries
= expand_binop (word_mode
, reverse_unsigned_shift
,
729 GEN_INT (BITS_PER_WORD
- shift_count
),
730 0, unsignedp
, next_methods
);
735 inter
= expand_binop (word_mode
, unsigned_shift
, into_input
,
736 op1
, 0, unsignedp
, next_methods
);
739 inter
= expand_binop (word_mode
, ior_optab
, carries
, inter
,
740 into_target
, unsignedp
, next_methods
);
742 if (inter
!= 0 && inter
!= into_target
)
743 emit_move_insn (into_target
, inter
);
746 inter
= expand_binop (word_mode
, binoptab
, outof_input
,
747 op1
, outof_target
, unsignedp
, next_methods
);
749 if (inter
!= 0 && inter
!= outof_target
)
750 emit_move_insn (outof_target
, inter
);
753 insns
= get_insns ();
758 if (binoptab
->code
!= UNKNOWN
)
759 equiv_value
= gen_rtx_fmt_ee (binoptab
->code
, mode
, op0
, op1
);
763 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv_value
);
768 /* Synthesize double word rotates from single word shifts. */
769 if ((binoptab
== rotl_optab
|| binoptab
== rotr_optab
)
771 && GET_CODE (op1
) == CONST_INT
772 && GET_MODE_SIZE (mode
) == 2 * UNITS_PER_WORD
773 && ashl_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
774 && lshr_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
776 rtx insns
, equiv_value
;
777 rtx into_target
, outof_target
;
778 rtx into_input
, outof_input
;
780 int shift_count
, left_shift
, outof_word
;
782 /* If TARGET is the same as one of the operands, the REG_EQUAL note
783 won't be accurate, so use a new target. */
784 if (target
== 0 || target
== op0
|| target
== op1
)
785 target
= gen_reg_rtx (mode
);
789 shift_count
= INTVAL (op1
);
791 /* OUTOF_* is the word we are shifting bits away from, and
792 INTO_* is the word that we are shifting bits towards, thus
793 they differ depending on the direction of the shift and
796 left_shift
= (binoptab
== rotl_optab
);
797 outof_word
= left_shift
^ ! WORDS_BIG_ENDIAN
;
799 outof_target
= operand_subword (target
, outof_word
, 1, mode
);
800 into_target
= operand_subword (target
, 1 - outof_word
, 1, mode
);
802 outof_input
= operand_subword_force (op0
, outof_word
, mode
);
803 into_input
= operand_subword_force (op0
, 1 - outof_word
, mode
);
805 if (shift_count
== BITS_PER_WORD
)
807 /* This is just a word swap. */
808 emit_move_insn (outof_target
, into_input
);
809 emit_move_insn (into_target
, outof_input
);
814 rtx into_temp1
, into_temp2
, outof_temp1
, outof_temp2
;
815 rtx first_shift_count
, second_shift_count
;
816 optab reverse_unsigned_shift
, unsigned_shift
;
818 reverse_unsigned_shift
= (left_shift
^ (shift_count
< BITS_PER_WORD
)
819 ? lshr_optab
: ashl_optab
);
821 unsigned_shift
= (left_shift
^ (shift_count
< BITS_PER_WORD
)
822 ? ashl_optab
: lshr_optab
);
824 if (shift_count
> BITS_PER_WORD
)
826 first_shift_count
= GEN_INT (shift_count
- BITS_PER_WORD
);
827 second_shift_count
= GEN_INT (2*BITS_PER_WORD
- shift_count
);
831 first_shift_count
= GEN_INT (BITS_PER_WORD
- shift_count
);
832 second_shift_count
= GEN_INT (shift_count
);
835 into_temp1
= expand_binop (word_mode
, unsigned_shift
,
836 outof_input
, first_shift_count
,
837 NULL_RTX
, unsignedp
, next_methods
);
838 into_temp2
= expand_binop (word_mode
, reverse_unsigned_shift
,
839 into_input
, second_shift_count
,
840 into_target
, unsignedp
, next_methods
);
842 if (into_temp1
!= 0 && into_temp2
!= 0)
843 inter
= expand_binop (word_mode
, ior_optab
, into_temp1
, into_temp2
,
844 into_target
, unsignedp
, next_methods
);
848 if (inter
!= 0 && inter
!= into_target
)
849 emit_move_insn (into_target
, inter
);
851 outof_temp1
= expand_binop (word_mode
, unsigned_shift
,
852 into_input
, first_shift_count
,
853 NULL_RTX
, unsignedp
, next_methods
);
854 outof_temp2
= expand_binop (word_mode
, reverse_unsigned_shift
,
855 outof_input
, second_shift_count
,
856 outof_target
, unsignedp
, next_methods
);
858 if (inter
!= 0 && outof_temp1
!= 0 && outof_temp2
!= 0)
859 inter
= expand_binop (word_mode
, ior_optab
,
860 outof_temp1
, outof_temp2
,
861 outof_target
, unsignedp
, next_methods
);
863 if (inter
!= 0 && inter
!= outof_target
)
864 emit_move_insn (outof_target
, inter
);
867 insns
= get_insns ();
872 if (binoptab
->code
!= UNKNOWN
)
873 equiv_value
= gen_rtx_fmt_ee (binoptab
->code
, mode
, op0
, op1
);
877 /* We can't make this a no conflict block if this is a word swap,
878 because the word swap case fails if the input and output values
879 are in the same register. */
880 if (shift_count
!= BITS_PER_WORD
)
881 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv_value
);
890 /* These can be done a word at a time by propagating carries. */
891 if ((binoptab
== add_optab
|| binoptab
== sub_optab
)
893 && GET_MODE_SIZE (mode
) >= 2 * UNITS_PER_WORD
894 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
897 rtx carry_tmp
= gen_reg_rtx (word_mode
);
898 optab otheroptab
= binoptab
== add_optab
? sub_optab
: add_optab
;
899 int nwords
= GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
;
900 rtx carry_in
, carry_out
;
903 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
904 value is one of those, use it. Otherwise, use 1 since it is the
905 one easiest to get. */
906 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
907 int normalizep
= STORE_FLAG_VALUE
;
912 /* Prepare the operands. */
913 xop0
= force_reg (mode
, op0
);
914 xop1
= force_reg (mode
, op1
);
916 if (target
== 0 || GET_CODE (target
) != REG
917 || target
== xop0
|| target
== xop1
)
918 target
= gen_reg_rtx (mode
);
920 /* Indicate for flow that the entire target reg is being set. */
921 if (GET_CODE (target
) == REG
)
922 emit_insn (gen_rtx_CLOBBER (VOIDmode
, target
));
924 /* Do the actual arithmetic. */
925 for (i
= 0; i
< nwords
; i
++)
927 int index
= (WORDS_BIG_ENDIAN
? nwords
- i
- 1 : i
);
928 rtx target_piece
= operand_subword (target
, index
, 1, mode
);
929 rtx op0_piece
= operand_subword_force (xop0
, index
, mode
);
930 rtx op1_piece
= operand_subword_force (xop1
, index
, mode
);
933 /* Main add/subtract of the input operands. */
934 x
= expand_binop (word_mode
, binoptab
,
935 op0_piece
, op1_piece
,
936 target_piece
, unsignedp
, next_methods
);
942 /* Store carry from main add/subtract. */
943 carry_out
= gen_reg_rtx (word_mode
);
944 carry_out
= emit_store_flag_force (carry_out
,
945 (binoptab
== add_optab
948 word_mode
, 1, normalizep
);
953 /* Add/subtract previous carry to main result. */
954 x
= expand_binop (word_mode
,
955 normalizep
== 1 ? binoptab
: otheroptab
,
957 target_piece
, 1, next_methods
);
960 else if (target_piece
!= x
)
961 emit_move_insn (target_piece
, x
);
965 /* THIS CODE HAS NOT BEEN TESTED. */
966 /* Get out carry from adding/subtracting carry in. */
967 carry_tmp
= emit_store_flag_force (carry_tmp
,
968 binoptab
== add_optab
971 word_mode
, 1, normalizep
);
973 /* Logical-ior the two poss. carry together. */
974 carry_out
= expand_binop (word_mode
, ior_optab
,
975 carry_out
, carry_tmp
,
976 carry_out
, 0, next_methods
);
982 carry_in
= carry_out
;
985 if (i
== GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
)
987 if (mov_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
989 rtx temp
= emit_move_insn (target
, target
);
991 set_unique_reg_note (temp
,
993 gen_rtx_fmt_ee (binoptab
->code
, mode
,
1000 delete_insns_since (last
);
1003 /* If we want to multiply two two-word values and have normal and widening
1004 multiplies of single-word values, we can do this with three smaller
1005 multiplications. Note that we do not make a REG_NO_CONFLICT block here
1006 because we are not operating on one word at a time.
1008 The multiplication proceeds as follows:
1009 _______________________
1010 [__op0_high_|__op0_low__]
1011 _______________________
1012 * [__op1_high_|__op1_low__]
1013 _______________________________________________
1014 _______________________
1015 (1) [__op0_low__*__op1_low__]
1016 _______________________
1017 (2a) [__op0_low__*__op1_high_]
1018 _______________________
1019 (2b) [__op0_high_*__op1_low__]
1020 _______________________
1021 (3) [__op0_high_*__op1_high_]
1024 This gives a 4-word result. Since we are only interested in the
1025 lower 2 words, partial result (3) and the upper words of (2a) and
1026 (2b) don't need to be calculated. Hence (2a) and (2b) can be
1027 calculated using non-widening multiplication.
1029 (1), however, needs to be calculated with an unsigned widening
1030 multiplication. If this operation is not directly supported we
1031 try using a signed widening multiplication and adjust the result.
1032 This adjustment works as follows:
1034 If both operands are positive then no adjustment is needed.
1036 If the operands have different signs, for example op0_low < 0 and
1037 op1_low >= 0, the instruction treats the most significant bit of
1038 op0_low as a sign bit instead of a bit with significance
1039 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
1040 with 2**BITS_PER_WORD - op0_low, and two's complements the
1041 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
1044 Similarly, if both operands are negative, we need to add
1045 (op0_low + op1_low) * 2**BITS_PER_WORD.
1047 We use a trick to adjust quickly. We logically shift op0_low right
1048 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
1049 op0_high (op1_high) before it is used to calculate 2b (2a). If no
1050 logical shift exists, we do an arithmetic right shift and subtract
1053 if (binoptab
== smul_optab
1054 && class == MODE_INT
1055 && GET_MODE_SIZE (mode
) == 2 * UNITS_PER_WORD
1056 && smul_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
1057 && add_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
1058 && ((umul_widen_optab
->handlers
[(int) mode
].insn_code
1059 != CODE_FOR_nothing
)
1060 || (smul_widen_optab
->handlers
[(int) mode
].insn_code
1061 != CODE_FOR_nothing
)))
1063 int low
= (WORDS_BIG_ENDIAN
? 1 : 0);
1064 int high
= (WORDS_BIG_ENDIAN
? 0 : 1);
1065 rtx op0_high
= operand_subword_force (op0
, high
, mode
);
1066 rtx op0_low
= operand_subword_force (op0
, low
, mode
);
1067 rtx op1_high
= operand_subword_force (op1
, high
, mode
);
1068 rtx op1_low
= operand_subword_force (op1
, low
, mode
);
1073 /* If the target is the same as one of the inputs, don't use it. This
1074 prevents problems with the REG_EQUAL note. */
1075 if (target
== op0
|| target
== op1
1076 || (target
!= 0 && GET_CODE (target
) != REG
))
1079 /* Multiply the two lower words to get a double-word product.
1080 If unsigned widening multiplication is available, use that;
1081 otherwise use the signed form and compensate. */
1083 if (umul_widen_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1085 product
= expand_binop (mode
, umul_widen_optab
, op0_low
, op1_low
,
1086 target
, 1, OPTAB_DIRECT
);
1088 /* If we didn't succeed, delete everything we did so far. */
1090 delete_insns_since (last
);
1092 op0_xhigh
= op0_high
, op1_xhigh
= op1_high
;
1096 && smul_widen_optab
->handlers
[(int) mode
].insn_code
1097 != CODE_FOR_nothing
)
1099 rtx wordm1
= GEN_INT (BITS_PER_WORD
- 1);
1100 product
= expand_binop (mode
, smul_widen_optab
, op0_low
, op1_low
,
1101 target
, 1, OPTAB_DIRECT
);
1102 op0_xhigh
= expand_binop (word_mode
, lshr_optab
, op0_low
, wordm1
,
1103 NULL_RTX
, 1, next_methods
);
1105 op0_xhigh
= expand_binop (word_mode
, add_optab
, op0_high
,
1106 op0_xhigh
, op0_xhigh
, 0, next_methods
);
1109 op0_xhigh
= expand_binop (word_mode
, ashr_optab
, op0_low
, wordm1
,
1110 NULL_RTX
, 0, next_methods
);
1112 op0_xhigh
= expand_binop (word_mode
, sub_optab
, op0_high
,
1113 op0_xhigh
, op0_xhigh
, 0,
1117 op1_xhigh
= expand_binop (word_mode
, lshr_optab
, op1_low
, wordm1
,
1118 NULL_RTX
, 1, next_methods
);
1120 op1_xhigh
= expand_binop (word_mode
, add_optab
, op1_high
,
1121 op1_xhigh
, op1_xhigh
, 0, next_methods
);
1124 op1_xhigh
= expand_binop (word_mode
, ashr_optab
, op1_low
, wordm1
,
1125 NULL_RTX
, 0, next_methods
);
1127 op1_xhigh
= expand_binop (word_mode
, sub_optab
, op1_high
,
1128 op1_xhigh
, op1_xhigh
, 0,
1133 /* If we have been able to directly compute the product of the
1134 low-order words of the operands and perform any required adjustments
1135 of the operands, we proceed by trying two more multiplications
1136 and then computing the appropriate sum.
1138 We have checked above that the required addition is provided.
1139 Full-word addition will normally always succeed, especially if
1140 it is provided at all, so we don't worry about its failure. The
1141 multiplication may well fail, however, so we do handle that. */
1143 if (product
&& op0_xhigh
&& op1_xhigh
)
1145 rtx product_high
= operand_subword (product
, high
, 1, mode
);
1146 rtx temp
= expand_binop (word_mode
, binoptab
, op0_low
, op1_xhigh
,
1147 NULL_RTX
, 0, OPTAB_DIRECT
);
1150 temp
= expand_binop (word_mode
, add_optab
, temp
, product_high
,
1151 product_high
, 0, next_methods
);
1153 if (temp
!= 0 && temp
!= product_high
)
1154 emit_move_insn (product_high
, temp
);
1157 temp
= expand_binop (word_mode
, binoptab
, op1_low
, op0_xhigh
,
1158 NULL_RTX
, 0, OPTAB_DIRECT
);
1161 temp
= expand_binop (word_mode
, add_optab
, temp
,
1162 product_high
, product_high
,
1165 if (temp
!= 0 && temp
!= product_high
)
1166 emit_move_insn (product_high
, temp
);
1170 if (mov_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1172 temp
= emit_move_insn (product
, product
);
1173 set_unique_reg_note (temp
,
1175 gen_rtx_fmt_ee (MULT
, mode
,
1183 /* If we get here, we couldn't do it for some reason even though we
1184 originally thought we could. Delete anything we've emitted in
1187 delete_insns_since (last
);
1190 /* We need to open-code the complex type operations: '+, -, * and /' */
1192 /* At this point we allow operations between two similar complex
1193 numbers, and also if one of the operands is not a complex number
1194 but rather of MODE_FLOAT or MODE_INT. However, the caller
1195 must make sure that the MODE of the non-complex operand matches
1196 the SUBMODE of the complex operand. */
1198 if (class == MODE_COMPLEX_FLOAT
|| class == MODE_COMPLEX_INT
)
1200 rtx real0
= 0, imag0
= 0;
1201 rtx real1
= 0, imag1
= 0;
1202 rtx realr
, imagr
, res
;
1207 /* Find the correct mode for the real and imaginary parts */
1208 enum machine_mode submode
1209 = mode_for_size (GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
,
1210 class == MODE_COMPLEX_INT
? MODE_INT
: MODE_FLOAT
,
1213 if (submode
== BLKmode
)
1217 target
= gen_reg_rtx (mode
);
1221 realr
= gen_realpart (submode
, target
);
1222 imagr
= gen_imagpart (submode
, target
);
1224 if (GET_MODE (op0
) == mode
)
1226 real0
= gen_realpart (submode
, op0
);
1227 imag0
= gen_imagpart (submode
, op0
);
1232 if (GET_MODE (op1
) == mode
)
1234 real1
= gen_realpart (submode
, op1
);
1235 imag1
= gen_imagpart (submode
, op1
);
1240 if (real0
== 0 || real1
== 0 || ! (imag0
!= 0|| imag1
!= 0))
1243 switch (binoptab
->code
)
1246 /* (a+ib) + (c+id) = (a+c) + i(b+d) */
1248 /* (a+ib) - (c+id) = (a-c) + i(b-d) */
1249 res
= expand_binop (submode
, binoptab
, real0
, real1
,
1250 realr
, unsignedp
, methods
);
1254 else if (res
!= realr
)
1255 emit_move_insn (realr
, res
);
1258 res
= expand_binop (submode
, binoptab
, imag0
, imag1
,
1259 imagr
, unsignedp
, methods
);
1262 else if (binoptab
->code
== MINUS
)
1263 res
= expand_unop (submode
, neg_optab
, imag1
, imagr
, unsignedp
);
1269 else if (res
!= imagr
)
1270 emit_move_insn (imagr
, res
);
1276 /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */
1282 /* Don't fetch these from memory more than once. */
1283 real0
= force_reg (submode
, real0
);
1284 real1
= force_reg (submode
, real1
);
1285 imag0
= force_reg (submode
, imag0
);
1286 imag1
= force_reg (submode
, imag1
);
1288 temp1
= expand_binop (submode
, binoptab
, real0
, real1
, NULL_RTX
,
1289 unsignedp
, methods
);
1291 temp2
= expand_binop (submode
, binoptab
, imag0
, imag1
, NULL_RTX
,
1292 unsignedp
, methods
);
1294 if (temp1
== 0 || temp2
== 0)
1297 res
= expand_binop (submode
, sub_optab
, temp1
, temp2
,
1298 realr
, unsignedp
, methods
);
1302 else if (res
!= realr
)
1303 emit_move_insn (realr
, res
);
1305 temp1
= expand_binop (submode
, binoptab
, real0
, imag1
,
1306 NULL_RTX
, unsignedp
, methods
);
1308 temp2
= expand_binop (submode
, binoptab
, real1
, imag0
,
1309 NULL_RTX
, unsignedp
, methods
);
1311 if (temp1
== 0 || temp2
== 0)
1314 res
= expand_binop (submode
, add_optab
, temp1
, temp2
,
1315 imagr
, unsignedp
, methods
);
1319 else if (res
!= imagr
)
1320 emit_move_insn (imagr
, res
);
1326 /* Don't fetch these from memory more than once. */
1327 real0
= force_reg (submode
, real0
);
1328 real1
= force_reg (submode
, real1
);
1330 res
= expand_binop (submode
, binoptab
, real0
, real1
,
1331 realr
, unsignedp
, methods
);
1334 else if (res
!= realr
)
1335 emit_move_insn (realr
, res
);
1338 res
= expand_binop (submode
, binoptab
,
1339 real1
, imag0
, imagr
, unsignedp
, methods
);
1341 res
= expand_binop (submode
, binoptab
,
1342 real0
, imag1
, imagr
, unsignedp
, methods
);
1346 else if (res
!= imagr
)
1347 emit_move_insn (imagr
, res
);
1354 /* (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) */
1358 /* (a+ib) / (c+i0) = (a/c) + i(b/c) */
1360 /* Don't fetch these from memory more than once. */
1361 real1
= force_reg (submode
, real1
);
1363 /* Simply divide the real and imaginary parts by `c' */
1364 if (class == MODE_COMPLEX_FLOAT
)
1365 res
= expand_binop (submode
, binoptab
, real0
, real1
,
1366 realr
, unsignedp
, methods
);
1368 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
1369 real0
, real1
, realr
, unsignedp
);
1373 else if (res
!= realr
)
1374 emit_move_insn (realr
, res
);
1376 if (class == MODE_COMPLEX_FLOAT
)
1377 res
= expand_binop (submode
, binoptab
, imag0
, real1
,
1378 imagr
, unsignedp
, methods
);
1380 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
1381 imag0
, real1
, imagr
, unsignedp
);
1385 else if (res
!= imagr
)
1386 emit_move_insn (imagr
, res
);
1392 /* Divisor is of complex type:
1398 /* Don't fetch these from memory more than once. */
1399 real0
= force_reg (submode
, real0
);
1400 real1
= force_reg (submode
, real1
);
1403 imag0
= force_reg (submode
, imag0
);
1405 imag1
= force_reg (submode
, imag1
);
1407 /* Divisor: c*c + d*d */
1408 temp1
= expand_binop (submode
, smul_optab
, real1
, real1
,
1409 NULL_RTX
, unsignedp
, methods
);
1411 temp2
= expand_binop (submode
, smul_optab
, imag1
, imag1
,
1412 NULL_RTX
, unsignedp
, methods
);
1414 if (temp1
== 0 || temp2
== 0)
1417 divisor
= expand_binop (submode
, add_optab
, temp1
, temp2
,
1418 NULL_RTX
, unsignedp
, methods
);
1424 /* ((a)(c-id))/divisor */
1425 /* (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)) */
1427 /* Calculate the dividend */
1428 real_t
= expand_binop (submode
, smul_optab
, real0
, real1
,
1429 NULL_RTX
, unsignedp
, methods
);
1431 imag_t
= expand_binop (submode
, smul_optab
, real0
, imag1
,
1432 NULL_RTX
, unsignedp
, methods
);
1434 if (real_t
== 0 || imag_t
== 0)
1437 imag_t
= expand_unop (submode
, neg_optab
, imag_t
,
1438 NULL_RTX
, unsignedp
);
1442 /* ((a+ib)(c-id))/divider */
1443 /* Calculate the dividend */
1444 temp1
= expand_binop (submode
, smul_optab
, real0
, real1
,
1445 NULL_RTX
, unsignedp
, methods
);
1447 temp2
= expand_binop (submode
, smul_optab
, imag0
, imag1
,
1448 NULL_RTX
, unsignedp
, methods
);
1450 if (temp1
== 0 || temp2
== 0)
1453 real_t
= expand_binop (submode
, add_optab
, temp1
, temp2
,
1454 NULL_RTX
, unsignedp
, methods
);
1456 temp1
= expand_binop (submode
, smul_optab
, imag0
, real1
,
1457 NULL_RTX
, unsignedp
, methods
);
1459 temp2
= expand_binop (submode
, smul_optab
, real0
, imag1
,
1460 NULL_RTX
, unsignedp
, methods
);
1462 if (temp1
== 0 || temp2
== 0)
1465 imag_t
= expand_binop (submode
, sub_optab
, temp1
, temp2
,
1466 NULL_RTX
, unsignedp
, methods
);
1468 if (real_t
== 0 || imag_t
== 0)
1472 if (class == MODE_COMPLEX_FLOAT
)
1473 res
= expand_binop (submode
, binoptab
, real_t
, divisor
,
1474 realr
, unsignedp
, methods
);
1476 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
1477 real_t
, divisor
, realr
, unsignedp
);
1481 else if (res
!= realr
)
1482 emit_move_insn (realr
, res
);
1484 if (class == MODE_COMPLEX_FLOAT
)
1485 res
= expand_binop (submode
, binoptab
, imag_t
, divisor
,
1486 imagr
, unsignedp
, methods
);
1488 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
1489 imag_t
, divisor
, imagr
, unsignedp
);
1493 else if (res
!= imagr
)
1494 emit_move_insn (imagr
, res
);
1509 if (binoptab
->code
!= UNKNOWN
)
1511 = gen_rtx_fmt_ee (binoptab
->code
, mode
,
1512 copy_rtx (op0
), copy_rtx (op1
));
1516 emit_no_conflict_block (seq
, target
, op0
, op1
, equiv_value
);
1522 /* It can't be open-coded in this mode.
1523 Use a library call if one is available and caller says that's ok. */
1525 if (binoptab
->handlers
[(int) mode
].libfunc
1526 && (methods
== OPTAB_LIB
|| methods
== OPTAB_LIB_WIDEN
))
1530 enum machine_mode op1_mode
= mode
;
1537 op1_mode
= word_mode
;
1538 /* Specify unsigned here,
1539 since negative shift counts are meaningless. */
1540 op1x
= convert_to_mode (word_mode
, op1
, 1);
1543 if (GET_MODE (op0
) != VOIDmode
1544 && GET_MODE (op0
) != mode
)
1545 op0
= convert_to_mode (mode
, op0
, unsignedp
);
1547 /* Pass 1 for NO_QUEUE so we don't lose any increments
1548 if the libcall is cse'd or moved. */
1549 value
= emit_library_call_value (binoptab
->handlers
[(int) mode
].libfunc
,
1550 NULL_RTX
, 1, mode
, 2,
1551 op0
, mode
, op1x
, op1_mode
);
1553 insns
= get_insns ();
1556 target
= gen_reg_rtx (mode
);
1557 emit_libcall_block (insns
, target
, value
,
1558 gen_rtx_fmt_ee (binoptab
->code
, mode
, op0
, op1
));
1563 delete_insns_since (last
);
1565 /* It can't be done in this mode. Can we do it in a wider mode? */
1567 if (! (methods
== OPTAB_WIDEN
|| methods
== OPTAB_LIB_WIDEN
1568 || methods
== OPTAB_MUST_WIDEN
))
1570 /* Caller says, don't even try. */
1571 delete_insns_since (entry_last
);
1575 /* Compute the value of METHODS to pass to recursive calls.
1576 Don't allow widening to be tried recursively. */
1578 methods
= (methods
== OPTAB_LIB_WIDEN
? OPTAB_LIB
: OPTAB_DIRECT
);
1580 /* Look for a wider mode of the same class for which it appears we can do
1583 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1585 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1586 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1588 if ((binoptab
->handlers
[(int) wider_mode
].insn_code
1589 != CODE_FOR_nothing
)
1590 || (methods
== OPTAB_LIB
1591 && binoptab
->handlers
[(int) wider_mode
].libfunc
))
1593 rtx xop0
= op0
, xop1
= op1
;
1596 /* For certain integer operations, we need not actually extend
1597 the narrow operands, as long as we will truncate
1598 the results to the same narrowness. */
1600 if ((binoptab
== ior_optab
|| binoptab
== and_optab
1601 || binoptab
== xor_optab
1602 || binoptab
== add_optab
|| binoptab
== sub_optab
1603 || binoptab
== smul_optab
|| binoptab
== ashl_optab
)
1604 && class == MODE_INT
)
1607 xop0
= widen_operand (xop0
, wider_mode
, mode
,
1608 unsignedp
, no_extend
);
1610 /* The second operand of a shift must always be extended. */
1611 xop1
= widen_operand (xop1
, wider_mode
, mode
, unsignedp
,
1612 no_extend
&& binoptab
!= ashl_optab
);
1614 temp
= expand_binop (wider_mode
, binoptab
, xop0
, xop1
, NULL_RTX
,
1615 unsignedp
, methods
);
1618 if (class != MODE_INT
)
1621 target
= gen_reg_rtx (mode
);
1622 convert_move (target
, temp
, 0);
1626 return gen_lowpart (mode
, temp
);
1629 delete_insns_since (last
);
1634 delete_insns_since (entry_last
);
1638 /* Expand a binary operator which has both signed and unsigned forms.
1639 UOPTAB is the optab for unsigned operations, and SOPTAB is for
1642 If we widen unsigned operands, we may use a signed wider operation instead
1643 of an unsigned wider operation, since the result would be the same. */
1646 sign_expand_binop (mode
, uoptab
, soptab
, op0
, op1
, target
, unsignedp
, methods
)
1647 enum machine_mode mode
;
1648 optab uoptab
, soptab
;
1649 rtx op0
, op1
, target
;
1651 enum optab_methods methods
;
1654 optab direct_optab
= unsignedp
? uoptab
: soptab
;
1655 struct optab wide_soptab
;
1657 /* Do it without widening, if possible. */
1658 temp
= expand_binop (mode
, direct_optab
, op0
, op1
, target
,
1659 unsignedp
, OPTAB_DIRECT
);
1660 if (temp
|| methods
== OPTAB_DIRECT
)
1663 /* Try widening to a signed int. Make a fake signed optab that
1664 hides any signed insn for direct use. */
1665 wide_soptab
= *soptab
;
1666 wide_soptab
.handlers
[(int) mode
].insn_code
= CODE_FOR_nothing
;
1667 wide_soptab
.handlers
[(int) mode
].libfunc
= 0;
1669 temp
= expand_binop (mode
, &wide_soptab
, op0
, op1
, target
,
1670 unsignedp
, OPTAB_WIDEN
);
1672 /* For unsigned operands, try widening to an unsigned int. */
1673 if (temp
== 0 && unsignedp
)
1674 temp
= expand_binop (mode
, uoptab
, op0
, op1
, target
,
1675 unsignedp
, OPTAB_WIDEN
);
1676 if (temp
|| methods
== OPTAB_WIDEN
)
1679 /* Use the right width lib call if that exists. */
1680 temp
= expand_binop (mode
, direct_optab
, op0
, op1
, target
, unsignedp
, OPTAB_LIB
);
1681 if (temp
|| methods
== OPTAB_LIB
)
1684 /* Must widen and use a lib call, use either signed or unsigned. */
1685 temp
= expand_binop (mode
, &wide_soptab
, op0
, op1
, target
,
1686 unsignedp
, methods
);
1690 return expand_binop (mode
, uoptab
, op0
, op1
, target
,
1691 unsignedp
, methods
);
1695 /* Generate code to perform an operation specified by BINOPTAB
1696 on operands OP0 and OP1, with two results to TARG1 and TARG2.
1697 We assume that the order of the operands for the instruction
1698 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
1699 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
1701 Either TARG0 or TARG1 may be zero, but what that means is that
1702 the result is not actually wanted. We will generate it into
1703 a dummy pseudo-reg and discard it. They may not both be zero.
1705 Returns 1 if this operation can be performed; 0 if not. */
1708 expand_twoval_binop (binoptab
, op0
, op1
, targ0
, targ1
, unsignedp
)
1714 enum machine_mode mode
= GET_MODE (targ0
? targ0
: targ1
);
1715 enum mode_class
class;
1716 enum machine_mode wider_mode
;
1717 rtx entry_last
= get_last_insn ();
1720 class = GET_MODE_CLASS (mode
);
1722 op0
= protect_from_queue (op0
, 0);
1723 op1
= protect_from_queue (op1
, 0);
1727 op0
= force_not_mem (op0
);
1728 op1
= force_not_mem (op1
);
1731 /* If we are inside an appropriately-short loop and one operand is an
1732 expensive constant, force it into a register. */
1733 if (CONSTANT_P (op0
) && preserve_subexpressions_p ()
1734 && rtx_cost (op0
, binoptab
->code
) > 2)
1735 op0
= force_reg (mode
, op0
);
1737 if (CONSTANT_P (op1
) && preserve_subexpressions_p ()
1738 && rtx_cost (op1
, binoptab
->code
) > 2)
1739 op1
= force_reg (mode
, op1
);
1742 targ0
= protect_from_queue (targ0
, 1);
1744 targ0
= gen_reg_rtx (mode
);
1746 targ1
= protect_from_queue (targ1
, 1);
1748 targ1
= gen_reg_rtx (mode
);
1750 /* Record where to go back to if we fail. */
1751 last
= get_last_insn ();
1753 if (binoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1755 int icode
= (int) binoptab
->handlers
[(int) mode
].insn_code
;
1756 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
1757 enum machine_mode mode1
= insn_operand_mode
[icode
][2];
1759 rtx xop0
= op0
, xop1
= op1
;
1761 /* In case this insn wants input operands in modes different from the
1762 result, convert the operands. */
1763 if (GET_MODE (op0
) != VOIDmode
&& GET_MODE (op0
) != mode0
)
1764 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
1766 if (GET_MODE (op1
) != VOIDmode
&& GET_MODE (op1
) != mode1
)
1767 xop1
= convert_to_mode (mode1
, xop1
, unsignedp
);
1769 /* Now, if insn doesn't accept these operands, put them into pseudos. */
1770 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
1771 xop0
= copy_to_mode_reg (mode0
, xop0
);
1773 if (! (*insn_operand_predicate
[icode
][2]) (xop1
, mode1
))
1774 xop1
= copy_to_mode_reg (mode1
, xop1
);
1776 /* We could handle this, but we should always be called with a pseudo
1777 for our targets and all insns should take them as outputs. */
1778 if (! (*insn_operand_predicate
[icode
][0]) (targ0
, mode
)
1779 || ! (*insn_operand_predicate
[icode
][3]) (targ1
, mode
))
1782 pat
= GEN_FCN (icode
) (targ0
, xop0
, xop1
, targ1
);
1789 delete_insns_since (last
);
1792 /* It can't be done in this mode. Can we do it in a wider mode? */
1794 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1796 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1797 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1799 if (binoptab
->handlers
[(int) wider_mode
].insn_code
1800 != CODE_FOR_nothing
)
1802 register rtx t0
= gen_reg_rtx (wider_mode
);
1803 register rtx t1
= gen_reg_rtx (wider_mode
);
1805 if (expand_twoval_binop (binoptab
,
1806 convert_modes (wider_mode
, mode
, op0
,
1808 convert_modes (wider_mode
, mode
, op1
,
1812 convert_move (targ0
, t0
, unsignedp
);
1813 convert_move (targ1
, t1
, unsignedp
);
1817 delete_insns_since (last
);
1822 delete_insns_since (entry_last
);
1826 /* Generate code to perform an operation specified by UNOPTAB
1827 on operand OP0, with result having machine-mode MODE.
1829 UNSIGNEDP is for the case where we have to widen the operands
1830 to perform the operation. It says to use zero-extension.
1832 If TARGET is nonzero, the value
1833 is generated there, if it is convenient to do so.
1834 In all cases an rtx is returned for the locus of the value;
1835 this may or may not be TARGET. */
1838 expand_unop (mode
, unoptab
, op0
, target
, unsignedp
)
1839 enum machine_mode mode
;
1845 enum mode_class
class;
1846 enum machine_mode wider_mode
;
1848 rtx last
= get_last_insn ();
1851 class = GET_MODE_CLASS (mode
);
1853 op0
= protect_from_queue (op0
, 0);
1857 op0
= force_not_mem (op0
);
1861 target
= protect_from_queue (target
, 1);
1863 if (unoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1865 int icode
= (int) unoptab
->handlers
[(int) mode
].insn_code
;
1866 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
1872 temp
= gen_reg_rtx (mode
);
1874 if (GET_MODE (xop0
) != VOIDmode
1875 && GET_MODE (xop0
) != mode0
)
1876 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
1878 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
1880 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
1881 xop0
= copy_to_mode_reg (mode0
, xop0
);
1883 if (! (*insn_operand_predicate
[icode
][0]) (temp
, mode
))
1884 temp
= gen_reg_rtx (mode
);
1886 pat
= GEN_FCN (icode
) (temp
, xop0
);
1889 if (GET_CODE (pat
) == SEQUENCE
1890 && ! add_equal_note (pat
, temp
, unoptab
->code
, xop0
, NULL_RTX
))
1892 delete_insns_since (last
);
1893 return expand_unop (mode
, unoptab
, op0
, NULL_RTX
, unsignedp
);
1901 delete_insns_since (last
);
1904 /* It can't be done in this mode. Can we open-code it in a wider mode? */
1906 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1907 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1908 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1910 if (unoptab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
)
1914 /* For certain operations, we need not actually extend
1915 the narrow operand, as long as we will truncate the
1916 results to the same narrowness. */
1918 xop0
= widen_operand (xop0
, wider_mode
, mode
, unsignedp
,
1919 (unoptab
== neg_optab
1920 || unoptab
== one_cmpl_optab
)
1921 && class == MODE_INT
);
1923 temp
= expand_unop (wider_mode
, unoptab
, xop0
, NULL_RTX
,
1928 if (class != MODE_INT
)
1931 target
= gen_reg_rtx (mode
);
1932 convert_move (target
, temp
, 0);
1936 return gen_lowpart (mode
, temp
);
1939 delete_insns_since (last
);
1943 /* These can be done a word at a time. */
1944 if (unoptab
== one_cmpl_optab
1945 && class == MODE_INT
1946 && GET_MODE_SIZE (mode
) > UNITS_PER_WORD
1947 && unoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
1952 if (target
== 0 || target
== op0
)
1953 target
= gen_reg_rtx (mode
);
1957 /* Do the actual arithmetic. */
1958 for (i
= 0; i
< GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
; i
++)
1960 rtx target_piece
= operand_subword (target
, i
, 1, mode
);
1961 rtx x
= expand_unop (word_mode
, unoptab
,
1962 operand_subword_force (op0
, i
, mode
),
1963 target_piece
, unsignedp
);
1964 if (target_piece
!= x
)
1965 emit_move_insn (target_piece
, x
);
1968 insns
= get_insns ();
1971 emit_no_conflict_block (insns
, target
, op0
, NULL_RTX
,
1972 gen_rtx_fmt_e (unoptab
->code
, mode
,
1977 /* Open-code the complex negation operation. */
1978 else if (unoptab
== neg_optab
1979 && (class == MODE_COMPLEX_FLOAT
|| class == MODE_COMPLEX_INT
))
1985 /* Find the correct mode for the real and imaginary parts */
1986 enum machine_mode submode
1987 = mode_for_size (GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
,
1988 class == MODE_COMPLEX_INT
? MODE_INT
: MODE_FLOAT
,
1991 if (submode
== BLKmode
)
1995 target
= gen_reg_rtx (mode
);
1999 target_piece
= gen_imagpart (submode
, target
);
2000 x
= expand_unop (submode
, unoptab
,
2001 gen_imagpart (submode
, op0
),
2002 target_piece
, unsignedp
);
2003 if (target_piece
!= x
)
2004 emit_move_insn (target_piece
, x
);
2006 target_piece
= gen_realpart (submode
, target
);
2007 x
= expand_unop (submode
, unoptab
,
2008 gen_realpart (submode
, op0
),
2009 target_piece
, unsignedp
);
2010 if (target_piece
!= x
)
2011 emit_move_insn (target_piece
, x
);
2016 emit_no_conflict_block (seq
, target
, op0
, 0,
2017 gen_rtx_fmt_e (unoptab
->code
, mode
,
2022 /* Now try a library call in this mode. */
2023 if (unoptab
->handlers
[(int) mode
].libfunc
)
2030 /* Pass 1 for NO_QUEUE so we don't lose any increments
2031 if the libcall is cse'd or moved. */
2032 value
= emit_library_call_value (unoptab
->handlers
[(int) mode
].libfunc
,
2033 NULL_RTX
, 1, mode
, 1, op0
, mode
);
2034 insns
= get_insns ();
2037 target
= gen_reg_rtx (mode
);
2038 emit_libcall_block (insns
, target
, value
,
2039 gen_rtx_fmt_e (unoptab
->code
, mode
, op0
));
2044 /* It can't be done in this mode. Can we do it in a wider mode? */
2046 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
2048 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2049 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2051 if ((unoptab
->handlers
[(int) wider_mode
].insn_code
2052 != CODE_FOR_nothing
)
2053 || unoptab
->handlers
[(int) wider_mode
].libfunc
)
2057 /* For certain operations, we need not actually extend
2058 the narrow operand, as long as we will truncate the
2059 results to the same narrowness. */
2061 xop0
= widen_operand (xop0
, wider_mode
, mode
, unsignedp
,
2062 (unoptab
== neg_optab
2063 || unoptab
== one_cmpl_optab
)
2064 && class == MODE_INT
);
2066 temp
= expand_unop (wider_mode
, unoptab
, xop0
, NULL_RTX
,
2071 if (class != MODE_INT
)
2074 target
= gen_reg_rtx (mode
);
2075 convert_move (target
, temp
, 0);
2079 return gen_lowpart (mode
, temp
);
2082 delete_insns_since (last
);
2087 /* If there is no negate operation, try doing a subtract from zero.
2088 The US Software GOFAST library needs this. */
2089 if (unoptab
== neg_optab
)
2092 temp
= expand_binop (mode
, sub_optab
, CONST0_RTX (mode
), op0
,
2093 target
, unsignedp
, OPTAB_LIB_WIDEN
);
2101 /* Emit code to compute the absolute value of OP0, with result to
2102 TARGET if convenient. (TARGET may be 0.) The return value says
2103 where the result actually is to be found.
2105 MODE is the mode of the operand; the mode of the result is
2106 different but can be deduced from MODE.
2111 expand_abs (mode
, op0
, target
, safe
)
2112 enum machine_mode mode
;
2119 /* First try to do it with a special abs instruction. */
2120 temp
= expand_unop (mode
, abs_optab
, op0
, target
, 0);
2124 /* If this machine has expensive jumps, we can do integer absolute
2125 value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
2126 where W is the width of MODE. */
2128 if (GET_MODE_CLASS (mode
) == MODE_INT
&& BRANCH_COST
>= 2)
2130 rtx extended
= expand_shift (RSHIFT_EXPR
, mode
, op0
,
2131 size_int (GET_MODE_BITSIZE (mode
) - 1),
2134 temp
= expand_binop (mode
, xor_optab
, extended
, op0
, target
, 0,
2137 temp
= expand_binop (mode
, sub_optab
, temp
, extended
, target
, 0,
2144 /* If that does not win, use conditional jump and negate. */
2146 /* It is safe to use the target if it is the same
2147 as the source if this is also a pseudo register */
2148 if (op0
== target
&& GET_CODE (op0
) == REG
2149 && REGNO (op0
) >= FIRST_PSEUDO_REGISTER
)
2152 op1
= gen_label_rtx ();
2153 if (target
== 0 || ! safe
2154 || GET_MODE (target
) != mode
2155 || (GET_CODE (target
) == MEM
&& MEM_VOLATILE_P (target
))
2156 || (GET_CODE (target
) == REG
2157 && REGNO (target
) < FIRST_PSEUDO_REGISTER
))
2158 target
= gen_reg_rtx (mode
);
2160 emit_move_insn (target
, op0
);
2163 /* If this mode is an integer too wide to compare properly,
2164 compare word by word. Rely on CSE to optimize constant cases. */
2165 if (GET_MODE_CLASS (mode
) == MODE_INT
&& ! can_compare_p (mode
))
2166 do_jump_by_parts_greater_rtx (mode
, 0, target
, const0_rtx
,
2170 temp
= compare_from_rtx (target
, CONST0_RTX (mode
), GE
, 0, mode
,
2172 if (temp
== const1_rtx
)
2174 else if (temp
!= const0_rtx
)
2176 if (bcc_gen_fctn
[(int) GET_CODE (temp
)] != 0)
2177 emit_jump_insn ((*bcc_gen_fctn
[(int) GET_CODE (temp
)]) (op1
));
2183 op0
= expand_unop (mode
, neg_optab
, target
, target
, 0);
2185 emit_move_insn (target
, op0
);
2191 /* Emit code to compute the absolute value of OP0, with result to
2192 TARGET if convenient. (TARGET may be 0.) The return value says
2193 where the result actually is to be found.
2195 MODE is the mode of the operand; the mode of the result is
2196 different but can be deduced from MODE.
2198 UNSIGNEDP is relevant for complex integer modes. */
2201 expand_complex_abs (mode
, op0
, target
, unsignedp
)
2202 enum machine_mode mode
;
2207 enum mode_class
class = GET_MODE_CLASS (mode
);
2208 enum machine_mode wider_mode
;
2210 rtx entry_last
= get_last_insn ();
2214 /* Find the correct mode for the real and imaginary parts. */
2215 enum machine_mode submode
2216 = mode_for_size (GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
,
2217 class == MODE_COMPLEX_INT
? MODE_INT
: MODE_FLOAT
,
2220 if (submode
== BLKmode
)
2223 op0
= protect_from_queue (op0
, 0);
2227 op0
= force_not_mem (op0
);
2230 last
= get_last_insn ();
2233 target
= protect_from_queue (target
, 1);
2235 if (abs_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
2237 int icode
= (int) abs_optab
->handlers
[(int) mode
].insn_code
;
2238 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
2244 temp
= gen_reg_rtx (submode
);
2246 if (GET_MODE (xop0
) != VOIDmode
2247 && GET_MODE (xop0
) != mode0
)
2248 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
2250 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
2252 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
2253 xop0
= copy_to_mode_reg (mode0
, xop0
);
2255 if (! (*insn_operand_predicate
[icode
][0]) (temp
, submode
))
2256 temp
= gen_reg_rtx (submode
);
2258 pat
= GEN_FCN (icode
) (temp
, xop0
);
2261 if (GET_CODE (pat
) == SEQUENCE
2262 && ! add_equal_note (pat
, temp
, abs_optab
->code
, xop0
, NULL_RTX
))
2264 delete_insns_since (last
);
2265 return expand_unop (mode
, abs_optab
, op0
, NULL_RTX
, unsignedp
);
2273 delete_insns_since (last
);
2276 /* It can't be done in this mode. Can we open-code it in a wider mode? */
2278 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2279 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2281 if (abs_optab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
)
2285 xop0
= convert_modes (wider_mode
, mode
, xop0
, unsignedp
);
2286 temp
= expand_complex_abs (wider_mode
, xop0
, NULL_RTX
, unsignedp
);
2290 if (class != MODE_COMPLEX_INT
)
2293 target
= gen_reg_rtx (submode
);
2294 convert_move (target
, temp
, 0);
2298 return gen_lowpart (submode
, temp
);
2301 delete_insns_since (last
);
2305 /* Open-code the complex absolute-value operation
2306 if we can open-code sqrt. Otherwise it's not worth while. */
2307 if (sqrt_optab
->handlers
[(int) submode
].insn_code
!= CODE_FOR_nothing
)
2309 rtx real
, imag
, total
;
2311 real
= gen_realpart (submode
, op0
);
2312 imag
= gen_imagpart (submode
, op0
);
2314 /* Square both parts. */
2315 real
= expand_mult (submode
, real
, real
, NULL_RTX
, 0);
2316 imag
= expand_mult (submode
, imag
, imag
, NULL_RTX
, 0);
2318 /* Sum the parts. */
2319 total
= expand_binop (submode
, add_optab
, real
, imag
, NULL_RTX
,
2320 0, OPTAB_LIB_WIDEN
);
2322 /* Get sqrt in TARGET. Set TARGET to where the result is. */
2323 target
= expand_unop (submode
, sqrt_optab
, total
, target
, 0);
2325 delete_insns_since (last
);
2330 /* Now try a library call in this mode. */
2331 if (abs_optab
->handlers
[(int) mode
].libfunc
)
2338 /* Pass 1 for NO_QUEUE so we don't lose any increments
2339 if the libcall is cse'd or moved. */
2340 value
= emit_library_call_value (abs_optab
->handlers
[(int) mode
].libfunc
,
2341 NULL_RTX
, 1, submode
, 1, op0
, mode
);
2342 insns
= get_insns ();
2345 target
= gen_reg_rtx (submode
);
2346 emit_libcall_block (insns
, target
, value
,
2347 gen_rtx_fmt_e (abs_optab
->code
, mode
, op0
));
2352 /* It can't be done in this mode. Can we do it in a wider mode? */
2354 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2355 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2357 if ((abs_optab
->handlers
[(int) wider_mode
].insn_code
2358 != CODE_FOR_nothing
)
2359 || abs_optab
->handlers
[(int) wider_mode
].libfunc
)
2363 xop0
= convert_modes (wider_mode
, mode
, xop0
, unsignedp
);
2365 temp
= expand_complex_abs (wider_mode
, xop0
, NULL_RTX
, unsignedp
);
2369 if (class != MODE_COMPLEX_INT
)
2372 target
= gen_reg_rtx (submode
);
2373 convert_move (target
, temp
, 0);
2377 return gen_lowpart (submode
, temp
);
2380 delete_insns_since (last
);
2384 delete_insns_since (entry_last
);
2388 /* Generate an instruction whose insn-code is INSN_CODE,
2389 with two operands: an output TARGET and an input OP0.
2390 TARGET *must* be nonzero, and the output is always stored there.
2391 CODE is an rtx code such that (CODE OP0) is an rtx that describes
2392 the value that is stored into TARGET. */
2395 emit_unop_insn (icode
, target
, op0
, code
)
2402 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
2405 temp
= target
= protect_from_queue (target
, 1);
2407 op0
= protect_from_queue (op0
, 0);
2409 /* Sign and zero extension from memory is often done specially on
2410 RISC machines, so forcing into a register here can pessimize
2412 if (flag_force_mem
&& code
!= SIGN_EXTEND
&& code
!= ZERO_EXTEND
)
2413 op0
= force_not_mem (op0
);
2415 /* Now, if insn does not accept our operands, put them into pseudos. */
2417 if (! (*insn_operand_predicate
[icode
][1]) (op0
, mode0
))
2418 op0
= copy_to_mode_reg (mode0
, op0
);
2420 if (! (*insn_operand_predicate
[icode
][0]) (temp
, GET_MODE (temp
))
2421 || (flag_force_mem
&& GET_CODE (temp
) == MEM
))
2422 temp
= gen_reg_rtx (GET_MODE (temp
));
2424 pat
= GEN_FCN (icode
) (temp
, op0
);
2426 if (GET_CODE (pat
) == SEQUENCE
&& code
!= UNKNOWN
)
2427 add_equal_note (pat
, temp
, code
, op0
, NULL_RTX
);
2432 emit_move_insn (target
, temp
);
2435 /* Emit code to perform a series of operations on a multi-word quantity, one
2438 Such a block is preceded by a CLOBBER of the output, consists of multiple
2439 insns, each setting one word of the output, and followed by a SET copying
2440 the output to itself.
2442 Each of the insns setting words of the output receives a REG_NO_CONFLICT
2443 note indicating that it doesn't conflict with the (also multi-word)
2444 inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
2447 INSNS is a block of code generated to perform the operation, not including
2448 the CLOBBER and final copy. All insns that compute intermediate values
2449 are first emitted, followed by the block as described above.
2451 TARGET, OP0, and OP1 are the output and inputs of the operations,
2452 respectively. OP1 may be zero for a unary operation.
2454 EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
2457 If TARGET is not a register, INSNS is simply emitted with no special
2458 processing. Likewise if anything in INSNS is not an INSN or if
2459 there is a libcall block inside INSNS.
2461 The final insn emitted is returned. */
2464 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv
)
2470 rtx prev
, next
, first
, last
, insn
;
2472 if (GET_CODE (target
) != REG
|| reload_in_progress
)
2473 return emit_insns (insns
);
2475 for (insn
= insns
; insn
; insn
= NEXT_INSN (insn
))
2476 if (GET_CODE (insn
) != INSN
2477 || find_reg_note (insn
, REG_LIBCALL
, NULL_RTX
))
2478 return emit_insns (insns
);
2480 /* First emit all insns that do not store into words of the output and remove
2481 these from the list. */
2482 for (insn
= insns
; insn
; insn
= next
)
2487 next
= NEXT_INSN (insn
);
2489 if (GET_CODE (PATTERN (insn
)) == SET
)
2490 set
= PATTERN (insn
);
2491 else if (GET_CODE (PATTERN (insn
)) == PARALLEL
)
2493 for (i
= 0; i
< XVECLEN (PATTERN (insn
), 0); i
++)
2494 if (GET_CODE (XVECEXP (PATTERN (insn
), 0, i
)) == SET
)
2496 set
= XVECEXP (PATTERN (insn
), 0, i
);
2504 if (! reg_overlap_mentioned_p (target
, SET_DEST (set
)))
2506 if (PREV_INSN (insn
))
2507 NEXT_INSN (PREV_INSN (insn
)) = next
;
2512 PREV_INSN (next
) = PREV_INSN (insn
);
2518 prev
= get_last_insn ();
2520 /* Now write the CLOBBER of the output, followed by the setting of each
2521 of the words, followed by the final copy. */
2522 if (target
!= op0
&& target
!= op1
)
2523 emit_insn (gen_rtx_CLOBBER (VOIDmode
, target
));
2525 for (insn
= insns
; insn
; insn
= next
)
2527 next
= NEXT_INSN (insn
);
2530 if (op1
&& GET_CODE (op1
) == REG
)
2531 REG_NOTES (insn
) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT
, op1
,
2534 if (op0
&& GET_CODE (op0
) == REG
)
2535 REG_NOTES (insn
) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT
, op0
,
2539 if (mov_optab
->handlers
[(int) GET_MODE (target
)].insn_code
2540 != CODE_FOR_nothing
)
2542 last
= emit_move_insn (target
, target
);
2544 set_unique_reg_note (last
, REG_EQUAL
, equiv
);
2547 last
= get_last_insn ();
2550 first
= get_insns ();
2552 first
= NEXT_INSN (prev
);
2554 /* Encapsulate the block so it gets manipulated as a unit. */
2555 REG_NOTES (first
) = gen_rtx_INSN_LIST (REG_LIBCALL
, last
,
2557 REG_NOTES (last
) = gen_rtx_INSN_LIST (REG_RETVAL
, first
, REG_NOTES (last
));
2562 /* Emit code to make a call to a constant function or a library call.
2564 INSNS is a list containing all insns emitted in the call.
2565 These insns leave the result in RESULT. Our block is to copy RESULT
2566 to TARGET, which is logically equivalent to EQUIV.
2568 We first emit any insns that set a pseudo on the assumption that these are
2569 loading constants into registers; doing so allows them to be safely cse'ed
2570 between blocks. Then we emit all the other insns in the block, followed by
2571 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
2572 note with an operand of EQUIV.
2574 Moving assignments to pseudos outside of the block is done to improve
2575 the generated code, but is not required to generate correct code,
2576 hence being unable to move an assignment is not grounds for not making
2577 a libcall block. There are two reasons why it is safe to leave these
2578 insns inside the block: First, we know that these pseudos cannot be
2579 used in generated RTL outside the block since they are created for
2580 temporary purposes within the block. Second, CSE will not record the
2581 values of anything set inside a libcall block, so we know they must
2582 be dead at the end of the block.
2584 Except for the first group of insns (the ones setting pseudos), the
2585 block is delimited by REG_RETVAL and REG_LIBCALL notes. */
2588 emit_libcall_block (insns
, target
, result
, equiv
)
2594 rtx prev
, next
, first
, last
, insn
;
2596 /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
2597 reg note to indicate that this call cannot throw. (Unless there is
2598 already a REG_EH_REGION note.) */
2600 for (insn
= insns
; insn
; insn
= NEXT_INSN (insn
))
2602 if (GET_CODE (insn
) == CALL_INSN
)
2604 rtx note
= find_reg_note (insn
, REG_EH_REGION
, NULL_RTX
);
2605 if (note
== NULL_RTX
)
2606 REG_NOTES (insn
) = gen_rtx_EXPR_LIST (REG_EH_REGION
, GEN_INT (0),
2611 /* First emit all insns that set pseudos. Remove them from the list as
2612 we go. Avoid insns that set pseudos which were referenced in previous
2613 insns. These can be generated by move_by_pieces, for example,
2614 to update an address. Similarly, avoid insns that reference things
2615 set in previous insns. */
2617 for (insn
= insns
; insn
; insn
= next
)
2619 rtx set
= single_set (insn
);
2621 next
= NEXT_INSN (insn
);
2623 if (set
!= 0 && GET_CODE (SET_DEST (set
)) == REG
2624 && REGNO (SET_DEST (set
)) >= FIRST_PSEUDO_REGISTER
2626 || (! reg_mentioned_p (SET_DEST (set
), PATTERN (insns
))
2627 && ! reg_used_between_p (SET_DEST (set
), insns
, insn
)
2628 && ! modified_in_p (SET_SRC (set
), insns
)
2629 && ! modified_between_p (SET_SRC (set
), insns
, insn
))))
2631 if (PREV_INSN (insn
))
2632 NEXT_INSN (PREV_INSN (insn
)) = next
;
2637 PREV_INSN (next
) = PREV_INSN (insn
);
2643 prev
= get_last_insn ();
2645 /* Write the remaining insns followed by the final copy. */
2647 for (insn
= insns
; insn
; insn
= next
)
2649 next
= NEXT_INSN (insn
);
2654 last
= emit_move_insn (target
, result
);
2655 if (mov_optab
->handlers
[(int) GET_MODE (target
)].insn_code
2656 != CODE_FOR_nothing
)
2657 set_unique_reg_note (last
, REG_EQUAL
, copy_rtx (equiv
));
2660 first
= get_insns ();
2662 first
= NEXT_INSN (prev
);
2664 /* Encapsulate the block so it gets manipulated as a unit. */
2665 REG_NOTES (first
) = gen_rtx_INSN_LIST (REG_LIBCALL
, last
,
2667 REG_NOTES (last
) = gen_rtx_INSN_LIST (REG_RETVAL
, first
, REG_NOTES (last
));
2670 /* Generate code to store zero in X. */
2676 emit_move_insn (x
, const0_rtx
);
2679 /* Generate code to store 1 in X
2680 assuming it contains zero beforehand. */
2683 emit_0_to_1_insn (x
)
2686 emit_move_insn (x
, const1_rtx
);
2689 /* Generate code to compare X with Y
2690 so that the condition codes are set.
2692 MODE is the mode of the inputs (in case they are const_int).
2693 UNSIGNEDP nonzero says that X and Y are unsigned;
2694 this matters if they need to be widened.
2696 If they have mode BLKmode, then SIZE specifies the size of both X and Y,
2697 and ALIGN specifies the known shared alignment of X and Y.
2699 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
2700 It is ignored for fixed-point and block comparisons;
2701 it is used only for floating-point comparisons. */
2704 emit_cmp_insn (x
, y
, comparison
, size
, mode
, unsignedp
, align
)
2706 enum rtx_code comparison
;
2708 enum machine_mode mode
;
2712 enum mode_class
class;
2713 enum machine_mode wider_mode
;
2715 class = GET_MODE_CLASS (mode
);
2717 /* They could both be VOIDmode if both args are immediate constants,
2718 but we should fold that at an earlier stage.
2719 With no special code here, this will call abort,
2720 reminding the programmer to implement such folding. */
2722 if (mode
!= BLKmode
&& flag_force_mem
)
2724 x
= force_not_mem (x
);
2725 y
= force_not_mem (y
);
2728 /* If we are inside an appropriately-short loop and one operand is an
2729 expensive constant, force it into a register. */
2730 if (CONSTANT_P (x
) && preserve_subexpressions_p () && rtx_cost (x
, COMPARE
) > 2)
2731 x
= force_reg (mode
, x
);
2733 if (CONSTANT_P (y
) && preserve_subexpressions_p () && rtx_cost (y
, COMPARE
) > 2)
2734 y
= force_reg (mode
, y
);
2737 /* Abort if we have a non-canonical comparison. The RTL documentation
2738 states that canonical comparisons are required only for targets which
2740 if (CONSTANT_P (x
) && ! CONSTANT_P (y
))
2744 /* Don't let both operands fail to indicate the mode. */
2745 if (GET_MODE (x
) == VOIDmode
&& GET_MODE (y
) == VOIDmode
)
2746 x
= force_reg (mode
, x
);
2748 /* Handle all BLKmode compares. */
2750 if (mode
== BLKmode
)
2753 x
= protect_from_queue (x
, 0);
2754 y
= protect_from_queue (y
, 0);
2758 #ifdef HAVE_cmpstrqi
2760 && GET_CODE (size
) == CONST_INT
2761 && INTVAL (size
) < (1 << GET_MODE_BITSIZE (QImode
)))
2763 enum machine_mode result_mode
2764 = insn_operand_mode
[(int) CODE_FOR_cmpstrqi
][0];
2765 rtx result
= gen_reg_rtx (result_mode
);
2766 emit_insn (gen_cmpstrqi (result
, x
, y
, size
, GEN_INT (align
)));
2767 emit_cmp_insn (result
, const0_rtx
, comparison
, NULL_RTX
,
2772 #ifdef HAVE_cmpstrhi
2774 && GET_CODE (size
) == CONST_INT
2775 && INTVAL (size
) < (1 << GET_MODE_BITSIZE (HImode
)))
2777 enum machine_mode result_mode
2778 = insn_operand_mode
[(int) CODE_FOR_cmpstrhi
][0];
2779 rtx result
= gen_reg_rtx (result_mode
);
2780 emit_insn (gen_cmpstrhi (result
, x
, y
, size
, GEN_INT (align
)));
2781 emit_cmp_insn (result
, const0_rtx
, comparison
, NULL_RTX
,
2786 #ifdef HAVE_cmpstrsi
2789 enum machine_mode result_mode
2790 = insn_operand_mode
[(int) CODE_FOR_cmpstrsi
][0];
2791 rtx result
= gen_reg_rtx (result_mode
);
2792 size
= protect_from_queue (size
, 0);
2793 emit_insn (gen_cmpstrsi (result
, x
, y
,
2794 convert_to_mode (SImode
, size
, 1),
2796 emit_cmp_insn (result
, const0_rtx
, comparison
, NULL_RTX
,
2804 #ifdef TARGET_MEM_FUNCTIONS
2805 emit_library_call (memcmp_libfunc
, 0,
2806 TYPE_MODE (integer_type_node
), 3,
2807 XEXP (x
, 0), Pmode
, XEXP (y
, 0), Pmode
,
2808 convert_to_mode (TYPE_MODE (sizetype
), size
,
2809 TREE_UNSIGNED (sizetype
)),
2810 TYPE_MODE (sizetype
));
2812 emit_library_call (bcmp_libfunc
, 0,
2813 TYPE_MODE (integer_type_node
), 3,
2814 XEXP (x
, 0), Pmode
, XEXP (y
, 0), Pmode
,
2815 convert_to_mode (TYPE_MODE (integer_type_node
),
2817 TREE_UNSIGNED (integer_type_node
)),
2818 TYPE_MODE (integer_type_node
));
2821 /* Immediately move the result of the libcall into a pseudo
2822 register so reload doesn't clobber the value if it needs
2823 the return register for a spill reg. */
2824 result
= gen_reg_rtx (TYPE_MODE (integer_type_node
));
2825 emit_move_insn (result
,
2826 hard_libcall_value (TYPE_MODE (integer_type_node
)));
2827 emit_cmp_insn (result
,
2828 const0_rtx
, comparison
, NULL_RTX
,
2829 TYPE_MODE (integer_type_node
), 0, 0);
2834 /* Handle some compares against zero. */
2836 if (y
== CONST0_RTX (mode
)
2837 && tst_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
2839 int icode
= (int) tst_optab
->handlers
[(int) mode
].insn_code
;
2842 x
= protect_from_queue (x
, 0);
2843 y
= protect_from_queue (y
, 0);
2845 /* Now, if insn does accept these operands, put them into pseudos. */
2846 if (! (*insn_operand_predicate
[icode
][0])
2847 (x
, insn_operand_mode
[icode
][0]))
2848 x
= copy_to_mode_reg (insn_operand_mode
[icode
][0], x
);
2850 emit_insn (GEN_FCN (icode
) (x
));
2854 /* Handle compares for which there is a directly suitable insn. */
2856 if (cmp_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
2858 int icode
= (int) cmp_optab
->handlers
[(int) mode
].insn_code
;
2861 x
= protect_from_queue (x
, 0);
2862 y
= protect_from_queue (y
, 0);
2864 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2865 if (! (*insn_operand_predicate
[icode
][0])
2866 (x
, insn_operand_mode
[icode
][0]))
2867 x
= copy_to_mode_reg (insn_operand_mode
[icode
][0], x
);
2869 if (! (*insn_operand_predicate
[icode
][1])
2870 (y
, insn_operand_mode
[icode
][1]))
2871 y
= copy_to_mode_reg (insn_operand_mode
[icode
][1], y
);
2873 emit_insn (GEN_FCN (icode
) (x
, y
));
2877 /* Try widening if we can find a direct insn that way. */
2879 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
2881 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2882 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2884 if (cmp_optab
->handlers
[(int) wider_mode
].insn_code
2885 != CODE_FOR_nothing
)
2887 x
= protect_from_queue (x
, 0);
2888 y
= protect_from_queue (y
, 0);
2889 x
= convert_modes (wider_mode
, mode
, x
, unsignedp
);
2890 y
= convert_modes (wider_mode
, mode
, y
, unsignedp
);
2891 emit_cmp_insn (x
, y
, comparison
, NULL_RTX
,
2892 wider_mode
, unsignedp
, align
);
2898 /* Handle a lib call just for the mode we are using. */
2900 if (cmp_optab
->handlers
[(int) mode
].libfunc
2901 && class != MODE_FLOAT
)
2903 rtx libfunc
= cmp_optab
->handlers
[(int) mode
].libfunc
;
2906 /* If we want unsigned, and this mode has a distinct unsigned
2907 comparison routine, use that. */
2908 if (unsignedp
&& ucmp_optab
->handlers
[(int) mode
].libfunc
)
2909 libfunc
= ucmp_optab
->handlers
[(int) mode
].libfunc
;
2911 emit_library_call (libfunc
, 1,
2912 word_mode
, 2, x
, mode
, y
, mode
);
2914 /* Immediately move the result of the libcall into a pseudo
2915 register so reload doesn't clobber the value if it needs
2916 the return register for a spill reg. */
2917 result
= gen_reg_rtx (word_mode
);
2918 emit_move_insn (result
, hard_libcall_value (word_mode
));
2920 /* Integer comparison returns a result that must be compared against 1,
2921 so that even if we do an unsigned compare afterward,
2922 there is still a value that can represent the result "less than". */
2923 emit_cmp_insn (result
, const1_rtx
,
2924 comparison
, NULL_RTX
, word_mode
, unsignedp
, 0);
2928 if (class == MODE_FLOAT
)
2929 emit_float_lib_cmp (x
, y
, comparison
);
2935 /* Generate code to compare X with Y so that the condition codes are
2936 set and to jump to LABEL if the condition is true. If X is a
2937 constant and Y is not a constant, then the comparison is swapped to
2938 ensure that the comparison RTL has the canonical form.
2940 UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
2941 need to be widened by emit_cmp_insn. UNSIGNEDP is also used to select
2942 the proper branch condition code.
2944 If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y,
2945 and ALIGN specifies the known shared alignment of X and Y.
2947 MODE is the mode of the inputs (in case they are const_int).
2949 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). It will
2950 be passed unchanged to emit_cmp_insn, then potentially converted into an
2951 unsigned variant based on UNSIGNEDP to select a proper jump instruction. */
2954 emit_cmp_and_jump_insns (x
, y
, comparison
, size
, mode
, unsignedp
, align
, label
)
2956 enum rtx_code comparison
;
2958 enum machine_mode mode
;
2968 /* Swap operands and condition to ensure canonical RTL. */
2971 comparison
= swap_condition (comparison
);
2978 emit_cmp_insn (op0
, op1
, comparison
, size
, mode
, unsignedp
, align
);
2981 comparison
= unsigned_condition (comparison
);
2982 emit_jump_insn ((*bcc_gen_fctn
[(int) comparison
]) (label
));
2986 /* Nonzero if a compare of mode MODE can be done straightforwardly
2987 (without splitting it into pieces). */
2990 can_compare_p (mode
)
2991 enum machine_mode mode
;
2995 if (cmp_optab
->handlers
[(int)mode
].insn_code
!= CODE_FOR_nothing
)
2997 mode
= GET_MODE_WIDER_MODE (mode
);
2998 } while (mode
!= VOIDmode
);
3003 /* Emit a library call comparison between floating point X and Y.
3004 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
3007 emit_float_lib_cmp (x
, y
, comparison
)
3009 enum rtx_code comparison
;
3011 enum machine_mode mode
= GET_MODE (x
);
3019 libfunc
= eqhf2_libfunc
;
3023 libfunc
= nehf2_libfunc
;
3027 libfunc
= gthf2_libfunc
;
3031 libfunc
= gehf2_libfunc
;
3035 libfunc
= lthf2_libfunc
;
3039 libfunc
= lehf2_libfunc
;
3045 else if (mode
== SFmode
)
3049 libfunc
= eqsf2_libfunc
;
3053 libfunc
= nesf2_libfunc
;
3057 libfunc
= gtsf2_libfunc
;
3061 libfunc
= gesf2_libfunc
;
3065 libfunc
= ltsf2_libfunc
;
3069 libfunc
= lesf2_libfunc
;
3075 else if (mode
== DFmode
)
3079 libfunc
= eqdf2_libfunc
;
3083 libfunc
= nedf2_libfunc
;
3087 libfunc
= gtdf2_libfunc
;
3091 libfunc
= gedf2_libfunc
;
3095 libfunc
= ltdf2_libfunc
;
3099 libfunc
= ledf2_libfunc
;
3105 else if (mode
== XFmode
)
3109 libfunc
= eqxf2_libfunc
;
3113 libfunc
= nexf2_libfunc
;
3117 libfunc
= gtxf2_libfunc
;
3121 libfunc
= gexf2_libfunc
;
3125 libfunc
= ltxf2_libfunc
;
3129 libfunc
= lexf2_libfunc
;
3135 else if (mode
== TFmode
)
3139 libfunc
= eqtf2_libfunc
;
3143 libfunc
= netf2_libfunc
;
3147 libfunc
= gttf2_libfunc
;
3151 libfunc
= getf2_libfunc
;
3155 libfunc
= lttf2_libfunc
;
3159 libfunc
= letf2_libfunc
;
3167 enum machine_mode wider_mode
;
3169 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
3170 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
3172 if ((cmp_optab
->handlers
[(int) wider_mode
].insn_code
3173 != CODE_FOR_nothing
)
3174 || (cmp_optab
->handlers
[(int) wider_mode
].libfunc
!= 0))
3176 x
= protect_from_queue (x
, 0);
3177 y
= protect_from_queue (y
, 0);
3178 x
= convert_to_mode (wider_mode
, x
, 0);
3179 y
= convert_to_mode (wider_mode
, y
, 0);
3180 emit_float_lib_cmp (x
, y
, comparison
);
3190 emit_library_call (libfunc
, 1,
3191 word_mode
, 2, x
, mode
, y
, mode
);
3193 /* Immediately move the result of the libcall into a pseudo
3194 register so reload doesn't clobber the value if it needs
3195 the return register for a spill reg. */
3196 result
= gen_reg_rtx (word_mode
);
3197 emit_move_insn (result
, hard_libcall_value (word_mode
));
3199 emit_cmp_insn (result
, const0_rtx
, comparison
,
3200 NULL_RTX
, word_mode
, 0, 0);
3203 /* Generate code to indirectly jump to a location given in the rtx LOC. */
3206 emit_indirect_jump (loc
)
3209 if (! ((*insn_operand_predicate
[(int)CODE_FOR_indirect_jump
][0])
3211 loc
= copy_to_mode_reg (Pmode
, loc
);
3213 emit_jump_insn (gen_indirect_jump (loc
));
3217 #ifdef HAVE_conditional_move
3219 /* Emit a conditional move instruction if the machine supports one for that
3220 condition and machine mode.
3222 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
3223 the mode to use should they be constants. If it is VOIDmode, they cannot
3226 OP2 should be stored in TARGET if the comparison is true, otherwise OP3
3227 should be stored there. MODE is the mode to use should they be constants.
3228 If it is VOIDmode, they cannot both be constants.
3230 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
3231 is not supported. */
3234 emit_conditional_move (target
, code
, op0
, op1
, cmode
, op2
, op3
, mode
,
3239 enum machine_mode cmode
;
3241 enum machine_mode mode
;
3244 rtx tem
, subtarget
, comparison
, insn
;
3245 enum insn_code icode
;
3247 /* If one operand is constant, make it the second one. Only do this
3248 if the other operand is not constant as well. */
3250 if ((CONSTANT_P (op0
) && ! CONSTANT_P (op1
))
3251 || (GET_CODE (op0
) == CONST_INT
&& GET_CODE (op1
) != CONST_INT
))
3256 code
= swap_condition (code
);
3259 if (cmode
== VOIDmode
)
3260 cmode
= GET_MODE (op0
);
3262 if (((CONSTANT_P (op2
) && ! CONSTANT_P (op3
))
3263 || (GET_CODE (op2
) == CONST_INT
&& GET_CODE (op3
) != CONST_INT
))
3264 && (GET_MODE_CLASS (GET_MODE (op1
)) != MODE_FLOAT
3265 || TARGET_FLOAT_FORMAT
!= IEEE_FLOAT_FORMAT
|| flag_fast_math
))
3270 code
= reverse_condition (code
);
3273 if (mode
== VOIDmode
)
3274 mode
= GET_MODE (op2
);
3276 icode
= movcc_gen_code
[mode
];
3278 if (icode
== CODE_FOR_nothing
)
3283 op2
= force_not_mem (op2
);
3284 op3
= force_not_mem (op3
);
3288 target
= protect_from_queue (target
, 1);
3290 target
= gen_reg_rtx (mode
);
3296 op2
= protect_from_queue (op2
, 0);
3297 op3
= protect_from_queue (op3
, 0);
3299 /* If the insn doesn't accept these operands, put them in pseudos. */
3301 if (! (*insn_operand_predicate
[icode
][0])
3302 (subtarget
, insn_operand_mode
[icode
][0]))
3303 subtarget
= gen_reg_rtx (insn_operand_mode
[icode
][0]);
3305 if (! (*insn_operand_predicate
[icode
][2])
3306 (op2
, insn_operand_mode
[icode
][2]))
3307 op2
= copy_to_mode_reg (insn_operand_mode
[icode
][2], op2
);
3309 if (! (*insn_operand_predicate
[icode
][3])
3310 (op3
, insn_operand_mode
[icode
][3]))
3311 op3
= copy_to_mode_reg (insn_operand_mode
[icode
][3], op3
);
3313 /* Everything should now be in the suitable form, so emit the compare insn
3314 and then the conditional move. */
3317 = compare_from_rtx (op0
, op1
, code
, unsignedp
, cmode
, NULL_RTX
, 0);
3319 /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)? */
3320 if (GET_CODE (comparison
) != code
)
3321 /* This shouldn't happen. */
3324 insn
= GEN_FCN (icode
) (subtarget
, comparison
, op2
, op3
);
3326 /* If that failed, then give up. */
3332 if (subtarget
!= target
)
3333 convert_move (target
, subtarget
, 0);
3338 /* Return non-zero if a conditional move of mode MODE is supported.
3340 This function is for combine so it can tell whether an insn that looks
3341 like a conditional move is actually supported by the hardware. If we
3342 guess wrong we lose a bit on optimization, but that's it. */
3343 /* ??? sparc64 supports conditionally moving integers values based on fp
3344 comparisons, and vice versa. How do we handle them? */
3347 can_conditionally_move_p (mode
)
3348 enum machine_mode mode
;
3350 if (movcc_gen_code
[mode
] != CODE_FOR_nothing
)
3356 #endif /* HAVE_conditional_move */
3358 /* These three functions generate an insn body and return it
3359 rather than emitting the insn.
3361 They do not protect from queued increments,
3362 because they may be used 1) in protect_from_queue itself
3363 and 2) in other passes where there is no queue. */
3365 /* Generate and return an insn body to add Y to X. */
3368 gen_add2_insn (x
, y
)
3371 int icode
= (int) add_optab
->handlers
[(int) GET_MODE (x
)].insn_code
;
3373 if (! (*insn_operand_predicate
[icode
][0]) (x
, insn_operand_mode
[icode
][0])
3374 || ! (*insn_operand_predicate
[icode
][1]) (x
, insn_operand_mode
[icode
][1])
3375 || ! (*insn_operand_predicate
[icode
][2]) (y
, insn_operand_mode
[icode
][2]))
3378 return (GEN_FCN (icode
) (x
, x
, y
));
3382 have_add2_insn (mode
)
3383 enum machine_mode mode
;
3385 return add_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
;
3388 /* Generate and return an insn body to subtract Y from X. */
3391 gen_sub2_insn (x
, y
)
3394 int icode
= (int) sub_optab
->handlers
[(int) GET_MODE (x
)].insn_code
;
3396 if (! (*insn_operand_predicate
[icode
][0]) (x
, insn_operand_mode
[icode
][0])
3397 || ! (*insn_operand_predicate
[icode
][1]) (x
, insn_operand_mode
[icode
][1])
3398 || ! (*insn_operand_predicate
[icode
][2]) (y
, insn_operand_mode
[icode
][2]))
3401 return (GEN_FCN (icode
) (x
, x
, y
));
3405 have_sub2_insn (mode
)
3406 enum machine_mode mode
;
3408 return sub_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
;
3411 /* Generate the body of an instruction to copy Y into X.
3412 It may be a SEQUENCE, if one insn isn't enough. */
3415 gen_move_insn (x
, y
)
3418 register enum machine_mode mode
= GET_MODE (x
);
3419 enum insn_code insn_code
;
3422 if (mode
== VOIDmode
)
3423 mode
= GET_MODE (y
);
3425 insn_code
= mov_optab
->handlers
[(int) mode
].insn_code
;
3427 /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
3428 find a mode to do it in. If we have a movcc, use it. Otherwise,
3429 find the MODE_INT mode of the same width. */
3431 if (GET_MODE_CLASS (mode
) == MODE_CC
&& insn_code
== CODE_FOR_nothing
)
3433 enum machine_mode tmode
= VOIDmode
;
3437 && mov_optab
->handlers
[(int) CCmode
].insn_code
!= CODE_FOR_nothing
)
3440 for (tmode
= QImode
; tmode
!= VOIDmode
;
3441 tmode
= GET_MODE_WIDER_MODE (tmode
))
3442 if (GET_MODE_SIZE (tmode
) == GET_MODE_SIZE (mode
))
3445 if (tmode
== VOIDmode
)
3448 /* Get X and Y in TMODE. We can't use gen_lowpart here because it
3449 may call change_address which is not appropriate if we were
3450 called when a reload was in progress. We don't have to worry
3451 about changing the address since the size in bytes is supposed to
3452 be the same. Copy the MEM to change the mode and move any
3453 substitutions from the old MEM to the new one. */
3455 if (reload_in_progress
)
3457 x
= gen_lowpart_common (tmode
, x1
);
3458 if (x
== 0 && GET_CODE (x1
) == MEM
)
3460 x
= gen_rtx_MEM (tmode
, XEXP (x1
, 0));
3461 RTX_UNCHANGING_P (x
) = RTX_UNCHANGING_P (x1
);
3462 MEM_COPY_ATTRIBUTES (x
, x1
);
3463 copy_replacements (x1
, x
);
3466 y
= gen_lowpart_common (tmode
, y1
);
3467 if (y
== 0 && GET_CODE (y1
) == MEM
)
3469 y
= gen_rtx_MEM (tmode
, XEXP (y1
, 0));
3470 RTX_UNCHANGING_P (y
) = RTX_UNCHANGING_P (y1
);
3471 MEM_COPY_ATTRIBUTES (y
, y1
);
3472 copy_replacements (y1
, y
);
3477 x
= gen_lowpart (tmode
, x
);
3478 y
= gen_lowpart (tmode
, y
);
3481 insn_code
= mov_optab
->handlers
[(int) tmode
].insn_code
;
3482 return (GEN_FCN (insn_code
) (x
, y
));
3486 emit_move_insn_1 (x
, y
);
3487 seq
= gen_sequence ();
3492 /* Return the insn code used to extend FROM_MODE to TO_MODE.
3493 UNSIGNEDP specifies zero-extension instead of sign-extension. If
3494 no such operation exists, CODE_FOR_nothing will be returned. */
3497 can_extend_p (to_mode
, from_mode
, unsignedp
)
3498 enum machine_mode to_mode
, from_mode
;
3501 return extendtab
[(int) to_mode
][(int) from_mode
][unsignedp
];
3504 /* Generate the body of an insn to extend Y (with mode MFROM)
3505 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
3508 gen_extend_insn (x
, y
, mto
, mfrom
, unsignedp
)
3510 enum machine_mode mto
, mfrom
;
3513 return (GEN_FCN (extendtab
[(int) mto
][(int) mfrom
][unsignedp
]) (x
, y
));
3516 /* can_fix_p and can_float_p say whether the target machine
3517 can directly convert a given fixed point type to
3518 a given floating point type, or vice versa.
3519 The returned value is the CODE_FOR_... value to use,
3520 or CODE_FOR_nothing if these modes cannot be directly converted.
3522 *TRUNCP_PTR is set to 1 if it is necessary to output
3523 an explicit FTRUNC insn before the fix insn; otherwise 0. */
3525 static enum insn_code
3526 can_fix_p (fixmode
, fltmode
, unsignedp
, truncp_ptr
)
3527 enum machine_mode fltmode
, fixmode
;
3532 if (fixtrunctab
[(int) fltmode
][(int) fixmode
][unsignedp
] != CODE_FOR_nothing
)
3533 return fixtrunctab
[(int) fltmode
][(int) fixmode
][unsignedp
];
3535 if (ftrunc_optab
->handlers
[(int) fltmode
].insn_code
!= CODE_FOR_nothing
)
3538 return fixtab
[(int) fltmode
][(int) fixmode
][unsignedp
];
3540 return CODE_FOR_nothing
;
3543 static enum insn_code
3544 can_float_p (fltmode
, fixmode
, unsignedp
)
3545 enum machine_mode fixmode
, fltmode
;
3548 return floattab
[(int) fltmode
][(int) fixmode
][unsignedp
];
3551 /* Generate code to convert FROM to floating point
3552 and store in TO. FROM must be fixed point and not VOIDmode.
3553 UNSIGNEDP nonzero means regard FROM as unsigned.
3554 Normally this is done by correcting the final value
3555 if it is negative. */
3558 expand_float (to
, from
, unsignedp
)
3562 enum insn_code icode
;
3563 register rtx target
= to
;
3564 enum machine_mode fmode
, imode
;
3566 /* Crash now, because we won't be able to decide which mode to use. */
3567 if (GET_MODE (from
) == VOIDmode
)
3570 /* Look for an insn to do the conversion. Do it in the specified
3571 modes if possible; otherwise convert either input, output or both to
3572 wider mode. If the integer mode is wider than the mode of FROM,
3573 we can do the conversion signed even if the input is unsigned. */
3575 for (imode
= GET_MODE (from
); imode
!= VOIDmode
;
3576 imode
= GET_MODE_WIDER_MODE (imode
))
3577 for (fmode
= GET_MODE (to
); fmode
!= VOIDmode
;
3578 fmode
= GET_MODE_WIDER_MODE (fmode
))
3580 int doing_unsigned
= unsignedp
;
3582 icode
= can_float_p (fmode
, imode
, unsignedp
);
3583 if (icode
== CODE_FOR_nothing
&& imode
!= GET_MODE (from
) && unsignedp
)
3584 icode
= can_float_p (fmode
, imode
, 0), doing_unsigned
= 0;
3586 if (icode
!= CODE_FOR_nothing
)
3588 to
= protect_from_queue (to
, 1);
3589 from
= protect_from_queue (from
, 0);
3591 if (imode
!= GET_MODE (from
))
3592 from
= convert_to_mode (imode
, from
, unsignedp
);
3594 if (fmode
!= GET_MODE (to
))
3595 target
= gen_reg_rtx (fmode
);
3597 emit_unop_insn (icode
, target
, from
,
3598 doing_unsigned
? UNSIGNED_FLOAT
: FLOAT
);
3601 convert_move (to
, target
, 0);
3606 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3608 /* Unsigned integer, and no way to convert directly.
3609 Convert as signed, then conditionally adjust the result. */
3612 rtx label
= gen_label_rtx ();
3614 REAL_VALUE_TYPE offset
;
3618 to
= protect_from_queue (to
, 1);
3619 from
= protect_from_queue (from
, 0);
3622 from
= force_not_mem (from
);
3624 /* Look for a usable floating mode FMODE wider than the source and at
3625 least as wide as the target. Using FMODE will avoid rounding woes
3626 with unsigned values greater than the signed maximum value. */
3628 for (fmode
= GET_MODE (to
); fmode
!= VOIDmode
;
3629 fmode
= GET_MODE_WIDER_MODE (fmode
))
3630 if (GET_MODE_BITSIZE (GET_MODE (from
)) < GET_MODE_BITSIZE (fmode
)
3631 && can_float_p (fmode
, GET_MODE (from
), 0) != CODE_FOR_nothing
)
3634 if (fmode
== VOIDmode
)
3636 /* There is no such mode. Pretend the target is wide enough. */
3637 fmode
= GET_MODE (to
);
3639 /* Avoid double-rounding when TO is narrower than FROM. */
3640 if ((significand_size (fmode
) + 1)
3641 < GET_MODE_BITSIZE (GET_MODE (from
)))
3644 rtx neglabel
= gen_label_rtx ();
3646 /* Don't use TARGET if it isn't a register, is a hard register,
3647 or is the wrong mode. */
3648 if (GET_CODE (target
) != REG
3649 || REGNO (target
) < FIRST_PSEUDO_REGISTER
3650 || GET_MODE (target
) != fmode
)
3651 target
= gen_reg_rtx (fmode
);
3653 imode
= GET_MODE (from
);
3654 do_pending_stack_adjust ();
3656 /* Test whether the sign bit is set. */
3657 emit_cmp_insn (from
, const0_rtx
, GE
, NULL_RTX
, imode
, 0, 0);
3658 emit_jump_insn (gen_blt (neglabel
));
3660 /* The sign bit is not set. Convert as signed. */
3661 expand_float (target
, from
, 0);
3662 emit_jump_insn (gen_jump (label
));
3665 /* The sign bit is set.
3666 Convert to a usable (positive signed) value by shifting right
3667 one bit, while remembering if a nonzero bit was shifted
3668 out; i.e., compute (from & 1) | (from >> 1). */
3670 emit_label (neglabel
);
3671 temp
= expand_binop (imode
, and_optab
, from
, const1_rtx
,
3672 NULL_RTX
, 1, OPTAB_LIB_WIDEN
);
3673 temp1
= expand_shift (RSHIFT_EXPR
, imode
, from
, integer_one_node
,
3675 temp
= expand_binop (imode
, ior_optab
, temp
, temp1
, temp
, 1,
3677 expand_float (target
, temp
, 0);
3679 /* Multiply by 2 to undo the shift above. */
3680 temp
= expand_binop (fmode
, add_optab
, target
, target
,
3681 target
, 0, OPTAB_LIB_WIDEN
);
3683 emit_move_insn (target
, temp
);
3685 do_pending_stack_adjust ();
3691 /* If we are about to do some arithmetic to correct for an
3692 unsigned operand, do it in a pseudo-register. */
3694 if (GET_MODE (to
) != fmode
3695 || GET_CODE (to
) != REG
|| REGNO (to
) < FIRST_PSEUDO_REGISTER
)
3696 target
= gen_reg_rtx (fmode
);
3698 /* Convert as signed integer to floating. */
3699 expand_float (target
, from
, 0);
3701 /* If FROM is negative (and therefore TO is negative),
3702 correct its value by 2**bitwidth. */
3704 do_pending_stack_adjust ();
3705 emit_cmp_and_jump_insns (from
, const0_rtx
, GE
, NULL_RTX
, GET_MODE (from
),
3708 /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
3709 Rather than setting up a dconst_dot_5, let's hope SCO
3711 offset
= REAL_VALUE_LDEXP (dconst1
, GET_MODE_BITSIZE (GET_MODE (from
)));
3712 temp
= expand_binop (fmode
, add_optab
, target
,
3713 CONST_DOUBLE_FROM_REAL_VALUE (offset
, fmode
),
3714 target
, 0, OPTAB_LIB_WIDEN
);
3716 emit_move_insn (target
, temp
);
3718 do_pending_stack_adjust ();
3724 /* No hardware instruction available; call a library routine to convert from
3725 SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */
3731 to
= protect_from_queue (to
, 1);
3732 from
= protect_from_queue (from
, 0);
3734 if (GET_MODE_SIZE (GET_MODE (from
)) < GET_MODE_SIZE (SImode
))
3735 from
= convert_to_mode (SImode
, from
, unsignedp
);
3738 from
= force_not_mem (from
);
3740 if (GET_MODE (to
) == SFmode
)
3742 if (GET_MODE (from
) == SImode
)
3743 libfcn
= floatsisf_libfunc
;
3744 else if (GET_MODE (from
) == DImode
)
3745 libfcn
= floatdisf_libfunc
;
3746 else if (GET_MODE (from
) == TImode
)
3747 libfcn
= floattisf_libfunc
;
3751 else if (GET_MODE (to
) == DFmode
)
3753 if (GET_MODE (from
) == SImode
)
3754 libfcn
= floatsidf_libfunc
;
3755 else if (GET_MODE (from
) == DImode
)
3756 libfcn
= floatdidf_libfunc
;
3757 else if (GET_MODE (from
) == TImode
)
3758 libfcn
= floattidf_libfunc
;
3762 else if (GET_MODE (to
) == XFmode
)
3764 if (GET_MODE (from
) == SImode
)
3765 libfcn
= floatsixf_libfunc
;
3766 else if (GET_MODE (from
) == DImode
)
3767 libfcn
= floatdixf_libfunc
;
3768 else if (GET_MODE (from
) == TImode
)
3769 libfcn
= floattixf_libfunc
;
3773 else if (GET_MODE (to
) == TFmode
)
3775 if (GET_MODE (from
) == SImode
)
3776 libfcn
= floatsitf_libfunc
;
3777 else if (GET_MODE (from
) == DImode
)
3778 libfcn
= floatditf_libfunc
;
3779 else if (GET_MODE (from
) == TImode
)
3780 libfcn
= floattitf_libfunc
;
3789 value
= emit_library_call_value (libfcn
, NULL_RTX
, 1,
3791 1, from
, GET_MODE (from
));
3792 insns
= get_insns ();
3795 emit_libcall_block (insns
, target
, value
,
3796 gen_rtx_FLOAT (GET_MODE (to
), from
));
3801 /* Copy result to requested destination
3802 if we have been computing in a temp location. */
3806 if (GET_MODE (target
) == GET_MODE (to
))
3807 emit_move_insn (to
, target
);
3809 convert_move (to
, target
, 0);
3813 /* expand_fix: generate code to convert FROM to fixed point
3814 and store in TO. FROM must be floating point. */
3820 rtx temp
= gen_reg_rtx (GET_MODE (x
));
3821 return expand_unop (GET_MODE (x
), ftrunc_optab
, x
, temp
, 0);
3825 expand_fix (to
, from
, unsignedp
)
3826 register rtx to
, from
;
3829 enum insn_code icode
;
3830 register rtx target
= to
;
3831 enum machine_mode fmode
, imode
;
3835 /* We first try to find a pair of modes, one real and one integer, at
3836 least as wide as FROM and TO, respectively, in which we can open-code
3837 this conversion. If the integer mode is wider than the mode of TO,
3838 we can do the conversion either signed or unsigned. */
3840 for (imode
= GET_MODE (to
); imode
!= VOIDmode
;
3841 imode
= GET_MODE_WIDER_MODE (imode
))
3842 for (fmode
= GET_MODE (from
); fmode
!= VOIDmode
;
3843 fmode
= GET_MODE_WIDER_MODE (fmode
))
3845 int doing_unsigned
= unsignedp
;
3847 icode
= can_fix_p (imode
, fmode
, unsignedp
, &must_trunc
);
3848 if (icode
== CODE_FOR_nothing
&& imode
!= GET_MODE (to
) && unsignedp
)
3849 icode
= can_fix_p (imode
, fmode
, 0, &must_trunc
), doing_unsigned
= 0;
3851 if (icode
!= CODE_FOR_nothing
)
3853 to
= protect_from_queue (to
, 1);
3854 from
= protect_from_queue (from
, 0);
3856 if (fmode
!= GET_MODE (from
))
3857 from
= convert_to_mode (fmode
, from
, 0);
3860 from
= ftruncify (from
);
3862 if (imode
!= GET_MODE (to
))
3863 target
= gen_reg_rtx (imode
);
3865 emit_unop_insn (icode
, target
, from
,
3866 doing_unsigned
? UNSIGNED_FIX
: FIX
);
3868 convert_move (to
, target
, unsignedp
);
3873 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3874 /* For an unsigned conversion, there is one more way to do it.
3875 If we have a signed conversion, we generate code that compares
3876 the real value to the largest representable positive number. If if
3877 is smaller, the conversion is done normally. Otherwise, subtract
3878 one plus the highest signed number, convert, and add it back.
3880 We only need to check all real modes, since we know we didn't find
3881 anything with a wider integer mode. */
3883 if (unsignedp
&& GET_MODE_BITSIZE (GET_MODE (to
)) <= HOST_BITS_PER_WIDE_INT
)
3884 for (fmode
= GET_MODE (from
); fmode
!= VOIDmode
;
3885 fmode
= GET_MODE_WIDER_MODE (fmode
))
3886 /* Make sure we won't lose significant bits doing this. */
3887 if (GET_MODE_BITSIZE (fmode
) > GET_MODE_BITSIZE (GET_MODE (to
))
3888 && CODE_FOR_nothing
!= can_fix_p (GET_MODE (to
), fmode
, 0,
3892 REAL_VALUE_TYPE offset
;
3893 rtx limit
, lab1
, lab2
, insn
;
3895 bitsize
= GET_MODE_BITSIZE (GET_MODE (to
));
3896 offset
= REAL_VALUE_LDEXP (dconst1
, bitsize
- 1);
3897 limit
= CONST_DOUBLE_FROM_REAL_VALUE (offset
, fmode
);
3898 lab1
= gen_label_rtx ();
3899 lab2
= gen_label_rtx ();
3902 to
= protect_from_queue (to
, 1);
3903 from
= protect_from_queue (from
, 0);
3906 from
= force_not_mem (from
);
3908 if (fmode
!= GET_MODE (from
))
3909 from
= convert_to_mode (fmode
, from
, 0);
3911 /* See if we need to do the subtraction. */
3912 do_pending_stack_adjust ();
3913 emit_cmp_and_jump_insns (from
, limit
, GE
, NULL_RTX
, GET_MODE (from
),
3916 /* If not, do the signed "fix" and branch around fixup code. */
3917 expand_fix (to
, from
, 0);
3918 emit_jump_insn (gen_jump (lab2
));
3921 /* Otherwise, subtract 2**(N-1), convert to signed number,
3922 then add 2**(N-1). Do the addition using XOR since this
3923 will often generate better code. */
3925 target
= expand_binop (GET_MODE (from
), sub_optab
, from
, limit
,
3926 NULL_RTX
, 0, OPTAB_LIB_WIDEN
);
3927 expand_fix (to
, target
, 0);
3928 target
= expand_binop (GET_MODE (to
), xor_optab
, to
,
3929 GEN_INT ((HOST_WIDE_INT
) 1 << (bitsize
- 1)),
3930 to
, 1, OPTAB_LIB_WIDEN
);
3933 emit_move_insn (to
, target
);
3937 if (mov_optab
->handlers
[(int) GET_MODE (to
)].insn_code
3938 != CODE_FOR_nothing
)
3940 /* Make a place for a REG_NOTE and add it. */
3941 insn
= emit_move_insn (to
, to
);
3942 set_unique_reg_note (insn
,
3944 gen_rtx_fmt_e (UNSIGNED_FIX
,
3952 /* We can't do it with an insn, so use a library call. But first ensure
3953 that the mode of TO is at least as wide as SImode, since those are the
3954 only library calls we know about. */
3956 if (GET_MODE_SIZE (GET_MODE (to
)) < GET_MODE_SIZE (SImode
))
3958 target
= gen_reg_rtx (SImode
);
3960 expand_fix (target
, from
, unsignedp
);
3962 else if (GET_MODE (from
) == SFmode
)
3964 if (GET_MODE (to
) == SImode
)
3965 libfcn
= unsignedp
? fixunssfsi_libfunc
: fixsfsi_libfunc
;
3966 else if (GET_MODE (to
) == DImode
)
3967 libfcn
= unsignedp
? fixunssfdi_libfunc
: fixsfdi_libfunc
;
3968 else if (GET_MODE (to
) == TImode
)
3969 libfcn
= unsignedp
? fixunssfti_libfunc
: fixsfti_libfunc
;
3973 else if (GET_MODE (from
) == DFmode
)
3975 if (GET_MODE (to
) == SImode
)
3976 libfcn
= unsignedp
? fixunsdfsi_libfunc
: fixdfsi_libfunc
;
3977 else if (GET_MODE (to
) == DImode
)
3978 libfcn
= unsignedp
? fixunsdfdi_libfunc
: fixdfdi_libfunc
;
3979 else if (GET_MODE (to
) == TImode
)
3980 libfcn
= unsignedp
? fixunsdfti_libfunc
: fixdfti_libfunc
;
3984 else if (GET_MODE (from
) == XFmode
)
3986 if (GET_MODE (to
) == SImode
)
3987 libfcn
= unsignedp
? fixunsxfsi_libfunc
: fixxfsi_libfunc
;
3988 else if (GET_MODE (to
) == DImode
)
3989 libfcn
= unsignedp
? fixunsxfdi_libfunc
: fixxfdi_libfunc
;
3990 else if (GET_MODE (to
) == TImode
)
3991 libfcn
= unsignedp
? fixunsxfti_libfunc
: fixxfti_libfunc
;
3995 else if (GET_MODE (from
) == TFmode
)
3997 if (GET_MODE (to
) == SImode
)
3998 libfcn
= unsignedp
? fixunstfsi_libfunc
: fixtfsi_libfunc
;
3999 else if (GET_MODE (to
) == DImode
)
4000 libfcn
= unsignedp
? fixunstfdi_libfunc
: fixtfdi_libfunc
;
4001 else if (GET_MODE (to
) == TImode
)
4002 libfcn
= unsignedp
? fixunstfti_libfunc
: fixtfti_libfunc
;
4014 to
= protect_from_queue (to
, 1);
4015 from
= protect_from_queue (from
, 0);
4018 from
= force_not_mem (from
);
4022 value
= emit_library_call_value (libfcn
, NULL_RTX
, 1, GET_MODE (to
),
4024 1, from
, GET_MODE (from
));
4025 insns
= get_insns ();
4028 emit_libcall_block (insns
, target
, value
,
4029 gen_rtx_fmt_e (unsignedp
? UNSIGNED_FIX
: FIX
,
4030 GET_MODE (to
), from
));
4035 if (GET_MODE (to
) == GET_MODE (target
))
4036 emit_move_insn (to
, target
);
4038 convert_move (to
, target
, 0);
4047 optab op
= (optab
) xmalloc (sizeof (struct optab
));
4049 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
4051 op
->handlers
[i
].insn_code
= CODE_FOR_nothing
;
4052 op
->handlers
[i
].libfunc
= 0;
4055 if (code
!= UNKNOWN
)
4056 code_to_optab
[(int) code
] = op
;
4061 /* Initialize the libfunc fields of an entire group of entries in some
4062 optab. Each entry is set equal to a string consisting of a leading
4063 pair of underscores followed by a generic operation name followed by
4064 a mode name (downshifted to lower case) followed by a single character
4065 representing the number of operands for the given operation (which is
4066 usually one of the characters '2', '3', or '4').
4068 OPTABLE is the table in which libfunc fields are to be initialized.
4069 FIRST_MODE is the first machine mode index in the given optab to
4071 LAST_MODE is the last machine mode index in the given optab to
4073 OPNAME is the generic (string) name of the operation.
4074 SUFFIX is the character which specifies the number of operands for
4075 the given generic operation.
4079 init_libfuncs (optable
, first_mode
, last_mode
, opname
, suffix
)
4080 register optab optable
;
4081 register int first_mode
;
4082 register int last_mode
;
4083 register const char *opname
;
4084 register int suffix
;
4087 register unsigned opname_len
= strlen (opname
);
4089 for (mode
= first_mode
; (int) mode
<= (int) last_mode
;
4090 mode
= (enum machine_mode
) ((int) mode
+ 1))
4092 register char *mname
= mode_name
[(int) mode
];
4093 register unsigned mname_len
= strlen (mname
);
4094 register char *libfunc_name
4095 = (char *) xmalloc (2 + opname_len
+ mname_len
+ 1 + 1);
4097 register const char *q
;
4102 for (q
= opname
; *q
; )
4104 for (q
= mname
; *q
; q
++)
4105 *p
++ = tolower ((unsigned char)*q
);
4108 optable
->handlers
[(int) mode
].libfunc
4109 = gen_rtx_SYMBOL_REF (Pmode
, libfunc_name
);
4113 /* Initialize the libfunc fields of an entire group of entries in some
4114 optab which correspond to all integer mode operations. The parameters
4115 have the same meaning as similarly named ones for the `init_libfuncs'
4116 routine. (See above). */
4119 init_integral_libfuncs (optable
, opname
, suffix
)
4120 register optab optable
;
4121 register const char *opname
;
4122 register int suffix
;
4124 init_libfuncs (optable
, SImode
, TImode
, opname
, suffix
);
4127 /* Initialize the libfunc fields of an entire group of entries in some
4128 optab which correspond to all real mode operations. The parameters
4129 have the same meaning as similarly named ones for the `init_libfuncs'
4130 routine. (See above). */
4133 init_floating_libfuncs (optable
, opname
, suffix
)
4134 register optab optable
;
4135 register const char *opname
;
4136 register int suffix
;
4138 init_libfuncs (optable
, SFmode
, TFmode
, opname
, suffix
);
4142 /* Call this once to initialize the contents of the optabs
4143 appropriately for the current target machine. */
4149 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
4155 /* Start by initializing all tables to contain CODE_FOR_nothing. */
4157 for (p
= fixtab
[0][0];
4158 p
< fixtab
[0][0] + sizeof fixtab
/ sizeof (fixtab
[0][0][0]);
4160 *p
= CODE_FOR_nothing
;
4162 for (p
= fixtrunctab
[0][0];
4163 p
< fixtrunctab
[0][0] + sizeof fixtrunctab
/ sizeof (fixtrunctab
[0][0][0]);
4165 *p
= CODE_FOR_nothing
;
4167 for (p
= floattab
[0][0];
4168 p
< floattab
[0][0] + sizeof floattab
/ sizeof (floattab
[0][0][0]);
4170 *p
= CODE_FOR_nothing
;
4172 for (p
= extendtab
[0][0];
4173 p
< extendtab
[0][0] + sizeof extendtab
/ sizeof extendtab
[0][0][0];
4175 *p
= CODE_FOR_nothing
;
4177 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
4178 setcc_gen_code
[i
] = CODE_FOR_nothing
;
4180 #ifdef HAVE_conditional_move
4181 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
4182 movcc_gen_code
[i
] = CODE_FOR_nothing
;
4185 add_optab
= init_optab (PLUS
);
4186 sub_optab
= init_optab (MINUS
);
4187 smul_optab
= init_optab (MULT
);
4188 smul_highpart_optab
= init_optab (UNKNOWN
);
4189 umul_highpart_optab
= init_optab (UNKNOWN
);
4190 smul_widen_optab
= init_optab (UNKNOWN
);
4191 umul_widen_optab
= init_optab (UNKNOWN
);
4192 sdiv_optab
= init_optab (DIV
);
4193 sdivmod_optab
= init_optab (UNKNOWN
);
4194 udiv_optab
= init_optab (UDIV
);
4195 udivmod_optab
= init_optab (UNKNOWN
);
4196 smod_optab
= init_optab (MOD
);
4197 umod_optab
= init_optab (UMOD
);
4198 flodiv_optab
= init_optab (DIV
);
4199 ftrunc_optab
= init_optab (UNKNOWN
);
4200 and_optab
= init_optab (AND
);
4201 ior_optab
= init_optab (IOR
);
4202 xor_optab
= init_optab (XOR
);
4203 ashl_optab
= init_optab (ASHIFT
);
4204 ashr_optab
= init_optab (ASHIFTRT
);
4205 lshr_optab
= init_optab (LSHIFTRT
);
4206 rotl_optab
= init_optab (ROTATE
);
4207 rotr_optab
= init_optab (ROTATERT
);
4208 smin_optab
= init_optab (SMIN
);
4209 smax_optab
= init_optab (SMAX
);
4210 umin_optab
= init_optab (UMIN
);
4211 umax_optab
= init_optab (UMAX
);
4212 mov_optab
= init_optab (UNKNOWN
);
4213 movstrict_optab
= init_optab (UNKNOWN
);
4214 cmp_optab
= init_optab (UNKNOWN
);
4215 ucmp_optab
= init_optab (UNKNOWN
);
4216 tst_optab
= init_optab (UNKNOWN
);
4217 neg_optab
= init_optab (NEG
);
4218 abs_optab
= init_optab (ABS
);
4219 one_cmpl_optab
= init_optab (NOT
);
4220 ffs_optab
= init_optab (FFS
);
4221 sqrt_optab
= init_optab (SQRT
);
4222 sin_optab
= init_optab (UNKNOWN
);
4223 cos_optab
= init_optab (UNKNOWN
);
4224 strlen_optab
= init_optab (UNKNOWN
);
4226 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
4228 movstr_optab
[i
] = CODE_FOR_nothing
;
4229 clrstr_optab
[i
] = CODE_FOR_nothing
;
4231 #ifdef HAVE_SECONDARY_RELOADS
4232 reload_in_optab
[i
] = reload_out_optab
[i
] = CODE_FOR_nothing
;
4236 /* Fill in the optabs with the insns we support. */
4239 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
4240 /* This flag says the same insns that convert to a signed fixnum
4241 also convert validly to an unsigned one. */
4242 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
4243 for (j
= 0; j
< NUM_MACHINE_MODES
; j
++)
4244 fixtrunctab
[i
][j
][1] = fixtrunctab
[i
][j
][0];
4247 #ifdef EXTRA_CC_MODES
4251 /* Initialize the optabs with the names of the library functions. */
4252 init_integral_libfuncs (add_optab
, "add", '3');
4253 init_floating_libfuncs (add_optab
, "add", '3');
4254 init_integral_libfuncs (sub_optab
, "sub", '3');
4255 init_floating_libfuncs (sub_optab
, "sub", '3');
4256 init_integral_libfuncs (smul_optab
, "mul", '3');
4257 init_floating_libfuncs (smul_optab
, "mul", '3');
4258 init_integral_libfuncs (sdiv_optab
, "div", '3');
4259 init_integral_libfuncs (udiv_optab
, "udiv", '3');
4260 init_integral_libfuncs (sdivmod_optab
, "divmod", '4');
4261 init_integral_libfuncs (udivmod_optab
, "udivmod", '4');
4262 init_integral_libfuncs (smod_optab
, "mod", '3');
4263 init_integral_libfuncs (umod_optab
, "umod", '3');
4264 init_floating_libfuncs (flodiv_optab
, "div", '3');
4265 init_floating_libfuncs (ftrunc_optab
, "ftrunc", '2');
4266 init_integral_libfuncs (and_optab
, "and", '3');
4267 init_integral_libfuncs (ior_optab
, "ior", '3');
4268 init_integral_libfuncs (xor_optab
, "xor", '3');
4269 init_integral_libfuncs (ashl_optab
, "ashl", '3');
4270 init_integral_libfuncs (ashr_optab
, "ashr", '3');
4271 init_integral_libfuncs (lshr_optab
, "lshr", '3');
4272 init_integral_libfuncs (smin_optab
, "min", '3');
4273 init_floating_libfuncs (smin_optab
, "min", '3');
4274 init_integral_libfuncs (smax_optab
, "max", '3');
4275 init_floating_libfuncs (smax_optab
, "max", '3');
4276 init_integral_libfuncs (umin_optab
, "umin", '3');
4277 init_integral_libfuncs (umax_optab
, "umax", '3');
4278 init_integral_libfuncs (neg_optab
, "neg", '2');
4279 init_floating_libfuncs (neg_optab
, "neg", '2');
4280 init_integral_libfuncs (one_cmpl_optab
, "one_cmpl", '2');
4281 init_integral_libfuncs (ffs_optab
, "ffs", '2');
4283 /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
4284 init_integral_libfuncs (cmp_optab
, "cmp", '2');
4285 init_integral_libfuncs (ucmp_optab
, "ucmp", '2');
4286 init_floating_libfuncs (cmp_optab
, "cmp", '2');
4288 #ifdef MULSI3_LIBCALL
4289 smul_optab
->handlers
[(int) SImode
].libfunc
4290 = gen_rtx_SYMBOL_REF (Pmode
, MULSI3_LIBCALL
);
4292 #ifdef MULDI3_LIBCALL
4293 smul_optab
->handlers
[(int) DImode
].libfunc
4294 = gen_rtx_SYMBOL_REF (Pmode
, MULDI3_LIBCALL
);
4297 #ifdef DIVSI3_LIBCALL
4298 sdiv_optab
->handlers
[(int) SImode
].libfunc
4299 = gen_rtx_SYMBOL_REF (Pmode
, DIVSI3_LIBCALL
);
4301 #ifdef DIVDI3_LIBCALL
4302 sdiv_optab
->handlers
[(int) DImode
].libfunc
4303 = gen_rtx_SYMBOL_REF (Pmode
, DIVDI3_LIBCALL
);
4306 #ifdef UDIVSI3_LIBCALL
4307 udiv_optab
->handlers
[(int) SImode
].libfunc
4308 = gen_rtx_SYMBOL_REF (Pmode
, UDIVSI3_LIBCALL
);
4310 #ifdef UDIVDI3_LIBCALL
4311 udiv_optab
->handlers
[(int) DImode
].libfunc
4312 = gen_rtx_SYMBOL_REF (Pmode
, UDIVDI3_LIBCALL
);
4315 #ifdef MODSI3_LIBCALL
4316 smod_optab
->handlers
[(int) SImode
].libfunc
4317 = gen_rtx_SYMBOL_REF (Pmode
, MODSI3_LIBCALL
);
4319 #ifdef MODDI3_LIBCALL
4320 smod_optab
->handlers
[(int) DImode
].libfunc
4321 = gen_rtx_SYMBOL_REF (Pmode
, MODDI3_LIBCALL
);
4324 #ifdef UMODSI3_LIBCALL
4325 umod_optab
->handlers
[(int) SImode
].libfunc
4326 = gen_rtx_SYMBOL_REF (Pmode
, UMODSI3_LIBCALL
);
4328 #ifdef UMODDI3_LIBCALL
4329 umod_optab
->handlers
[(int) DImode
].libfunc
4330 = gen_rtx_SYMBOL_REF (Pmode
, UMODDI3_LIBCALL
);
4333 /* Use cabs for DC complex abs, since systems generally have cabs.
4334 Don't define any libcall for SCmode, so that cabs will be used. */
4335 abs_optab
->handlers
[(int) DCmode
].libfunc
4336 = gen_rtx_SYMBOL_REF (Pmode
, "cabs");
4338 /* The ffs function operates on `int'. */
4339 #ifndef INT_TYPE_SIZE
4340 #define INT_TYPE_SIZE BITS_PER_WORD
4342 ffs_optab
->handlers
[(int) mode_for_size (INT_TYPE_SIZE
, MODE_INT
, 0)] .libfunc
4343 = gen_rtx_SYMBOL_REF (Pmode
, "ffs");
4345 extendsfdf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__extendsfdf2");
4346 extendsfxf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__extendsfxf2");
4347 extendsftf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__extendsftf2");
4348 extenddfxf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__extenddfxf2");
4349 extenddftf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__extenddftf2");
4351 truncdfsf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__truncdfsf2");
4352 truncxfsf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__truncxfsf2");
4353 trunctfsf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__trunctfsf2");
4354 truncxfdf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__truncxfdf2");
4355 trunctfdf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__trunctfdf2");
4357 memcpy_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "memcpy");
4358 bcopy_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "bcopy");
4359 memcmp_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "memcmp");
4360 bcmp_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gcc_bcmp");
4361 memset_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "memset");
4362 bzero_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "bzero");
4364 throw_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__throw");
4365 rethrow_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__rethrow");
4366 sjthrow_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__sjthrow");
4367 sjpopnthrow_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__sjpopnthrow");
4368 terminate_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__terminate");
4369 eh_rtime_match_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__eh_rtime_match");
4370 #ifndef DONT_USE_BUILTIN_SETJMP
4371 setjmp_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__builtin_setjmp");
4372 longjmp_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__builtin_longjmp");
4374 setjmp_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "setjmp");
4375 longjmp_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "longjmp");
4378 eqhf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__eqhf2");
4379 nehf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__nehf2");
4380 gthf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gthf2");
4381 gehf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gehf2");
4382 lthf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__lthf2");
4383 lehf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__lehf2");
4385 eqsf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__eqsf2");
4386 nesf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__nesf2");
4387 gtsf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gtsf2");
4388 gesf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gesf2");
4389 ltsf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__ltsf2");
4390 lesf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__lesf2");
4392 eqdf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__eqdf2");
4393 nedf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__nedf2");
4394 gtdf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gtdf2");
4395 gedf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gedf2");
4396 ltdf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__ltdf2");
4397 ledf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__ledf2");
4399 eqxf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__eqxf2");
4400 nexf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__nexf2");
4401 gtxf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gtxf2");
4402 gexf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gexf2");
4403 ltxf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__ltxf2");
4404 lexf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__lexf2");
4406 eqtf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__eqtf2");
4407 netf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__netf2");
4408 gttf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gttf2");
4409 getf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__getf2");
4410 lttf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__lttf2");
4411 letf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__letf2");
4413 floatsisf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatsisf");
4414 floatdisf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatdisf");
4415 floattisf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floattisf");
4417 floatsidf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatsidf");
4418 floatdidf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatdidf");
4419 floattidf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floattidf");
4421 floatsixf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatsixf");
4422 floatdixf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatdixf");
4423 floattixf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floattixf");
4425 floatsitf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatsitf");
4426 floatditf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatditf");
4427 floattitf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floattitf");
4429 fixsfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixsfsi");
4430 fixsfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixsfdi");
4431 fixsfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixsfti");
4433 fixdfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixdfsi");
4434 fixdfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixdfdi");
4435 fixdfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixdfti");
4437 fixxfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixxfsi");
4438 fixxfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixxfdi");
4439 fixxfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixxfti");
4441 fixtfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixtfsi");
4442 fixtfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixtfdi");
4443 fixtfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixtfti");
4445 fixunssfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunssfsi");
4446 fixunssfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunssfdi");
4447 fixunssfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunssfti");
4449 fixunsdfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunsdfsi");
4450 fixunsdfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunsdfdi");
4451 fixunsdfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunsdfti");
4453 fixunsxfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunsxfsi");
4454 fixunsxfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunsxfdi");
4455 fixunsxfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunsxfti");
4457 fixunstfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunstfsi");
4458 fixunstfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunstfdi");
4459 fixunstfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunstfti");
4461 /* For check-memory-usage. */
4462 chkr_check_addr_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "chkr_check_addr");
4463 chkr_set_right_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "chkr_set_right");
4464 chkr_copy_bitmap_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "chkr_copy_bitmap");
4465 chkr_check_exec_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "chkr_check_exec");
4466 chkr_check_str_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "chkr_check_str");
4468 /* For function entry/exit instrumentation. */
4469 profile_function_entry_libfunc
4470 = gen_rtx_SYMBOL_REF (Pmode
, "__cyg_profile_func_enter");
4471 profile_function_exit_libfunc
4472 = gen_rtx_SYMBOL_REF (Pmode
, "__cyg_profile_func_exit");
4474 #ifdef HAVE_conditional_trap
4478 #ifdef INIT_TARGET_OPTABS
4479 /* Allow the target to add more libcalls or rename some, etc. */
4486 /* SCO 3.2 apparently has a broken ldexp. */
4499 #endif /* BROKEN_LDEXP */
4501 #ifdef HAVE_conditional_trap
4502 /* The insn generating function can not take an rtx_code argument.
4503 TRAP_RTX is used as an rtx argument. Its code is replaced with
4504 the code to be used in the trap insn and all other fields are
4507 ??? Will need to change to support garbage collection. */
4508 static rtx trap_rtx
;
4513 if (HAVE_conditional_trap
)
4514 trap_rtx
= gen_rtx_fmt_ee (EQ
, VOIDmode
, NULL_RTX
, NULL_RTX
);
4518 /* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
4519 CODE. Return 0 on failure. */
4522 gen_cond_trap (code
, op1
, op2
, tcode
)
4523 enum rtx_code code ATTRIBUTE_UNUSED
;
4524 rtx op1
, op2 ATTRIBUTE_UNUSED
, tcode ATTRIBUTE_UNUSED
;
4526 enum machine_mode mode
= GET_MODE (op1
);
4528 if (mode
== VOIDmode
)
4531 #ifdef HAVE_conditional_trap
4532 if (HAVE_conditional_trap
4533 && cmp_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
4536 emit_insn (GEN_FCN (cmp_optab
->handlers
[(int) mode
].insn_code
) (op1
, op2
));
4537 PUT_CODE (trap_rtx
, code
);
4538 insn
= gen_conditional_trap (trap_rtx
, tcode
);