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. */
26 /* Include insn-config.h before expr.h so that HAVE_conditional_move
27 is properly defined. */
28 #include "insn-config.h"
32 #include "insn-flags.h"
33 #include "insn-codes.h"
38 /* Each optab contains info on how this target machine
39 can perform a particular operation
40 for all sizes and kinds of operands.
42 The operation to be performed is often specified
43 by passing one of these optabs as an argument.
45 See expr.h for documentation of these optabs. */
50 optab smul_highpart_optab
;
51 optab umul_highpart_optab
;
52 optab smul_widen_optab
;
53 optab umul_widen_optab
;
76 optab movstrict_optab
;
87 optab ucmp_optab
; /* Used only for libcalls for unsigned comparisons. */
92 /* Tables of patterns for extending one integer mode to another. */
93 enum insn_code extendtab
[MAX_MACHINE_MODE
][MAX_MACHINE_MODE
][2];
95 /* Tables of patterns for converting between fixed and floating point. */
96 enum insn_code fixtab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
97 enum insn_code fixtrunctab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
98 enum insn_code floattab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
100 /* Contains the optab used for each rtx code. */
101 optab code_to_optab
[NUM_RTX_CODE
+ 1];
103 /* SYMBOL_REF rtx's for the library functions that are called
104 implicitly and not via optabs. */
106 rtx extendsfdf2_libfunc
;
107 rtx extendsfxf2_libfunc
;
108 rtx extendsftf2_libfunc
;
109 rtx extenddfxf2_libfunc
;
110 rtx extenddftf2_libfunc
;
112 rtx truncdfsf2_libfunc
;
113 rtx truncxfsf2_libfunc
;
114 rtx trunctfsf2_libfunc
;
115 rtx truncxfdf2_libfunc
;
116 rtx trunctfdf2_libfunc
;
128 rtx sjpopnthrow_libfunc
;
129 rtx terminate_libfunc
;
132 rtx eh_rtime_match_libfunc
;
169 rtx floatsisf_libfunc
;
170 rtx floatdisf_libfunc
;
171 rtx floattisf_libfunc
;
173 rtx floatsidf_libfunc
;
174 rtx floatdidf_libfunc
;
175 rtx floattidf_libfunc
;
177 rtx floatsixf_libfunc
;
178 rtx floatdixf_libfunc
;
179 rtx floattixf_libfunc
;
181 rtx floatsitf_libfunc
;
182 rtx floatditf_libfunc
;
183 rtx floattitf_libfunc
;
201 rtx fixunssfsi_libfunc
;
202 rtx fixunssfdi_libfunc
;
203 rtx fixunssfti_libfunc
;
205 rtx fixunsdfsi_libfunc
;
206 rtx fixunsdfdi_libfunc
;
207 rtx fixunsdfti_libfunc
;
209 rtx fixunsxfsi_libfunc
;
210 rtx fixunsxfdi_libfunc
;
211 rtx fixunsxfti_libfunc
;
213 rtx fixunstfsi_libfunc
;
214 rtx fixunstfdi_libfunc
;
215 rtx fixunstfti_libfunc
;
217 rtx chkr_check_addr_libfunc
;
218 rtx chkr_set_right_libfunc
;
219 rtx chkr_copy_bitmap_libfunc
;
220 rtx chkr_check_exec_libfunc
;
221 rtx chkr_check_str_libfunc
;
223 rtx profile_function_entry_libfunc
;
224 rtx profile_function_exit_libfunc
;
226 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
227 gives the gen_function to make a branch to test that condition. */
229 rtxfun bcc_gen_fctn
[NUM_RTX_CODE
];
231 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
232 gives the insn code to make a store-condition insn
233 to test that condition. */
235 enum insn_code setcc_gen_code
[NUM_RTX_CODE
];
237 #ifdef HAVE_conditional_move
238 /* Indexed by the machine mode, gives the insn code to make a conditional
239 move insn. This is not indexed by the rtx-code like bcc_gen_fctn and
240 setcc_gen_code to cut down on the number of named patterns. Consider a day
241 when a lot more rtx codes are conditional (eg: for the ARM). */
243 enum insn_code movcc_gen_code
[NUM_MACHINE_MODES
];
246 static int add_equal_note
PROTO((rtx
, rtx
, enum rtx_code
, rtx
, rtx
));
247 static rtx widen_operand
PROTO((rtx
, enum machine_mode
,
248 enum machine_mode
, int, int));
249 static int expand_cmplxdiv_straight
PROTO((rtx
, rtx
, rtx
, rtx
,
250 rtx
, rtx
, enum machine_mode
,
251 int, enum optab_methods
,
252 enum mode_class
, optab
));
253 static int expand_cmplxdiv_wide
PROTO((rtx
, rtx
, rtx
, rtx
,
254 rtx
, rtx
, enum machine_mode
,
255 int, enum optab_methods
,
256 enum mode_class
, optab
));
257 static enum insn_code can_fix_p
PROTO((enum machine_mode
, enum machine_mode
,
259 static enum insn_code can_float_p
PROTO((enum machine_mode
, enum machine_mode
,
261 static rtx ftruncify
PROTO((rtx
));
262 static optab init_optab
PROTO((enum rtx_code
));
263 static void init_libfuncs
PROTO((optab
, int, int, const char *, int));
264 static void init_integral_libfuncs
PROTO((optab
, const char *, int));
265 static void init_floating_libfuncs
PROTO((optab
, const char *, int));
266 #ifdef HAVE_conditional_trap
267 static void init_traps
PROTO((void));
270 /* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
271 the result of operation CODE applied to OP0 (and OP1 if it is a binary
274 If the last insn does not set TARGET, don't do anything, but return 1.
276 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
277 don't add the REG_EQUAL note but return 0. Our caller can then try
278 again, ensuring that TARGET is not one of the operands. */
281 add_equal_note (seq
, target
, code
, op0
, op1
)
291 if ((GET_RTX_CLASS (code
) != '1' && GET_RTX_CLASS (code
) != '2'
292 && GET_RTX_CLASS (code
) != 'c' && GET_RTX_CLASS (code
) != '<')
293 || GET_CODE (seq
) != SEQUENCE
294 || (set
= single_set (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1))) == 0
295 || GET_CODE (target
) == ZERO_EXTRACT
296 || (! rtx_equal_p (SET_DEST (set
), target
)
297 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
299 && (GET_CODE (SET_DEST (set
)) != STRICT_LOW_PART
300 || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set
), 0)),
304 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
305 besides the last insn. */
306 if (reg_overlap_mentioned_p (target
, op0
)
307 || (op1
&& reg_overlap_mentioned_p (target
, op1
)))
308 for (i
= XVECLEN (seq
, 0) - 2; i
>= 0; i
--)
309 if (reg_set_p (target
, XVECEXP (seq
, 0, i
)))
312 if (GET_RTX_CLASS (code
) == '1')
313 note
= gen_rtx_fmt_e (code
, GET_MODE (target
), copy_rtx (op0
));
315 note
= gen_rtx_fmt_ee (code
, GET_MODE (target
), copy_rtx (op0
), copy_rtx (op1
));
317 set_unique_reg_note (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1), REG_EQUAL
, note
);
322 /* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP
323 says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need
324 not actually do a sign-extend or zero-extend, but can leave the
325 higher-order bits of the result rtx undefined, for example, in the case
326 of logical operations, but not right shifts. */
329 widen_operand (op
, mode
, oldmode
, unsignedp
, no_extend
)
331 enum machine_mode mode
, oldmode
;
337 /* If we must extend do so. If OP is either a constant or a SUBREG
338 for a promoted object, also extend since it will be more efficient to
341 || GET_MODE (op
) == VOIDmode
342 || (GET_CODE (op
) == SUBREG
&& SUBREG_PROMOTED_VAR_P (op
)))
343 return convert_modes (mode
, oldmode
, op
, unsignedp
);
345 /* If MODE is no wider than a single word, we return a paradoxical
347 if (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
)
348 return gen_rtx_SUBREG (mode
, force_reg (GET_MODE (op
), op
), 0);
350 /* Otherwise, get an object of MODE, clobber it, and set the low-order
353 result
= gen_reg_rtx (mode
);
354 emit_insn (gen_rtx_CLOBBER (VOIDmode
, result
));
355 emit_move_insn (gen_lowpart (GET_MODE (op
), result
), op
);
359 /* Generate code to perform a straightforward complex divide. */
362 expand_cmplxdiv_straight (real0
, real1
, imag0
, imag1
, realr
, imagr
, submode
,
363 unsignedp
, methods
, class, binoptab
)
364 rtx real0
, real1
, imag0
, imag1
, realr
, imagr
;
365 enum machine_mode submode
;
367 enum optab_methods methods
;
368 enum mode_class
class;
376 /* Don't fetch these from memory more than once. */
377 real0
= force_reg (submode
, real0
);
378 real1
= force_reg (submode
, real1
);
381 imag0
= force_reg (submode
, imag0
);
383 imag1
= force_reg (submode
, imag1
);
385 /* Divisor: c*c + d*d. */
386 temp1
= expand_binop (submode
, smul_optab
, real1
, real1
,
387 NULL_RTX
, unsignedp
, methods
);
389 temp2
= expand_binop (submode
, smul_optab
, imag1
, imag1
,
390 NULL_RTX
, unsignedp
, methods
);
392 if (temp1
== 0 || temp2
== 0)
395 divisor
= expand_binop (submode
, add_optab
, temp1
, temp2
,
396 NULL_RTX
, unsignedp
, methods
);
402 /* Mathematically, ((a)(c-id))/divisor. */
403 /* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)). */
405 /* Calculate the dividend. */
406 real_t
= expand_binop (submode
, smul_optab
, real0
, real1
,
407 NULL_RTX
, unsignedp
, methods
);
409 imag_t
= expand_binop (submode
, smul_optab
, real0
, imag1
,
410 NULL_RTX
, unsignedp
, methods
);
412 if (real_t
== 0 || imag_t
== 0)
415 imag_t
= expand_unop (submode
, neg_optab
, imag_t
,
416 NULL_RTX
, unsignedp
);
420 /* Mathematically, ((a+ib)(c-id))/divider. */
421 /* Calculate the dividend. */
422 temp1
= expand_binop (submode
, smul_optab
, real0
, real1
,
423 NULL_RTX
, unsignedp
, methods
);
425 temp2
= expand_binop (submode
, smul_optab
, imag0
, imag1
,
426 NULL_RTX
, unsignedp
, methods
);
428 if (temp1
== 0 || temp2
== 0)
431 real_t
= expand_binop (submode
, add_optab
, temp1
, temp2
,
432 NULL_RTX
, unsignedp
, methods
);
434 temp1
= expand_binop (submode
, smul_optab
, imag0
, real1
,
435 NULL_RTX
, unsignedp
, methods
);
437 temp2
= expand_binop (submode
, smul_optab
, real0
, imag1
,
438 NULL_RTX
, unsignedp
, methods
);
440 if (temp1
== 0 || temp2
== 0)
443 imag_t
= expand_binop (submode
, sub_optab
, temp1
, temp2
,
444 NULL_RTX
, unsignedp
, methods
);
446 if (real_t
== 0 || imag_t
== 0)
450 if (class == MODE_COMPLEX_FLOAT
)
451 res
= expand_binop (submode
, binoptab
, real_t
, divisor
,
452 realr
, unsignedp
, methods
);
454 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
455 real_t
, divisor
, realr
, unsignedp
);
461 emit_move_insn (realr
, res
);
463 if (class == MODE_COMPLEX_FLOAT
)
464 res
= expand_binop (submode
, binoptab
, imag_t
, divisor
,
465 imagr
, unsignedp
, methods
);
467 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
468 imag_t
, divisor
, imagr
, unsignedp
);
474 emit_move_insn (imagr
, res
);
479 /* Generate code to perform a wide-input-range-acceptable complex divide. */
482 expand_cmplxdiv_wide (real0
, real1
, imag0
, imag1
, realr
, imagr
, submode
,
483 unsignedp
, methods
, class, binoptab
)
484 rtx real0
, real1
, imag0
, imag1
, realr
, imagr
;
485 enum machine_mode submode
;
487 enum optab_methods methods
;
488 enum mode_class
class;
493 rtx temp1
, temp2
, lab1
, lab2
;
494 enum machine_mode mode
;
498 /* Don't fetch these from memory more than once. */
499 real0
= force_reg (submode
, real0
);
500 real1
= force_reg (submode
, real1
);
503 imag0
= force_reg (submode
, imag0
);
505 imag1
= force_reg (submode
, imag1
);
507 /* XXX What's an "unsigned" complex number? */
515 temp1
= expand_abs (submode
, real1
, NULL_RTX
, 1);
516 temp2
= expand_abs (submode
, imag1
, NULL_RTX
, 1);
519 if (temp1
== 0 || temp2
== 0)
522 mode
= GET_MODE (temp1
);
523 align
= GET_MODE_ALIGNMENT (mode
);
524 lab1
= gen_label_rtx ();
525 emit_cmp_and_jump_insns (temp1
, temp2
, LT
, NULL_RTX
,
526 mode
, unsignedp
, align
, lab1
);
528 /* |c| >= |d|; use ratio d/c to scale dividend and divisor. */
530 if (class == MODE_COMPLEX_FLOAT
)
531 ratio
= expand_binop (submode
, binoptab
, imag1
, real1
,
532 NULL_RTX
, unsignedp
, methods
);
534 ratio
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
535 imag1
, real1
, NULL_RTX
, unsignedp
);
540 /* Calculate divisor. */
542 temp1
= expand_binop (submode
, smul_optab
, imag1
, ratio
,
543 NULL_RTX
, unsignedp
, methods
);
548 divisor
= expand_binop (submode
, add_optab
, temp1
, real1
,
549 NULL_RTX
, unsignedp
, methods
);
554 /* Calculate dividend. */
560 /* Compute a / (c+id) as a / (c+d(d/c)) + i (-a(d/c)) / (c+d(d/c)). */
562 imag_t
= expand_binop (submode
, smul_optab
, real0
, ratio
,
563 NULL_RTX
, unsignedp
, methods
);
568 imag_t
= expand_unop (submode
, neg_optab
, imag_t
,
569 NULL_RTX
, unsignedp
);
571 if (real_t
== 0 || imag_t
== 0)
576 /* Compute (a+ib)/(c+id) as
577 (a+b(d/c))/(c+d(d/c) + i(b-a(d/c))/(c+d(d/c)). */
579 temp1
= expand_binop (submode
, smul_optab
, imag0
, ratio
,
580 NULL_RTX
, unsignedp
, methods
);
585 real_t
= expand_binop (submode
, add_optab
, temp1
, real0
,
586 NULL_RTX
, unsignedp
, methods
);
588 temp1
= expand_binop (submode
, smul_optab
, real0
, ratio
,
589 NULL_RTX
, unsignedp
, methods
);
594 imag_t
= expand_binop (submode
, sub_optab
, imag0
, temp1
,
595 NULL_RTX
, unsignedp
, methods
);
597 if (real_t
== 0 || imag_t
== 0)
601 if (class == MODE_COMPLEX_FLOAT
)
602 res
= expand_binop (submode
, binoptab
, real_t
, divisor
,
603 realr
, unsignedp
, methods
);
605 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
606 real_t
, divisor
, realr
, unsignedp
);
612 emit_move_insn (realr
, res
);
614 if (class == MODE_COMPLEX_FLOAT
)
615 res
= expand_binop (submode
, binoptab
, imag_t
, divisor
,
616 imagr
, unsignedp
, methods
);
618 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
619 imag_t
, divisor
, imagr
, unsignedp
);
625 emit_move_insn (imagr
, res
);
627 lab2
= gen_label_rtx ();
628 emit_jump_insn (gen_jump (lab2
));
633 /* |d| > |c|; use ratio c/d to scale dividend and divisor. */
635 if (class == MODE_COMPLEX_FLOAT
)
636 ratio
= expand_binop (submode
, binoptab
, real1
, imag1
,
637 NULL_RTX
, unsignedp
, methods
);
639 ratio
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
640 real1
, imag1
, NULL_RTX
, unsignedp
);
645 /* Calculate divisor. */
647 temp1
= expand_binop (submode
, smul_optab
, real1
, ratio
,
648 NULL_RTX
, unsignedp
, methods
);
653 divisor
= expand_binop (submode
, add_optab
, temp1
, imag1
,
654 NULL_RTX
, unsignedp
, methods
);
659 /* Calculate dividend. */
663 /* Compute a / (c+id) as a(c/d) / (c(c/d)+d) + i (-a) / (c(c/d)+d). */
665 real_t
= expand_binop (submode
, smul_optab
, real0
, ratio
,
666 NULL_RTX
, unsignedp
, methods
);
668 imag_t
= expand_unop (submode
, neg_optab
, real0
,
669 NULL_RTX
, unsignedp
);
671 if (real_t
== 0 || imag_t
== 0)
676 /* Compute (a+ib)/(c+id) as
677 (a(c/d)+b)/(c(c/d)+d) + i (b(c/d)-a)/(c(c/d)+d). */
679 temp1
= expand_binop (submode
, smul_optab
, real0
, ratio
,
680 NULL_RTX
, unsignedp
, methods
);
685 real_t
= expand_binop (submode
, add_optab
, temp1
, imag0
,
686 NULL_RTX
, unsignedp
, methods
);
688 temp1
= expand_binop (submode
, smul_optab
, imag0
, ratio
,
689 NULL_RTX
, unsignedp
, methods
);
694 imag_t
= expand_binop (submode
, sub_optab
, temp1
, real0
,
695 NULL_RTX
, unsignedp
, methods
);
697 if (real_t
== 0 || imag_t
== 0)
701 if (class == MODE_COMPLEX_FLOAT
)
702 res
= expand_binop (submode
, binoptab
, real_t
, divisor
,
703 realr
, unsignedp
, methods
);
705 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
706 real_t
, divisor
, realr
, unsignedp
);
712 emit_move_insn (realr
, res
);
714 if (class == MODE_COMPLEX_FLOAT
)
715 res
= expand_binop (submode
, binoptab
, imag_t
, divisor
,
716 imagr
, unsignedp
, methods
);
718 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
719 imag_t
, divisor
, imagr
, unsignedp
);
725 emit_move_insn (imagr
, res
);
732 /* Generate code to perform an operation specified by BINOPTAB
733 on operands OP0 and OP1, with result having machine-mode MODE.
735 UNSIGNEDP is for the case where we have to widen the operands
736 to perform the operation. It says to use zero-extension.
738 If TARGET is nonzero, the value
739 is generated there, if it is convenient to do so.
740 In all cases an rtx is returned for the locus of the value;
741 this may or may not be TARGET. */
744 expand_binop (mode
, binoptab
, op0
, op1
, target
, unsignedp
, methods
)
745 enum machine_mode mode
;
750 enum optab_methods methods
;
752 enum optab_methods next_methods
753 = (methods
== OPTAB_LIB
|| methods
== OPTAB_LIB_WIDEN
754 ? OPTAB_WIDEN
: methods
);
755 enum mode_class
class;
756 enum machine_mode wider_mode
;
758 int commutative_op
= 0;
759 int shift_op
= (binoptab
->code
== ASHIFT
760 || binoptab
->code
== ASHIFTRT
761 || binoptab
->code
== LSHIFTRT
762 || binoptab
->code
== ROTATE
763 || binoptab
->code
== ROTATERT
);
764 rtx entry_last
= get_last_insn ();
767 class = GET_MODE_CLASS (mode
);
769 op0
= protect_from_queue (op0
, 0);
770 op1
= protect_from_queue (op1
, 0);
772 target
= protect_from_queue (target
, 1);
776 op0
= force_not_mem (op0
);
777 op1
= force_not_mem (op1
);
780 /* If subtracting an integer constant, convert this into an addition of
781 the negated constant. */
783 if (binoptab
== sub_optab
&& GET_CODE (op1
) == CONST_INT
)
785 op1
= negate_rtx (mode
, op1
);
786 binoptab
= add_optab
;
789 /* If we are inside an appropriately-short loop and one operand is an
790 expensive constant, force it into a register. */
791 if (CONSTANT_P (op0
) && preserve_subexpressions_p ()
792 && rtx_cost (op0
, binoptab
->code
) > 2)
793 op0
= force_reg (mode
, op0
);
795 if (CONSTANT_P (op1
) && preserve_subexpressions_p ()
796 && ! shift_op
&& rtx_cost (op1
, binoptab
->code
) > 2)
797 op1
= force_reg (mode
, op1
);
799 /* Record where to delete back to if we backtrack. */
800 last
= get_last_insn ();
802 /* If operation is commutative,
803 try to make the first operand a register.
804 Even better, try to make it the same as the target.
805 Also try to make the last operand a constant. */
806 if (GET_RTX_CLASS (binoptab
->code
) == 'c'
807 || binoptab
== smul_widen_optab
808 || binoptab
== umul_widen_optab
809 || binoptab
== smul_highpart_optab
810 || binoptab
== umul_highpart_optab
)
814 if (((target
== 0 || GET_CODE (target
) == REG
)
815 ? ((GET_CODE (op1
) == REG
816 && GET_CODE (op0
) != REG
)
818 : rtx_equal_p (op1
, target
))
819 || GET_CODE (op0
) == CONST_INT
)
827 /* If we can do it with a three-operand insn, do so. */
829 if (methods
!= OPTAB_MUST_WIDEN
830 && binoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
832 int icode
= (int) binoptab
->handlers
[(int) mode
].insn_code
;
833 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
834 enum machine_mode mode1
= insn_operand_mode
[icode
][2];
836 rtx xop0
= op0
, xop1
= op1
;
841 temp
= gen_reg_rtx (mode
);
843 /* If it is a commutative operator and the modes would match
844 if we would swap the operands, we can save the conversions. */
847 if (GET_MODE (op0
) != mode0
&& GET_MODE (op1
) != mode1
848 && GET_MODE (op0
) == mode1
&& GET_MODE (op1
) == mode0
)
852 tmp
= op0
; op0
= op1
; op1
= tmp
;
853 tmp
= xop0
; xop0
= xop1
; xop1
= tmp
;
857 /* In case the insn wants input operands in modes different from
858 the result, convert the operands. */
860 if (GET_MODE (op0
) != VOIDmode
861 && GET_MODE (op0
) != mode0
862 && mode0
!= VOIDmode
)
863 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
865 if (GET_MODE (xop1
) != VOIDmode
866 && GET_MODE (xop1
) != mode1
867 && mode1
!= VOIDmode
)
868 xop1
= convert_to_mode (mode1
, xop1
, unsignedp
);
870 /* Now, if insn's predicates don't allow our operands, put them into
873 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
)
874 && mode0
!= VOIDmode
)
875 xop0
= copy_to_mode_reg (mode0
, xop0
);
877 if (! (*insn_operand_predicate
[icode
][2]) (xop1
, mode1
)
878 && mode1
!= VOIDmode
)
879 xop1
= copy_to_mode_reg (mode1
, xop1
);
881 if (! (*insn_operand_predicate
[icode
][0]) (temp
, mode
))
882 temp
= gen_reg_rtx (mode
);
884 pat
= GEN_FCN (icode
) (temp
, xop0
, xop1
);
887 /* If PAT is a multi-insn sequence, try to add an appropriate
888 REG_EQUAL note to it. If we can't because TEMP conflicts with an
889 operand, call ourselves again, this time without a target. */
890 if (GET_CODE (pat
) == SEQUENCE
891 && ! add_equal_note (pat
, temp
, binoptab
->code
, xop0
, xop1
))
893 delete_insns_since (last
);
894 return expand_binop (mode
, binoptab
, op0
, op1
, NULL_RTX
,
902 delete_insns_since (last
);
905 /* If this is a multiply, see if we can do a widening operation that
906 takes operands of this mode and makes a wider mode. */
908 if (binoptab
== smul_optab
&& GET_MODE_WIDER_MODE (mode
) != VOIDmode
909 && (((unsignedp
? umul_widen_optab
: smul_widen_optab
)
910 ->handlers
[(int) GET_MODE_WIDER_MODE (mode
)].insn_code
)
911 != CODE_FOR_nothing
))
913 temp
= expand_binop (GET_MODE_WIDER_MODE (mode
),
914 unsignedp
? umul_widen_optab
: smul_widen_optab
,
915 op0
, op1
, NULL_RTX
, unsignedp
, OPTAB_DIRECT
);
919 if (GET_MODE_CLASS (mode
) == MODE_INT
)
920 return gen_lowpart (mode
, temp
);
922 return convert_to_mode (mode
, temp
, unsignedp
);
926 /* Look for a wider mode of the same class for which we think we
927 can open-code the operation. Check for a widening multiply at the
928 wider mode as well. */
930 if ((class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
931 && methods
!= OPTAB_DIRECT
&& methods
!= OPTAB_LIB
)
932 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
933 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
935 if (binoptab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
936 || (binoptab
== smul_optab
937 && GET_MODE_WIDER_MODE (wider_mode
) != VOIDmode
938 && (((unsignedp
? umul_widen_optab
: smul_widen_optab
)
939 ->handlers
[(int) GET_MODE_WIDER_MODE (wider_mode
)].insn_code
)
940 != CODE_FOR_nothing
)))
942 rtx xop0
= op0
, xop1
= op1
;
945 /* For certain integer operations, we need not actually extend
946 the narrow operands, as long as we will truncate
947 the results to the same narrowness. */
949 if ((binoptab
== ior_optab
|| binoptab
== and_optab
950 || binoptab
== xor_optab
951 || binoptab
== add_optab
|| binoptab
== sub_optab
952 || binoptab
== smul_optab
|| binoptab
== ashl_optab
)
953 && class == MODE_INT
)
956 xop0
= widen_operand (xop0
, wider_mode
, mode
, unsignedp
, no_extend
);
958 /* The second operand of a shift must always be extended. */
959 xop1
= widen_operand (xop1
, wider_mode
, mode
, unsignedp
,
960 no_extend
&& binoptab
!= ashl_optab
);
962 temp
= expand_binop (wider_mode
, binoptab
, xop0
, xop1
, NULL_RTX
,
963 unsignedp
, OPTAB_DIRECT
);
966 if (class != MODE_INT
)
969 target
= gen_reg_rtx (mode
);
970 convert_move (target
, temp
, 0);
974 return gen_lowpart (mode
, temp
);
977 delete_insns_since (last
);
981 /* These can be done a word at a time. */
982 if ((binoptab
== and_optab
|| binoptab
== ior_optab
|| binoptab
== xor_optab
)
984 && GET_MODE_SIZE (mode
) > UNITS_PER_WORD
985 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
991 /* If TARGET is the same as one of the operands, the REG_EQUAL note
992 won't be accurate, so use a new target. */
993 if (target
== 0 || target
== op0
|| target
== op1
)
994 target
= gen_reg_rtx (mode
);
998 /* Do the actual arithmetic. */
999 for (i
= 0; i
< GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
; i
++)
1001 rtx target_piece
= operand_subword (target
, i
, 1, mode
);
1002 rtx x
= expand_binop (word_mode
, binoptab
,
1003 operand_subword_force (op0
, i
, mode
),
1004 operand_subword_force (op1
, i
, mode
),
1005 target_piece
, unsignedp
, next_methods
);
1010 if (target_piece
!= x
)
1011 emit_move_insn (target_piece
, x
);
1014 insns
= get_insns ();
1017 if (i
== GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
)
1019 if (binoptab
->code
!= UNKNOWN
)
1021 = gen_rtx_fmt_ee (binoptab
->code
, mode
,
1022 copy_rtx (op0
), copy_rtx (op1
));
1026 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv_value
);
1031 /* Synthesize double word shifts from single word shifts. */
1032 if ((binoptab
== lshr_optab
|| binoptab
== ashl_optab
1033 || binoptab
== ashr_optab
)
1034 && class == MODE_INT
1035 && GET_CODE (op1
) == CONST_INT
1036 && GET_MODE_SIZE (mode
) == 2 * UNITS_PER_WORD
1037 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
1038 && ashl_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
1039 && lshr_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
1041 rtx insns
, inter
, equiv_value
;
1042 rtx into_target
, outof_target
;
1043 rtx into_input
, outof_input
;
1044 int shift_count
, left_shift
, outof_word
;
1046 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1047 won't be accurate, so use a new target. */
1048 if (target
== 0 || target
== op0
|| target
== op1
)
1049 target
= gen_reg_rtx (mode
);
1053 shift_count
= INTVAL (op1
);
1055 /* OUTOF_* is the word we are shifting bits away from, and
1056 INTO_* is the word that we are shifting bits towards, thus
1057 they differ depending on the direction of the shift and
1058 WORDS_BIG_ENDIAN. */
1060 left_shift
= binoptab
== ashl_optab
;
1061 outof_word
= left_shift
^ ! WORDS_BIG_ENDIAN
;
1063 outof_target
= operand_subword (target
, outof_word
, 1, mode
);
1064 into_target
= operand_subword (target
, 1 - outof_word
, 1, mode
);
1066 outof_input
= operand_subword_force (op0
, outof_word
, mode
);
1067 into_input
= operand_subword_force (op0
, 1 - outof_word
, mode
);
1069 if (shift_count
>= BITS_PER_WORD
)
1071 inter
= expand_binop (word_mode
, binoptab
,
1073 GEN_INT (shift_count
- BITS_PER_WORD
),
1074 into_target
, unsignedp
, next_methods
);
1076 if (inter
!= 0 && inter
!= into_target
)
1077 emit_move_insn (into_target
, inter
);
1079 /* For a signed right shift, we must fill the word we are shifting
1080 out of with copies of the sign bit. Otherwise it is zeroed. */
1081 if (inter
!= 0 && binoptab
!= ashr_optab
)
1082 inter
= CONST0_RTX (word_mode
);
1083 else if (inter
!= 0)
1084 inter
= expand_binop (word_mode
, binoptab
,
1086 GEN_INT (BITS_PER_WORD
- 1),
1087 outof_target
, unsignedp
, next_methods
);
1089 if (inter
!= 0 && inter
!= outof_target
)
1090 emit_move_insn (outof_target
, inter
);
1095 optab reverse_unsigned_shift
, unsigned_shift
;
1097 /* For a shift of less then BITS_PER_WORD, to compute the carry,
1098 we must do a logical shift in the opposite direction of the
1101 reverse_unsigned_shift
= (left_shift
? lshr_optab
: ashl_optab
);
1103 /* For a shift of less than BITS_PER_WORD, to compute the word
1104 shifted towards, we need to unsigned shift the orig value of
1107 unsigned_shift
= (left_shift
? ashl_optab
: lshr_optab
);
1109 carries
= expand_binop (word_mode
, reverse_unsigned_shift
,
1111 GEN_INT (BITS_PER_WORD
- shift_count
),
1112 0, unsignedp
, next_methods
);
1117 inter
= expand_binop (word_mode
, unsigned_shift
, into_input
,
1118 op1
, 0, unsignedp
, next_methods
);
1121 inter
= expand_binop (word_mode
, ior_optab
, carries
, inter
,
1122 into_target
, unsignedp
, next_methods
);
1124 if (inter
!= 0 && inter
!= into_target
)
1125 emit_move_insn (into_target
, inter
);
1128 inter
= expand_binop (word_mode
, binoptab
, outof_input
,
1129 op1
, outof_target
, unsignedp
, next_methods
);
1131 if (inter
!= 0 && inter
!= outof_target
)
1132 emit_move_insn (outof_target
, inter
);
1135 insns
= get_insns ();
1140 if (binoptab
->code
!= UNKNOWN
)
1141 equiv_value
= gen_rtx_fmt_ee (binoptab
->code
, mode
, op0
, op1
);
1145 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv_value
);
1150 /* Synthesize double word rotates from single word shifts. */
1151 if ((binoptab
== rotl_optab
|| binoptab
== rotr_optab
)
1152 && class == MODE_INT
1153 && GET_CODE (op1
) == CONST_INT
1154 && GET_MODE_SIZE (mode
) == 2 * UNITS_PER_WORD
1155 && ashl_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
1156 && lshr_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
1158 rtx insns
, equiv_value
;
1159 rtx into_target
, outof_target
;
1160 rtx into_input
, outof_input
;
1162 int shift_count
, left_shift
, outof_word
;
1164 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1165 won't be accurate, so use a new target. */
1166 if (target
== 0 || target
== op0
|| target
== op1
)
1167 target
= gen_reg_rtx (mode
);
1171 shift_count
= INTVAL (op1
);
1173 /* OUTOF_* is the word we are shifting bits away from, and
1174 INTO_* is the word that we are shifting bits towards, thus
1175 they differ depending on the direction of the shift and
1176 WORDS_BIG_ENDIAN. */
1178 left_shift
= (binoptab
== rotl_optab
);
1179 outof_word
= left_shift
^ ! WORDS_BIG_ENDIAN
;
1181 outof_target
= operand_subword (target
, outof_word
, 1, mode
);
1182 into_target
= operand_subword (target
, 1 - outof_word
, 1, mode
);
1184 outof_input
= operand_subword_force (op0
, outof_word
, mode
);
1185 into_input
= operand_subword_force (op0
, 1 - outof_word
, mode
);
1187 if (shift_count
== BITS_PER_WORD
)
1189 /* This is just a word swap. */
1190 emit_move_insn (outof_target
, into_input
);
1191 emit_move_insn (into_target
, outof_input
);
1196 rtx into_temp1
, into_temp2
, outof_temp1
, outof_temp2
;
1197 rtx first_shift_count
, second_shift_count
;
1198 optab reverse_unsigned_shift
, unsigned_shift
;
1200 reverse_unsigned_shift
= (left_shift
^ (shift_count
< BITS_PER_WORD
)
1201 ? lshr_optab
: ashl_optab
);
1203 unsigned_shift
= (left_shift
^ (shift_count
< BITS_PER_WORD
)
1204 ? ashl_optab
: lshr_optab
);
1206 if (shift_count
> BITS_PER_WORD
)
1208 first_shift_count
= GEN_INT (shift_count
- BITS_PER_WORD
);
1209 second_shift_count
= GEN_INT (2*BITS_PER_WORD
- shift_count
);
1213 first_shift_count
= GEN_INT (BITS_PER_WORD
- shift_count
);
1214 second_shift_count
= GEN_INT (shift_count
);
1217 into_temp1
= expand_binop (word_mode
, unsigned_shift
,
1218 outof_input
, first_shift_count
,
1219 NULL_RTX
, unsignedp
, next_methods
);
1220 into_temp2
= expand_binop (word_mode
, reverse_unsigned_shift
,
1221 into_input
, second_shift_count
,
1222 into_target
, unsignedp
, next_methods
);
1224 if (into_temp1
!= 0 && into_temp2
!= 0)
1225 inter
= expand_binop (word_mode
, ior_optab
, into_temp1
, into_temp2
,
1226 into_target
, unsignedp
, next_methods
);
1230 if (inter
!= 0 && inter
!= into_target
)
1231 emit_move_insn (into_target
, inter
);
1233 outof_temp1
= expand_binop (word_mode
, unsigned_shift
,
1234 into_input
, first_shift_count
,
1235 NULL_RTX
, unsignedp
, next_methods
);
1236 outof_temp2
= expand_binop (word_mode
, reverse_unsigned_shift
,
1237 outof_input
, second_shift_count
,
1238 outof_target
, unsignedp
, next_methods
);
1240 if (inter
!= 0 && outof_temp1
!= 0 && outof_temp2
!= 0)
1241 inter
= expand_binop (word_mode
, ior_optab
,
1242 outof_temp1
, outof_temp2
,
1243 outof_target
, unsignedp
, next_methods
);
1245 if (inter
!= 0 && inter
!= outof_target
)
1246 emit_move_insn (outof_target
, inter
);
1249 insns
= get_insns ();
1254 if (binoptab
->code
!= UNKNOWN
)
1255 equiv_value
= gen_rtx_fmt_ee (binoptab
->code
, mode
, op0
, op1
);
1259 /* We can't make this a no conflict block if this is a word swap,
1260 because the word swap case fails if the input and output values
1261 are in the same register. */
1262 if (shift_count
!= BITS_PER_WORD
)
1263 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv_value
);
1272 /* These can be done a word at a time by propagating carries. */
1273 if ((binoptab
== add_optab
|| binoptab
== sub_optab
)
1274 && class == MODE_INT
1275 && GET_MODE_SIZE (mode
) >= 2 * UNITS_PER_WORD
1276 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
1279 rtx carry_tmp
= gen_reg_rtx (word_mode
);
1280 optab otheroptab
= binoptab
== add_optab
? sub_optab
: add_optab
;
1281 int nwords
= GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
;
1282 rtx carry_in
= NULL_RTX
, carry_out
= NULL_RTX
;
1285 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
1286 value is one of those, use it. Otherwise, use 1 since it is the
1287 one easiest to get. */
1288 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
1289 int normalizep
= STORE_FLAG_VALUE
;
1294 /* Prepare the operands. */
1295 xop0
= force_reg (mode
, op0
);
1296 xop1
= force_reg (mode
, op1
);
1298 if (target
== 0 || GET_CODE (target
) != REG
1299 || target
== xop0
|| target
== xop1
)
1300 target
= gen_reg_rtx (mode
);
1302 /* Indicate for flow that the entire target reg is being set. */
1303 if (GET_CODE (target
) == REG
)
1304 emit_insn (gen_rtx_CLOBBER (VOIDmode
, target
));
1306 /* Do the actual arithmetic. */
1307 for (i
= 0; i
< nwords
; i
++)
1309 int index
= (WORDS_BIG_ENDIAN
? nwords
- i
- 1 : i
);
1310 rtx target_piece
= operand_subword (target
, index
, 1, mode
);
1311 rtx op0_piece
= operand_subword_force (xop0
, index
, mode
);
1312 rtx op1_piece
= operand_subword_force (xop1
, index
, mode
);
1315 /* Main add/subtract of the input operands. */
1316 x
= expand_binop (word_mode
, binoptab
,
1317 op0_piece
, op1_piece
,
1318 target_piece
, unsignedp
, next_methods
);
1324 /* Store carry from main add/subtract. */
1325 carry_out
= gen_reg_rtx (word_mode
);
1326 carry_out
= emit_store_flag_force (carry_out
,
1327 (binoptab
== add_optab
1330 word_mode
, 1, normalizep
);
1335 /* Add/subtract previous carry to main result. */
1336 x
= expand_binop (word_mode
,
1337 normalizep
== 1 ? binoptab
: otheroptab
,
1339 target_piece
, 1, next_methods
);
1342 else if (target_piece
!= x
)
1343 emit_move_insn (target_piece
, x
);
1347 /* THIS CODE HAS NOT BEEN TESTED. */
1348 /* Get out carry from adding/subtracting carry in. */
1349 carry_tmp
= emit_store_flag_force (carry_tmp
,
1350 binoptab
== add_optab
1353 word_mode
, 1, normalizep
);
1355 /* Logical-ior the two poss. carry together. */
1356 carry_out
= expand_binop (word_mode
, ior_optab
,
1357 carry_out
, carry_tmp
,
1358 carry_out
, 0, next_methods
);
1364 carry_in
= carry_out
;
1367 if (i
== GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
)
1369 if (mov_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1371 rtx temp
= emit_move_insn (target
, target
);
1373 set_unique_reg_note (temp
,
1375 gen_rtx_fmt_ee (binoptab
->code
, mode
,
1382 delete_insns_since (last
);
1385 /* If we want to multiply two two-word values and have normal and widening
1386 multiplies of single-word values, we can do this with three smaller
1387 multiplications. Note that we do not make a REG_NO_CONFLICT block here
1388 because we are not operating on one word at a time.
1390 The multiplication proceeds as follows:
1391 _______________________
1392 [__op0_high_|__op0_low__]
1393 _______________________
1394 * [__op1_high_|__op1_low__]
1395 _______________________________________________
1396 _______________________
1397 (1) [__op0_low__*__op1_low__]
1398 _______________________
1399 (2a) [__op0_low__*__op1_high_]
1400 _______________________
1401 (2b) [__op0_high_*__op1_low__]
1402 _______________________
1403 (3) [__op0_high_*__op1_high_]
1406 This gives a 4-word result. Since we are only interested in the
1407 lower 2 words, partial result (3) and the upper words of (2a) and
1408 (2b) don't need to be calculated. Hence (2a) and (2b) can be
1409 calculated using non-widening multiplication.
1411 (1), however, needs to be calculated with an unsigned widening
1412 multiplication. If this operation is not directly supported we
1413 try using a signed widening multiplication and adjust the result.
1414 This adjustment works as follows:
1416 If both operands are positive then no adjustment is needed.
1418 If the operands have different signs, for example op0_low < 0 and
1419 op1_low >= 0, the instruction treats the most significant bit of
1420 op0_low as a sign bit instead of a bit with significance
1421 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
1422 with 2**BITS_PER_WORD - op0_low, and two's complements the
1423 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
1426 Similarly, if both operands are negative, we need to add
1427 (op0_low + op1_low) * 2**BITS_PER_WORD.
1429 We use a trick to adjust quickly. We logically shift op0_low right
1430 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
1431 op0_high (op1_high) before it is used to calculate 2b (2a). If no
1432 logical shift exists, we do an arithmetic right shift and subtract
1435 if (binoptab
== smul_optab
1436 && class == MODE_INT
1437 && GET_MODE_SIZE (mode
) == 2 * UNITS_PER_WORD
1438 && smul_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
1439 && add_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
1440 && ((umul_widen_optab
->handlers
[(int) mode
].insn_code
1441 != CODE_FOR_nothing
)
1442 || (smul_widen_optab
->handlers
[(int) mode
].insn_code
1443 != CODE_FOR_nothing
)))
1445 int low
= (WORDS_BIG_ENDIAN
? 1 : 0);
1446 int high
= (WORDS_BIG_ENDIAN
? 0 : 1);
1447 rtx op0_high
= operand_subword_force (op0
, high
, mode
);
1448 rtx op0_low
= operand_subword_force (op0
, low
, mode
);
1449 rtx op1_high
= operand_subword_force (op1
, high
, mode
);
1450 rtx op1_low
= operand_subword_force (op1
, low
, mode
);
1452 rtx op0_xhigh
= NULL_RTX
;
1453 rtx op1_xhigh
= NULL_RTX
;
1455 /* If the target is the same as one of the inputs, don't use it. This
1456 prevents problems with the REG_EQUAL note. */
1457 if (target
== op0
|| target
== op1
1458 || (target
!= 0 && GET_CODE (target
) != REG
))
1461 /* Multiply the two lower words to get a double-word product.
1462 If unsigned widening multiplication is available, use that;
1463 otherwise use the signed form and compensate. */
1465 if (umul_widen_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1467 product
= expand_binop (mode
, umul_widen_optab
, op0_low
, op1_low
,
1468 target
, 1, OPTAB_DIRECT
);
1470 /* If we didn't succeed, delete everything we did so far. */
1472 delete_insns_since (last
);
1474 op0_xhigh
= op0_high
, op1_xhigh
= op1_high
;
1478 && smul_widen_optab
->handlers
[(int) mode
].insn_code
1479 != CODE_FOR_nothing
)
1481 rtx wordm1
= GEN_INT (BITS_PER_WORD
- 1);
1482 product
= expand_binop (mode
, smul_widen_optab
, op0_low
, op1_low
,
1483 target
, 1, OPTAB_DIRECT
);
1484 op0_xhigh
= expand_binop (word_mode
, lshr_optab
, op0_low
, wordm1
,
1485 NULL_RTX
, 1, next_methods
);
1487 op0_xhigh
= expand_binop (word_mode
, add_optab
, op0_high
,
1488 op0_xhigh
, op0_xhigh
, 0, next_methods
);
1491 op0_xhigh
= expand_binop (word_mode
, ashr_optab
, op0_low
, wordm1
,
1492 NULL_RTX
, 0, next_methods
);
1494 op0_xhigh
= expand_binop (word_mode
, sub_optab
, op0_high
,
1495 op0_xhigh
, op0_xhigh
, 0,
1499 op1_xhigh
= expand_binop (word_mode
, lshr_optab
, op1_low
, wordm1
,
1500 NULL_RTX
, 1, next_methods
);
1502 op1_xhigh
= expand_binop (word_mode
, add_optab
, op1_high
,
1503 op1_xhigh
, op1_xhigh
, 0, next_methods
);
1506 op1_xhigh
= expand_binop (word_mode
, ashr_optab
, op1_low
, wordm1
,
1507 NULL_RTX
, 0, next_methods
);
1509 op1_xhigh
= expand_binop (word_mode
, sub_optab
, op1_high
,
1510 op1_xhigh
, op1_xhigh
, 0,
1515 /* If we have been able to directly compute the product of the
1516 low-order words of the operands and perform any required adjustments
1517 of the operands, we proceed by trying two more multiplications
1518 and then computing the appropriate sum.
1520 We have checked above that the required addition is provided.
1521 Full-word addition will normally always succeed, especially if
1522 it is provided at all, so we don't worry about its failure. The
1523 multiplication may well fail, however, so we do handle that. */
1525 if (product
&& op0_xhigh
&& op1_xhigh
)
1527 rtx product_high
= operand_subword (product
, high
, 1, mode
);
1528 rtx temp
= expand_binop (word_mode
, binoptab
, op0_low
, op1_xhigh
,
1529 NULL_RTX
, 0, OPTAB_DIRECT
);
1532 temp
= expand_binop (word_mode
, add_optab
, temp
, product_high
,
1533 product_high
, 0, next_methods
);
1535 if (temp
!= 0 && temp
!= product_high
)
1536 emit_move_insn (product_high
, temp
);
1539 temp
= expand_binop (word_mode
, binoptab
, op1_low
, op0_xhigh
,
1540 NULL_RTX
, 0, OPTAB_DIRECT
);
1543 temp
= expand_binop (word_mode
, add_optab
, temp
,
1544 product_high
, product_high
,
1547 if (temp
!= 0 && temp
!= product_high
)
1548 emit_move_insn (product_high
, temp
);
1552 if (mov_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1554 temp
= emit_move_insn (product
, product
);
1555 set_unique_reg_note (temp
,
1557 gen_rtx_fmt_ee (MULT
, mode
,
1565 /* If we get here, we couldn't do it for some reason even though we
1566 originally thought we could. Delete anything we've emitted in
1569 delete_insns_since (last
);
1572 /* We need to open-code the complex type operations: '+, -, * and /' */
1574 /* At this point we allow operations between two similar complex
1575 numbers, and also if one of the operands is not a complex number
1576 but rather of MODE_FLOAT or MODE_INT. However, the caller
1577 must make sure that the MODE of the non-complex operand matches
1578 the SUBMODE of the complex operand. */
1580 if (class == MODE_COMPLEX_FLOAT
|| class == MODE_COMPLEX_INT
)
1582 rtx real0
= 0, imag0
= 0;
1583 rtx real1
= 0, imag1
= 0;
1584 rtx realr
, imagr
, res
;
1589 /* Find the correct mode for the real and imaginary parts */
1590 enum machine_mode submode
1591 = mode_for_size (GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
,
1592 class == MODE_COMPLEX_INT
? MODE_INT
: MODE_FLOAT
,
1595 if (submode
== BLKmode
)
1599 target
= gen_reg_rtx (mode
);
1603 realr
= gen_realpart (submode
, target
);
1604 imagr
= gen_imagpart (submode
, target
);
1606 if (GET_MODE (op0
) == mode
)
1608 real0
= gen_realpart (submode
, op0
);
1609 imag0
= gen_imagpart (submode
, op0
);
1614 if (GET_MODE (op1
) == mode
)
1616 real1
= gen_realpart (submode
, op1
);
1617 imag1
= gen_imagpart (submode
, op1
);
1622 if (real0
== 0 || real1
== 0 || ! (imag0
!= 0|| imag1
!= 0))
1625 switch (binoptab
->code
)
1628 /* (a+ib) + (c+id) = (a+c) + i(b+d) */
1630 /* (a+ib) - (c+id) = (a-c) + i(b-d) */
1631 res
= expand_binop (submode
, binoptab
, real0
, real1
,
1632 realr
, unsignedp
, methods
);
1636 else if (res
!= realr
)
1637 emit_move_insn (realr
, res
);
1640 res
= expand_binop (submode
, binoptab
, imag0
, imag1
,
1641 imagr
, unsignedp
, methods
);
1644 else if (binoptab
->code
== MINUS
)
1645 res
= expand_unop (submode
, neg_optab
, imag1
, imagr
, unsignedp
);
1651 else if (res
!= imagr
)
1652 emit_move_insn (imagr
, res
);
1658 /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */
1664 /* Don't fetch these from memory more than once. */
1665 real0
= force_reg (submode
, real0
);
1666 real1
= force_reg (submode
, real1
);
1667 imag0
= force_reg (submode
, imag0
);
1668 imag1
= force_reg (submode
, imag1
);
1670 temp1
= expand_binop (submode
, binoptab
, real0
, real1
, NULL_RTX
,
1671 unsignedp
, methods
);
1673 temp2
= expand_binop (submode
, binoptab
, imag0
, imag1
, NULL_RTX
,
1674 unsignedp
, methods
);
1676 if (temp1
== 0 || temp2
== 0)
1679 res
= expand_binop (submode
, sub_optab
, temp1
, temp2
,
1680 realr
, unsignedp
, methods
);
1684 else if (res
!= realr
)
1685 emit_move_insn (realr
, res
);
1687 temp1
= expand_binop (submode
, binoptab
, real0
, imag1
,
1688 NULL_RTX
, unsignedp
, methods
);
1690 temp2
= expand_binop (submode
, binoptab
, real1
, imag0
,
1691 NULL_RTX
, unsignedp
, methods
);
1693 if (temp1
== 0 || temp2
== 0)
1696 res
= expand_binop (submode
, add_optab
, temp1
, temp2
,
1697 imagr
, unsignedp
, methods
);
1701 else if (res
!= imagr
)
1702 emit_move_insn (imagr
, res
);
1708 /* Don't fetch these from memory more than once. */
1709 real0
= force_reg (submode
, real0
);
1710 real1
= force_reg (submode
, real1
);
1712 res
= expand_binop (submode
, binoptab
, real0
, real1
,
1713 realr
, unsignedp
, methods
);
1716 else if (res
!= realr
)
1717 emit_move_insn (realr
, res
);
1720 res
= expand_binop (submode
, binoptab
,
1721 real1
, imag0
, imagr
, unsignedp
, methods
);
1723 res
= expand_binop (submode
, binoptab
,
1724 real0
, imag1
, imagr
, unsignedp
, methods
);
1728 else if (res
!= imagr
)
1729 emit_move_insn (imagr
, res
);
1736 /* (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) */
1740 /* (a+ib) / (c+i0) = (a/c) + i(b/c) */
1742 /* Don't fetch these from memory more than once. */
1743 real1
= force_reg (submode
, real1
);
1745 /* Simply divide the real and imaginary parts by `c' */
1746 if (class == MODE_COMPLEX_FLOAT
)
1747 res
= expand_binop (submode
, binoptab
, real0
, real1
,
1748 realr
, unsignedp
, methods
);
1750 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
1751 real0
, real1
, realr
, unsignedp
);
1755 else if (res
!= realr
)
1756 emit_move_insn (realr
, res
);
1758 if (class == MODE_COMPLEX_FLOAT
)
1759 res
= expand_binop (submode
, binoptab
, imag0
, real1
,
1760 imagr
, unsignedp
, methods
);
1762 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
1763 imag0
, real1
, imagr
, unsignedp
);
1767 else if (res
!= imagr
)
1768 emit_move_insn (imagr
, res
);
1774 switch (flag_complex_divide_method
)
1777 ok
= expand_cmplxdiv_straight (real0
, real1
, imag0
, imag1
,
1778 realr
, imagr
, submode
,
1784 ok
= expand_cmplxdiv_wide (real0
, real1
, imag0
, imag1
,
1785 realr
, imagr
, submode
,
1805 if (binoptab
->code
!= UNKNOWN
)
1807 = gen_rtx_fmt_ee (binoptab
->code
, mode
,
1808 copy_rtx (op0
), copy_rtx (op1
));
1812 emit_no_conflict_block (seq
, target
, op0
, op1
, equiv_value
);
1818 /* It can't be open-coded in this mode.
1819 Use a library call if one is available and caller says that's ok. */
1821 if (binoptab
->handlers
[(int) mode
].libfunc
1822 && (methods
== OPTAB_LIB
|| methods
== OPTAB_LIB_WIDEN
))
1826 enum machine_mode op1_mode
= mode
;
1833 op1_mode
= word_mode
;
1834 /* Specify unsigned here,
1835 since negative shift counts are meaningless. */
1836 op1x
= convert_to_mode (word_mode
, op1
, 1);
1839 if (GET_MODE (op0
) != VOIDmode
1840 && GET_MODE (op0
) != mode
)
1841 op0
= convert_to_mode (mode
, op0
, unsignedp
);
1843 /* Pass 1 for NO_QUEUE so we don't lose any increments
1844 if the libcall is cse'd or moved. */
1845 value
= emit_library_call_value (binoptab
->handlers
[(int) mode
].libfunc
,
1846 NULL_RTX
, 1, mode
, 2,
1847 op0
, mode
, op1x
, op1_mode
);
1849 insns
= get_insns ();
1852 target
= gen_reg_rtx (mode
);
1853 emit_libcall_block (insns
, target
, value
,
1854 gen_rtx_fmt_ee (binoptab
->code
, mode
, op0
, op1
));
1859 delete_insns_since (last
);
1861 /* It can't be done in this mode. Can we do it in a wider mode? */
1863 if (! (methods
== OPTAB_WIDEN
|| methods
== OPTAB_LIB_WIDEN
1864 || methods
== OPTAB_MUST_WIDEN
))
1866 /* Caller says, don't even try. */
1867 delete_insns_since (entry_last
);
1871 /* Compute the value of METHODS to pass to recursive calls.
1872 Don't allow widening to be tried recursively. */
1874 methods
= (methods
== OPTAB_LIB_WIDEN
? OPTAB_LIB
: OPTAB_DIRECT
);
1876 /* Look for a wider mode of the same class for which it appears we can do
1879 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1881 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1882 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1884 if ((binoptab
->handlers
[(int) wider_mode
].insn_code
1885 != CODE_FOR_nothing
)
1886 || (methods
== OPTAB_LIB
1887 && binoptab
->handlers
[(int) wider_mode
].libfunc
))
1889 rtx xop0
= op0
, xop1
= op1
;
1892 /* For certain integer operations, we need not actually extend
1893 the narrow operands, as long as we will truncate
1894 the results to the same narrowness. */
1896 if ((binoptab
== ior_optab
|| binoptab
== and_optab
1897 || binoptab
== xor_optab
1898 || binoptab
== add_optab
|| binoptab
== sub_optab
1899 || binoptab
== smul_optab
|| binoptab
== ashl_optab
)
1900 && class == MODE_INT
)
1903 xop0
= widen_operand (xop0
, wider_mode
, mode
,
1904 unsignedp
, no_extend
);
1906 /* The second operand of a shift must always be extended. */
1907 xop1
= widen_operand (xop1
, wider_mode
, mode
, unsignedp
,
1908 no_extend
&& binoptab
!= ashl_optab
);
1910 temp
= expand_binop (wider_mode
, binoptab
, xop0
, xop1
, NULL_RTX
,
1911 unsignedp
, methods
);
1914 if (class != MODE_INT
)
1917 target
= gen_reg_rtx (mode
);
1918 convert_move (target
, temp
, 0);
1922 return gen_lowpart (mode
, temp
);
1925 delete_insns_since (last
);
1930 delete_insns_since (entry_last
);
1934 /* Expand a binary operator which has both signed and unsigned forms.
1935 UOPTAB is the optab for unsigned operations, and SOPTAB is for
1938 If we widen unsigned operands, we may use a signed wider operation instead
1939 of an unsigned wider operation, since the result would be the same. */
1942 sign_expand_binop (mode
, uoptab
, soptab
, op0
, op1
, target
, unsignedp
, methods
)
1943 enum machine_mode mode
;
1944 optab uoptab
, soptab
;
1945 rtx op0
, op1
, target
;
1947 enum optab_methods methods
;
1950 optab direct_optab
= unsignedp
? uoptab
: soptab
;
1951 struct optab wide_soptab
;
1953 /* Do it without widening, if possible. */
1954 temp
= expand_binop (mode
, direct_optab
, op0
, op1
, target
,
1955 unsignedp
, OPTAB_DIRECT
);
1956 if (temp
|| methods
== OPTAB_DIRECT
)
1959 /* Try widening to a signed int. Make a fake signed optab that
1960 hides any signed insn for direct use. */
1961 wide_soptab
= *soptab
;
1962 wide_soptab
.handlers
[(int) mode
].insn_code
= CODE_FOR_nothing
;
1963 wide_soptab
.handlers
[(int) mode
].libfunc
= 0;
1965 temp
= expand_binop (mode
, &wide_soptab
, op0
, op1
, target
,
1966 unsignedp
, OPTAB_WIDEN
);
1968 /* For unsigned operands, try widening to an unsigned int. */
1969 if (temp
== 0 && unsignedp
)
1970 temp
= expand_binop (mode
, uoptab
, op0
, op1
, target
,
1971 unsignedp
, OPTAB_WIDEN
);
1972 if (temp
|| methods
== OPTAB_WIDEN
)
1975 /* Use the right width lib call if that exists. */
1976 temp
= expand_binop (mode
, direct_optab
, op0
, op1
, target
, unsignedp
, OPTAB_LIB
);
1977 if (temp
|| methods
== OPTAB_LIB
)
1980 /* Must widen and use a lib call, use either signed or unsigned. */
1981 temp
= expand_binop (mode
, &wide_soptab
, op0
, op1
, target
,
1982 unsignedp
, methods
);
1986 return expand_binop (mode
, uoptab
, op0
, op1
, target
,
1987 unsignedp
, methods
);
1991 /* Generate code to perform an operation specified by BINOPTAB
1992 on operands OP0 and OP1, with two results to TARG1 and TARG2.
1993 We assume that the order of the operands for the instruction
1994 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
1995 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
1997 Either TARG0 or TARG1 may be zero, but what that means is that
1998 the result is not actually wanted. We will generate it into
1999 a dummy pseudo-reg and discard it. They may not both be zero.
2001 Returns 1 if this operation can be performed; 0 if not. */
2004 expand_twoval_binop (binoptab
, op0
, op1
, targ0
, targ1
, unsignedp
)
2010 enum machine_mode mode
= GET_MODE (targ0
? targ0
: targ1
);
2011 enum mode_class
class;
2012 enum machine_mode wider_mode
;
2013 rtx entry_last
= get_last_insn ();
2016 class = GET_MODE_CLASS (mode
);
2018 op0
= protect_from_queue (op0
, 0);
2019 op1
= protect_from_queue (op1
, 0);
2023 op0
= force_not_mem (op0
);
2024 op1
= force_not_mem (op1
);
2027 /* If we are inside an appropriately-short loop and one operand is an
2028 expensive constant, force it into a register. */
2029 if (CONSTANT_P (op0
) && preserve_subexpressions_p ()
2030 && rtx_cost (op0
, binoptab
->code
) > 2)
2031 op0
= force_reg (mode
, op0
);
2033 if (CONSTANT_P (op1
) && preserve_subexpressions_p ()
2034 && rtx_cost (op1
, binoptab
->code
) > 2)
2035 op1
= force_reg (mode
, op1
);
2038 targ0
= protect_from_queue (targ0
, 1);
2040 targ0
= gen_reg_rtx (mode
);
2042 targ1
= protect_from_queue (targ1
, 1);
2044 targ1
= gen_reg_rtx (mode
);
2046 /* Record where to go back to if we fail. */
2047 last
= get_last_insn ();
2049 if (binoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
2051 int icode
= (int) binoptab
->handlers
[(int) mode
].insn_code
;
2052 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
2053 enum machine_mode mode1
= insn_operand_mode
[icode
][2];
2055 rtx xop0
= op0
, xop1
= op1
;
2057 /* In case this insn wants input operands in modes different from the
2058 result, convert the operands. */
2059 if (GET_MODE (op0
) != VOIDmode
&& GET_MODE (op0
) != mode0
)
2060 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
2062 if (GET_MODE (op1
) != VOIDmode
&& GET_MODE (op1
) != mode1
)
2063 xop1
= convert_to_mode (mode1
, xop1
, unsignedp
);
2065 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2066 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
2067 xop0
= copy_to_mode_reg (mode0
, xop0
);
2069 if (! (*insn_operand_predicate
[icode
][2]) (xop1
, mode1
))
2070 xop1
= copy_to_mode_reg (mode1
, xop1
);
2072 /* We could handle this, but we should always be called with a pseudo
2073 for our targets and all insns should take them as outputs. */
2074 if (! (*insn_operand_predicate
[icode
][0]) (targ0
, mode
)
2075 || ! (*insn_operand_predicate
[icode
][3]) (targ1
, mode
))
2078 pat
= GEN_FCN (icode
) (targ0
, xop0
, xop1
, targ1
);
2085 delete_insns_since (last
);
2088 /* It can't be done in this mode. Can we do it in a wider mode? */
2090 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
2092 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2093 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2095 if (binoptab
->handlers
[(int) wider_mode
].insn_code
2096 != CODE_FOR_nothing
)
2098 register rtx t0
= gen_reg_rtx (wider_mode
);
2099 register rtx t1
= gen_reg_rtx (wider_mode
);
2101 if (expand_twoval_binop (binoptab
,
2102 convert_modes (wider_mode
, mode
, op0
,
2104 convert_modes (wider_mode
, mode
, op1
,
2108 convert_move (targ0
, t0
, unsignedp
);
2109 convert_move (targ1
, t1
, unsignedp
);
2113 delete_insns_since (last
);
2118 delete_insns_since (entry_last
);
2122 /* Generate code to perform an operation specified by UNOPTAB
2123 on operand OP0, with result having machine-mode MODE.
2125 UNSIGNEDP is for the case where we have to widen the operands
2126 to perform the operation. It says to use zero-extension.
2128 If TARGET is nonzero, the value
2129 is generated there, if it is convenient to do so.
2130 In all cases an rtx is returned for the locus of the value;
2131 this may or may not be TARGET. */
2134 expand_unop (mode
, unoptab
, op0
, target
, unsignedp
)
2135 enum machine_mode mode
;
2141 enum mode_class
class;
2142 enum machine_mode wider_mode
;
2144 rtx last
= get_last_insn ();
2147 class = GET_MODE_CLASS (mode
);
2149 op0
= protect_from_queue (op0
, 0);
2153 op0
= force_not_mem (op0
);
2157 target
= protect_from_queue (target
, 1);
2159 if (unoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
2161 int icode
= (int) unoptab
->handlers
[(int) mode
].insn_code
;
2162 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
2168 temp
= gen_reg_rtx (mode
);
2170 if (GET_MODE (xop0
) != VOIDmode
2171 && GET_MODE (xop0
) != mode0
)
2172 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
2174 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
2176 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
2177 xop0
= copy_to_mode_reg (mode0
, xop0
);
2179 if (! (*insn_operand_predicate
[icode
][0]) (temp
, mode
))
2180 temp
= gen_reg_rtx (mode
);
2182 pat
= GEN_FCN (icode
) (temp
, xop0
);
2185 if (GET_CODE (pat
) == SEQUENCE
2186 && ! add_equal_note (pat
, temp
, unoptab
->code
, xop0
, NULL_RTX
))
2188 delete_insns_since (last
);
2189 return expand_unop (mode
, unoptab
, op0
, NULL_RTX
, unsignedp
);
2197 delete_insns_since (last
);
2200 /* It can't be done in this mode. Can we open-code it in a wider mode? */
2202 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
2203 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2204 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2206 if (unoptab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
)
2210 /* For certain operations, we need not actually extend
2211 the narrow operand, as long as we will truncate the
2212 results to the same narrowness. */
2214 xop0
= widen_operand (xop0
, wider_mode
, mode
, unsignedp
,
2215 (unoptab
== neg_optab
2216 || unoptab
== one_cmpl_optab
)
2217 && class == MODE_INT
);
2219 temp
= expand_unop (wider_mode
, unoptab
, xop0
, NULL_RTX
,
2224 if (class != MODE_INT
)
2227 target
= gen_reg_rtx (mode
);
2228 convert_move (target
, temp
, 0);
2232 return gen_lowpart (mode
, temp
);
2235 delete_insns_since (last
);
2239 /* These can be done a word at a time. */
2240 if (unoptab
== one_cmpl_optab
2241 && class == MODE_INT
2242 && GET_MODE_SIZE (mode
) > UNITS_PER_WORD
2243 && unoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
2248 if (target
== 0 || target
== op0
)
2249 target
= gen_reg_rtx (mode
);
2253 /* Do the actual arithmetic. */
2254 for (i
= 0; i
< GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
; i
++)
2256 rtx target_piece
= operand_subword (target
, i
, 1, mode
);
2257 rtx x
= expand_unop (word_mode
, unoptab
,
2258 operand_subword_force (op0
, i
, mode
),
2259 target_piece
, unsignedp
);
2260 if (target_piece
!= x
)
2261 emit_move_insn (target_piece
, x
);
2264 insns
= get_insns ();
2267 emit_no_conflict_block (insns
, target
, op0
, NULL_RTX
,
2268 gen_rtx_fmt_e (unoptab
->code
, mode
,
2273 /* Open-code the complex negation operation. */
2274 else if (unoptab
== neg_optab
2275 && (class == MODE_COMPLEX_FLOAT
|| class == MODE_COMPLEX_INT
))
2281 /* Find the correct mode for the real and imaginary parts */
2282 enum machine_mode submode
2283 = mode_for_size (GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
,
2284 class == MODE_COMPLEX_INT
? MODE_INT
: MODE_FLOAT
,
2287 if (submode
== BLKmode
)
2291 target
= gen_reg_rtx (mode
);
2295 target_piece
= gen_imagpart (submode
, target
);
2296 x
= expand_unop (submode
, unoptab
,
2297 gen_imagpart (submode
, op0
),
2298 target_piece
, unsignedp
);
2299 if (target_piece
!= x
)
2300 emit_move_insn (target_piece
, x
);
2302 target_piece
= gen_realpart (submode
, target
);
2303 x
= expand_unop (submode
, unoptab
,
2304 gen_realpart (submode
, op0
),
2305 target_piece
, unsignedp
);
2306 if (target_piece
!= x
)
2307 emit_move_insn (target_piece
, x
);
2312 emit_no_conflict_block (seq
, target
, op0
, 0,
2313 gen_rtx_fmt_e (unoptab
->code
, mode
,
2318 /* Now try a library call in this mode. */
2319 if (unoptab
->handlers
[(int) mode
].libfunc
)
2326 /* Pass 1 for NO_QUEUE so we don't lose any increments
2327 if the libcall is cse'd or moved. */
2328 value
= emit_library_call_value (unoptab
->handlers
[(int) mode
].libfunc
,
2329 NULL_RTX
, 1, mode
, 1, op0
, mode
);
2330 insns
= get_insns ();
2333 target
= gen_reg_rtx (mode
);
2334 emit_libcall_block (insns
, target
, value
,
2335 gen_rtx_fmt_e (unoptab
->code
, mode
, op0
));
2340 /* It can't be done in this mode. Can we do it in a wider mode? */
2342 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
2344 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2345 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2347 if ((unoptab
->handlers
[(int) wider_mode
].insn_code
2348 != CODE_FOR_nothing
)
2349 || unoptab
->handlers
[(int) wider_mode
].libfunc
)
2353 /* For certain operations, we need not actually extend
2354 the narrow operand, as long as we will truncate the
2355 results to the same narrowness. */
2357 xop0
= widen_operand (xop0
, wider_mode
, mode
, unsignedp
,
2358 (unoptab
== neg_optab
2359 || unoptab
== one_cmpl_optab
)
2360 && class == MODE_INT
);
2362 temp
= expand_unop (wider_mode
, unoptab
, xop0
, NULL_RTX
,
2367 if (class != MODE_INT
)
2370 target
= gen_reg_rtx (mode
);
2371 convert_move (target
, temp
, 0);
2375 return gen_lowpart (mode
, temp
);
2378 delete_insns_since (last
);
2383 /* If there is no negate operation, try doing a subtract from zero.
2384 The US Software GOFAST library needs this. */
2385 if (unoptab
== neg_optab
)
2388 temp
= expand_binop (mode
, sub_optab
, CONST0_RTX (mode
), op0
,
2389 target
, unsignedp
, OPTAB_LIB_WIDEN
);
2397 /* Emit code to compute the absolute value of OP0, with result to
2398 TARGET if convenient. (TARGET may be 0.) The return value says
2399 where the result actually is to be found.
2401 MODE is the mode of the operand; the mode of the result is
2402 different but can be deduced from MODE.
2407 expand_abs (mode
, op0
, target
, safe
)
2408 enum machine_mode mode
;
2415 /* First try to do it with a special abs instruction. */
2416 temp
= expand_unop (mode
, abs_optab
, op0
, target
, 0);
2420 /* If this machine has expensive jumps, we can do integer absolute
2421 value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
2422 where W is the width of MODE. */
2424 if (GET_MODE_CLASS (mode
) == MODE_INT
&& BRANCH_COST
>= 2)
2426 rtx extended
= expand_shift (RSHIFT_EXPR
, mode
, op0
,
2427 size_int (GET_MODE_BITSIZE (mode
) - 1),
2430 temp
= expand_binop (mode
, xor_optab
, extended
, op0
, target
, 0,
2433 temp
= expand_binop (mode
, sub_optab
, temp
, extended
, target
, 0,
2440 /* If that does not win, use conditional jump and negate. */
2442 /* It is safe to use the target if it is the same
2443 as the source if this is also a pseudo register */
2444 if (op0
== target
&& GET_CODE (op0
) == REG
2445 && REGNO (op0
) >= FIRST_PSEUDO_REGISTER
)
2448 op1
= gen_label_rtx ();
2449 if (target
== 0 || ! safe
2450 || GET_MODE (target
) != mode
2451 || (GET_CODE (target
) == MEM
&& MEM_VOLATILE_P (target
))
2452 || (GET_CODE (target
) == REG
2453 && REGNO (target
) < FIRST_PSEUDO_REGISTER
))
2454 target
= gen_reg_rtx (mode
);
2456 emit_move_insn (target
, op0
);
2459 /* If this mode is an integer too wide to compare properly,
2460 compare word by word. Rely on CSE to optimize constant cases. */
2461 if (GET_MODE_CLASS (mode
) == MODE_INT
&& ! can_compare_p (mode
))
2462 do_jump_by_parts_greater_rtx (mode
, 0, target
, const0_rtx
,
2466 temp
= compare_from_rtx (target
, CONST0_RTX (mode
), GE
, 0, mode
,
2468 if (temp
== const1_rtx
)
2470 else if (temp
!= const0_rtx
)
2472 if (bcc_gen_fctn
[(int) GET_CODE (temp
)] != 0)
2473 emit_jump_insn ((*bcc_gen_fctn
[(int) GET_CODE (temp
)]) (op1
));
2479 op0
= expand_unop (mode
, neg_optab
, target
, target
, 0);
2481 emit_move_insn (target
, op0
);
2487 /* Emit code to compute the absolute value of OP0, with result to
2488 TARGET if convenient. (TARGET may be 0.) The return value says
2489 where the result actually is to be found.
2491 MODE is the mode of the operand; the mode of the result is
2492 different but can be deduced from MODE.
2494 UNSIGNEDP is relevant for complex integer modes. */
2497 expand_complex_abs (mode
, op0
, target
, unsignedp
)
2498 enum machine_mode mode
;
2503 enum mode_class
class = GET_MODE_CLASS (mode
);
2504 enum machine_mode wider_mode
;
2506 rtx entry_last
= get_last_insn ();
2510 /* Find the correct mode for the real and imaginary parts. */
2511 enum machine_mode submode
2512 = mode_for_size (GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
,
2513 class == MODE_COMPLEX_INT
? MODE_INT
: MODE_FLOAT
,
2516 if (submode
== BLKmode
)
2519 op0
= protect_from_queue (op0
, 0);
2523 op0
= force_not_mem (op0
);
2526 last
= get_last_insn ();
2529 target
= protect_from_queue (target
, 1);
2531 if (abs_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
2533 int icode
= (int) abs_optab
->handlers
[(int) mode
].insn_code
;
2534 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
2540 temp
= gen_reg_rtx (submode
);
2542 if (GET_MODE (xop0
) != VOIDmode
2543 && GET_MODE (xop0
) != mode0
)
2544 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
2546 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
2548 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
2549 xop0
= copy_to_mode_reg (mode0
, xop0
);
2551 if (! (*insn_operand_predicate
[icode
][0]) (temp
, submode
))
2552 temp
= gen_reg_rtx (submode
);
2554 pat
= GEN_FCN (icode
) (temp
, xop0
);
2557 if (GET_CODE (pat
) == SEQUENCE
2558 && ! add_equal_note (pat
, temp
, abs_optab
->code
, xop0
, NULL_RTX
))
2560 delete_insns_since (last
);
2561 return expand_unop (mode
, abs_optab
, op0
, NULL_RTX
, unsignedp
);
2569 delete_insns_since (last
);
2572 /* It can't be done in this mode. Can we open-code it in a wider mode? */
2574 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2575 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2577 if (abs_optab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
)
2581 xop0
= convert_modes (wider_mode
, mode
, xop0
, unsignedp
);
2582 temp
= expand_complex_abs (wider_mode
, xop0
, NULL_RTX
, unsignedp
);
2586 if (class != MODE_COMPLEX_INT
)
2589 target
= gen_reg_rtx (submode
);
2590 convert_move (target
, temp
, 0);
2594 return gen_lowpart (submode
, temp
);
2597 delete_insns_since (last
);
2601 /* Open-code the complex absolute-value operation
2602 if we can open-code sqrt. Otherwise it's not worth while. */
2603 if (sqrt_optab
->handlers
[(int) submode
].insn_code
!= CODE_FOR_nothing
)
2605 rtx real
, imag
, total
;
2607 real
= gen_realpart (submode
, op0
);
2608 imag
= gen_imagpart (submode
, op0
);
2610 /* Square both parts. */
2611 real
= expand_mult (submode
, real
, real
, NULL_RTX
, 0);
2612 imag
= expand_mult (submode
, imag
, imag
, NULL_RTX
, 0);
2614 /* Sum the parts. */
2615 total
= expand_binop (submode
, add_optab
, real
, imag
, NULL_RTX
,
2616 0, OPTAB_LIB_WIDEN
);
2618 /* Get sqrt in TARGET. Set TARGET to where the result is. */
2619 target
= expand_unop (submode
, sqrt_optab
, total
, target
, 0);
2621 delete_insns_since (last
);
2626 /* Now try a library call in this mode. */
2627 if (abs_optab
->handlers
[(int) mode
].libfunc
)
2634 /* Pass 1 for NO_QUEUE so we don't lose any increments
2635 if the libcall is cse'd or moved. */
2636 value
= emit_library_call_value (abs_optab
->handlers
[(int) mode
].libfunc
,
2637 NULL_RTX
, 1, submode
, 1, op0
, mode
);
2638 insns
= get_insns ();
2641 target
= gen_reg_rtx (submode
);
2642 emit_libcall_block (insns
, target
, value
,
2643 gen_rtx_fmt_e (abs_optab
->code
, mode
, op0
));
2648 /* It can't be done in this mode. Can we do it in a wider mode? */
2650 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2651 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2653 if ((abs_optab
->handlers
[(int) wider_mode
].insn_code
2654 != CODE_FOR_nothing
)
2655 || abs_optab
->handlers
[(int) wider_mode
].libfunc
)
2659 xop0
= convert_modes (wider_mode
, mode
, xop0
, unsignedp
);
2661 temp
= expand_complex_abs (wider_mode
, xop0
, NULL_RTX
, unsignedp
);
2665 if (class != MODE_COMPLEX_INT
)
2668 target
= gen_reg_rtx (submode
);
2669 convert_move (target
, temp
, 0);
2673 return gen_lowpart (submode
, temp
);
2676 delete_insns_since (last
);
2680 delete_insns_since (entry_last
);
2684 /* Generate an instruction whose insn-code is INSN_CODE,
2685 with two operands: an output TARGET and an input OP0.
2686 TARGET *must* be nonzero, and the output is always stored there.
2687 CODE is an rtx code such that (CODE OP0) is an rtx that describes
2688 the value that is stored into TARGET. */
2691 emit_unop_insn (icode
, target
, op0
, code
)
2698 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
2701 temp
= target
= protect_from_queue (target
, 1);
2703 op0
= protect_from_queue (op0
, 0);
2705 /* Sign and zero extension from memory is often done specially on
2706 RISC machines, so forcing into a register here can pessimize
2708 if (flag_force_mem
&& code
!= SIGN_EXTEND
&& code
!= ZERO_EXTEND
)
2709 op0
= force_not_mem (op0
);
2711 /* Now, if insn does not accept our operands, put them into pseudos. */
2713 if (! (*insn_operand_predicate
[icode
][1]) (op0
, mode0
))
2714 op0
= copy_to_mode_reg (mode0
, op0
);
2716 if (! (*insn_operand_predicate
[icode
][0]) (temp
, GET_MODE (temp
))
2717 || (flag_force_mem
&& GET_CODE (temp
) == MEM
))
2718 temp
= gen_reg_rtx (GET_MODE (temp
));
2720 pat
= GEN_FCN (icode
) (temp
, op0
);
2722 if (GET_CODE (pat
) == SEQUENCE
&& code
!= UNKNOWN
)
2723 add_equal_note (pat
, temp
, code
, op0
, NULL_RTX
);
2728 emit_move_insn (target
, temp
);
2731 /* Emit code to perform a series of operations on a multi-word quantity, one
2734 Such a block is preceded by a CLOBBER of the output, consists of multiple
2735 insns, each setting one word of the output, and followed by a SET copying
2736 the output to itself.
2738 Each of the insns setting words of the output receives a REG_NO_CONFLICT
2739 note indicating that it doesn't conflict with the (also multi-word)
2740 inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
2743 INSNS is a block of code generated to perform the operation, not including
2744 the CLOBBER and final copy. All insns that compute intermediate values
2745 are first emitted, followed by the block as described above.
2747 TARGET, OP0, and OP1 are the output and inputs of the operations,
2748 respectively. OP1 may be zero for a unary operation.
2750 EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
2753 If TARGET is not a register, INSNS is simply emitted with no special
2754 processing. Likewise if anything in INSNS is not an INSN or if
2755 there is a libcall block inside INSNS.
2757 The final insn emitted is returned. */
2760 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv
)
2766 rtx prev
, next
, first
, last
, insn
;
2768 if (GET_CODE (target
) != REG
|| reload_in_progress
)
2769 return emit_insns (insns
);
2771 for (insn
= insns
; insn
; insn
= NEXT_INSN (insn
))
2772 if (GET_CODE (insn
) != INSN
2773 || find_reg_note (insn
, REG_LIBCALL
, NULL_RTX
))
2774 return emit_insns (insns
);
2776 /* First emit all insns that do not store into words of the output and remove
2777 these from the list. */
2778 for (insn
= insns
; insn
; insn
= next
)
2783 next
= NEXT_INSN (insn
);
2785 if (GET_CODE (PATTERN (insn
)) == SET
)
2786 set
= PATTERN (insn
);
2787 else if (GET_CODE (PATTERN (insn
)) == PARALLEL
)
2789 for (i
= 0; i
< XVECLEN (PATTERN (insn
), 0); i
++)
2790 if (GET_CODE (XVECEXP (PATTERN (insn
), 0, i
)) == SET
)
2792 set
= XVECEXP (PATTERN (insn
), 0, i
);
2800 if (! reg_overlap_mentioned_p (target
, SET_DEST (set
)))
2802 if (PREV_INSN (insn
))
2803 NEXT_INSN (PREV_INSN (insn
)) = next
;
2808 PREV_INSN (next
) = PREV_INSN (insn
);
2814 prev
= get_last_insn ();
2816 /* Now write the CLOBBER of the output, followed by the setting of each
2817 of the words, followed by the final copy. */
2818 if (target
!= op0
&& target
!= op1
)
2819 emit_insn (gen_rtx_CLOBBER (VOIDmode
, target
));
2821 for (insn
= insns
; insn
; insn
= next
)
2823 next
= NEXT_INSN (insn
);
2826 if (op1
&& GET_CODE (op1
) == REG
)
2827 REG_NOTES (insn
) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT
, op1
,
2830 if (op0
&& GET_CODE (op0
) == REG
)
2831 REG_NOTES (insn
) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT
, op0
,
2835 if (mov_optab
->handlers
[(int) GET_MODE (target
)].insn_code
2836 != CODE_FOR_nothing
)
2838 last
= emit_move_insn (target
, target
);
2840 set_unique_reg_note (last
, REG_EQUAL
, equiv
);
2843 last
= get_last_insn ();
2846 first
= get_insns ();
2848 first
= NEXT_INSN (prev
);
2850 /* Encapsulate the block so it gets manipulated as a unit. */
2851 REG_NOTES (first
) = gen_rtx_INSN_LIST (REG_LIBCALL
, last
,
2853 REG_NOTES (last
) = gen_rtx_INSN_LIST (REG_RETVAL
, first
, REG_NOTES (last
));
2858 /* Emit code to make a call to a constant function or a library call.
2860 INSNS is a list containing all insns emitted in the call.
2861 These insns leave the result in RESULT. Our block is to copy RESULT
2862 to TARGET, which is logically equivalent to EQUIV.
2864 We first emit any insns that set a pseudo on the assumption that these are
2865 loading constants into registers; doing so allows them to be safely cse'ed
2866 between blocks. Then we emit all the other insns in the block, followed by
2867 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
2868 note with an operand of EQUIV.
2870 Moving assignments to pseudos outside of the block is done to improve
2871 the generated code, but is not required to generate correct code,
2872 hence being unable to move an assignment is not grounds for not making
2873 a libcall block. There are two reasons why it is safe to leave these
2874 insns inside the block: First, we know that these pseudos cannot be
2875 used in generated RTL outside the block since they are created for
2876 temporary purposes within the block. Second, CSE will not record the
2877 values of anything set inside a libcall block, so we know they must
2878 be dead at the end of the block.
2880 Except for the first group of insns (the ones setting pseudos), the
2881 block is delimited by REG_RETVAL and REG_LIBCALL notes. */
2884 emit_libcall_block (insns
, target
, result
, equiv
)
2890 rtx prev
, next
, first
, last
, insn
;
2892 /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
2893 reg note to indicate that this call cannot throw. (Unless there is
2894 already a REG_EH_REGION note.) */
2896 for (insn
= insns
; insn
; insn
= NEXT_INSN (insn
))
2898 if (GET_CODE (insn
) == CALL_INSN
)
2900 rtx note
= find_reg_note (insn
, REG_EH_REGION
, NULL_RTX
);
2901 if (note
== NULL_RTX
)
2902 REG_NOTES (insn
) = gen_rtx_EXPR_LIST (REG_EH_REGION
, GEN_INT (-1),
2907 /* First emit all insns that set pseudos. Remove them from the list as
2908 we go. Avoid insns that set pseudos which were referenced in previous
2909 insns. These can be generated by move_by_pieces, for example,
2910 to update an address. Similarly, avoid insns that reference things
2911 set in previous insns. */
2913 for (insn
= insns
; insn
; insn
= next
)
2915 rtx set
= single_set (insn
);
2917 next
= NEXT_INSN (insn
);
2919 if (set
!= 0 && GET_CODE (SET_DEST (set
)) == REG
2920 && REGNO (SET_DEST (set
)) >= FIRST_PSEUDO_REGISTER
2922 || (! reg_mentioned_p (SET_DEST (set
), PATTERN (insns
))
2923 && ! reg_used_between_p (SET_DEST (set
), insns
, insn
)
2924 && ! modified_in_p (SET_SRC (set
), insns
)
2925 && ! modified_between_p (SET_SRC (set
), insns
, insn
))))
2927 if (PREV_INSN (insn
))
2928 NEXT_INSN (PREV_INSN (insn
)) = next
;
2933 PREV_INSN (next
) = PREV_INSN (insn
);
2939 prev
= get_last_insn ();
2941 /* Write the remaining insns followed by the final copy. */
2943 for (insn
= insns
; insn
; insn
= next
)
2945 next
= NEXT_INSN (insn
);
2950 last
= emit_move_insn (target
, result
);
2951 if (mov_optab
->handlers
[(int) GET_MODE (target
)].insn_code
2952 != CODE_FOR_nothing
)
2953 set_unique_reg_note (last
, REG_EQUAL
, copy_rtx (equiv
));
2956 first
= get_insns ();
2958 first
= NEXT_INSN (prev
);
2960 /* Encapsulate the block so it gets manipulated as a unit. */
2961 REG_NOTES (first
) = gen_rtx_INSN_LIST (REG_LIBCALL
, last
,
2963 REG_NOTES (last
) = gen_rtx_INSN_LIST (REG_RETVAL
, first
, REG_NOTES (last
));
2966 /* Generate code to store zero in X. */
2972 emit_move_insn (x
, const0_rtx
);
2975 /* Generate code to store 1 in X
2976 assuming it contains zero beforehand. */
2979 emit_0_to_1_insn (x
)
2982 emit_move_insn (x
, const1_rtx
);
2985 /* Generate code to compare X with Y
2986 so that the condition codes are set.
2988 MODE is the mode of the inputs (in case they are const_int).
2989 UNSIGNEDP nonzero says that X and Y are unsigned;
2990 this matters if they need to be widened.
2992 If they have mode BLKmode, then SIZE specifies the size of both X and Y,
2993 and ALIGN specifies the known shared alignment of X and Y.
2995 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
2996 It is ignored for fixed-point and block comparisons;
2997 it is used only for floating-point comparisons. */
3000 emit_cmp_insn (x
, y
, comparison
, size
, mode
, unsignedp
, align
)
3002 enum rtx_code comparison
;
3004 enum machine_mode mode
;
3008 enum mode_class
class;
3009 enum machine_mode wider_mode
;
3011 class = GET_MODE_CLASS (mode
);
3013 /* They could both be VOIDmode if both args are immediate constants,
3014 but we should fold that at an earlier stage.
3015 With no special code here, this will call abort,
3016 reminding the programmer to implement such folding. */
3018 if (mode
!= BLKmode
&& flag_force_mem
)
3020 x
= force_not_mem (x
);
3021 y
= force_not_mem (y
);
3024 /* If we are inside an appropriately-short loop and one operand is an
3025 expensive constant, force it into a register. */
3026 if (CONSTANT_P (x
) && preserve_subexpressions_p () && rtx_cost (x
, COMPARE
) > 2)
3027 x
= force_reg (mode
, x
);
3029 if (CONSTANT_P (y
) && preserve_subexpressions_p () && rtx_cost (y
, COMPARE
) > 2)
3030 y
= force_reg (mode
, y
);
3033 /* Abort if we have a non-canonical comparison. The RTL documentation
3034 states that canonical comparisons are required only for targets which
3036 if (CONSTANT_P (x
) && ! CONSTANT_P (y
))
3040 /* Don't let both operands fail to indicate the mode. */
3041 if (GET_MODE (x
) == VOIDmode
&& GET_MODE (y
) == VOIDmode
)
3042 x
= force_reg (mode
, x
);
3044 /* Handle all BLKmode compares. */
3046 if (mode
== BLKmode
)
3049 x
= protect_from_queue (x
, 0);
3050 y
= protect_from_queue (y
, 0);
3054 #ifdef HAVE_cmpstrqi
3056 && GET_CODE (size
) == CONST_INT
3057 && INTVAL (size
) < (1 << GET_MODE_BITSIZE (QImode
)))
3059 enum machine_mode result_mode
3060 = insn_operand_mode
[(int) CODE_FOR_cmpstrqi
][0];
3061 rtx result
= gen_reg_rtx (result_mode
);
3062 emit_insn (gen_cmpstrqi (result
, x
, y
, size
, GEN_INT (align
)));
3063 emit_cmp_insn (result
, const0_rtx
, comparison
, NULL_RTX
,
3068 #ifdef HAVE_cmpstrhi
3070 && GET_CODE (size
) == CONST_INT
3071 && INTVAL (size
) < (1 << GET_MODE_BITSIZE (HImode
)))
3073 enum machine_mode result_mode
3074 = insn_operand_mode
[(int) CODE_FOR_cmpstrhi
][0];
3075 rtx result
= gen_reg_rtx (result_mode
);
3076 emit_insn (gen_cmpstrhi (result
, x
, y
, size
, GEN_INT (align
)));
3077 emit_cmp_insn (result
, const0_rtx
, comparison
, NULL_RTX
,
3082 #ifdef HAVE_cmpstrsi
3085 enum machine_mode result_mode
3086 = insn_operand_mode
[(int) CODE_FOR_cmpstrsi
][0];
3087 rtx result
= gen_reg_rtx (result_mode
);
3088 size
= protect_from_queue (size
, 0);
3089 emit_insn (gen_cmpstrsi (result
, x
, y
,
3090 convert_to_mode (SImode
, size
, 1),
3092 emit_cmp_insn (result
, const0_rtx
, comparison
, NULL_RTX
,
3100 #ifdef TARGET_MEM_FUNCTIONS
3101 emit_library_call (memcmp_libfunc
, 0,
3102 TYPE_MODE (integer_type_node
), 3,
3103 XEXP (x
, 0), Pmode
, XEXP (y
, 0), Pmode
,
3104 convert_to_mode (TYPE_MODE (sizetype
), size
,
3105 TREE_UNSIGNED (sizetype
)),
3106 TYPE_MODE (sizetype
));
3108 emit_library_call (bcmp_libfunc
, 0,
3109 TYPE_MODE (integer_type_node
), 3,
3110 XEXP (x
, 0), Pmode
, XEXP (y
, 0), Pmode
,
3111 convert_to_mode (TYPE_MODE (integer_type_node
),
3113 TREE_UNSIGNED (integer_type_node
)),
3114 TYPE_MODE (integer_type_node
));
3117 /* Immediately move the result of the libcall into a pseudo
3118 register so reload doesn't clobber the value if it needs
3119 the return register for a spill reg. */
3120 result
= gen_reg_rtx (TYPE_MODE (integer_type_node
));
3121 emit_move_insn (result
,
3122 hard_libcall_value (TYPE_MODE (integer_type_node
)));
3123 emit_cmp_insn (result
,
3124 const0_rtx
, comparison
, NULL_RTX
,
3125 TYPE_MODE (integer_type_node
), 0, 0);
3130 /* Handle some compares against zero. */
3132 if (y
== CONST0_RTX (mode
)
3133 && tst_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
3135 int icode
= (int) tst_optab
->handlers
[(int) mode
].insn_code
;
3138 x
= protect_from_queue (x
, 0);
3139 y
= protect_from_queue (y
, 0);
3141 /* Now, if insn does accept these operands, put them into pseudos. */
3142 if (! (*insn_operand_predicate
[icode
][0])
3143 (x
, insn_operand_mode
[icode
][0]))
3144 x
= copy_to_mode_reg (insn_operand_mode
[icode
][0], x
);
3146 emit_insn (GEN_FCN (icode
) (x
));
3150 /* Handle compares for which there is a directly suitable insn. */
3152 if (cmp_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
3154 int icode
= (int) cmp_optab
->handlers
[(int) mode
].insn_code
;
3157 x
= protect_from_queue (x
, 0);
3158 y
= protect_from_queue (y
, 0);
3160 /* Now, if insn doesn't accept these operands, put them into pseudos. */
3161 if (! (*insn_operand_predicate
[icode
][0])
3162 (x
, insn_operand_mode
[icode
][0]))
3163 x
= copy_to_mode_reg (insn_operand_mode
[icode
][0], x
);
3165 if (! (*insn_operand_predicate
[icode
][1])
3166 (y
, insn_operand_mode
[icode
][1]))
3167 y
= copy_to_mode_reg (insn_operand_mode
[icode
][1], y
);
3169 emit_insn (GEN_FCN (icode
) (x
, y
));
3173 /* Try widening if we can find a direct insn that way. */
3175 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
3177 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
3178 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
3180 if (cmp_optab
->handlers
[(int) wider_mode
].insn_code
3181 != CODE_FOR_nothing
)
3183 x
= protect_from_queue (x
, 0);
3184 y
= protect_from_queue (y
, 0);
3185 x
= convert_modes (wider_mode
, mode
, x
, unsignedp
);
3186 y
= convert_modes (wider_mode
, mode
, y
, unsignedp
);
3187 emit_cmp_insn (x
, y
, comparison
, NULL_RTX
,
3188 wider_mode
, unsignedp
, align
);
3194 /* Handle a lib call just for the mode we are using. */
3196 if (cmp_optab
->handlers
[(int) mode
].libfunc
3197 && class != MODE_FLOAT
)
3199 rtx libfunc
= cmp_optab
->handlers
[(int) mode
].libfunc
;
3202 /* If we want unsigned, and this mode has a distinct unsigned
3203 comparison routine, use that. */
3204 if (unsignedp
&& ucmp_optab
->handlers
[(int) mode
].libfunc
)
3205 libfunc
= ucmp_optab
->handlers
[(int) mode
].libfunc
;
3207 emit_library_call (libfunc
, 1,
3208 word_mode
, 2, x
, mode
, y
, mode
);
3210 /* Immediately move the result of the libcall into a pseudo
3211 register so reload doesn't clobber the value if it needs
3212 the return register for a spill reg. */
3213 result
= gen_reg_rtx (word_mode
);
3214 emit_move_insn (result
, hard_libcall_value (word_mode
));
3216 /* Integer comparison returns a result that must be compared against 1,
3217 so that even if we do an unsigned compare afterward,
3218 there is still a value that can represent the result "less than". */
3219 emit_cmp_insn (result
, const1_rtx
,
3220 comparison
, NULL_RTX
, word_mode
, unsignedp
, 0);
3224 if (class == MODE_FLOAT
)
3225 emit_float_lib_cmp (x
, y
, comparison
);
3231 /* Generate code to compare X with Y so that the condition codes are
3232 set and to jump to LABEL if the condition is true. If X is a
3233 constant and Y is not a constant, then the comparison is swapped to
3234 ensure that the comparison RTL has the canonical form.
3236 UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
3237 need to be widened by emit_cmp_insn. UNSIGNEDP is also used to select
3238 the proper branch condition code.
3240 If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y,
3241 and ALIGN specifies the known shared alignment of X and Y.
3243 MODE is the mode of the inputs (in case they are const_int).
3245 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). It will
3246 be passed unchanged to emit_cmp_insn, then potentially converted into an
3247 unsigned variant based on UNSIGNEDP to select a proper jump instruction. */
3250 emit_cmp_and_jump_insns (x
, y
, comparison
, size
, mode
, unsignedp
, align
, label
)
3252 enum rtx_code comparison
;
3254 enum machine_mode mode
;
3264 /* Swap operands and condition to ensure canonical RTL. */
3267 comparison
= swap_condition (comparison
);
3276 /* If OP0 is still a constant, then both X and Y must be constants. Force
3277 X into a register to avoid aborting in emit_cmp_insn due to non-canonical
3279 if (CONSTANT_P (op0
))
3280 op0
= force_reg (mode
, op0
);
3283 emit_cmp_insn (op0
, op1
, comparison
, size
, mode
, unsignedp
, align
);
3286 comparison
= unsigned_condition (comparison
);
3287 emit_jump_insn ((*bcc_gen_fctn
[(int) comparison
]) (label
));
3291 /* Nonzero if a compare of mode MODE can be done straightforwardly
3292 (without splitting it into pieces). */
3295 can_compare_p (mode
)
3296 enum machine_mode mode
;
3300 if (cmp_optab
->handlers
[(int)mode
].insn_code
!= CODE_FOR_nothing
)
3302 mode
= GET_MODE_WIDER_MODE (mode
);
3303 } while (mode
!= VOIDmode
);
3308 /* Emit a library call comparison between floating point X and Y.
3309 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
3312 emit_float_lib_cmp (x
, y
, comparison
)
3314 enum rtx_code comparison
;
3316 enum machine_mode mode
= GET_MODE (x
);
3324 libfunc
= eqhf2_libfunc
;
3328 libfunc
= nehf2_libfunc
;
3332 libfunc
= gthf2_libfunc
;
3336 libfunc
= gehf2_libfunc
;
3340 libfunc
= lthf2_libfunc
;
3344 libfunc
= lehf2_libfunc
;
3350 else if (mode
== SFmode
)
3354 libfunc
= eqsf2_libfunc
;
3358 libfunc
= nesf2_libfunc
;
3362 libfunc
= gtsf2_libfunc
;
3366 libfunc
= gesf2_libfunc
;
3370 libfunc
= ltsf2_libfunc
;
3374 libfunc
= lesf2_libfunc
;
3380 else if (mode
== DFmode
)
3384 libfunc
= eqdf2_libfunc
;
3388 libfunc
= nedf2_libfunc
;
3392 libfunc
= gtdf2_libfunc
;
3396 libfunc
= gedf2_libfunc
;
3400 libfunc
= ltdf2_libfunc
;
3404 libfunc
= ledf2_libfunc
;
3410 else if (mode
== XFmode
)
3414 libfunc
= eqxf2_libfunc
;
3418 libfunc
= nexf2_libfunc
;
3422 libfunc
= gtxf2_libfunc
;
3426 libfunc
= gexf2_libfunc
;
3430 libfunc
= ltxf2_libfunc
;
3434 libfunc
= lexf2_libfunc
;
3440 else if (mode
== TFmode
)
3444 libfunc
= eqtf2_libfunc
;
3448 libfunc
= netf2_libfunc
;
3452 libfunc
= gttf2_libfunc
;
3456 libfunc
= getf2_libfunc
;
3460 libfunc
= lttf2_libfunc
;
3464 libfunc
= letf2_libfunc
;
3472 enum machine_mode wider_mode
;
3474 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
3475 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
3477 if ((cmp_optab
->handlers
[(int) wider_mode
].insn_code
3478 != CODE_FOR_nothing
)
3479 || (cmp_optab
->handlers
[(int) wider_mode
].libfunc
!= 0))
3481 x
= protect_from_queue (x
, 0);
3482 y
= protect_from_queue (y
, 0);
3483 x
= convert_to_mode (wider_mode
, x
, 0);
3484 y
= convert_to_mode (wider_mode
, y
, 0);
3485 emit_float_lib_cmp (x
, y
, comparison
);
3495 emit_library_call (libfunc
, 1,
3496 word_mode
, 2, x
, mode
, y
, mode
);
3498 /* Immediately move the result of the libcall into a pseudo
3499 register so reload doesn't clobber the value if it needs
3500 the return register for a spill reg. */
3501 result
= gen_reg_rtx (word_mode
);
3502 emit_move_insn (result
, hard_libcall_value (word_mode
));
3504 emit_cmp_insn (result
, const0_rtx
, comparison
,
3505 NULL_RTX
, word_mode
, 0, 0);
3508 /* Generate code to indirectly jump to a location given in the rtx LOC. */
3511 emit_indirect_jump (loc
)
3514 if (! ((*insn_operand_predicate
[(int)CODE_FOR_indirect_jump
][0])
3516 loc
= copy_to_mode_reg (Pmode
, loc
);
3518 emit_jump_insn (gen_indirect_jump (loc
));
3522 #ifdef HAVE_conditional_move
3524 /* Emit a conditional move instruction if the machine supports one for that
3525 condition and machine mode.
3527 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
3528 the mode to use should they be constants. If it is VOIDmode, they cannot
3531 OP2 should be stored in TARGET if the comparison is true, otherwise OP3
3532 should be stored there. MODE is the mode to use should they be constants.
3533 If it is VOIDmode, they cannot both be constants.
3535 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
3536 is not supported. */
3539 emit_conditional_move (target
, code
, op0
, op1
, cmode
, op2
, op3
, mode
,
3544 enum machine_mode cmode
;
3546 enum machine_mode mode
;
3549 rtx tem
, subtarget
, comparison
, insn
;
3550 enum insn_code icode
;
3552 /* If one operand is constant, make it the second one. Only do this
3553 if the other operand is not constant as well. */
3555 if ((CONSTANT_P (op0
) && ! CONSTANT_P (op1
))
3556 || (GET_CODE (op0
) == CONST_INT
&& GET_CODE (op1
) != CONST_INT
))
3561 code
= swap_condition (code
);
3564 if (cmode
== VOIDmode
)
3565 cmode
= GET_MODE (op0
);
3567 if (((CONSTANT_P (op2
) && ! CONSTANT_P (op3
))
3568 || (GET_CODE (op2
) == CONST_INT
&& GET_CODE (op3
) != CONST_INT
))
3569 && (GET_MODE_CLASS (GET_MODE (op1
)) != MODE_FLOAT
3570 || TARGET_FLOAT_FORMAT
!= IEEE_FLOAT_FORMAT
|| flag_fast_math
))
3575 code
= reverse_condition (code
);
3578 if (mode
== VOIDmode
)
3579 mode
= GET_MODE (op2
);
3581 icode
= movcc_gen_code
[mode
];
3583 if (icode
== CODE_FOR_nothing
)
3588 op2
= force_not_mem (op2
);
3589 op3
= force_not_mem (op3
);
3593 target
= protect_from_queue (target
, 1);
3595 target
= gen_reg_rtx (mode
);
3601 op2
= protect_from_queue (op2
, 0);
3602 op3
= protect_from_queue (op3
, 0);
3604 /* If the insn doesn't accept these operands, put them in pseudos. */
3606 if (! (*insn_operand_predicate
[icode
][0])
3607 (subtarget
, insn_operand_mode
[icode
][0]))
3608 subtarget
= gen_reg_rtx (insn_operand_mode
[icode
][0]);
3610 if (! (*insn_operand_predicate
[icode
][2])
3611 (op2
, insn_operand_mode
[icode
][2]))
3612 op2
= copy_to_mode_reg (insn_operand_mode
[icode
][2], op2
);
3614 if (! (*insn_operand_predicate
[icode
][3])
3615 (op3
, insn_operand_mode
[icode
][3]))
3616 op3
= copy_to_mode_reg (insn_operand_mode
[icode
][3], op3
);
3618 /* Everything should now be in the suitable form, so emit the compare insn
3619 and then the conditional move. */
3622 = compare_from_rtx (op0
, op1
, code
, unsignedp
, cmode
, NULL_RTX
, 0);
3624 /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)? */
3625 if (GET_CODE (comparison
) != code
)
3626 /* This shouldn't happen. */
3629 insn
= GEN_FCN (icode
) (subtarget
, comparison
, op2
, op3
);
3631 /* If that failed, then give up. */
3637 if (subtarget
!= target
)
3638 convert_move (target
, subtarget
, 0);
3643 /* Return non-zero if a conditional move of mode MODE is supported.
3645 This function is for combine so it can tell whether an insn that looks
3646 like a conditional move is actually supported by the hardware. If we
3647 guess wrong we lose a bit on optimization, but that's it. */
3648 /* ??? sparc64 supports conditionally moving integers values based on fp
3649 comparisons, and vice versa. How do we handle them? */
3652 can_conditionally_move_p (mode
)
3653 enum machine_mode mode
;
3655 if (movcc_gen_code
[mode
] != CODE_FOR_nothing
)
3661 #endif /* HAVE_conditional_move */
3663 /* These three functions generate an insn body and return it
3664 rather than emitting the insn.
3666 They do not protect from queued increments,
3667 because they may be used 1) in protect_from_queue itself
3668 and 2) in other passes where there is no queue. */
3670 /* Generate and return an insn body to add Y to X. */
3673 gen_add2_insn (x
, y
)
3676 int icode
= (int) add_optab
->handlers
[(int) GET_MODE (x
)].insn_code
;
3678 if (! (*insn_operand_predicate
[icode
][0]) (x
, insn_operand_mode
[icode
][0])
3679 || ! (*insn_operand_predicate
[icode
][1]) (x
, insn_operand_mode
[icode
][1])
3680 || ! (*insn_operand_predicate
[icode
][2]) (y
, insn_operand_mode
[icode
][2]))
3683 return (GEN_FCN (icode
) (x
, x
, y
));
3687 have_add2_insn (mode
)
3688 enum machine_mode mode
;
3690 return add_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
;
3693 /* Generate and return an insn body to subtract Y from X. */
3696 gen_sub2_insn (x
, y
)
3699 int icode
= (int) sub_optab
->handlers
[(int) GET_MODE (x
)].insn_code
;
3701 if (! (*insn_operand_predicate
[icode
][0]) (x
, insn_operand_mode
[icode
][0])
3702 || ! (*insn_operand_predicate
[icode
][1]) (x
, insn_operand_mode
[icode
][1])
3703 || ! (*insn_operand_predicate
[icode
][2]) (y
, insn_operand_mode
[icode
][2]))
3706 return (GEN_FCN (icode
) (x
, x
, y
));
3710 have_sub2_insn (mode
)
3711 enum machine_mode mode
;
3713 return sub_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
;
3716 /* Generate the body of an instruction to copy Y into X.
3717 It may be a SEQUENCE, if one insn isn't enough. */
3720 gen_move_insn (x
, y
)
3723 register enum machine_mode mode
= GET_MODE (x
);
3724 enum insn_code insn_code
;
3727 if (mode
== VOIDmode
)
3728 mode
= GET_MODE (y
);
3730 insn_code
= mov_optab
->handlers
[(int) mode
].insn_code
;
3732 /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
3733 find a mode to do it in. If we have a movcc, use it. Otherwise,
3734 find the MODE_INT mode of the same width. */
3736 if (GET_MODE_CLASS (mode
) == MODE_CC
&& insn_code
== CODE_FOR_nothing
)
3738 enum machine_mode tmode
= VOIDmode
;
3742 && mov_optab
->handlers
[(int) CCmode
].insn_code
!= CODE_FOR_nothing
)
3745 for (tmode
= QImode
; tmode
!= VOIDmode
;
3746 tmode
= GET_MODE_WIDER_MODE (tmode
))
3747 if (GET_MODE_SIZE (tmode
) == GET_MODE_SIZE (mode
))
3750 if (tmode
== VOIDmode
)
3753 /* Get X and Y in TMODE. We can't use gen_lowpart here because it
3754 may call change_address which is not appropriate if we were
3755 called when a reload was in progress. We don't have to worry
3756 about changing the address since the size in bytes is supposed to
3757 be the same. Copy the MEM to change the mode and move any
3758 substitutions from the old MEM to the new one. */
3760 if (reload_in_progress
)
3762 x
= gen_lowpart_common (tmode
, x1
);
3763 if (x
== 0 && GET_CODE (x1
) == MEM
)
3765 x
= gen_rtx_MEM (tmode
, XEXP (x1
, 0));
3766 RTX_UNCHANGING_P (x
) = RTX_UNCHANGING_P (x1
);
3767 MEM_COPY_ATTRIBUTES (x
, x1
);
3768 copy_replacements (x1
, x
);
3771 y
= gen_lowpart_common (tmode
, y1
);
3772 if (y
== 0 && GET_CODE (y1
) == MEM
)
3774 y
= gen_rtx_MEM (tmode
, XEXP (y1
, 0));
3775 RTX_UNCHANGING_P (y
) = RTX_UNCHANGING_P (y1
);
3776 MEM_COPY_ATTRIBUTES (y
, y1
);
3777 copy_replacements (y1
, y
);
3782 x
= gen_lowpart (tmode
, x
);
3783 y
= gen_lowpart (tmode
, y
);
3786 insn_code
= mov_optab
->handlers
[(int) tmode
].insn_code
;
3787 return (GEN_FCN (insn_code
) (x
, y
));
3791 emit_move_insn_1 (x
, y
);
3792 seq
= gen_sequence ();
3797 /* Return the insn code used to extend FROM_MODE to TO_MODE.
3798 UNSIGNEDP specifies zero-extension instead of sign-extension. If
3799 no such operation exists, CODE_FOR_nothing will be returned. */
3802 can_extend_p (to_mode
, from_mode
, unsignedp
)
3803 enum machine_mode to_mode
, from_mode
;
3806 return extendtab
[(int) to_mode
][(int) from_mode
][unsignedp
];
3809 /* Generate the body of an insn to extend Y (with mode MFROM)
3810 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
3813 gen_extend_insn (x
, y
, mto
, mfrom
, unsignedp
)
3815 enum machine_mode mto
, mfrom
;
3818 return (GEN_FCN (extendtab
[(int) mto
][(int) mfrom
][unsignedp
]) (x
, y
));
3821 /* can_fix_p and can_float_p say whether the target machine
3822 can directly convert a given fixed point type to
3823 a given floating point type, or vice versa.
3824 The returned value is the CODE_FOR_... value to use,
3825 or CODE_FOR_nothing if these modes cannot be directly converted.
3827 *TRUNCP_PTR is set to 1 if it is necessary to output
3828 an explicit FTRUNC insn before the fix insn; otherwise 0. */
3830 static enum insn_code
3831 can_fix_p (fixmode
, fltmode
, unsignedp
, truncp_ptr
)
3832 enum machine_mode fltmode
, fixmode
;
3837 if (fixtrunctab
[(int) fltmode
][(int) fixmode
][unsignedp
] != CODE_FOR_nothing
)
3838 return fixtrunctab
[(int) fltmode
][(int) fixmode
][unsignedp
];
3840 if (ftrunc_optab
->handlers
[(int) fltmode
].insn_code
!= CODE_FOR_nothing
)
3843 return fixtab
[(int) fltmode
][(int) fixmode
][unsignedp
];
3845 return CODE_FOR_nothing
;
3848 static enum insn_code
3849 can_float_p (fltmode
, fixmode
, unsignedp
)
3850 enum machine_mode fixmode
, fltmode
;
3853 return floattab
[(int) fltmode
][(int) fixmode
][unsignedp
];
3856 /* Generate code to convert FROM to floating point
3857 and store in TO. FROM must be fixed point and not VOIDmode.
3858 UNSIGNEDP nonzero means regard FROM as unsigned.
3859 Normally this is done by correcting the final value
3860 if it is negative. */
3863 expand_float (to
, from
, unsignedp
)
3867 enum insn_code icode
;
3868 register rtx target
= to
;
3869 enum machine_mode fmode
, imode
;
3871 /* Crash now, because we won't be able to decide which mode to use. */
3872 if (GET_MODE (from
) == VOIDmode
)
3875 /* Look for an insn to do the conversion. Do it in the specified
3876 modes if possible; otherwise convert either input, output or both to
3877 wider mode. If the integer mode is wider than the mode of FROM,
3878 we can do the conversion signed even if the input is unsigned. */
3880 for (imode
= GET_MODE (from
); imode
!= VOIDmode
;
3881 imode
= GET_MODE_WIDER_MODE (imode
))
3882 for (fmode
= GET_MODE (to
); fmode
!= VOIDmode
;
3883 fmode
= GET_MODE_WIDER_MODE (fmode
))
3885 int doing_unsigned
= unsignedp
;
3887 icode
= can_float_p (fmode
, imode
, unsignedp
);
3888 if (icode
== CODE_FOR_nothing
&& imode
!= GET_MODE (from
) && unsignedp
)
3889 icode
= can_float_p (fmode
, imode
, 0), doing_unsigned
= 0;
3891 if (icode
!= CODE_FOR_nothing
)
3893 to
= protect_from_queue (to
, 1);
3894 from
= protect_from_queue (from
, 0);
3896 if (imode
!= GET_MODE (from
))
3897 from
= convert_to_mode (imode
, from
, unsignedp
);
3899 if (fmode
!= GET_MODE (to
))
3900 target
= gen_reg_rtx (fmode
);
3902 emit_unop_insn (icode
, target
, from
,
3903 doing_unsigned
? UNSIGNED_FLOAT
: FLOAT
);
3906 convert_move (to
, target
, 0);
3911 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3913 /* Unsigned integer, and no way to convert directly.
3914 Convert as signed, then conditionally adjust the result. */
3917 rtx label
= gen_label_rtx ();
3919 REAL_VALUE_TYPE offset
;
3923 to
= protect_from_queue (to
, 1);
3924 from
= protect_from_queue (from
, 0);
3927 from
= force_not_mem (from
);
3929 /* Look for a usable floating mode FMODE wider than the source and at
3930 least as wide as the target. Using FMODE will avoid rounding woes
3931 with unsigned values greater than the signed maximum value. */
3933 for (fmode
= GET_MODE (to
); fmode
!= VOIDmode
;
3934 fmode
= GET_MODE_WIDER_MODE (fmode
))
3935 if (GET_MODE_BITSIZE (GET_MODE (from
)) < GET_MODE_BITSIZE (fmode
)
3936 && can_float_p (fmode
, GET_MODE (from
), 0) != CODE_FOR_nothing
)
3939 if (fmode
== VOIDmode
)
3941 /* There is no such mode. Pretend the target is wide enough. */
3942 fmode
= GET_MODE (to
);
3944 /* Avoid double-rounding when TO is narrower than FROM. */
3945 if ((significand_size (fmode
) + 1)
3946 < GET_MODE_BITSIZE (GET_MODE (from
)))
3949 rtx neglabel
= gen_label_rtx ();
3951 /* Don't use TARGET if it isn't a register, is a hard register,
3952 or is the wrong mode. */
3953 if (GET_CODE (target
) != REG
3954 || REGNO (target
) < FIRST_PSEUDO_REGISTER
3955 || GET_MODE (target
) != fmode
)
3956 target
= gen_reg_rtx (fmode
);
3958 imode
= GET_MODE (from
);
3959 do_pending_stack_adjust ();
3961 /* Test whether the sign bit is set. */
3962 emit_cmp_insn (from
, const0_rtx
, GE
, NULL_RTX
, imode
, 0, 0);
3963 emit_jump_insn (gen_blt (neglabel
));
3965 /* The sign bit is not set. Convert as signed. */
3966 expand_float (target
, from
, 0);
3967 emit_jump_insn (gen_jump (label
));
3970 /* The sign bit is set.
3971 Convert to a usable (positive signed) value by shifting right
3972 one bit, while remembering if a nonzero bit was shifted
3973 out; i.e., compute (from & 1) | (from >> 1). */
3975 emit_label (neglabel
);
3976 temp
= expand_binop (imode
, and_optab
, from
, const1_rtx
,
3977 NULL_RTX
, 1, OPTAB_LIB_WIDEN
);
3978 temp1
= expand_shift (RSHIFT_EXPR
, imode
, from
, integer_one_node
,
3980 temp
= expand_binop (imode
, ior_optab
, temp
, temp1
, temp
, 1,
3982 expand_float (target
, temp
, 0);
3984 /* Multiply by 2 to undo the shift above. */
3985 temp
= expand_binop (fmode
, add_optab
, target
, target
,
3986 target
, 0, OPTAB_LIB_WIDEN
);
3988 emit_move_insn (target
, temp
);
3990 do_pending_stack_adjust ();
3996 /* If we are about to do some arithmetic to correct for an
3997 unsigned operand, do it in a pseudo-register. */
3999 if (GET_MODE (to
) != fmode
4000 || GET_CODE (to
) != REG
|| REGNO (to
) < FIRST_PSEUDO_REGISTER
)
4001 target
= gen_reg_rtx (fmode
);
4003 /* Convert as signed integer to floating. */
4004 expand_float (target
, from
, 0);
4006 /* If FROM is negative (and therefore TO is negative),
4007 correct its value by 2**bitwidth. */
4009 do_pending_stack_adjust ();
4010 emit_cmp_and_jump_insns (from
, const0_rtx
, GE
, NULL_RTX
, GET_MODE (from
),
4013 /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
4014 Rather than setting up a dconst_dot_5, let's hope SCO
4016 offset
= REAL_VALUE_LDEXP (dconst1
, GET_MODE_BITSIZE (GET_MODE (from
)));
4017 temp
= expand_binop (fmode
, add_optab
, target
,
4018 CONST_DOUBLE_FROM_REAL_VALUE (offset
, fmode
),
4019 target
, 0, OPTAB_LIB_WIDEN
);
4021 emit_move_insn (target
, temp
);
4023 do_pending_stack_adjust ();
4029 /* No hardware instruction available; call a library routine to convert from
4030 SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */
4036 to
= protect_from_queue (to
, 1);
4037 from
= protect_from_queue (from
, 0);
4039 if (GET_MODE_SIZE (GET_MODE (from
)) < GET_MODE_SIZE (SImode
))
4040 from
= convert_to_mode (SImode
, from
, unsignedp
);
4043 from
= force_not_mem (from
);
4045 if (GET_MODE (to
) == SFmode
)
4047 if (GET_MODE (from
) == SImode
)
4048 libfcn
= floatsisf_libfunc
;
4049 else if (GET_MODE (from
) == DImode
)
4050 libfcn
= floatdisf_libfunc
;
4051 else if (GET_MODE (from
) == TImode
)
4052 libfcn
= floattisf_libfunc
;
4056 else if (GET_MODE (to
) == DFmode
)
4058 if (GET_MODE (from
) == SImode
)
4059 libfcn
= floatsidf_libfunc
;
4060 else if (GET_MODE (from
) == DImode
)
4061 libfcn
= floatdidf_libfunc
;
4062 else if (GET_MODE (from
) == TImode
)
4063 libfcn
= floattidf_libfunc
;
4067 else if (GET_MODE (to
) == XFmode
)
4069 if (GET_MODE (from
) == SImode
)
4070 libfcn
= floatsixf_libfunc
;
4071 else if (GET_MODE (from
) == DImode
)
4072 libfcn
= floatdixf_libfunc
;
4073 else if (GET_MODE (from
) == TImode
)
4074 libfcn
= floattixf_libfunc
;
4078 else if (GET_MODE (to
) == TFmode
)
4080 if (GET_MODE (from
) == SImode
)
4081 libfcn
= floatsitf_libfunc
;
4082 else if (GET_MODE (from
) == DImode
)
4083 libfcn
= floatditf_libfunc
;
4084 else if (GET_MODE (from
) == TImode
)
4085 libfcn
= floattitf_libfunc
;
4094 value
= emit_library_call_value (libfcn
, NULL_RTX
, 1,
4096 1, from
, GET_MODE (from
));
4097 insns
= get_insns ();
4100 emit_libcall_block (insns
, target
, value
,
4101 gen_rtx_FLOAT (GET_MODE (to
), from
));
4106 /* Copy result to requested destination
4107 if we have been computing in a temp location. */
4111 if (GET_MODE (target
) == GET_MODE (to
))
4112 emit_move_insn (to
, target
);
4114 convert_move (to
, target
, 0);
4118 /* expand_fix: generate code to convert FROM to fixed point
4119 and store in TO. FROM must be floating point. */
4125 rtx temp
= gen_reg_rtx (GET_MODE (x
));
4126 return expand_unop (GET_MODE (x
), ftrunc_optab
, x
, temp
, 0);
4130 expand_fix (to
, from
, unsignedp
)
4131 register rtx to
, from
;
4134 enum insn_code icode
;
4135 register rtx target
= to
;
4136 enum machine_mode fmode
, imode
;
4140 /* We first try to find a pair of modes, one real and one integer, at
4141 least as wide as FROM and TO, respectively, in which we can open-code
4142 this conversion. If the integer mode is wider than the mode of TO,
4143 we can do the conversion either signed or unsigned. */
4145 for (imode
= GET_MODE (to
); imode
!= VOIDmode
;
4146 imode
= GET_MODE_WIDER_MODE (imode
))
4147 for (fmode
= GET_MODE (from
); fmode
!= VOIDmode
;
4148 fmode
= GET_MODE_WIDER_MODE (fmode
))
4150 int doing_unsigned
= unsignedp
;
4152 icode
= can_fix_p (imode
, fmode
, unsignedp
, &must_trunc
);
4153 if (icode
== CODE_FOR_nothing
&& imode
!= GET_MODE (to
) && unsignedp
)
4154 icode
= can_fix_p (imode
, fmode
, 0, &must_trunc
), doing_unsigned
= 0;
4156 if (icode
!= CODE_FOR_nothing
)
4158 to
= protect_from_queue (to
, 1);
4159 from
= protect_from_queue (from
, 0);
4161 if (fmode
!= GET_MODE (from
))
4162 from
= convert_to_mode (fmode
, from
, 0);
4165 from
= ftruncify (from
);
4167 if (imode
!= GET_MODE (to
))
4168 target
= gen_reg_rtx (imode
);
4170 emit_unop_insn (icode
, target
, from
,
4171 doing_unsigned
? UNSIGNED_FIX
: FIX
);
4173 convert_move (to
, target
, unsignedp
);
4178 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
4179 /* For an unsigned conversion, there is one more way to do it.
4180 If we have a signed conversion, we generate code that compares
4181 the real value to the largest representable positive number. If if
4182 is smaller, the conversion is done normally. Otherwise, subtract
4183 one plus the highest signed number, convert, and add it back.
4185 We only need to check all real modes, since we know we didn't find
4186 anything with a wider integer mode. */
4188 if (unsignedp
&& GET_MODE_BITSIZE (GET_MODE (to
)) <= HOST_BITS_PER_WIDE_INT
)
4189 for (fmode
= GET_MODE (from
); fmode
!= VOIDmode
;
4190 fmode
= GET_MODE_WIDER_MODE (fmode
))
4191 /* Make sure we won't lose significant bits doing this. */
4192 if (GET_MODE_BITSIZE (fmode
) > GET_MODE_BITSIZE (GET_MODE (to
))
4193 && CODE_FOR_nothing
!= can_fix_p (GET_MODE (to
), fmode
, 0,
4197 REAL_VALUE_TYPE offset
;
4198 rtx limit
, lab1
, lab2
, insn
;
4200 bitsize
= GET_MODE_BITSIZE (GET_MODE (to
));
4201 offset
= REAL_VALUE_LDEXP (dconst1
, bitsize
- 1);
4202 limit
= CONST_DOUBLE_FROM_REAL_VALUE (offset
, fmode
);
4203 lab1
= gen_label_rtx ();
4204 lab2
= gen_label_rtx ();
4207 to
= protect_from_queue (to
, 1);
4208 from
= protect_from_queue (from
, 0);
4211 from
= force_not_mem (from
);
4213 if (fmode
!= GET_MODE (from
))
4214 from
= convert_to_mode (fmode
, from
, 0);
4216 /* See if we need to do the subtraction. */
4217 do_pending_stack_adjust ();
4218 emit_cmp_and_jump_insns (from
, limit
, GE
, NULL_RTX
, GET_MODE (from
),
4221 /* If not, do the signed "fix" and branch around fixup code. */
4222 expand_fix (to
, from
, 0);
4223 emit_jump_insn (gen_jump (lab2
));
4226 /* Otherwise, subtract 2**(N-1), convert to signed number,
4227 then add 2**(N-1). Do the addition using XOR since this
4228 will often generate better code. */
4230 target
= expand_binop (GET_MODE (from
), sub_optab
, from
, limit
,
4231 NULL_RTX
, 0, OPTAB_LIB_WIDEN
);
4232 expand_fix (to
, target
, 0);
4233 target
= expand_binop (GET_MODE (to
), xor_optab
, to
,
4234 GEN_INT ((HOST_WIDE_INT
) 1 << (bitsize
- 1)),
4235 to
, 1, OPTAB_LIB_WIDEN
);
4238 emit_move_insn (to
, target
);
4242 if (mov_optab
->handlers
[(int) GET_MODE (to
)].insn_code
4243 != CODE_FOR_nothing
)
4245 /* Make a place for a REG_NOTE and add it. */
4246 insn
= emit_move_insn (to
, to
);
4247 set_unique_reg_note (insn
,
4249 gen_rtx_fmt_e (UNSIGNED_FIX
,
4257 /* We can't do it with an insn, so use a library call. But first ensure
4258 that the mode of TO is at least as wide as SImode, since those are the
4259 only library calls we know about. */
4261 if (GET_MODE_SIZE (GET_MODE (to
)) < GET_MODE_SIZE (SImode
))
4263 target
= gen_reg_rtx (SImode
);
4265 expand_fix (target
, from
, unsignedp
);
4267 else if (GET_MODE (from
) == SFmode
)
4269 if (GET_MODE (to
) == SImode
)
4270 libfcn
= unsignedp
? fixunssfsi_libfunc
: fixsfsi_libfunc
;
4271 else if (GET_MODE (to
) == DImode
)
4272 libfcn
= unsignedp
? fixunssfdi_libfunc
: fixsfdi_libfunc
;
4273 else if (GET_MODE (to
) == TImode
)
4274 libfcn
= unsignedp
? fixunssfti_libfunc
: fixsfti_libfunc
;
4278 else if (GET_MODE (from
) == DFmode
)
4280 if (GET_MODE (to
) == SImode
)
4281 libfcn
= unsignedp
? fixunsdfsi_libfunc
: fixdfsi_libfunc
;
4282 else if (GET_MODE (to
) == DImode
)
4283 libfcn
= unsignedp
? fixunsdfdi_libfunc
: fixdfdi_libfunc
;
4284 else if (GET_MODE (to
) == TImode
)
4285 libfcn
= unsignedp
? fixunsdfti_libfunc
: fixdfti_libfunc
;
4289 else if (GET_MODE (from
) == XFmode
)
4291 if (GET_MODE (to
) == SImode
)
4292 libfcn
= unsignedp
? fixunsxfsi_libfunc
: fixxfsi_libfunc
;
4293 else if (GET_MODE (to
) == DImode
)
4294 libfcn
= unsignedp
? fixunsxfdi_libfunc
: fixxfdi_libfunc
;
4295 else if (GET_MODE (to
) == TImode
)
4296 libfcn
= unsignedp
? fixunsxfti_libfunc
: fixxfti_libfunc
;
4300 else if (GET_MODE (from
) == TFmode
)
4302 if (GET_MODE (to
) == SImode
)
4303 libfcn
= unsignedp
? fixunstfsi_libfunc
: fixtfsi_libfunc
;
4304 else if (GET_MODE (to
) == DImode
)
4305 libfcn
= unsignedp
? fixunstfdi_libfunc
: fixtfdi_libfunc
;
4306 else if (GET_MODE (to
) == TImode
)
4307 libfcn
= unsignedp
? fixunstfti_libfunc
: fixtfti_libfunc
;
4319 to
= protect_from_queue (to
, 1);
4320 from
= protect_from_queue (from
, 0);
4323 from
= force_not_mem (from
);
4327 value
= emit_library_call_value (libfcn
, NULL_RTX
, 1, GET_MODE (to
),
4329 1, from
, GET_MODE (from
));
4330 insns
= get_insns ();
4333 emit_libcall_block (insns
, target
, value
,
4334 gen_rtx_fmt_e (unsignedp
? UNSIGNED_FIX
: FIX
,
4335 GET_MODE (to
), from
));
4340 if (GET_MODE (to
) == GET_MODE (target
))
4341 emit_move_insn (to
, target
);
4343 convert_move (to
, target
, 0);
4352 optab op
= (optab
) xmalloc (sizeof (struct optab
));
4354 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
4356 op
->handlers
[i
].insn_code
= CODE_FOR_nothing
;
4357 op
->handlers
[i
].libfunc
= 0;
4360 if (code
!= UNKNOWN
)
4361 code_to_optab
[(int) code
] = op
;
4366 /* Initialize the libfunc fields of an entire group of entries in some
4367 optab. Each entry is set equal to a string consisting of a leading
4368 pair of underscores followed by a generic operation name followed by
4369 a mode name (downshifted to lower case) followed by a single character
4370 representing the number of operands for the given operation (which is
4371 usually one of the characters '2', '3', or '4').
4373 OPTABLE is the table in which libfunc fields are to be initialized.
4374 FIRST_MODE is the first machine mode index in the given optab to
4376 LAST_MODE is the last machine mode index in the given optab to
4378 OPNAME is the generic (string) name of the operation.
4379 SUFFIX is the character which specifies the number of operands for
4380 the given generic operation.
4384 init_libfuncs (optable
, first_mode
, last_mode
, opname
, suffix
)
4385 register optab optable
;
4386 register int first_mode
;
4387 register int last_mode
;
4388 register const char *opname
;
4389 register int suffix
;
4392 register unsigned opname_len
= strlen (opname
);
4394 for (mode
= first_mode
; (int) mode
<= (int) last_mode
;
4395 mode
= (enum machine_mode
) ((int) mode
+ 1))
4397 register char *mname
= mode_name
[(int) mode
];
4398 register unsigned mname_len
= strlen (mname
);
4399 register char *libfunc_name
4400 = (char *) xmalloc (2 + opname_len
+ mname_len
+ 1 + 1);
4402 register const char *q
;
4407 for (q
= opname
; *q
; )
4409 for (q
= mname
; *q
; q
++)
4410 *p
++ = tolower ((unsigned char)*q
);
4413 optable
->handlers
[(int) mode
].libfunc
4414 = gen_rtx_SYMBOL_REF (Pmode
, libfunc_name
);
4418 /* Initialize the libfunc fields of an entire group of entries in some
4419 optab which correspond to all integer mode operations. The parameters
4420 have the same meaning as similarly named ones for the `init_libfuncs'
4421 routine. (See above). */
4424 init_integral_libfuncs (optable
, opname
, suffix
)
4425 register optab optable
;
4426 register const char *opname
;
4427 register int suffix
;
4429 init_libfuncs (optable
, SImode
, TImode
, opname
, suffix
);
4432 /* Initialize the libfunc fields of an entire group of entries in some
4433 optab which correspond to all real mode operations. The parameters
4434 have the same meaning as similarly named ones for the `init_libfuncs'
4435 routine. (See above). */
4438 init_floating_libfuncs (optable
, opname
, suffix
)
4439 register optab optable
;
4440 register const char *opname
;
4441 register int suffix
;
4443 init_libfuncs (optable
, SFmode
, TFmode
, opname
, suffix
);
4447 /* Call this once to initialize the contents of the optabs
4448 appropriately for the current target machine. */
4454 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
4460 /* Start by initializing all tables to contain CODE_FOR_nothing. */
4462 for (p
= fixtab
[0][0];
4463 p
< fixtab
[0][0] + sizeof fixtab
/ sizeof (fixtab
[0][0][0]);
4465 *p
= CODE_FOR_nothing
;
4467 for (p
= fixtrunctab
[0][0];
4468 p
< fixtrunctab
[0][0] + sizeof fixtrunctab
/ sizeof (fixtrunctab
[0][0][0]);
4470 *p
= CODE_FOR_nothing
;
4472 for (p
= floattab
[0][0];
4473 p
< floattab
[0][0] + sizeof floattab
/ sizeof (floattab
[0][0][0]);
4475 *p
= CODE_FOR_nothing
;
4477 for (p
= extendtab
[0][0];
4478 p
< extendtab
[0][0] + sizeof extendtab
/ sizeof extendtab
[0][0][0];
4480 *p
= CODE_FOR_nothing
;
4482 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
4483 setcc_gen_code
[i
] = CODE_FOR_nothing
;
4485 #ifdef HAVE_conditional_move
4486 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
4487 movcc_gen_code
[i
] = CODE_FOR_nothing
;
4490 add_optab
= init_optab (PLUS
);
4491 sub_optab
= init_optab (MINUS
);
4492 smul_optab
= init_optab (MULT
);
4493 smul_highpart_optab
= init_optab (UNKNOWN
);
4494 umul_highpart_optab
= init_optab (UNKNOWN
);
4495 smul_widen_optab
= init_optab (UNKNOWN
);
4496 umul_widen_optab
= init_optab (UNKNOWN
);
4497 sdiv_optab
= init_optab (DIV
);
4498 sdivmod_optab
= init_optab (UNKNOWN
);
4499 udiv_optab
= init_optab (UDIV
);
4500 udivmod_optab
= init_optab (UNKNOWN
);
4501 smod_optab
= init_optab (MOD
);
4502 umod_optab
= init_optab (UMOD
);
4503 flodiv_optab
= init_optab (DIV
);
4504 ftrunc_optab
= init_optab (UNKNOWN
);
4505 and_optab
= init_optab (AND
);
4506 ior_optab
= init_optab (IOR
);
4507 xor_optab
= init_optab (XOR
);
4508 ashl_optab
= init_optab (ASHIFT
);
4509 ashr_optab
= init_optab (ASHIFTRT
);
4510 lshr_optab
= init_optab (LSHIFTRT
);
4511 rotl_optab
= init_optab (ROTATE
);
4512 rotr_optab
= init_optab (ROTATERT
);
4513 smin_optab
= init_optab (SMIN
);
4514 smax_optab
= init_optab (SMAX
);
4515 umin_optab
= init_optab (UMIN
);
4516 umax_optab
= init_optab (UMAX
);
4517 mov_optab
= init_optab (UNKNOWN
);
4518 movstrict_optab
= init_optab (UNKNOWN
);
4519 cmp_optab
= init_optab (UNKNOWN
);
4520 ucmp_optab
= init_optab (UNKNOWN
);
4521 tst_optab
= init_optab (UNKNOWN
);
4522 neg_optab
= init_optab (NEG
);
4523 abs_optab
= init_optab (ABS
);
4524 one_cmpl_optab
= init_optab (NOT
);
4525 ffs_optab
= init_optab (FFS
);
4526 sqrt_optab
= init_optab (SQRT
);
4527 sin_optab
= init_optab (UNKNOWN
);
4528 cos_optab
= init_optab (UNKNOWN
);
4529 strlen_optab
= init_optab (UNKNOWN
);
4531 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
4533 movstr_optab
[i
] = CODE_FOR_nothing
;
4534 clrstr_optab
[i
] = CODE_FOR_nothing
;
4536 #ifdef HAVE_SECONDARY_RELOADS
4537 reload_in_optab
[i
] = reload_out_optab
[i
] = CODE_FOR_nothing
;
4541 /* Fill in the optabs with the insns we support. */
4544 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
4545 /* This flag says the same insns that convert to a signed fixnum
4546 also convert validly to an unsigned one. */
4547 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
4548 for (j
= 0; j
< NUM_MACHINE_MODES
; j
++)
4549 fixtrunctab
[i
][j
][1] = fixtrunctab
[i
][j
][0];
4552 #ifdef EXTRA_CC_MODES
4556 /* Initialize the optabs with the names of the library functions. */
4557 init_integral_libfuncs (add_optab
, "add", '3');
4558 init_floating_libfuncs (add_optab
, "add", '3');
4559 init_integral_libfuncs (sub_optab
, "sub", '3');
4560 init_floating_libfuncs (sub_optab
, "sub", '3');
4561 init_integral_libfuncs (smul_optab
, "mul", '3');
4562 init_floating_libfuncs (smul_optab
, "mul", '3');
4563 init_integral_libfuncs (sdiv_optab
, "div", '3');
4564 init_integral_libfuncs (udiv_optab
, "udiv", '3');
4565 init_integral_libfuncs (sdivmod_optab
, "divmod", '4');
4566 init_integral_libfuncs (udivmod_optab
, "udivmod", '4');
4567 init_integral_libfuncs (smod_optab
, "mod", '3');
4568 init_integral_libfuncs (umod_optab
, "umod", '3');
4569 init_floating_libfuncs (flodiv_optab
, "div", '3');
4570 init_floating_libfuncs (ftrunc_optab
, "ftrunc", '2');
4571 init_integral_libfuncs (and_optab
, "and", '3');
4572 init_integral_libfuncs (ior_optab
, "ior", '3');
4573 init_integral_libfuncs (xor_optab
, "xor", '3');
4574 init_integral_libfuncs (ashl_optab
, "ashl", '3');
4575 init_integral_libfuncs (ashr_optab
, "ashr", '3');
4576 init_integral_libfuncs (lshr_optab
, "lshr", '3');
4577 init_integral_libfuncs (smin_optab
, "min", '3');
4578 init_floating_libfuncs (smin_optab
, "min", '3');
4579 init_integral_libfuncs (smax_optab
, "max", '3');
4580 init_floating_libfuncs (smax_optab
, "max", '3');
4581 init_integral_libfuncs (umin_optab
, "umin", '3');
4582 init_integral_libfuncs (umax_optab
, "umax", '3');
4583 init_integral_libfuncs (neg_optab
, "neg", '2');
4584 init_floating_libfuncs (neg_optab
, "neg", '2');
4585 init_integral_libfuncs (one_cmpl_optab
, "one_cmpl", '2');
4586 init_integral_libfuncs (ffs_optab
, "ffs", '2');
4588 /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
4589 init_integral_libfuncs (cmp_optab
, "cmp", '2');
4590 init_integral_libfuncs (ucmp_optab
, "ucmp", '2');
4591 init_floating_libfuncs (cmp_optab
, "cmp", '2');
4593 #ifdef MULSI3_LIBCALL
4594 smul_optab
->handlers
[(int) SImode
].libfunc
4595 = gen_rtx_SYMBOL_REF (Pmode
, MULSI3_LIBCALL
);
4597 #ifdef MULDI3_LIBCALL
4598 smul_optab
->handlers
[(int) DImode
].libfunc
4599 = gen_rtx_SYMBOL_REF (Pmode
, MULDI3_LIBCALL
);
4602 #ifdef DIVSI3_LIBCALL
4603 sdiv_optab
->handlers
[(int) SImode
].libfunc
4604 = gen_rtx_SYMBOL_REF (Pmode
, DIVSI3_LIBCALL
);
4606 #ifdef DIVDI3_LIBCALL
4607 sdiv_optab
->handlers
[(int) DImode
].libfunc
4608 = gen_rtx_SYMBOL_REF (Pmode
, DIVDI3_LIBCALL
);
4611 #ifdef UDIVSI3_LIBCALL
4612 udiv_optab
->handlers
[(int) SImode
].libfunc
4613 = gen_rtx_SYMBOL_REF (Pmode
, UDIVSI3_LIBCALL
);
4615 #ifdef UDIVDI3_LIBCALL
4616 udiv_optab
->handlers
[(int) DImode
].libfunc
4617 = gen_rtx_SYMBOL_REF (Pmode
, UDIVDI3_LIBCALL
);
4620 #ifdef MODSI3_LIBCALL
4621 smod_optab
->handlers
[(int) SImode
].libfunc
4622 = gen_rtx_SYMBOL_REF (Pmode
, MODSI3_LIBCALL
);
4624 #ifdef MODDI3_LIBCALL
4625 smod_optab
->handlers
[(int) DImode
].libfunc
4626 = gen_rtx_SYMBOL_REF (Pmode
, MODDI3_LIBCALL
);
4629 #ifdef UMODSI3_LIBCALL
4630 umod_optab
->handlers
[(int) SImode
].libfunc
4631 = gen_rtx_SYMBOL_REF (Pmode
, UMODSI3_LIBCALL
);
4633 #ifdef UMODDI3_LIBCALL
4634 umod_optab
->handlers
[(int) DImode
].libfunc
4635 = gen_rtx_SYMBOL_REF (Pmode
, UMODDI3_LIBCALL
);
4638 /* Use cabs for DC complex abs, since systems generally have cabs.
4639 Don't define any libcall for SCmode, so that cabs will be used. */
4640 abs_optab
->handlers
[(int) DCmode
].libfunc
4641 = gen_rtx_SYMBOL_REF (Pmode
, "cabs");
4643 /* The ffs function operates on `int'. */
4644 #ifndef INT_TYPE_SIZE
4645 #define INT_TYPE_SIZE BITS_PER_WORD
4647 ffs_optab
->handlers
[(int) mode_for_size (INT_TYPE_SIZE
, MODE_INT
, 0)] .libfunc
4648 = gen_rtx_SYMBOL_REF (Pmode
, "ffs");
4650 extendsfdf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__extendsfdf2");
4651 extendsfxf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__extendsfxf2");
4652 extendsftf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__extendsftf2");
4653 extenddfxf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__extenddfxf2");
4654 extenddftf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__extenddftf2");
4656 truncdfsf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__truncdfsf2");
4657 truncxfsf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__truncxfsf2");
4658 trunctfsf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__trunctfsf2");
4659 truncxfdf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__truncxfdf2");
4660 trunctfdf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__trunctfdf2");
4662 memcpy_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "memcpy");
4663 bcopy_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "bcopy");
4664 memcmp_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "memcmp");
4665 bcmp_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gcc_bcmp");
4666 memset_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "memset");
4667 bzero_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "bzero");
4669 throw_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__throw");
4670 rethrow_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__rethrow");
4671 sjthrow_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__sjthrow");
4672 sjpopnthrow_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__sjpopnthrow");
4673 terminate_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__terminate");
4674 eh_rtime_match_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__eh_rtime_match");
4675 #ifndef DONT_USE_BUILTIN_SETJMP
4676 setjmp_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__builtin_setjmp");
4677 longjmp_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__builtin_longjmp");
4679 setjmp_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "setjmp");
4680 longjmp_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "longjmp");
4683 eqhf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__eqhf2");
4684 nehf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__nehf2");
4685 gthf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gthf2");
4686 gehf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gehf2");
4687 lthf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__lthf2");
4688 lehf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__lehf2");
4690 eqsf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__eqsf2");
4691 nesf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__nesf2");
4692 gtsf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gtsf2");
4693 gesf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gesf2");
4694 ltsf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__ltsf2");
4695 lesf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__lesf2");
4697 eqdf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__eqdf2");
4698 nedf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__nedf2");
4699 gtdf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gtdf2");
4700 gedf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gedf2");
4701 ltdf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__ltdf2");
4702 ledf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__ledf2");
4704 eqxf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__eqxf2");
4705 nexf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__nexf2");
4706 gtxf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gtxf2");
4707 gexf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gexf2");
4708 ltxf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__ltxf2");
4709 lexf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__lexf2");
4711 eqtf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__eqtf2");
4712 netf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__netf2");
4713 gttf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gttf2");
4714 getf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__getf2");
4715 lttf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__lttf2");
4716 letf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__letf2");
4718 floatsisf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatsisf");
4719 floatdisf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatdisf");
4720 floattisf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floattisf");
4722 floatsidf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatsidf");
4723 floatdidf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatdidf");
4724 floattidf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floattidf");
4726 floatsixf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatsixf");
4727 floatdixf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatdixf");
4728 floattixf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floattixf");
4730 floatsitf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatsitf");
4731 floatditf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatditf");
4732 floattitf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floattitf");
4734 fixsfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixsfsi");
4735 fixsfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixsfdi");
4736 fixsfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixsfti");
4738 fixdfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixdfsi");
4739 fixdfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixdfdi");
4740 fixdfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixdfti");
4742 fixxfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixxfsi");
4743 fixxfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixxfdi");
4744 fixxfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixxfti");
4746 fixtfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixtfsi");
4747 fixtfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixtfdi");
4748 fixtfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixtfti");
4750 fixunssfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunssfsi");
4751 fixunssfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunssfdi");
4752 fixunssfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunssfti");
4754 fixunsdfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunsdfsi");
4755 fixunsdfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunsdfdi");
4756 fixunsdfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunsdfti");
4758 fixunsxfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunsxfsi");
4759 fixunsxfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunsxfdi");
4760 fixunsxfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunsxfti");
4762 fixunstfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunstfsi");
4763 fixunstfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunstfdi");
4764 fixunstfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunstfti");
4766 /* For check-memory-usage. */
4767 chkr_check_addr_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "chkr_check_addr");
4768 chkr_set_right_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "chkr_set_right");
4769 chkr_copy_bitmap_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "chkr_copy_bitmap");
4770 chkr_check_exec_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "chkr_check_exec");
4771 chkr_check_str_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "chkr_check_str");
4773 /* For function entry/exit instrumentation. */
4774 profile_function_entry_libfunc
4775 = gen_rtx_SYMBOL_REF (Pmode
, "__cyg_profile_func_enter");
4776 profile_function_exit_libfunc
4777 = gen_rtx_SYMBOL_REF (Pmode
, "__cyg_profile_func_exit");
4779 #ifdef HAVE_conditional_trap
4783 #ifdef INIT_TARGET_OPTABS
4784 /* Allow the target to add more libcalls or rename some, etc. */
4791 /* SCO 3.2 apparently has a broken ldexp. */
4804 #endif /* BROKEN_LDEXP */
4806 #ifdef HAVE_conditional_trap
4807 /* The insn generating function can not take an rtx_code argument.
4808 TRAP_RTX is used as an rtx argument. Its code is replaced with
4809 the code to be used in the trap insn and all other fields are
4812 ??? Will need to change to support garbage collection. */
4813 static rtx trap_rtx
;
4818 if (HAVE_conditional_trap
)
4819 trap_rtx
= gen_rtx_fmt_ee (EQ
, VOIDmode
, NULL_RTX
, NULL_RTX
);
4823 /* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
4824 CODE. Return 0 on failure. */
4827 gen_cond_trap (code
, op1
, op2
, tcode
)
4828 enum rtx_code code ATTRIBUTE_UNUSED
;
4829 rtx op1
, op2 ATTRIBUTE_UNUSED
, tcode ATTRIBUTE_UNUSED
;
4831 enum machine_mode mode
= GET_MODE (op1
);
4833 if (mode
== VOIDmode
)
4836 #ifdef HAVE_conditional_trap
4837 if (HAVE_conditional_trap
4838 && cmp_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
4841 emit_insn (GEN_FCN (cmp_optab
->handlers
[(int) mode
].insn_code
) (op1
, op2
));
4842 PUT_CODE (trap_rtx
, code
);
4843 insn
= gen_conditional_trap (trap_rtx
, tcode
);