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"
39 /* Each optab contains info on how this target machine
40 can perform a particular operation
41 for all sizes and kinds of operands.
43 The operation to be performed is often specified
44 by passing one of these optabs as an argument.
46 See expr.h for documentation of these optabs. */
51 optab smul_highpart_optab
;
52 optab umul_highpart_optab
;
53 optab smul_widen_optab
;
54 optab umul_widen_optab
;
77 optab movstrict_optab
;
88 optab ucmp_optab
; /* Used only for libcalls for unsigned comparisons. */
93 /* Tables of patterns for extending one integer mode to another. */
94 enum insn_code extendtab
[MAX_MACHINE_MODE
][MAX_MACHINE_MODE
][2];
96 /* Tables of patterns for converting between fixed and floating point. */
97 enum insn_code fixtab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
98 enum insn_code fixtrunctab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
99 enum insn_code floattab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
101 /* Contains the optab used for each rtx code. */
102 optab code_to_optab
[NUM_RTX_CODE
+ 1];
104 /* SYMBOL_REF rtx's for the library functions that are called
105 implicitly and not via optabs. */
107 rtx extendsfdf2_libfunc
;
108 rtx extendsfxf2_libfunc
;
109 rtx extendsftf2_libfunc
;
110 rtx extenddfxf2_libfunc
;
111 rtx extenddftf2_libfunc
;
113 rtx truncdfsf2_libfunc
;
114 rtx truncxfsf2_libfunc
;
115 rtx trunctfsf2_libfunc
;
116 rtx truncxfdf2_libfunc
;
117 rtx trunctfdf2_libfunc
;
129 rtx sjpopnthrow_libfunc
;
130 rtx terminate_libfunc
;
133 rtx eh_rtime_match_libfunc
;
170 rtx floatsisf_libfunc
;
171 rtx floatdisf_libfunc
;
172 rtx floattisf_libfunc
;
174 rtx floatsidf_libfunc
;
175 rtx floatdidf_libfunc
;
176 rtx floattidf_libfunc
;
178 rtx floatsixf_libfunc
;
179 rtx floatdixf_libfunc
;
180 rtx floattixf_libfunc
;
182 rtx floatsitf_libfunc
;
183 rtx floatditf_libfunc
;
184 rtx floattitf_libfunc
;
202 rtx fixunssfsi_libfunc
;
203 rtx fixunssfdi_libfunc
;
204 rtx fixunssfti_libfunc
;
206 rtx fixunsdfsi_libfunc
;
207 rtx fixunsdfdi_libfunc
;
208 rtx fixunsdfti_libfunc
;
210 rtx fixunsxfsi_libfunc
;
211 rtx fixunsxfdi_libfunc
;
212 rtx fixunsxfti_libfunc
;
214 rtx fixunstfsi_libfunc
;
215 rtx fixunstfdi_libfunc
;
216 rtx fixunstfti_libfunc
;
218 rtx chkr_check_addr_libfunc
;
219 rtx chkr_set_right_libfunc
;
220 rtx chkr_copy_bitmap_libfunc
;
221 rtx chkr_check_exec_libfunc
;
222 rtx chkr_check_str_libfunc
;
224 rtx profile_function_entry_libfunc
;
225 rtx profile_function_exit_libfunc
;
227 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
228 gives the gen_function to make a branch to test that condition. */
230 rtxfun bcc_gen_fctn
[NUM_RTX_CODE
];
232 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
233 gives the insn code to make a store-condition insn
234 to test that condition. */
236 enum insn_code setcc_gen_code
[NUM_RTX_CODE
];
238 #ifdef HAVE_conditional_move
239 /* Indexed by the machine mode, gives the insn code to make a conditional
240 move insn. This is not indexed by the rtx-code like bcc_gen_fctn and
241 setcc_gen_code to cut down on the number of named patterns. Consider a day
242 when a lot more rtx codes are conditional (eg: for the ARM). */
244 enum insn_code movcc_gen_code
[NUM_MACHINE_MODES
];
247 static int add_equal_note
PROTO((rtx
, rtx
, enum rtx_code
, rtx
, rtx
));
248 static rtx widen_operand
PROTO((rtx
, enum machine_mode
,
249 enum machine_mode
, int, int));
250 static int expand_cmplxdiv_straight
PROTO((rtx
, rtx
, rtx
, rtx
,
251 rtx
, rtx
, enum machine_mode
,
252 int, enum optab_methods
,
253 enum mode_class
, optab
));
254 static int expand_cmplxdiv_wide
PROTO((rtx
, rtx
, rtx
, rtx
,
255 rtx
, rtx
, enum machine_mode
,
256 int, enum optab_methods
,
257 enum mode_class
, optab
));
258 static enum insn_code can_fix_p
PROTO((enum machine_mode
, enum machine_mode
,
260 static enum insn_code can_float_p
PROTO((enum machine_mode
, enum machine_mode
,
262 static rtx ftruncify
PROTO((rtx
));
263 static optab init_optab
PROTO((enum rtx_code
));
264 static void init_libfuncs
PROTO((optab
, int, int, const char *, int));
265 static void init_integral_libfuncs
PROTO((optab
, const char *, int));
266 static void init_floating_libfuncs
PROTO((optab
, const char *, int));
267 #ifdef HAVE_conditional_trap
268 static void init_traps
PROTO((void));
270 static int cmp_available_p
PROTO((enum machine_mode
, enum rtx_code
, int));
271 static void emit_cmp_and_jump_insn_1
PROTO((rtx
, rtx
, enum machine_mode
,
272 enum rtx_code
, int, rtx
));
273 static void prepare_cmp_insn
PROTO((rtx
*, rtx
*, enum rtx_code
*, rtx
,
274 enum machine_mode
*, int *, int));
275 static rtx prepare_operand
PROTO((int, rtx
, int, enum machine_mode
,
276 enum machine_mode
, int));
277 static void prepare_float_lib_cmp
PROTO((rtx
*, rtx
*, enum rtx_code
*,
278 enum machine_mode
*, int *));
280 /* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
281 the result of operation CODE applied to OP0 (and OP1 if it is a binary
284 If the last insn does not set TARGET, don't do anything, but return 1.
286 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
287 don't add the REG_EQUAL note but return 0. Our caller can then try
288 again, ensuring that TARGET is not one of the operands. */
291 add_equal_note (seq
, target
, code
, op0
, op1
)
301 if ((GET_RTX_CLASS (code
) != '1' && GET_RTX_CLASS (code
) != '2'
302 && GET_RTX_CLASS (code
) != 'c' && GET_RTX_CLASS (code
) != '<')
303 || GET_CODE (seq
) != SEQUENCE
304 || (set
= single_set (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1))) == 0
305 || GET_CODE (target
) == ZERO_EXTRACT
306 || (! rtx_equal_p (SET_DEST (set
), target
)
307 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
309 && (GET_CODE (SET_DEST (set
)) != STRICT_LOW_PART
310 || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set
), 0)),
314 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
315 besides the last insn. */
316 if (reg_overlap_mentioned_p (target
, op0
)
317 || (op1
&& reg_overlap_mentioned_p (target
, op1
)))
318 for (i
= XVECLEN (seq
, 0) - 2; i
>= 0; i
--)
319 if (reg_set_p (target
, XVECEXP (seq
, 0, i
)))
322 if (GET_RTX_CLASS (code
) == '1')
323 note
= gen_rtx_fmt_e (code
, GET_MODE (target
), copy_rtx (op0
));
325 note
= gen_rtx_fmt_ee (code
, GET_MODE (target
), copy_rtx (op0
), copy_rtx (op1
));
327 set_unique_reg_note (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1), REG_EQUAL
, note
);
332 /* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP
333 says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need
334 not actually do a sign-extend or zero-extend, but can leave the
335 higher-order bits of the result rtx undefined, for example, in the case
336 of logical operations, but not right shifts. */
339 widen_operand (op
, mode
, oldmode
, unsignedp
, no_extend
)
341 enum machine_mode mode
, oldmode
;
347 /* If we must extend do so. If OP is either a constant or a SUBREG
348 for a promoted object, also extend since it will be more efficient to
351 || GET_MODE (op
) == VOIDmode
352 || (GET_CODE (op
) == SUBREG
&& SUBREG_PROMOTED_VAR_P (op
)))
353 return convert_modes (mode
, oldmode
, op
, unsignedp
);
355 /* If MODE is no wider than a single word, we return a paradoxical
357 if (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
)
358 return gen_rtx_SUBREG (mode
, force_reg (GET_MODE (op
), op
), 0);
360 /* Otherwise, get an object of MODE, clobber it, and set the low-order
363 result
= gen_reg_rtx (mode
);
364 emit_insn (gen_rtx_CLOBBER (VOIDmode
, result
));
365 emit_move_insn (gen_lowpart (GET_MODE (op
), result
), op
);
369 /* Generate code to perform a straightforward complex divide. */
372 expand_cmplxdiv_straight (real0
, real1
, imag0
, imag1
, realr
, imagr
, submode
,
373 unsignedp
, methods
, class, binoptab
)
374 rtx real0
, real1
, imag0
, imag1
, realr
, imagr
;
375 enum machine_mode submode
;
377 enum optab_methods methods
;
378 enum mode_class
class;
386 /* Don't fetch these from memory more than once. */
387 real0
= force_reg (submode
, real0
);
388 real1
= force_reg (submode
, real1
);
391 imag0
= force_reg (submode
, imag0
);
393 imag1
= force_reg (submode
, imag1
);
395 /* Divisor: c*c + d*d. */
396 temp1
= expand_binop (submode
, smul_optab
, real1
, real1
,
397 NULL_RTX
, unsignedp
, methods
);
399 temp2
= expand_binop (submode
, smul_optab
, imag1
, imag1
,
400 NULL_RTX
, unsignedp
, methods
);
402 if (temp1
== 0 || temp2
== 0)
405 divisor
= expand_binop (submode
, add_optab
, temp1
, temp2
,
406 NULL_RTX
, unsignedp
, methods
);
412 /* Mathematically, ((a)(c-id))/divisor. */
413 /* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)). */
415 /* Calculate the dividend. */
416 real_t
= expand_binop (submode
, smul_optab
, real0
, real1
,
417 NULL_RTX
, unsignedp
, methods
);
419 imag_t
= expand_binop (submode
, smul_optab
, real0
, imag1
,
420 NULL_RTX
, unsignedp
, methods
);
422 if (real_t
== 0 || imag_t
== 0)
425 imag_t
= expand_unop (submode
, neg_optab
, imag_t
,
426 NULL_RTX
, unsignedp
);
430 /* Mathematically, ((a+ib)(c-id))/divider. */
431 /* Calculate the dividend. */
432 temp1
= expand_binop (submode
, smul_optab
, real0
, real1
,
433 NULL_RTX
, unsignedp
, methods
);
435 temp2
= expand_binop (submode
, smul_optab
, imag0
, imag1
,
436 NULL_RTX
, unsignedp
, methods
);
438 if (temp1
== 0 || temp2
== 0)
441 real_t
= expand_binop (submode
, add_optab
, temp1
, temp2
,
442 NULL_RTX
, unsignedp
, methods
);
444 temp1
= expand_binop (submode
, smul_optab
, imag0
, real1
,
445 NULL_RTX
, unsignedp
, methods
);
447 temp2
= expand_binop (submode
, smul_optab
, real0
, imag1
,
448 NULL_RTX
, unsignedp
, methods
);
450 if (temp1
== 0 || temp2
== 0)
453 imag_t
= expand_binop (submode
, sub_optab
, temp1
, temp2
,
454 NULL_RTX
, unsignedp
, methods
);
456 if (real_t
== 0 || imag_t
== 0)
460 if (class == MODE_COMPLEX_FLOAT
)
461 res
= expand_binop (submode
, binoptab
, real_t
, divisor
,
462 realr
, unsignedp
, methods
);
464 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
465 real_t
, divisor
, realr
, unsignedp
);
471 emit_move_insn (realr
, res
);
473 if (class == MODE_COMPLEX_FLOAT
)
474 res
= expand_binop (submode
, binoptab
, imag_t
, divisor
,
475 imagr
, unsignedp
, methods
);
477 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
478 imag_t
, divisor
, imagr
, unsignedp
);
484 emit_move_insn (imagr
, res
);
489 /* Generate code to perform a wide-input-range-acceptable complex divide. */
492 expand_cmplxdiv_wide (real0
, real1
, imag0
, imag1
, realr
, imagr
, submode
,
493 unsignedp
, methods
, class, binoptab
)
494 rtx real0
, real1
, imag0
, imag1
, realr
, imagr
;
495 enum machine_mode submode
;
497 enum optab_methods methods
;
498 enum mode_class
class;
503 rtx temp1
, temp2
, lab1
, lab2
;
504 enum machine_mode mode
;
508 /* Don't fetch these from memory more than once. */
509 real0
= force_reg (submode
, real0
);
510 real1
= force_reg (submode
, real1
);
513 imag0
= force_reg (submode
, imag0
);
515 imag1
= force_reg (submode
, imag1
);
517 /* XXX What's an "unsigned" complex number? */
525 temp1
= expand_abs (submode
, real1
, NULL_RTX
, 1);
526 temp2
= expand_abs (submode
, imag1
, NULL_RTX
, 1);
529 if (temp1
== 0 || temp2
== 0)
532 mode
= GET_MODE (temp1
);
533 align
= GET_MODE_ALIGNMENT (mode
);
534 lab1
= gen_label_rtx ();
535 emit_cmp_and_jump_insns (temp1
, temp2
, LT
, NULL_RTX
,
536 mode
, unsignedp
, align
, lab1
);
538 /* |c| >= |d|; use ratio d/c to scale dividend and divisor. */
540 if (class == MODE_COMPLEX_FLOAT
)
541 ratio
= expand_binop (submode
, binoptab
, imag1
, real1
,
542 NULL_RTX
, unsignedp
, methods
);
544 ratio
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
545 imag1
, real1
, NULL_RTX
, unsignedp
);
550 /* Calculate divisor. */
552 temp1
= expand_binop (submode
, smul_optab
, imag1
, ratio
,
553 NULL_RTX
, unsignedp
, methods
);
558 divisor
= expand_binop (submode
, add_optab
, temp1
, real1
,
559 NULL_RTX
, unsignedp
, methods
);
564 /* Calculate dividend. */
570 /* Compute a / (c+id) as a / (c+d(d/c)) + i (-a(d/c)) / (c+d(d/c)). */
572 imag_t
= expand_binop (submode
, smul_optab
, real0
, ratio
,
573 NULL_RTX
, unsignedp
, methods
);
578 imag_t
= expand_unop (submode
, neg_optab
, imag_t
,
579 NULL_RTX
, unsignedp
);
581 if (real_t
== 0 || imag_t
== 0)
586 /* Compute (a+ib)/(c+id) as
587 (a+b(d/c))/(c+d(d/c) + i(b-a(d/c))/(c+d(d/c)). */
589 temp1
= expand_binop (submode
, smul_optab
, imag0
, ratio
,
590 NULL_RTX
, unsignedp
, methods
);
595 real_t
= expand_binop (submode
, add_optab
, temp1
, real0
,
596 NULL_RTX
, unsignedp
, methods
);
598 temp1
= expand_binop (submode
, smul_optab
, real0
, ratio
,
599 NULL_RTX
, unsignedp
, methods
);
604 imag_t
= expand_binop (submode
, sub_optab
, imag0
, temp1
,
605 NULL_RTX
, unsignedp
, methods
);
607 if (real_t
== 0 || imag_t
== 0)
611 if (class == MODE_COMPLEX_FLOAT
)
612 res
= expand_binop (submode
, binoptab
, real_t
, divisor
,
613 realr
, unsignedp
, methods
);
615 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
616 real_t
, divisor
, realr
, unsignedp
);
622 emit_move_insn (realr
, res
);
624 if (class == MODE_COMPLEX_FLOAT
)
625 res
= expand_binop (submode
, binoptab
, imag_t
, divisor
,
626 imagr
, unsignedp
, methods
);
628 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
629 imag_t
, divisor
, imagr
, unsignedp
);
635 emit_move_insn (imagr
, res
);
637 lab2
= gen_label_rtx ();
638 emit_jump_insn (gen_jump (lab2
));
643 /* |d| > |c|; use ratio c/d to scale dividend and divisor. */
645 if (class == MODE_COMPLEX_FLOAT
)
646 ratio
= expand_binop (submode
, binoptab
, real1
, imag1
,
647 NULL_RTX
, unsignedp
, methods
);
649 ratio
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
650 real1
, imag1
, NULL_RTX
, unsignedp
);
655 /* Calculate divisor. */
657 temp1
= expand_binop (submode
, smul_optab
, real1
, ratio
,
658 NULL_RTX
, unsignedp
, methods
);
663 divisor
= expand_binop (submode
, add_optab
, temp1
, imag1
,
664 NULL_RTX
, unsignedp
, methods
);
669 /* Calculate dividend. */
673 /* Compute a / (c+id) as a(c/d) / (c(c/d)+d) + i (-a) / (c(c/d)+d). */
675 real_t
= expand_binop (submode
, smul_optab
, real0
, ratio
,
676 NULL_RTX
, unsignedp
, methods
);
678 imag_t
= expand_unop (submode
, neg_optab
, real0
,
679 NULL_RTX
, unsignedp
);
681 if (real_t
== 0 || imag_t
== 0)
686 /* Compute (a+ib)/(c+id) as
687 (a(c/d)+b)/(c(c/d)+d) + i (b(c/d)-a)/(c(c/d)+d). */
689 temp1
= expand_binop (submode
, smul_optab
, real0
, ratio
,
690 NULL_RTX
, unsignedp
, methods
);
695 real_t
= expand_binop (submode
, add_optab
, temp1
, imag0
,
696 NULL_RTX
, unsignedp
, methods
);
698 temp1
= expand_binop (submode
, smul_optab
, imag0
, ratio
,
699 NULL_RTX
, unsignedp
, methods
);
704 imag_t
= expand_binop (submode
, sub_optab
, temp1
, real0
,
705 NULL_RTX
, unsignedp
, methods
);
707 if (real_t
== 0 || imag_t
== 0)
711 if (class == MODE_COMPLEX_FLOAT
)
712 res
= expand_binop (submode
, binoptab
, real_t
, divisor
,
713 realr
, unsignedp
, methods
);
715 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
716 real_t
, divisor
, realr
, unsignedp
);
722 emit_move_insn (realr
, res
);
724 if (class == MODE_COMPLEX_FLOAT
)
725 res
= expand_binop (submode
, binoptab
, imag_t
, divisor
,
726 imagr
, unsignedp
, methods
);
728 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
729 imag_t
, divisor
, imagr
, unsignedp
);
735 emit_move_insn (imagr
, res
);
742 /* Generate code to perform an operation specified by BINOPTAB
743 on operands OP0 and OP1, with result having machine-mode MODE.
745 UNSIGNEDP is for the case where we have to widen the operands
746 to perform the operation. It says to use zero-extension.
748 If TARGET is nonzero, the value
749 is generated there, if it is convenient to do so.
750 In all cases an rtx is returned for the locus of the value;
751 this may or may not be TARGET. */
754 expand_binop (mode
, binoptab
, op0
, op1
, target
, unsignedp
, methods
)
755 enum machine_mode mode
;
760 enum optab_methods methods
;
762 enum optab_methods next_methods
763 = (methods
== OPTAB_LIB
|| methods
== OPTAB_LIB_WIDEN
764 ? OPTAB_WIDEN
: methods
);
765 enum mode_class
class;
766 enum machine_mode wider_mode
;
768 int commutative_op
= 0;
769 int shift_op
= (binoptab
->code
== ASHIFT
770 || binoptab
->code
== ASHIFTRT
771 || binoptab
->code
== LSHIFTRT
772 || binoptab
->code
== ROTATE
773 || binoptab
->code
== ROTATERT
);
774 rtx entry_last
= get_last_insn ();
777 class = GET_MODE_CLASS (mode
);
779 op0
= protect_from_queue (op0
, 0);
780 op1
= protect_from_queue (op1
, 0);
782 target
= protect_from_queue (target
, 1);
786 op0
= force_not_mem (op0
);
787 op1
= force_not_mem (op1
);
790 /* If subtracting an integer constant, convert this into an addition of
791 the negated constant. */
793 if (binoptab
== sub_optab
&& GET_CODE (op1
) == CONST_INT
)
795 op1
= negate_rtx (mode
, op1
);
796 binoptab
= add_optab
;
799 /* If we are inside an appropriately-short loop and one operand is an
800 expensive constant, force it into a register. */
801 if (CONSTANT_P (op0
) && preserve_subexpressions_p ()
802 && rtx_cost (op0
, binoptab
->code
) > 2)
803 op0
= force_reg (mode
, op0
);
805 if (CONSTANT_P (op1
) && preserve_subexpressions_p ()
806 && ! shift_op
&& rtx_cost (op1
, binoptab
->code
) > 2)
807 op1
= force_reg (mode
, op1
);
809 /* Record where to delete back to if we backtrack. */
810 last
= get_last_insn ();
812 /* If operation is commutative,
813 try to make the first operand a register.
814 Even better, try to make it the same as the target.
815 Also try to make the last operand a constant. */
816 if (GET_RTX_CLASS (binoptab
->code
) == 'c'
817 || binoptab
== smul_widen_optab
818 || binoptab
== umul_widen_optab
819 || binoptab
== smul_highpart_optab
820 || binoptab
== umul_highpart_optab
)
824 if (((target
== 0 || GET_CODE (target
) == REG
)
825 ? ((GET_CODE (op1
) == REG
826 && GET_CODE (op0
) != REG
)
828 : rtx_equal_p (op1
, target
))
829 || GET_CODE (op0
) == CONST_INT
)
837 /* If we can do it with a three-operand insn, do so. */
839 if (methods
!= OPTAB_MUST_WIDEN
840 && binoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
842 int icode
= (int) binoptab
->handlers
[(int) mode
].insn_code
;
843 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
844 enum machine_mode mode1
= insn_operand_mode
[icode
][2];
846 rtx xop0
= op0
, xop1
= op1
;
851 temp
= gen_reg_rtx (mode
);
853 /* If it is a commutative operator and the modes would match
854 if we would swap the operands, we can save the conversions. */
857 if (GET_MODE (op0
) != mode0
&& GET_MODE (op1
) != mode1
858 && GET_MODE (op0
) == mode1
&& GET_MODE (op1
) == mode0
)
862 tmp
= op0
; op0
= op1
; op1
= tmp
;
863 tmp
= xop0
; xop0
= xop1
; xop1
= tmp
;
867 /* In case the insn wants input operands in modes different from
868 the result, convert the operands. */
870 if (GET_MODE (op0
) != VOIDmode
871 && GET_MODE (op0
) != mode0
872 && mode0
!= VOIDmode
)
873 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
875 if (GET_MODE (xop1
) != VOIDmode
876 && GET_MODE (xop1
) != mode1
877 && mode1
!= VOIDmode
)
878 xop1
= convert_to_mode (mode1
, xop1
, unsignedp
);
880 /* Now, if insn's predicates don't allow our operands, put them into
883 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
)
884 && mode0
!= VOIDmode
)
885 xop0
= copy_to_mode_reg (mode0
, xop0
);
887 if (! (*insn_operand_predicate
[icode
][2]) (xop1
, mode1
)
888 && mode1
!= VOIDmode
)
889 xop1
= copy_to_mode_reg (mode1
, xop1
);
891 if (! (*insn_operand_predicate
[icode
][0]) (temp
, mode
))
892 temp
= gen_reg_rtx (mode
);
894 pat
= GEN_FCN (icode
) (temp
, xop0
, xop1
);
897 /* If PAT is a multi-insn sequence, try to add an appropriate
898 REG_EQUAL note to it. If we can't because TEMP conflicts with an
899 operand, call ourselves again, this time without a target. */
900 if (GET_CODE (pat
) == SEQUENCE
901 && ! add_equal_note (pat
, temp
, binoptab
->code
, xop0
, xop1
))
903 delete_insns_since (last
);
904 return expand_binop (mode
, binoptab
, op0
, op1
, NULL_RTX
,
912 delete_insns_since (last
);
915 /* If this is a multiply, see if we can do a widening operation that
916 takes operands of this mode and makes a wider mode. */
918 if (binoptab
== smul_optab
&& GET_MODE_WIDER_MODE (mode
) != VOIDmode
919 && (((unsignedp
? umul_widen_optab
: smul_widen_optab
)
920 ->handlers
[(int) GET_MODE_WIDER_MODE (mode
)].insn_code
)
921 != CODE_FOR_nothing
))
923 temp
= expand_binop (GET_MODE_WIDER_MODE (mode
),
924 unsignedp
? umul_widen_optab
: smul_widen_optab
,
925 op0
, op1
, NULL_RTX
, unsignedp
, OPTAB_DIRECT
);
929 if (GET_MODE_CLASS (mode
) == MODE_INT
)
930 return gen_lowpart (mode
, temp
);
932 return convert_to_mode (mode
, temp
, unsignedp
);
936 /* Look for a wider mode of the same class for which we think we
937 can open-code the operation. Check for a widening multiply at the
938 wider mode as well. */
940 if ((class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
941 && methods
!= OPTAB_DIRECT
&& methods
!= OPTAB_LIB
)
942 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
943 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
945 if (binoptab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
946 || (binoptab
== smul_optab
947 && GET_MODE_WIDER_MODE (wider_mode
) != VOIDmode
948 && (((unsignedp
? umul_widen_optab
: smul_widen_optab
)
949 ->handlers
[(int) GET_MODE_WIDER_MODE (wider_mode
)].insn_code
)
950 != CODE_FOR_nothing
)))
952 rtx xop0
= op0
, xop1
= op1
;
955 /* For certain integer operations, we need not actually extend
956 the narrow operands, as long as we will truncate
957 the results to the same narrowness. */
959 if ((binoptab
== ior_optab
|| binoptab
== and_optab
960 || binoptab
== xor_optab
961 || binoptab
== add_optab
|| binoptab
== sub_optab
962 || binoptab
== smul_optab
|| binoptab
== ashl_optab
)
963 && class == MODE_INT
)
966 xop0
= widen_operand (xop0
, wider_mode
, mode
, unsignedp
, no_extend
);
968 /* The second operand of a shift must always be extended. */
969 xop1
= widen_operand (xop1
, wider_mode
, mode
, unsignedp
,
970 no_extend
&& binoptab
!= ashl_optab
);
972 temp
= expand_binop (wider_mode
, binoptab
, xop0
, xop1
, NULL_RTX
,
973 unsignedp
, OPTAB_DIRECT
);
976 if (class != MODE_INT
)
979 target
= gen_reg_rtx (mode
);
980 convert_move (target
, temp
, 0);
984 return gen_lowpart (mode
, temp
);
987 delete_insns_since (last
);
991 /* These can be done a word at a time. */
992 if ((binoptab
== and_optab
|| binoptab
== ior_optab
|| binoptab
== xor_optab
)
994 && GET_MODE_SIZE (mode
) > UNITS_PER_WORD
995 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
1001 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1002 won't be accurate, so use a new target. */
1003 if (target
== 0 || target
== op0
|| target
== op1
)
1004 target
= gen_reg_rtx (mode
);
1008 /* Do the actual arithmetic. */
1009 for (i
= 0; i
< GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
; i
++)
1011 rtx target_piece
= operand_subword (target
, i
, 1, mode
);
1012 rtx x
= expand_binop (word_mode
, binoptab
,
1013 operand_subword_force (op0
, i
, mode
),
1014 operand_subword_force (op1
, i
, mode
),
1015 target_piece
, unsignedp
, next_methods
);
1020 if (target_piece
!= x
)
1021 emit_move_insn (target_piece
, x
);
1024 insns
= get_insns ();
1027 if (i
== GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
)
1029 if (binoptab
->code
!= UNKNOWN
)
1031 = gen_rtx_fmt_ee (binoptab
->code
, mode
,
1032 copy_rtx (op0
), copy_rtx (op1
));
1036 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv_value
);
1041 /* Synthesize double word shifts from single word shifts. */
1042 if ((binoptab
== lshr_optab
|| binoptab
== ashl_optab
1043 || binoptab
== ashr_optab
)
1044 && class == MODE_INT
1045 && GET_CODE (op1
) == CONST_INT
1046 && GET_MODE_SIZE (mode
) == 2 * UNITS_PER_WORD
1047 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
1048 && ashl_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
1049 && lshr_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
1051 rtx insns
, inter
, equiv_value
;
1052 rtx into_target
, outof_target
;
1053 rtx into_input
, outof_input
;
1054 int shift_count
, left_shift
, outof_word
;
1056 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1057 won't be accurate, so use a new target. */
1058 if (target
== 0 || target
== op0
|| target
== op1
)
1059 target
= gen_reg_rtx (mode
);
1063 shift_count
= INTVAL (op1
);
1065 /* OUTOF_* is the word we are shifting bits away from, and
1066 INTO_* is the word that we are shifting bits towards, thus
1067 they differ depending on the direction of the shift and
1068 WORDS_BIG_ENDIAN. */
1070 left_shift
= binoptab
== ashl_optab
;
1071 outof_word
= left_shift
^ ! WORDS_BIG_ENDIAN
;
1073 outof_target
= operand_subword (target
, outof_word
, 1, mode
);
1074 into_target
= operand_subword (target
, 1 - outof_word
, 1, mode
);
1076 outof_input
= operand_subword_force (op0
, outof_word
, mode
);
1077 into_input
= operand_subword_force (op0
, 1 - outof_word
, mode
);
1079 if (shift_count
>= BITS_PER_WORD
)
1081 inter
= expand_binop (word_mode
, binoptab
,
1083 GEN_INT (shift_count
- BITS_PER_WORD
),
1084 into_target
, unsignedp
, next_methods
);
1086 if (inter
!= 0 && inter
!= into_target
)
1087 emit_move_insn (into_target
, inter
);
1089 /* For a signed right shift, we must fill the word we are shifting
1090 out of with copies of the sign bit. Otherwise it is zeroed. */
1091 if (inter
!= 0 && binoptab
!= ashr_optab
)
1092 inter
= CONST0_RTX (word_mode
);
1093 else if (inter
!= 0)
1094 inter
= expand_binop (word_mode
, binoptab
,
1096 GEN_INT (BITS_PER_WORD
- 1),
1097 outof_target
, unsignedp
, next_methods
);
1099 if (inter
!= 0 && inter
!= outof_target
)
1100 emit_move_insn (outof_target
, inter
);
1105 optab reverse_unsigned_shift
, unsigned_shift
;
1107 /* For a shift of less then BITS_PER_WORD, to compute the carry,
1108 we must do a logical shift in the opposite direction of the
1111 reverse_unsigned_shift
= (left_shift
? lshr_optab
: ashl_optab
);
1113 /* For a shift of less than BITS_PER_WORD, to compute the word
1114 shifted towards, we need to unsigned shift the orig value of
1117 unsigned_shift
= (left_shift
? ashl_optab
: lshr_optab
);
1119 carries
= expand_binop (word_mode
, reverse_unsigned_shift
,
1121 GEN_INT (BITS_PER_WORD
- shift_count
),
1122 0, unsignedp
, next_methods
);
1127 inter
= expand_binop (word_mode
, unsigned_shift
, into_input
,
1128 op1
, 0, unsignedp
, next_methods
);
1131 inter
= expand_binop (word_mode
, ior_optab
, carries
, inter
,
1132 into_target
, unsignedp
, next_methods
);
1134 if (inter
!= 0 && inter
!= into_target
)
1135 emit_move_insn (into_target
, inter
);
1138 inter
= expand_binop (word_mode
, binoptab
, outof_input
,
1139 op1
, outof_target
, unsignedp
, next_methods
);
1141 if (inter
!= 0 && inter
!= outof_target
)
1142 emit_move_insn (outof_target
, inter
);
1145 insns
= get_insns ();
1150 if (binoptab
->code
!= UNKNOWN
)
1151 equiv_value
= gen_rtx_fmt_ee (binoptab
->code
, mode
, op0
, op1
);
1155 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv_value
);
1160 /* Synthesize double word rotates from single word shifts. */
1161 if ((binoptab
== rotl_optab
|| binoptab
== rotr_optab
)
1162 && class == MODE_INT
1163 && GET_CODE (op1
) == CONST_INT
1164 && GET_MODE_SIZE (mode
) == 2 * UNITS_PER_WORD
1165 && ashl_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
1166 && lshr_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
1168 rtx insns
, equiv_value
;
1169 rtx into_target
, outof_target
;
1170 rtx into_input
, outof_input
;
1172 int shift_count
, left_shift
, outof_word
;
1174 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1175 won't be accurate, so use a new target. */
1176 if (target
== 0 || target
== op0
|| target
== op1
)
1177 target
= gen_reg_rtx (mode
);
1181 shift_count
= INTVAL (op1
);
1183 /* OUTOF_* is the word we are shifting bits away from, and
1184 INTO_* is the word that we are shifting bits towards, thus
1185 they differ depending on the direction of the shift and
1186 WORDS_BIG_ENDIAN. */
1188 left_shift
= (binoptab
== rotl_optab
);
1189 outof_word
= left_shift
^ ! WORDS_BIG_ENDIAN
;
1191 outof_target
= operand_subword (target
, outof_word
, 1, mode
);
1192 into_target
= operand_subword (target
, 1 - outof_word
, 1, mode
);
1194 outof_input
= operand_subword_force (op0
, outof_word
, mode
);
1195 into_input
= operand_subword_force (op0
, 1 - outof_word
, mode
);
1197 if (shift_count
== BITS_PER_WORD
)
1199 /* This is just a word swap. */
1200 emit_move_insn (outof_target
, into_input
);
1201 emit_move_insn (into_target
, outof_input
);
1206 rtx into_temp1
, into_temp2
, outof_temp1
, outof_temp2
;
1207 rtx first_shift_count
, second_shift_count
;
1208 optab reverse_unsigned_shift
, unsigned_shift
;
1210 reverse_unsigned_shift
= (left_shift
^ (shift_count
< BITS_PER_WORD
)
1211 ? lshr_optab
: ashl_optab
);
1213 unsigned_shift
= (left_shift
^ (shift_count
< BITS_PER_WORD
)
1214 ? ashl_optab
: lshr_optab
);
1216 if (shift_count
> BITS_PER_WORD
)
1218 first_shift_count
= GEN_INT (shift_count
- BITS_PER_WORD
);
1219 second_shift_count
= GEN_INT (2*BITS_PER_WORD
- shift_count
);
1223 first_shift_count
= GEN_INT (BITS_PER_WORD
- shift_count
);
1224 second_shift_count
= GEN_INT (shift_count
);
1227 into_temp1
= expand_binop (word_mode
, unsigned_shift
,
1228 outof_input
, first_shift_count
,
1229 NULL_RTX
, unsignedp
, next_methods
);
1230 into_temp2
= expand_binop (word_mode
, reverse_unsigned_shift
,
1231 into_input
, second_shift_count
,
1232 into_target
, unsignedp
, next_methods
);
1234 if (into_temp1
!= 0 && into_temp2
!= 0)
1235 inter
= expand_binop (word_mode
, ior_optab
, into_temp1
, into_temp2
,
1236 into_target
, unsignedp
, next_methods
);
1240 if (inter
!= 0 && inter
!= into_target
)
1241 emit_move_insn (into_target
, inter
);
1243 outof_temp1
= expand_binop (word_mode
, unsigned_shift
,
1244 into_input
, first_shift_count
,
1245 NULL_RTX
, unsignedp
, next_methods
);
1246 outof_temp2
= expand_binop (word_mode
, reverse_unsigned_shift
,
1247 outof_input
, second_shift_count
,
1248 outof_target
, unsignedp
, next_methods
);
1250 if (inter
!= 0 && outof_temp1
!= 0 && outof_temp2
!= 0)
1251 inter
= expand_binop (word_mode
, ior_optab
,
1252 outof_temp1
, outof_temp2
,
1253 outof_target
, unsignedp
, next_methods
);
1255 if (inter
!= 0 && inter
!= outof_target
)
1256 emit_move_insn (outof_target
, inter
);
1259 insns
= get_insns ();
1264 if (binoptab
->code
!= UNKNOWN
)
1265 equiv_value
= gen_rtx_fmt_ee (binoptab
->code
, mode
, op0
, op1
);
1269 /* We can't make this a no conflict block if this is a word swap,
1270 because the word swap case fails if the input and output values
1271 are in the same register. */
1272 if (shift_count
!= BITS_PER_WORD
)
1273 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv_value
);
1282 /* These can be done a word at a time by propagating carries. */
1283 if ((binoptab
== add_optab
|| binoptab
== sub_optab
)
1284 && class == MODE_INT
1285 && GET_MODE_SIZE (mode
) >= 2 * UNITS_PER_WORD
1286 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
1289 rtx carry_tmp
= gen_reg_rtx (word_mode
);
1290 optab otheroptab
= binoptab
== add_optab
? sub_optab
: add_optab
;
1291 int nwords
= GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
;
1292 rtx carry_in
= NULL_RTX
, carry_out
= NULL_RTX
;
1295 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
1296 value is one of those, use it. Otherwise, use 1 since it is the
1297 one easiest to get. */
1298 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
1299 int normalizep
= STORE_FLAG_VALUE
;
1304 /* Prepare the operands. */
1305 xop0
= force_reg (mode
, op0
);
1306 xop1
= force_reg (mode
, op1
);
1308 if (target
== 0 || GET_CODE (target
) != REG
1309 || target
== xop0
|| target
== xop1
)
1310 target
= gen_reg_rtx (mode
);
1312 /* Indicate for flow that the entire target reg is being set. */
1313 if (GET_CODE (target
) == REG
)
1314 emit_insn (gen_rtx_CLOBBER (VOIDmode
, target
));
1316 /* Do the actual arithmetic. */
1317 for (i
= 0; i
< nwords
; i
++)
1319 int index
= (WORDS_BIG_ENDIAN
? nwords
- i
- 1 : i
);
1320 rtx target_piece
= operand_subword (target
, index
, 1, mode
);
1321 rtx op0_piece
= operand_subword_force (xop0
, index
, mode
);
1322 rtx op1_piece
= operand_subword_force (xop1
, index
, mode
);
1325 /* Main add/subtract of the input operands. */
1326 x
= expand_binop (word_mode
, binoptab
,
1327 op0_piece
, op1_piece
,
1328 target_piece
, unsignedp
, next_methods
);
1334 /* Store carry from main add/subtract. */
1335 carry_out
= gen_reg_rtx (word_mode
);
1336 carry_out
= emit_store_flag_force (carry_out
,
1337 (binoptab
== add_optab
1340 word_mode
, 1, normalizep
);
1345 /* Add/subtract previous carry to main result. */
1346 x
= expand_binop (word_mode
,
1347 normalizep
== 1 ? binoptab
: otheroptab
,
1349 target_piece
, 1, next_methods
);
1352 else if (target_piece
!= x
)
1353 emit_move_insn (target_piece
, x
);
1357 /* THIS CODE HAS NOT BEEN TESTED. */
1358 /* Get out carry from adding/subtracting carry in. */
1359 carry_tmp
= emit_store_flag_force (carry_tmp
,
1360 binoptab
== add_optab
1363 word_mode
, 1, normalizep
);
1365 /* Logical-ior the two poss. carry together. */
1366 carry_out
= expand_binop (word_mode
, ior_optab
,
1367 carry_out
, carry_tmp
,
1368 carry_out
, 0, next_methods
);
1374 carry_in
= carry_out
;
1377 if (i
== GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
)
1379 if (mov_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1381 rtx temp
= emit_move_insn (target
, target
);
1383 set_unique_reg_note (temp
,
1385 gen_rtx_fmt_ee (binoptab
->code
, mode
,
1392 delete_insns_since (last
);
1395 /* If we want to multiply two two-word values and have normal and widening
1396 multiplies of single-word values, we can do this with three smaller
1397 multiplications. Note that we do not make a REG_NO_CONFLICT block here
1398 because we are not operating on one word at a time.
1400 The multiplication proceeds as follows:
1401 _______________________
1402 [__op0_high_|__op0_low__]
1403 _______________________
1404 * [__op1_high_|__op1_low__]
1405 _______________________________________________
1406 _______________________
1407 (1) [__op0_low__*__op1_low__]
1408 _______________________
1409 (2a) [__op0_low__*__op1_high_]
1410 _______________________
1411 (2b) [__op0_high_*__op1_low__]
1412 _______________________
1413 (3) [__op0_high_*__op1_high_]
1416 This gives a 4-word result. Since we are only interested in the
1417 lower 2 words, partial result (3) and the upper words of (2a) and
1418 (2b) don't need to be calculated. Hence (2a) and (2b) can be
1419 calculated using non-widening multiplication.
1421 (1), however, needs to be calculated with an unsigned widening
1422 multiplication. If this operation is not directly supported we
1423 try using a signed widening multiplication and adjust the result.
1424 This adjustment works as follows:
1426 If both operands are positive then no adjustment is needed.
1428 If the operands have different signs, for example op0_low < 0 and
1429 op1_low >= 0, the instruction treats the most significant bit of
1430 op0_low as a sign bit instead of a bit with significance
1431 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
1432 with 2**BITS_PER_WORD - op0_low, and two's complements the
1433 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
1436 Similarly, if both operands are negative, we need to add
1437 (op0_low + op1_low) * 2**BITS_PER_WORD.
1439 We use a trick to adjust quickly. We logically shift op0_low right
1440 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
1441 op0_high (op1_high) before it is used to calculate 2b (2a). If no
1442 logical shift exists, we do an arithmetic right shift and subtract
1445 if (binoptab
== smul_optab
1446 && class == MODE_INT
1447 && GET_MODE_SIZE (mode
) == 2 * UNITS_PER_WORD
1448 && smul_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
1449 && add_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
1450 && ((umul_widen_optab
->handlers
[(int) mode
].insn_code
1451 != CODE_FOR_nothing
)
1452 || (smul_widen_optab
->handlers
[(int) mode
].insn_code
1453 != CODE_FOR_nothing
)))
1455 int low
= (WORDS_BIG_ENDIAN
? 1 : 0);
1456 int high
= (WORDS_BIG_ENDIAN
? 0 : 1);
1457 rtx op0_high
= operand_subword_force (op0
, high
, mode
);
1458 rtx op0_low
= operand_subword_force (op0
, low
, mode
);
1459 rtx op1_high
= operand_subword_force (op1
, high
, mode
);
1460 rtx op1_low
= operand_subword_force (op1
, low
, mode
);
1462 rtx op0_xhigh
= NULL_RTX
;
1463 rtx op1_xhigh
= NULL_RTX
;
1465 /* If the target is the same as one of the inputs, don't use it. This
1466 prevents problems with the REG_EQUAL note. */
1467 if (target
== op0
|| target
== op1
1468 || (target
!= 0 && GET_CODE (target
) != REG
))
1471 /* Multiply the two lower words to get a double-word product.
1472 If unsigned widening multiplication is available, use that;
1473 otherwise use the signed form and compensate. */
1475 if (umul_widen_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1477 product
= expand_binop (mode
, umul_widen_optab
, op0_low
, op1_low
,
1478 target
, 1, OPTAB_DIRECT
);
1480 /* If we didn't succeed, delete everything we did so far. */
1482 delete_insns_since (last
);
1484 op0_xhigh
= op0_high
, op1_xhigh
= op1_high
;
1488 && smul_widen_optab
->handlers
[(int) mode
].insn_code
1489 != CODE_FOR_nothing
)
1491 rtx wordm1
= GEN_INT (BITS_PER_WORD
- 1);
1492 product
= expand_binop (mode
, smul_widen_optab
, op0_low
, op1_low
,
1493 target
, 1, OPTAB_DIRECT
);
1494 op0_xhigh
= expand_binop (word_mode
, lshr_optab
, op0_low
, wordm1
,
1495 NULL_RTX
, 1, next_methods
);
1497 op0_xhigh
= expand_binop (word_mode
, add_optab
, op0_high
,
1498 op0_xhigh
, op0_xhigh
, 0, next_methods
);
1501 op0_xhigh
= expand_binop (word_mode
, ashr_optab
, op0_low
, wordm1
,
1502 NULL_RTX
, 0, next_methods
);
1504 op0_xhigh
= expand_binop (word_mode
, sub_optab
, op0_high
,
1505 op0_xhigh
, op0_xhigh
, 0,
1509 op1_xhigh
= expand_binop (word_mode
, lshr_optab
, op1_low
, wordm1
,
1510 NULL_RTX
, 1, next_methods
);
1512 op1_xhigh
= expand_binop (word_mode
, add_optab
, op1_high
,
1513 op1_xhigh
, op1_xhigh
, 0, next_methods
);
1516 op1_xhigh
= expand_binop (word_mode
, ashr_optab
, op1_low
, wordm1
,
1517 NULL_RTX
, 0, next_methods
);
1519 op1_xhigh
= expand_binop (word_mode
, sub_optab
, op1_high
,
1520 op1_xhigh
, op1_xhigh
, 0,
1525 /* If we have been able to directly compute the product of the
1526 low-order words of the operands and perform any required adjustments
1527 of the operands, we proceed by trying two more multiplications
1528 and then computing the appropriate sum.
1530 We have checked above that the required addition is provided.
1531 Full-word addition will normally always succeed, especially if
1532 it is provided at all, so we don't worry about its failure. The
1533 multiplication may well fail, however, so we do handle that. */
1535 if (product
&& op0_xhigh
&& op1_xhigh
)
1537 rtx product_high
= operand_subword (product
, high
, 1, mode
);
1538 rtx temp
= expand_binop (word_mode
, binoptab
, op0_low
, op1_xhigh
,
1539 NULL_RTX
, 0, OPTAB_DIRECT
);
1542 temp
= expand_binop (word_mode
, add_optab
, temp
, product_high
,
1543 product_high
, 0, next_methods
);
1545 if (temp
!= 0 && temp
!= product_high
)
1546 emit_move_insn (product_high
, temp
);
1549 temp
= expand_binop (word_mode
, binoptab
, op1_low
, op0_xhigh
,
1550 NULL_RTX
, 0, OPTAB_DIRECT
);
1553 temp
= expand_binop (word_mode
, add_optab
, temp
,
1554 product_high
, product_high
,
1557 if (temp
!= 0 && temp
!= product_high
)
1558 emit_move_insn (product_high
, temp
);
1562 if (mov_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1564 temp
= emit_move_insn (product
, product
);
1565 set_unique_reg_note (temp
,
1567 gen_rtx_fmt_ee (MULT
, mode
,
1575 /* If we get here, we couldn't do it for some reason even though we
1576 originally thought we could. Delete anything we've emitted in
1579 delete_insns_since (last
);
1582 /* We need to open-code the complex type operations: '+, -, * and /' */
1584 /* At this point we allow operations between two similar complex
1585 numbers, and also if one of the operands is not a complex number
1586 but rather of MODE_FLOAT or MODE_INT. However, the caller
1587 must make sure that the MODE of the non-complex operand matches
1588 the SUBMODE of the complex operand. */
1590 if (class == MODE_COMPLEX_FLOAT
|| class == MODE_COMPLEX_INT
)
1592 rtx real0
= 0, imag0
= 0;
1593 rtx real1
= 0, imag1
= 0;
1594 rtx realr
, imagr
, res
;
1599 /* Find the correct mode for the real and imaginary parts */
1600 enum machine_mode submode
1601 = mode_for_size (GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
,
1602 class == MODE_COMPLEX_INT
? MODE_INT
: MODE_FLOAT
,
1605 if (submode
== BLKmode
)
1609 target
= gen_reg_rtx (mode
);
1613 realr
= gen_realpart (submode
, target
);
1614 imagr
= gen_imagpart (submode
, target
);
1616 if (GET_MODE (op0
) == mode
)
1618 real0
= gen_realpart (submode
, op0
);
1619 imag0
= gen_imagpart (submode
, op0
);
1624 if (GET_MODE (op1
) == mode
)
1626 real1
= gen_realpart (submode
, op1
);
1627 imag1
= gen_imagpart (submode
, op1
);
1632 if (real0
== 0 || real1
== 0 || ! (imag0
!= 0|| imag1
!= 0))
1635 switch (binoptab
->code
)
1638 /* (a+ib) + (c+id) = (a+c) + i(b+d) */
1640 /* (a+ib) - (c+id) = (a-c) + i(b-d) */
1641 res
= expand_binop (submode
, binoptab
, real0
, real1
,
1642 realr
, unsignedp
, methods
);
1646 else if (res
!= realr
)
1647 emit_move_insn (realr
, res
);
1650 res
= expand_binop (submode
, binoptab
, imag0
, imag1
,
1651 imagr
, unsignedp
, methods
);
1654 else if (binoptab
->code
== MINUS
)
1655 res
= expand_unop (submode
, neg_optab
, imag1
, imagr
, unsignedp
);
1661 else if (res
!= imagr
)
1662 emit_move_insn (imagr
, res
);
1668 /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */
1674 /* Don't fetch these from memory more than once. */
1675 real0
= force_reg (submode
, real0
);
1676 real1
= force_reg (submode
, real1
);
1677 imag0
= force_reg (submode
, imag0
);
1678 imag1
= force_reg (submode
, imag1
);
1680 temp1
= expand_binop (submode
, binoptab
, real0
, real1
, NULL_RTX
,
1681 unsignedp
, methods
);
1683 temp2
= expand_binop (submode
, binoptab
, imag0
, imag1
, NULL_RTX
,
1684 unsignedp
, methods
);
1686 if (temp1
== 0 || temp2
== 0)
1689 res
= expand_binop (submode
, sub_optab
, temp1
, temp2
,
1690 realr
, unsignedp
, methods
);
1694 else if (res
!= realr
)
1695 emit_move_insn (realr
, res
);
1697 temp1
= expand_binop (submode
, binoptab
, real0
, imag1
,
1698 NULL_RTX
, unsignedp
, methods
);
1700 temp2
= expand_binop (submode
, binoptab
, real1
, imag0
,
1701 NULL_RTX
, unsignedp
, methods
);
1703 if (temp1
== 0 || temp2
== 0)
1706 res
= expand_binop (submode
, add_optab
, temp1
, temp2
,
1707 imagr
, unsignedp
, methods
);
1711 else if (res
!= imagr
)
1712 emit_move_insn (imagr
, res
);
1718 /* Don't fetch these from memory more than once. */
1719 real0
= force_reg (submode
, real0
);
1720 real1
= force_reg (submode
, real1
);
1722 res
= expand_binop (submode
, binoptab
, real0
, real1
,
1723 realr
, unsignedp
, methods
);
1726 else if (res
!= realr
)
1727 emit_move_insn (realr
, res
);
1730 res
= expand_binop (submode
, binoptab
,
1731 real1
, imag0
, imagr
, unsignedp
, methods
);
1733 res
= expand_binop (submode
, binoptab
,
1734 real0
, imag1
, imagr
, unsignedp
, methods
);
1738 else if (res
!= imagr
)
1739 emit_move_insn (imagr
, res
);
1746 /* (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) */
1750 /* (a+ib) / (c+i0) = (a/c) + i(b/c) */
1752 /* Don't fetch these from memory more than once. */
1753 real1
= force_reg (submode
, real1
);
1755 /* Simply divide the real and imaginary parts by `c' */
1756 if (class == MODE_COMPLEX_FLOAT
)
1757 res
= expand_binop (submode
, binoptab
, real0
, real1
,
1758 realr
, unsignedp
, methods
);
1760 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
1761 real0
, real1
, realr
, unsignedp
);
1765 else if (res
!= realr
)
1766 emit_move_insn (realr
, res
);
1768 if (class == MODE_COMPLEX_FLOAT
)
1769 res
= expand_binop (submode
, binoptab
, imag0
, real1
,
1770 imagr
, unsignedp
, methods
);
1772 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
1773 imag0
, real1
, imagr
, unsignedp
);
1777 else if (res
!= imagr
)
1778 emit_move_insn (imagr
, res
);
1784 switch (flag_complex_divide_method
)
1787 ok
= expand_cmplxdiv_straight (real0
, real1
, imag0
, imag1
,
1788 realr
, imagr
, submode
,
1794 ok
= expand_cmplxdiv_wide (real0
, real1
, imag0
, imag1
,
1795 realr
, imagr
, submode
,
1815 if (binoptab
->code
!= UNKNOWN
)
1817 = gen_rtx_fmt_ee (binoptab
->code
, mode
,
1818 copy_rtx (op0
), copy_rtx (op1
));
1822 emit_no_conflict_block (seq
, target
, op0
, op1
, equiv_value
);
1828 /* It can't be open-coded in this mode.
1829 Use a library call if one is available and caller says that's ok. */
1831 if (binoptab
->handlers
[(int) mode
].libfunc
1832 && (methods
== OPTAB_LIB
|| methods
== OPTAB_LIB_WIDEN
))
1836 enum machine_mode op1_mode
= mode
;
1843 op1_mode
= word_mode
;
1844 /* Specify unsigned here,
1845 since negative shift counts are meaningless. */
1846 op1x
= convert_to_mode (word_mode
, op1
, 1);
1849 if (GET_MODE (op0
) != VOIDmode
1850 && GET_MODE (op0
) != mode
)
1851 op0
= convert_to_mode (mode
, op0
, unsignedp
);
1853 /* Pass 1 for NO_QUEUE so we don't lose any increments
1854 if the libcall is cse'd or moved. */
1855 value
= emit_library_call_value (binoptab
->handlers
[(int) mode
].libfunc
,
1856 NULL_RTX
, 1, mode
, 2,
1857 op0
, mode
, op1x
, op1_mode
);
1859 insns
= get_insns ();
1862 target
= gen_reg_rtx (mode
);
1863 emit_libcall_block (insns
, target
, value
,
1864 gen_rtx_fmt_ee (binoptab
->code
, mode
, op0
, op1
));
1869 delete_insns_since (last
);
1871 /* It can't be done in this mode. Can we do it in a wider mode? */
1873 if (! (methods
== OPTAB_WIDEN
|| methods
== OPTAB_LIB_WIDEN
1874 || methods
== OPTAB_MUST_WIDEN
))
1876 /* Caller says, don't even try. */
1877 delete_insns_since (entry_last
);
1881 /* Compute the value of METHODS to pass to recursive calls.
1882 Don't allow widening to be tried recursively. */
1884 methods
= (methods
== OPTAB_LIB_WIDEN
? OPTAB_LIB
: OPTAB_DIRECT
);
1886 /* Look for a wider mode of the same class for which it appears we can do
1889 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1891 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1892 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1894 if ((binoptab
->handlers
[(int) wider_mode
].insn_code
1895 != CODE_FOR_nothing
)
1896 || (methods
== OPTAB_LIB
1897 && binoptab
->handlers
[(int) wider_mode
].libfunc
))
1899 rtx xop0
= op0
, xop1
= op1
;
1902 /* For certain integer operations, we need not actually extend
1903 the narrow operands, as long as we will truncate
1904 the results to the same narrowness. */
1906 if ((binoptab
== ior_optab
|| binoptab
== and_optab
1907 || binoptab
== xor_optab
1908 || binoptab
== add_optab
|| binoptab
== sub_optab
1909 || binoptab
== smul_optab
|| binoptab
== ashl_optab
)
1910 && class == MODE_INT
)
1913 xop0
= widen_operand (xop0
, wider_mode
, mode
,
1914 unsignedp
, no_extend
);
1916 /* The second operand of a shift must always be extended. */
1917 xop1
= widen_operand (xop1
, wider_mode
, mode
, unsignedp
,
1918 no_extend
&& binoptab
!= ashl_optab
);
1920 temp
= expand_binop (wider_mode
, binoptab
, xop0
, xop1
, NULL_RTX
,
1921 unsignedp
, methods
);
1924 if (class != MODE_INT
)
1927 target
= gen_reg_rtx (mode
);
1928 convert_move (target
, temp
, 0);
1932 return gen_lowpart (mode
, temp
);
1935 delete_insns_since (last
);
1940 delete_insns_since (entry_last
);
1944 /* Expand a binary operator which has both signed and unsigned forms.
1945 UOPTAB is the optab for unsigned operations, and SOPTAB is for
1948 If we widen unsigned operands, we may use a signed wider operation instead
1949 of an unsigned wider operation, since the result would be the same. */
1952 sign_expand_binop (mode
, uoptab
, soptab
, op0
, op1
, target
, unsignedp
, methods
)
1953 enum machine_mode mode
;
1954 optab uoptab
, soptab
;
1955 rtx op0
, op1
, target
;
1957 enum optab_methods methods
;
1960 optab direct_optab
= unsignedp
? uoptab
: soptab
;
1961 struct optab wide_soptab
;
1963 /* Do it without widening, if possible. */
1964 temp
= expand_binop (mode
, direct_optab
, op0
, op1
, target
,
1965 unsignedp
, OPTAB_DIRECT
);
1966 if (temp
|| methods
== OPTAB_DIRECT
)
1969 /* Try widening to a signed int. Make a fake signed optab that
1970 hides any signed insn for direct use. */
1971 wide_soptab
= *soptab
;
1972 wide_soptab
.handlers
[(int) mode
].insn_code
= CODE_FOR_nothing
;
1973 wide_soptab
.handlers
[(int) mode
].libfunc
= 0;
1975 temp
= expand_binop (mode
, &wide_soptab
, op0
, op1
, target
,
1976 unsignedp
, OPTAB_WIDEN
);
1978 /* For unsigned operands, try widening to an unsigned int. */
1979 if (temp
== 0 && unsignedp
)
1980 temp
= expand_binop (mode
, uoptab
, op0
, op1
, target
,
1981 unsignedp
, OPTAB_WIDEN
);
1982 if (temp
|| methods
== OPTAB_WIDEN
)
1985 /* Use the right width lib call if that exists. */
1986 temp
= expand_binop (mode
, direct_optab
, op0
, op1
, target
, unsignedp
, OPTAB_LIB
);
1987 if (temp
|| methods
== OPTAB_LIB
)
1990 /* Must widen and use a lib call, use either signed or unsigned. */
1991 temp
= expand_binop (mode
, &wide_soptab
, op0
, op1
, target
,
1992 unsignedp
, methods
);
1996 return expand_binop (mode
, uoptab
, op0
, op1
, target
,
1997 unsignedp
, methods
);
2001 /* Generate code to perform an operation specified by BINOPTAB
2002 on operands OP0 and OP1, with two results to TARG1 and TARG2.
2003 We assume that the order of the operands for the instruction
2004 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
2005 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
2007 Either TARG0 or TARG1 may be zero, but what that means is that
2008 the result is not actually wanted. We will generate it into
2009 a dummy pseudo-reg and discard it. They may not both be zero.
2011 Returns 1 if this operation can be performed; 0 if not. */
2014 expand_twoval_binop (binoptab
, op0
, op1
, targ0
, targ1
, unsignedp
)
2020 enum machine_mode mode
= GET_MODE (targ0
? targ0
: targ1
);
2021 enum mode_class
class;
2022 enum machine_mode wider_mode
;
2023 rtx entry_last
= get_last_insn ();
2026 class = GET_MODE_CLASS (mode
);
2028 op0
= protect_from_queue (op0
, 0);
2029 op1
= protect_from_queue (op1
, 0);
2033 op0
= force_not_mem (op0
);
2034 op1
= force_not_mem (op1
);
2037 /* If we are inside an appropriately-short loop and one operand is an
2038 expensive constant, force it into a register. */
2039 if (CONSTANT_P (op0
) && preserve_subexpressions_p ()
2040 && rtx_cost (op0
, binoptab
->code
) > 2)
2041 op0
= force_reg (mode
, op0
);
2043 if (CONSTANT_P (op1
) && preserve_subexpressions_p ()
2044 && rtx_cost (op1
, binoptab
->code
) > 2)
2045 op1
= force_reg (mode
, op1
);
2048 targ0
= protect_from_queue (targ0
, 1);
2050 targ0
= gen_reg_rtx (mode
);
2052 targ1
= protect_from_queue (targ1
, 1);
2054 targ1
= gen_reg_rtx (mode
);
2056 /* Record where to go back to if we fail. */
2057 last
= get_last_insn ();
2059 if (binoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
2061 int icode
= (int) binoptab
->handlers
[(int) mode
].insn_code
;
2062 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
2063 enum machine_mode mode1
= insn_operand_mode
[icode
][2];
2065 rtx xop0
= op0
, xop1
= op1
;
2067 /* In case this insn wants input operands in modes different from the
2068 result, convert the operands. */
2069 if (GET_MODE (op0
) != VOIDmode
&& GET_MODE (op0
) != mode0
)
2070 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
2072 if (GET_MODE (op1
) != VOIDmode
&& GET_MODE (op1
) != mode1
)
2073 xop1
= convert_to_mode (mode1
, xop1
, unsignedp
);
2075 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2076 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
2077 xop0
= copy_to_mode_reg (mode0
, xop0
);
2079 if (! (*insn_operand_predicate
[icode
][2]) (xop1
, mode1
))
2080 xop1
= copy_to_mode_reg (mode1
, xop1
);
2082 /* We could handle this, but we should always be called with a pseudo
2083 for our targets and all insns should take them as outputs. */
2084 if (! (*insn_operand_predicate
[icode
][0]) (targ0
, mode
)
2085 || ! (*insn_operand_predicate
[icode
][3]) (targ1
, mode
))
2088 pat
= GEN_FCN (icode
) (targ0
, xop0
, xop1
, targ1
);
2095 delete_insns_since (last
);
2098 /* It can't be done in this mode. Can we do it in a wider mode? */
2100 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
2102 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2103 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2105 if (binoptab
->handlers
[(int) wider_mode
].insn_code
2106 != CODE_FOR_nothing
)
2108 register rtx t0
= gen_reg_rtx (wider_mode
);
2109 register rtx t1
= gen_reg_rtx (wider_mode
);
2111 if (expand_twoval_binop (binoptab
,
2112 convert_modes (wider_mode
, mode
, op0
,
2114 convert_modes (wider_mode
, mode
, op1
,
2118 convert_move (targ0
, t0
, unsignedp
);
2119 convert_move (targ1
, t1
, unsignedp
);
2123 delete_insns_since (last
);
2128 delete_insns_since (entry_last
);
2132 /* Generate code to perform an operation specified by UNOPTAB
2133 on operand OP0, with result having machine-mode MODE.
2135 UNSIGNEDP is for the case where we have to widen the operands
2136 to perform the operation. It says to use zero-extension.
2138 If TARGET is nonzero, the value
2139 is generated there, if it is convenient to do so.
2140 In all cases an rtx is returned for the locus of the value;
2141 this may or may not be TARGET. */
2144 expand_unop (mode
, unoptab
, op0
, target
, unsignedp
)
2145 enum machine_mode mode
;
2151 enum mode_class
class;
2152 enum machine_mode wider_mode
;
2154 rtx last
= get_last_insn ();
2157 class = GET_MODE_CLASS (mode
);
2159 op0
= protect_from_queue (op0
, 0);
2163 op0
= force_not_mem (op0
);
2167 target
= protect_from_queue (target
, 1);
2169 if (unoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
2171 int icode
= (int) unoptab
->handlers
[(int) mode
].insn_code
;
2172 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
2178 temp
= gen_reg_rtx (mode
);
2180 if (GET_MODE (xop0
) != VOIDmode
2181 && GET_MODE (xop0
) != mode0
)
2182 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
2184 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
2186 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
2187 xop0
= copy_to_mode_reg (mode0
, xop0
);
2189 if (! (*insn_operand_predicate
[icode
][0]) (temp
, mode
))
2190 temp
= gen_reg_rtx (mode
);
2192 pat
= GEN_FCN (icode
) (temp
, xop0
);
2195 if (GET_CODE (pat
) == SEQUENCE
2196 && ! add_equal_note (pat
, temp
, unoptab
->code
, xop0
, NULL_RTX
))
2198 delete_insns_since (last
);
2199 return expand_unop (mode
, unoptab
, op0
, NULL_RTX
, unsignedp
);
2207 delete_insns_since (last
);
2210 /* It can't be done in this mode. Can we open-code it in a wider mode? */
2212 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
2213 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2214 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2216 if (unoptab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
)
2220 /* For certain operations, we need not actually extend
2221 the narrow operand, as long as we will truncate the
2222 results to the same narrowness. */
2224 xop0
= widen_operand (xop0
, wider_mode
, mode
, unsignedp
,
2225 (unoptab
== neg_optab
2226 || unoptab
== one_cmpl_optab
)
2227 && class == MODE_INT
);
2229 temp
= expand_unop (wider_mode
, unoptab
, xop0
, NULL_RTX
,
2234 if (class != MODE_INT
)
2237 target
= gen_reg_rtx (mode
);
2238 convert_move (target
, temp
, 0);
2242 return gen_lowpart (mode
, temp
);
2245 delete_insns_since (last
);
2249 /* These can be done a word at a time. */
2250 if (unoptab
== one_cmpl_optab
2251 && class == MODE_INT
2252 && GET_MODE_SIZE (mode
) > UNITS_PER_WORD
2253 && unoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
2258 if (target
== 0 || target
== op0
)
2259 target
= gen_reg_rtx (mode
);
2263 /* Do the actual arithmetic. */
2264 for (i
= 0; i
< GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
; i
++)
2266 rtx target_piece
= operand_subword (target
, i
, 1, mode
);
2267 rtx x
= expand_unop (word_mode
, unoptab
,
2268 operand_subword_force (op0
, i
, mode
),
2269 target_piece
, unsignedp
);
2270 if (target_piece
!= x
)
2271 emit_move_insn (target_piece
, x
);
2274 insns
= get_insns ();
2277 emit_no_conflict_block (insns
, target
, op0
, NULL_RTX
,
2278 gen_rtx_fmt_e (unoptab
->code
, mode
,
2283 /* Open-code the complex negation operation. */
2284 else if (unoptab
== neg_optab
2285 && (class == MODE_COMPLEX_FLOAT
|| class == MODE_COMPLEX_INT
))
2291 /* Find the correct mode for the real and imaginary parts */
2292 enum machine_mode submode
2293 = mode_for_size (GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
,
2294 class == MODE_COMPLEX_INT
? MODE_INT
: MODE_FLOAT
,
2297 if (submode
== BLKmode
)
2301 target
= gen_reg_rtx (mode
);
2305 target_piece
= gen_imagpart (submode
, target
);
2306 x
= expand_unop (submode
, unoptab
,
2307 gen_imagpart (submode
, op0
),
2308 target_piece
, unsignedp
);
2309 if (target_piece
!= x
)
2310 emit_move_insn (target_piece
, x
);
2312 target_piece
= gen_realpart (submode
, target
);
2313 x
= expand_unop (submode
, unoptab
,
2314 gen_realpart (submode
, op0
),
2315 target_piece
, unsignedp
);
2316 if (target_piece
!= x
)
2317 emit_move_insn (target_piece
, x
);
2322 emit_no_conflict_block (seq
, target
, op0
, 0,
2323 gen_rtx_fmt_e (unoptab
->code
, mode
,
2328 /* Now try a library call in this mode. */
2329 if (unoptab
->handlers
[(int) mode
].libfunc
)
2336 /* Pass 1 for NO_QUEUE so we don't lose any increments
2337 if the libcall is cse'd or moved. */
2338 value
= emit_library_call_value (unoptab
->handlers
[(int) mode
].libfunc
,
2339 NULL_RTX
, 1, mode
, 1, op0
, mode
);
2340 insns
= get_insns ();
2343 target
= gen_reg_rtx (mode
);
2344 emit_libcall_block (insns
, target
, value
,
2345 gen_rtx_fmt_e (unoptab
->code
, mode
, op0
));
2350 /* It can't be done in this mode. Can we do it in a wider mode? */
2352 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
2354 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2355 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2357 if ((unoptab
->handlers
[(int) wider_mode
].insn_code
2358 != CODE_FOR_nothing
)
2359 || unoptab
->handlers
[(int) wider_mode
].libfunc
)
2363 /* For certain operations, we need not actually extend
2364 the narrow operand, as long as we will truncate the
2365 results to the same narrowness. */
2367 xop0
= widen_operand (xop0
, wider_mode
, mode
, unsignedp
,
2368 (unoptab
== neg_optab
2369 || unoptab
== one_cmpl_optab
)
2370 && class == MODE_INT
);
2372 temp
= expand_unop (wider_mode
, unoptab
, xop0
, NULL_RTX
,
2377 if (class != MODE_INT
)
2380 target
= gen_reg_rtx (mode
);
2381 convert_move (target
, temp
, 0);
2385 return gen_lowpart (mode
, temp
);
2388 delete_insns_since (last
);
2393 /* If there is no negate operation, try doing a subtract from zero.
2394 The US Software GOFAST library needs this. */
2395 if (unoptab
== neg_optab
)
2398 temp
= expand_binop (mode
, sub_optab
, CONST0_RTX (mode
), op0
,
2399 target
, unsignedp
, OPTAB_LIB_WIDEN
);
2407 /* Emit code to compute the absolute value of OP0, with result to
2408 TARGET if convenient. (TARGET may be 0.) The return value says
2409 where the result actually is to be found.
2411 MODE is the mode of the operand; the mode of the result is
2412 different but can be deduced from MODE.
2417 expand_abs (mode
, op0
, target
, safe
)
2418 enum machine_mode mode
;
2425 /* First try to do it with a special abs instruction. */
2426 temp
= expand_unop (mode
, abs_optab
, op0
, target
, 0);
2430 /* If this machine has expensive jumps, we can do integer absolute
2431 value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
2432 where W is the width of MODE. */
2434 if (GET_MODE_CLASS (mode
) == MODE_INT
&& BRANCH_COST
>= 2)
2436 rtx extended
= expand_shift (RSHIFT_EXPR
, mode
, op0
,
2437 size_int (GET_MODE_BITSIZE (mode
) - 1),
2440 temp
= expand_binop (mode
, xor_optab
, extended
, op0
, target
, 0,
2443 temp
= expand_binop (mode
, sub_optab
, temp
, extended
, target
, 0,
2450 /* If that does not win, use conditional jump and negate. */
2452 /* It is safe to use the target if it is the same
2453 as the source if this is also a pseudo register */
2454 if (op0
== target
&& GET_CODE (op0
) == REG
2455 && REGNO (op0
) >= FIRST_PSEUDO_REGISTER
)
2458 op1
= gen_label_rtx ();
2459 if (target
== 0 || ! safe
2460 || GET_MODE (target
) != mode
2461 || (GET_CODE (target
) == MEM
&& MEM_VOLATILE_P (target
))
2462 || (GET_CODE (target
) == REG
2463 && REGNO (target
) < FIRST_PSEUDO_REGISTER
))
2464 target
= gen_reg_rtx (mode
);
2466 emit_move_insn (target
, op0
);
2469 /* If this mode is an integer too wide to compare properly,
2470 compare word by word. Rely on CSE to optimize constant cases. */
2471 if (GET_MODE_CLASS (mode
) == MODE_INT
&& ! can_compare_p (mode
))
2472 do_jump_by_parts_greater_rtx (mode
, 0, target
, const0_rtx
,
2475 do_compare_rtx_and_jump (target
, CONST0_RTX (mode
), GE
, 0, mode
,
2476 NULL_RTX
, 0, NULL_RTX
, op1
);
2478 op0
= expand_unop (mode
, neg_optab
, target
, target
, 0);
2480 emit_move_insn (target
, op0
);
2486 /* Emit code to compute the absolute value of OP0, with result to
2487 TARGET if convenient. (TARGET may be 0.) The return value says
2488 where the result actually is to be found.
2490 MODE is the mode of the operand; the mode of the result is
2491 different but can be deduced from MODE.
2493 UNSIGNEDP is relevant for complex integer modes. */
2496 expand_complex_abs (mode
, op0
, target
, unsignedp
)
2497 enum machine_mode mode
;
2502 enum mode_class
class = GET_MODE_CLASS (mode
);
2503 enum machine_mode wider_mode
;
2505 rtx entry_last
= get_last_insn ();
2509 /* Find the correct mode for the real and imaginary parts. */
2510 enum machine_mode submode
2511 = mode_for_size (GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
,
2512 class == MODE_COMPLEX_INT
? MODE_INT
: MODE_FLOAT
,
2515 if (submode
== BLKmode
)
2518 op0
= protect_from_queue (op0
, 0);
2522 op0
= force_not_mem (op0
);
2525 last
= get_last_insn ();
2528 target
= protect_from_queue (target
, 1);
2530 if (abs_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
2532 int icode
= (int) abs_optab
->handlers
[(int) mode
].insn_code
;
2533 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
2539 temp
= gen_reg_rtx (submode
);
2541 if (GET_MODE (xop0
) != VOIDmode
2542 && GET_MODE (xop0
) != mode0
)
2543 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
2545 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
2547 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
2548 xop0
= copy_to_mode_reg (mode0
, xop0
);
2550 if (! (*insn_operand_predicate
[icode
][0]) (temp
, submode
))
2551 temp
= gen_reg_rtx (submode
);
2553 pat
= GEN_FCN (icode
) (temp
, xop0
);
2556 if (GET_CODE (pat
) == SEQUENCE
2557 && ! add_equal_note (pat
, temp
, abs_optab
->code
, xop0
, NULL_RTX
))
2559 delete_insns_since (last
);
2560 return expand_unop (mode
, abs_optab
, op0
, NULL_RTX
, unsignedp
);
2568 delete_insns_since (last
);
2571 /* It can't be done in this mode. Can we open-code it in a wider mode? */
2573 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2574 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2576 if (abs_optab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
)
2580 xop0
= convert_modes (wider_mode
, mode
, xop0
, unsignedp
);
2581 temp
= expand_complex_abs (wider_mode
, xop0
, NULL_RTX
, unsignedp
);
2585 if (class != MODE_COMPLEX_INT
)
2588 target
= gen_reg_rtx (submode
);
2589 convert_move (target
, temp
, 0);
2593 return gen_lowpart (submode
, temp
);
2596 delete_insns_since (last
);
2600 /* Open-code the complex absolute-value operation
2601 if we can open-code sqrt. Otherwise it's not worth while. */
2602 if (sqrt_optab
->handlers
[(int) submode
].insn_code
!= CODE_FOR_nothing
)
2604 rtx real
, imag
, total
;
2606 real
= gen_realpart (submode
, op0
);
2607 imag
= gen_imagpart (submode
, op0
);
2609 /* Square both parts. */
2610 real
= expand_mult (submode
, real
, real
, NULL_RTX
, 0);
2611 imag
= expand_mult (submode
, imag
, imag
, NULL_RTX
, 0);
2613 /* Sum the parts. */
2614 total
= expand_binop (submode
, add_optab
, real
, imag
, NULL_RTX
,
2615 0, OPTAB_LIB_WIDEN
);
2617 /* Get sqrt in TARGET. Set TARGET to where the result is. */
2618 target
= expand_unop (submode
, sqrt_optab
, total
, target
, 0);
2620 delete_insns_since (last
);
2625 /* Now try a library call in this mode. */
2626 if (abs_optab
->handlers
[(int) mode
].libfunc
)
2633 /* Pass 1 for NO_QUEUE so we don't lose any increments
2634 if the libcall is cse'd or moved. */
2635 value
= emit_library_call_value (abs_optab
->handlers
[(int) mode
].libfunc
,
2636 NULL_RTX
, 1, submode
, 1, op0
, mode
);
2637 insns
= get_insns ();
2640 target
= gen_reg_rtx (submode
);
2641 emit_libcall_block (insns
, target
, value
,
2642 gen_rtx_fmt_e (abs_optab
->code
, mode
, op0
));
2647 /* It can't be done in this mode. Can we do it in a wider mode? */
2649 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2650 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2652 if ((abs_optab
->handlers
[(int) wider_mode
].insn_code
2653 != CODE_FOR_nothing
)
2654 || abs_optab
->handlers
[(int) wider_mode
].libfunc
)
2658 xop0
= convert_modes (wider_mode
, mode
, xop0
, unsignedp
);
2660 temp
= expand_complex_abs (wider_mode
, xop0
, NULL_RTX
, unsignedp
);
2664 if (class != MODE_COMPLEX_INT
)
2667 target
= gen_reg_rtx (submode
);
2668 convert_move (target
, temp
, 0);
2672 return gen_lowpart (submode
, temp
);
2675 delete_insns_since (last
);
2679 delete_insns_since (entry_last
);
2683 /* Generate an instruction whose insn-code is INSN_CODE,
2684 with two operands: an output TARGET and an input OP0.
2685 TARGET *must* be nonzero, and the output is always stored there.
2686 CODE is an rtx code such that (CODE OP0) is an rtx that describes
2687 the value that is stored into TARGET. */
2690 emit_unop_insn (icode
, target
, op0
, code
)
2697 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
2700 temp
= target
= protect_from_queue (target
, 1);
2702 op0
= protect_from_queue (op0
, 0);
2704 /* Sign and zero extension from memory is often done specially on
2705 RISC machines, so forcing into a register here can pessimize
2707 if (flag_force_mem
&& code
!= SIGN_EXTEND
&& code
!= ZERO_EXTEND
)
2708 op0
= force_not_mem (op0
);
2710 /* Now, if insn does not accept our operands, put them into pseudos. */
2712 if (! (*insn_operand_predicate
[icode
][1]) (op0
, mode0
))
2713 op0
= copy_to_mode_reg (mode0
, op0
);
2715 if (! (*insn_operand_predicate
[icode
][0]) (temp
, GET_MODE (temp
))
2716 || (flag_force_mem
&& GET_CODE (temp
) == MEM
))
2717 temp
= gen_reg_rtx (GET_MODE (temp
));
2719 pat
= GEN_FCN (icode
) (temp
, op0
);
2721 if (GET_CODE (pat
) == SEQUENCE
&& code
!= UNKNOWN
)
2722 add_equal_note (pat
, temp
, code
, op0
, NULL_RTX
);
2727 emit_move_insn (target
, temp
);
2730 /* Emit code to perform a series of operations on a multi-word quantity, one
2733 Such a block is preceded by a CLOBBER of the output, consists of multiple
2734 insns, each setting one word of the output, and followed by a SET copying
2735 the output to itself.
2737 Each of the insns setting words of the output receives a REG_NO_CONFLICT
2738 note indicating that it doesn't conflict with the (also multi-word)
2739 inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
2742 INSNS is a block of code generated to perform the operation, not including
2743 the CLOBBER and final copy. All insns that compute intermediate values
2744 are first emitted, followed by the block as described above.
2746 TARGET, OP0, and OP1 are the output and inputs of the operations,
2747 respectively. OP1 may be zero for a unary operation.
2749 EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
2752 If TARGET is not a register, INSNS is simply emitted with no special
2753 processing. Likewise if anything in INSNS is not an INSN or if
2754 there is a libcall block inside INSNS.
2756 The final insn emitted is returned. */
2759 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv
)
2765 rtx prev
, next
, first
, last
, insn
;
2767 if (GET_CODE (target
) != REG
|| reload_in_progress
)
2768 return emit_insns (insns
);
2770 for (insn
= insns
; insn
; insn
= NEXT_INSN (insn
))
2771 if (GET_CODE (insn
) != INSN
2772 || find_reg_note (insn
, REG_LIBCALL
, NULL_RTX
))
2773 return emit_insns (insns
);
2775 /* First emit all insns that do not store into words of the output and remove
2776 these from the list. */
2777 for (insn
= insns
; insn
; insn
= next
)
2782 next
= NEXT_INSN (insn
);
2784 if (GET_CODE (PATTERN (insn
)) == SET
)
2785 set
= PATTERN (insn
);
2786 else if (GET_CODE (PATTERN (insn
)) == PARALLEL
)
2788 for (i
= 0; i
< XVECLEN (PATTERN (insn
), 0); i
++)
2789 if (GET_CODE (XVECEXP (PATTERN (insn
), 0, i
)) == SET
)
2791 set
= XVECEXP (PATTERN (insn
), 0, i
);
2799 if (! reg_overlap_mentioned_p (target
, SET_DEST (set
)))
2801 if (PREV_INSN (insn
))
2802 NEXT_INSN (PREV_INSN (insn
)) = next
;
2807 PREV_INSN (next
) = PREV_INSN (insn
);
2813 prev
= get_last_insn ();
2815 /* Now write the CLOBBER of the output, followed by the setting of each
2816 of the words, followed by the final copy. */
2817 if (target
!= op0
&& target
!= op1
)
2818 emit_insn (gen_rtx_CLOBBER (VOIDmode
, target
));
2820 for (insn
= insns
; insn
; insn
= next
)
2822 next
= NEXT_INSN (insn
);
2825 if (op1
&& GET_CODE (op1
) == REG
)
2826 REG_NOTES (insn
) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT
, op1
,
2829 if (op0
&& GET_CODE (op0
) == REG
)
2830 REG_NOTES (insn
) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT
, op0
,
2834 if (mov_optab
->handlers
[(int) GET_MODE (target
)].insn_code
2835 != CODE_FOR_nothing
)
2837 last
= emit_move_insn (target
, target
);
2839 set_unique_reg_note (last
, REG_EQUAL
, equiv
);
2842 last
= get_last_insn ();
2845 first
= get_insns ();
2847 first
= NEXT_INSN (prev
);
2849 /* Encapsulate the block so it gets manipulated as a unit. */
2850 REG_NOTES (first
) = gen_rtx_INSN_LIST (REG_LIBCALL
, last
,
2852 REG_NOTES (last
) = gen_rtx_INSN_LIST (REG_RETVAL
, first
, REG_NOTES (last
));
2857 /* Emit code to make a call to a constant function or a library call.
2859 INSNS is a list containing all insns emitted in the call.
2860 These insns leave the result in RESULT. Our block is to copy RESULT
2861 to TARGET, which is logically equivalent to EQUIV.
2863 We first emit any insns that set a pseudo on the assumption that these are
2864 loading constants into registers; doing so allows them to be safely cse'ed
2865 between blocks. Then we emit all the other insns in the block, followed by
2866 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
2867 note with an operand of EQUIV.
2869 Moving assignments to pseudos outside of the block is done to improve
2870 the generated code, but is not required to generate correct code,
2871 hence being unable to move an assignment is not grounds for not making
2872 a libcall block. There are two reasons why it is safe to leave these
2873 insns inside the block: First, we know that these pseudos cannot be
2874 used in generated RTL outside the block since they are created for
2875 temporary purposes within the block. Second, CSE will not record the
2876 values of anything set inside a libcall block, so we know they must
2877 be dead at the end of the block.
2879 Except for the first group of insns (the ones setting pseudos), the
2880 block is delimited by REG_RETVAL and REG_LIBCALL notes. */
2883 emit_libcall_block (insns
, target
, result
, equiv
)
2889 rtx prev
, next
, first
, last
, insn
;
2891 /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
2892 reg note to indicate that this call cannot throw. (Unless there is
2893 already a REG_EH_REGION note.) */
2895 for (insn
= insns
; insn
; insn
= NEXT_INSN (insn
))
2897 if (GET_CODE (insn
) == CALL_INSN
)
2899 rtx note
= find_reg_note (insn
, REG_EH_REGION
, NULL_RTX
);
2900 if (note
== NULL_RTX
)
2901 REG_NOTES (insn
) = gen_rtx_EXPR_LIST (REG_EH_REGION
, GEN_INT (-1),
2906 /* First emit all insns that set pseudos. Remove them from the list as
2907 we go. Avoid insns that set pseudos which were referenced in previous
2908 insns. These can be generated by move_by_pieces, for example,
2909 to update an address. Similarly, avoid insns that reference things
2910 set in previous insns. */
2912 for (insn
= insns
; insn
; insn
= next
)
2914 rtx set
= single_set (insn
);
2916 next
= NEXT_INSN (insn
);
2918 if (set
!= 0 && GET_CODE (SET_DEST (set
)) == REG
2919 && REGNO (SET_DEST (set
)) >= FIRST_PSEUDO_REGISTER
2921 || (! reg_mentioned_p (SET_DEST (set
), PATTERN (insns
))
2922 && ! reg_used_between_p (SET_DEST (set
), insns
, insn
)
2923 && ! modified_in_p (SET_SRC (set
), insns
)
2924 && ! modified_between_p (SET_SRC (set
), insns
, insn
))))
2926 if (PREV_INSN (insn
))
2927 NEXT_INSN (PREV_INSN (insn
)) = next
;
2932 PREV_INSN (next
) = PREV_INSN (insn
);
2938 prev
= get_last_insn ();
2940 /* Write the remaining insns followed by the final copy. */
2942 for (insn
= insns
; insn
; insn
= next
)
2944 next
= NEXT_INSN (insn
);
2949 last
= emit_move_insn (target
, result
);
2950 if (mov_optab
->handlers
[(int) GET_MODE (target
)].insn_code
2951 != CODE_FOR_nothing
)
2952 set_unique_reg_note (last
, REG_EQUAL
, copy_rtx (equiv
));
2955 first
= get_insns ();
2957 first
= NEXT_INSN (prev
);
2959 /* Encapsulate the block so it gets manipulated as a unit. */
2960 REG_NOTES (first
) = gen_rtx_INSN_LIST (REG_LIBCALL
, last
,
2962 REG_NOTES (last
) = gen_rtx_INSN_LIST (REG_RETVAL
, first
, REG_NOTES (last
));
2965 /* Generate code to store zero in X. */
2971 emit_move_insn (x
, const0_rtx
);
2974 /* Generate code to store 1 in X
2975 assuming it contains zero beforehand. */
2978 emit_0_to_1_insn (x
)
2981 emit_move_insn (x
, const1_rtx
);
2984 /* Nonzero if we can perform a comparison of mode MODE for a conditional jump
2985 straightforwardly. */
2988 cmp_available_p (mode
, code
, can_use_tst_p
)
2989 enum machine_mode mode
;
2995 if (cmp_optab
->handlers
[(int)mode
].insn_code
!= CODE_FOR_nothing
2997 && tst_optab
->handlers
[(int)mode
].insn_code
!= CODE_FOR_nothing
))
2999 mode
= GET_MODE_WIDER_MODE (mode
);
3000 } while (mode
!= VOIDmode
);
3005 /* This function is called when we are going to emit a compare instruction that
3006 compares the values found in *PX and *PY, using the rtl operator COMPARISON.
3008 *PMODE is the mode of the inputs (in case they are const_int).
3009 *PUNSIGNEDP nonzero says that the operands are unsigned;
3010 this matters if they need to be widened.
3012 If they have mode BLKmode, then SIZE specifies the size of both operands,
3013 and ALIGN specifies the known shared alignment of the operands.
3015 This function performs all the setup necessary so that the caller only has
3016 to emit a single comparison insn. This setup can involve doing a BLKmode
3017 comparison or emitting a library call to perform the comparison if no insn
3018 is available to handle it.
3019 The values which are passed in through pointers can be modified; the caller
3020 should perform the comparison on the modified values. */
3023 prepare_cmp_insn (px
, py
, pcomparison
, size
, pmode
, punsignedp
, align
)
3025 enum rtx_code
*pcomparison
;
3027 enum machine_mode
*pmode
;
3031 enum rtx_code comparison
= *pcomparison
;
3032 enum machine_mode mode
= *pmode
;
3033 rtx x
= *px
, y
= *py
;
3034 int unsignedp
= *punsignedp
;
3035 enum mode_class
class;
3037 class = GET_MODE_CLASS (mode
);
3039 /* They could both be VOIDmode if both args are immediate constants,
3040 but we should fold that at an earlier stage.
3041 With no special code here, this will call abort,
3042 reminding the programmer to implement such folding. */
3044 if (mode
!= BLKmode
&& flag_force_mem
)
3046 x
= force_not_mem (x
);
3047 y
= force_not_mem (y
);
3050 /* If we are inside an appropriately-short loop and one operand is an
3051 expensive constant, force it into a register. */
3052 if (CONSTANT_P (x
) && preserve_subexpressions_p () && rtx_cost (x
, COMPARE
) > 2)
3053 x
= force_reg (mode
, x
);
3055 if (CONSTANT_P (y
) && preserve_subexpressions_p () && rtx_cost (y
, COMPARE
) > 2)
3056 y
= force_reg (mode
, y
);
3059 /* Abort if we have a non-canonical comparison. The RTL documentation
3060 states that canonical comparisons are required only for targets which
3062 if (CONSTANT_P (x
) && ! CONSTANT_P (y
))
3066 /* Don't let both operands fail to indicate the mode. */
3067 if (GET_MODE (x
) == VOIDmode
&& GET_MODE (y
) == VOIDmode
)
3068 x
= force_reg (mode
, x
);
3070 /* Handle all BLKmode compares. */
3072 if (mode
== BLKmode
)
3075 enum machine_mode result_mode
;
3078 x
= protect_from_queue (x
, 0);
3079 y
= protect_from_queue (y
, 0);
3083 #ifdef HAVE_cmpstrqi
3085 && GET_CODE (size
) == CONST_INT
3086 && INTVAL (size
) < (1 << GET_MODE_BITSIZE (QImode
)))
3088 result_mode
= insn_operand_mode
[(int) CODE_FOR_cmpstrqi
][0];
3089 result
= gen_reg_rtx (result_mode
);
3090 emit_insn (gen_cmpstrqi (result
, x
, y
, size
, GEN_INT (align
)));
3094 #ifdef HAVE_cmpstrhi
3096 && GET_CODE (size
) == CONST_INT
3097 && INTVAL (size
) < (1 << GET_MODE_BITSIZE (HImode
)))
3099 result_mode
= insn_operand_mode
[(int) CODE_FOR_cmpstrhi
][0];
3100 result
= gen_reg_rtx (result_mode
);
3101 emit_insn (gen_cmpstrhi (result
, x
, y
, size
, GEN_INT (align
)));
3105 #ifdef HAVE_cmpstrsi
3108 result_mode
= insn_operand_mode
[(int) CODE_FOR_cmpstrsi
][0];
3109 result
= gen_reg_rtx (result_mode
);
3110 size
= protect_from_queue (size
, 0);
3111 emit_insn (gen_cmpstrsi (result
, x
, y
,
3112 convert_to_mode (SImode
, size
, 1),
3118 #ifdef TARGET_MEM_FUNCTIONS
3119 emit_library_call (memcmp_libfunc
, 0,
3120 TYPE_MODE (integer_type_node
), 3,
3121 XEXP (x
, 0), Pmode
, XEXP (y
, 0), Pmode
,
3122 convert_to_mode (TYPE_MODE (sizetype
), size
,
3123 TREE_UNSIGNED (sizetype
)),
3124 TYPE_MODE (sizetype
));
3126 emit_library_call (bcmp_libfunc
, 0,
3127 TYPE_MODE (integer_type_node
), 3,
3128 XEXP (x
, 0), Pmode
, XEXP (y
, 0), Pmode
,
3129 convert_to_mode (TYPE_MODE (integer_type_node
),
3131 TREE_UNSIGNED (integer_type_node
)),
3132 TYPE_MODE (integer_type_node
));
3135 /* Immediately move the result of the libcall into a pseudo
3136 register so reload doesn't clobber the value if it needs
3137 the return register for a spill reg. */
3138 result
= gen_reg_rtx (TYPE_MODE (integer_type_node
));
3139 result_mode
= TYPE_MODE (integer_type_node
);
3140 emit_move_insn (result
,
3141 hard_libcall_value (result_mode
));
3145 *pmode
= result_mode
;
3151 if (cmp_available_p (mode
, comparison
, y
== CONST0_RTX (mode
)))
3154 /* Handle a lib call just for the mode we are using. */
3156 if (cmp_optab
->handlers
[(int) mode
].libfunc
&& class != MODE_FLOAT
)
3158 rtx libfunc
= cmp_optab
->handlers
[(int) mode
].libfunc
;
3161 /* If we want unsigned, and this mode has a distinct unsigned
3162 comparison routine, use that. */
3163 if (unsignedp
&& ucmp_optab
->handlers
[(int) mode
].libfunc
)
3164 libfunc
= ucmp_optab
->handlers
[(int) mode
].libfunc
;
3166 emit_library_call (libfunc
, 1,
3167 word_mode
, 2, x
, mode
, y
, mode
);
3169 /* Immediately move the result of the libcall into a pseudo
3170 register so reload doesn't clobber the value if it needs
3171 the return register for a spill reg. */
3172 result
= gen_reg_rtx (word_mode
);
3173 emit_move_insn (result
, hard_libcall_value (word_mode
));
3175 /* Integer comparison returns a result that must be compared against 1,
3176 so that even if we do an unsigned compare afterward,
3177 there is still a value that can represent the result "less than". */
3184 if (class == MODE_FLOAT
)
3185 prepare_float_lib_cmp (px
, py
, pcomparison
, pmode
, punsignedp
);
3191 /* Before emitting an insn with code ICODE, make sure that X, which is going
3192 to be used for operand OPNUM of the insn, is converted from mode MODE to
3193 WIDER_MODE (UNSIGNEDP determines whether it is a unsigned conversion), and
3194 that it is accepted by the operand predicate. Return the new value. */
3196 prepare_operand (icode
, x
, opnum
, mode
, wider_mode
, unsignedp
)
3200 enum machine_mode mode
, wider_mode
;
3203 x
= protect_from_queue (x
, 0);
3205 if (mode
!= wider_mode
)
3206 x
= convert_modes (wider_mode
, mode
, x
, unsignedp
);
3208 if (! (*insn_operand_predicate
[icode
][opnum
])
3209 (x
, insn_operand_mode
[icode
][opnum
]))
3210 x
= copy_to_mode_reg (insn_operand_mode
[icode
][opnum
], x
);
3214 /* Subroutine of emit_cmp_and_jump_insns; this function is called when we know
3215 we can do the comparison.
3216 The arguments are the same as for emit_cmp_and_jump_insns; but LABEL may
3217 be NULL_RTX which indicates that only a comparison is to be generated. */
3220 emit_cmp_and_jump_insn_1 (x
, y
, mode
, comparison
, unsignedp
, label
)
3222 enum machine_mode mode
;
3223 enum rtx_code comparison
;
3227 rtx test
= gen_rtx_fmt_ee (comparison
, mode
, x
, y
);
3228 enum mode_class
class = GET_MODE_CLASS (mode
);
3229 enum machine_mode wider_mode
= mode
;
3231 /* Try combined insns first. */
3234 enum insn_code icode
;
3235 PUT_MODE (test
, wider_mode
);
3237 /* Handle some compares against zero. */
3238 icode
= (int) tst_optab
->handlers
[(int) wider_mode
].insn_code
;
3239 if (y
== CONST0_RTX (mode
) && icode
!= CODE_FOR_nothing
)
3241 x
= prepare_operand (icode
, x
, 0, mode
, wider_mode
, unsignedp
);
3242 emit_insn (GEN_FCN (icode
) (x
));
3244 emit_jump_insn ((*bcc_gen_fctn
[(int) comparison
]) (label
));
3248 /* Handle compares for which there is a directly suitable insn. */
3250 icode
= (int) cmp_optab
->handlers
[(int) wider_mode
].insn_code
;
3251 if (icode
!= CODE_FOR_nothing
)
3253 x
= prepare_operand (icode
, x
, 0, mode
, wider_mode
, unsignedp
);
3254 y
= prepare_operand (icode
, y
, 1, mode
, wider_mode
, unsignedp
);
3255 emit_insn (GEN_FCN (icode
) (x
, y
));
3257 emit_jump_insn ((*bcc_gen_fctn
[(int) comparison
]) (label
));
3261 if (class != MODE_INT
&& class != MODE_FLOAT
3262 && class != MODE_COMPLEX_FLOAT
)
3265 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
);
3266 } while (wider_mode
!= VOIDmode
);
3271 /* Generate code to compare X with Y so that the condition codes are
3272 set and to jump to LABEL if the condition is true. If X is a
3273 constant and Y is not a constant, then the comparison is swapped to
3274 ensure that the comparison RTL has the canonical form.
3276 UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
3277 need to be widened by emit_cmp_insn. UNSIGNEDP is also used to select
3278 the proper branch condition code.
3280 If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y,
3281 and ALIGN specifies the known shared alignment of X and Y.
3283 MODE is the mode of the inputs (in case they are const_int).
3285 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). It will
3286 be passed unchanged to emit_cmp_insn, then potentially converted into an
3287 unsigned variant based on UNSIGNEDP to select a proper jump instruction. */
3290 emit_cmp_and_jump_insns (x
, y
, comparison
, size
, mode
, unsignedp
, align
, label
)
3292 enum rtx_code comparison
;
3294 enum machine_mode mode
;
3302 if ((CONSTANT_P (x
) && ! CONSTANT_P (y
))
3303 || (GET_CODE (x
) == CONST_INT
&& GET_CODE (y
) != CONST_INT
))
3305 /* Swap operands and condition to ensure canonical RTL. */
3308 comparison
= swap_condition (comparison
);
3317 /* If OP0 is still a constant, then both X and Y must be constants. Force
3318 X into a register to avoid aborting in emit_cmp_insn due to non-canonical
3320 if (CONSTANT_P (op0
))
3321 op0
= force_reg (mode
, op0
);
3326 comparison
= unsigned_condition (comparison
);
3327 prepare_cmp_insn (&op0
, &op1
, &comparison
, size
, &mode
, &unsignedp
, align
);
3328 emit_cmp_and_jump_insn_1 (op0
, op1
, mode
, comparison
, unsignedp
, label
);
3331 /* Like emit_cmp_and_jump_insns, but generate only the comparison. */
3333 emit_cmp_insn (x
, y
, comparison
, size
, mode
, unsignedp
, align
)
3335 enum rtx_code comparison
;
3337 enum machine_mode mode
;
3341 emit_cmp_and_jump_insns (x
, y
, comparison
, size
, mode
, unsignedp
, align
, 0);
3345 /* Nonzero if a compare of mode MODE can be done straightforwardly
3346 (without splitting it into pieces). */
3349 can_compare_p (mode
)
3350 enum machine_mode mode
;
3354 if (cmp_optab
->handlers
[(int)mode
].insn_code
!= CODE_FOR_nothing
)
3356 mode
= GET_MODE_WIDER_MODE (mode
);
3357 } while (mode
!= VOIDmode
);
3362 /* Emit a library call comparison between floating point X and Y.
3363 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
3366 prepare_float_lib_cmp (px
, py
, pcomparison
, pmode
, punsignedp
)
3368 enum rtx_code
*pcomparison
;
3369 enum machine_mode
*pmode
;
3372 enum rtx_code comparison
= *pcomparison
;
3373 rtx x
= *px
, y
= *py
;
3374 enum machine_mode mode
= GET_MODE (x
);
3382 libfunc
= eqhf2_libfunc
;
3386 libfunc
= nehf2_libfunc
;
3390 libfunc
= gthf2_libfunc
;
3394 libfunc
= gehf2_libfunc
;
3398 libfunc
= lthf2_libfunc
;
3402 libfunc
= lehf2_libfunc
;
3408 else if (mode
== SFmode
)
3412 libfunc
= eqsf2_libfunc
;
3416 libfunc
= nesf2_libfunc
;
3420 libfunc
= gtsf2_libfunc
;
3424 libfunc
= gesf2_libfunc
;
3428 libfunc
= ltsf2_libfunc
;
3432 libfunc
= lesf2_libfunc
;
3438 else if (mode
== DFmode
)
3442 libfunc
= eqdf2_libfunc
;
3446 libfunc
= nedf2_libfunc
;
3450 libfunc
= gtdf2_libfunc
;
3454 libfunc
= gedf2_libfunc
;
3458 libfunc
= ltdf2_libfunc
;
3462 libfunc
= ledf2_libfunc
;
3468 else if (mode
== XFmode
)
3472 libfunc
= eqxf2_libfunc
;
3476 libfunc
= nexf2_libfunc
;
3480 libfunc
= gtxf2_libfunc
;
3484 libfunc
= gexf2_libfunc
;
3488 libfunc
= ltxf2_libfunc
;
3492 libfunc
= lexf2_libfunc
;
3498 else if (mode
== TFmode
)
3502 libfunc
= eqtf2_libfunc
;
3506 libfunc
= netf2_libfunc
;
3510 libfunc
= gttf2_libfunc
;
3514 libfunc
= getf2_libfunc
;
3518 libfunc
= lttf2_libfunc
;
3522 libfunc
= letf2_libfunc
;
3530 enum machine_mode wider_mode
;
3532 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
3533 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
3535 if ((cmp_optab
->handlers
[(int) wider_mode
].insn_code
3536 != CODE_FOR_nothing
)
3537 || (cmp_optab
->handlers
[(int) wider_mode
].libfunc
!= 0))
3539 x
= protect_from_queue (x
, 0);
3540 y
= protect_from_queue (y
, 0);
3541 *px
= convert_to_mode (wider_mode
, x
, 0);
3542 *py
= convert_to_mode (wider_mode
, y
, 0);
3543 prepare_float_lib_cmp (px
, py
, pcomparison
, pmode
, punsignedp
);
3553 emit_library_call (libfunc
, 1,
3554 word_mode
, 2, x
, mode
, y
, mode
);
3556 /* Immediately move the result of the libcall into a pseudo
3557 register so reload doesn't clobber the value if it needs
3558 the return register for a spill reg. */
3559 result
= gen_reg_rtx (word_mode
);
3560 emit_move_insn (result
, hard_libcall_value (word_mode
));
3564 #ifdef FLOAT_LIB_COMPARE_RETURNS_BOOL
3565 if (FLOAT_LIB_COMPARE_RETURNS_BOOL (mode
, comparison
))
3571 /* Generate code to indirectly jump to a location given in the rtx LOC. */
3574 emit_indirect_jump (loc
)
3577 if (! ((*insn_operand_predicate
[(int)CODE_FOR_indirect_jump
][0])
3579 loc
= copy_to_mode_reg (Pmode
, loc
);
3581 emit_jump_insn (gen_indirect_jump (loc
));
3585 #ifdef HAVE_conditional_move
3587 /* Emit a conditional move instruction if the machine supports one for that
3588 condition and machine mode.
3590 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
3591 the mode to use should they be constants. If it is VOIDmode, they cannot
3594 OP2 should be stored in TARGET if the comparison is true, otherwise OP3
3595 should be stored there. MODE is the mode to use should they be constants.
3596 If it is VOIDmode, they cannot both be constants.
3598 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
3599 is not supported. */
3602 emit_conditional_move (target
, code
, op0
, op1
, cmode
, op2
, op3
, mode
,
3607 enum machine_mode cmode
;
3609 enum machine_mode mode
;
3612 rtx tem
, subtarget
, comparison
, insn
;
3613 enum insn_code icode
;
3615 /* If one operand is constant, make it the second one. Only do this
3616 if the other operand is not constant as well. */
3618 if ((CONSTANT_P (op0
) && ! CONSTANT_P (op1
))
3619 || (GET_CODE (op0
) == CONST_INT
&& GET_CODE (op1
) != CONST_INT
))
3624 code
= swap_condition (code
);
3627 if (cmode
== VOIDmode
)
3628 cmode
= GET_MODE (op0
);
3630 if (((CONSTANT_P (op2
) && ! CONSTANT_P (op3
))
3631 || (GET_CODE (op2
) == CONST_INT
&& GET_CODE (op3
) != CONST_INT
))
3632 && (GET_MODE_CLASS (GET_MODE (op1
)) != MODE_FLOAT
3633 || TARGET_FLOAT_FORMAT
!= IEEE_FLOAT_FORMAT
|| flag_fast_math
))
3638 code
= reverse_condition (code
);
3641 if (mode
== VOIDmode
)
3642 mode
= GET_MODE (op2
);
3644 icode
= movcc_gen_code
[mode
];
3646 if (icode
== CODE_FOR_nothing
)
3651 op2
= force_not_mem (op2
);
3652 op3
= force_not_mem (op3
);
3656 target
= protect_from_queue (target
, 1);
3658 target
= gen_reg_rtx (mode
);
3664 op2
= protect_from_queue (op2
, 0);
3665 op3
= protect_from_queue (op3
, 0);
3667 /* If the insn doesn't accept these operands, put them in pseudos. */
3669 if (! (*insn_operand_predicate
[icode
][0])
3670 (subtarget
, insn_operand_mode
[icode
][0]))
3671 subtarget
= gen_reg_rtx (insn_operand_mode
[icode
][0]);
3673 if (! (*insn_operand_predicate
[icode
][2])
3674 (op2
, insn_operand_mode
[icode
][2]))
3675 op2
= copy_to_mode_reg (insn_operand_mode
[icode
][2], op2
);
3677 if (! (*insn_operand_predicate
[icode
][3])
3678 (op3
, insn_operand_mode
[icode
][3]))
3679 op3
= copy_to_mode_reg (insn_operand_mode
[icode
][3], op3
);
3681 /* Everything should now be in the suitable form, so emit the compare insn
3682 and then the conditional move. */
3685 = compare_from_rtx (op0
, op1
, code
, unsignedp
, cmode
, NULL_RTX
, 0);
3687 /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)? */
3688 if (GET_CODE (comparison
) != code
)
3689 /* This shouldn't happen. */
3692 insn
= GEN_FCN (icode
) (subtarget
, comparison
, op2
, op3
);
3694 /* If that failed, then give up. */
3700 if (subtarget
!= target
)
3701 convert_move (target
, subtarget
, 0);
3706 /* Return non-zero if a conditional move of mode MODE is supported.
3708 This function is for combine so it can tell whether an insn that looks
3709 like a conditional move is actually supported by the hardware. If we
3710 guess wrong we lose a bit on optimization, but that's it. */
3711 /* ??? sparc64 supports conditionally moving integers values based on fp
3712 comparisons, and vice versa. How do we handle them? */
3715 can_conditionally_move_p (mode
)
3716 enum machine_mode mode
;
3718 if (movcc_gen_code
[mode
] != CODE_FOR_nothing
)
3724 #endif /* HAVE_conditional_move */
3726 /* These three functions generate an insn body and return it
3727 rather than emitting the insn.
3729 They do not protect from queued increments,
3730 because they may be used 1) in protect_from_queue itself
3731 and 2) in other passes where there is no queue. */
3733 /* Generate and return an insn body to add Y to X. */
3736 gen_add2_insn (x
, y
)
3739 int icode
= (int) add_optab
->handlers
[(int) GET_MODE (x
)].insn_code
;
3741 if (! (*insn_operand_predicate
[icode
][0]) (x
, insn_operand_mode
[icode
][0])
3742 || ! (*insn_operand_predicate
[icode
][1]) (x
, insn_operand_mode
[icode
][1])
3743 || ! (*insn_operand_predicate
[icode
][2]) (y
, insn_operand_mode
[icode
][2]))
3746 return (GEN_FCN (icode
) (x
, x
, y
));
3750 have_add2_insn (mode
)
3751 enum machine_mode mode
;
3753 return add_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
;
3756 /* Generate and return an insn body to subtract Y from X. */
3759 gen_sub2_insn (x
, y
)
3762 int icode
= (int) sub_optab
->handlers
[(int) GET_MODE (x
)].insn_code
;
3764 if (! (*insn_operand_predicate
[icode
][0]) (x
, insn_operand_mode
[icode
][0])
3765 || ! (*insn_operand_predicate
[icode
][1]) (x
, insn_operand_mode
[icode
][1])
3766 || ! (*insn_operand_predicate
[icode
][2]) (y
, insn_operand_mode
[icode
][2]))
3769 return (GEN_FCN (icode
) (x
, x
, y
));
3773 have_sub2_insn (mode
)
3774 enum machine_mode mode
;
3776 return sub_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
;
3779 /* Generate the body of an instruction to copy Y into X.
3780 It may be a SEQUENCE, if one insn isn't enough. */
3783 gen_move_insn (x
, y
)
3786 register enum machine_mode mode
= GET_MODE (x
);
3787 enum insn_code insn_code
;
3790 if (mode
== VOIDmode
)
3791 mode
= GET_MODE (y
);
3793 insn_code
= mov_optab
->handlers
[(int) mode
].insn_code
;
3795 /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
3796 find a mode to do it in. If we have a movcc, use it. Otherwise,
3797 find the MODE_INT mode of the same width. */
3799 if (GET_MODE_CLASS (mode
) == MODE_CC
&& insn_code
== CODE_FOR_nothing
)
3801 enum machine_mode tmode
= VOIDmode
;
3805 && mov_optab
->handlers
[(int) CCmode
].insn_code
!= CODE_FOR_nothing
)
3808 for (tmode
= QImode
; tmode
!= VOIDmode
;
3809 tmode
= GET_MODE_WIDER_MODE (tmode
))
3810 if (GET_MODE_SIZE (tmode
) == GET_MODE_SIZE (mode
))
3813 if (tmode
== VOIDmode
)
3816 /* Get X and Y in TMODE. We can't use gen_lowpart here because it
3817 may call change_address which is not appropriate if we were
3818 called when a reload was in progress. We don't have to worry
3819 about changing the address since the size in bytes is supposed to
3820 be the same. Copy the MEM to change the mode and move any
3821 substitutions from the old MEM to the new one. */
3823 if (reload_in_progress
)
3825 x
= gen_lowpart_common (tmode
, x1
);
3826 if (x
== 0 && GET_CODE (x1
) == MEM
)
3828 x
= gen_rtx_MEM (tmode
, XEXP (x1
, 0));
3829 RTX_UNCHANGING_P (x
) = RTX_UNCHANGING_P (x1
);
3830 MEM_COPY_ATTRIBUTES (x
, x1
);
3831 copy_replacements (x1
, x
);
3834 y
= gen_lowpart_common (tmode
, y1
);
3835 if (y
== 0 && GET_CODE (y1
) == MEM
)
3837 y
= gen_rtx_MEM (tmode
, XEXP (y1
, 0));
3838 RTX_UNCHANGING_P (y
) = RTX_UNCHANGING_P (y1
);
3839 MEM_COPY_ATTRIBUTES (y
, y1
);
3840 copy_replacements (y1
, y
);
3845 x
= gen_lowpart (tmode
, x
);
3846 y
= gen_lowpart (tmode
, y
);
3849 insn_code
= mov_optab
->handlers
[(int) tmode
].insn_code
;
3850 return (GEN_FCN (insn_code
) (x
, y
));
3854 emit_move_insn_1 (x
, y
);
3855 seq
= gen_sequence ();
3860 /* Return the insn code used to extend FROM_MODE to TO_MODE.
3861 UNSIGNEDP specifies zero-extension instead of sign-extension. If
3862 no such operation exists, CODE_FOR_nothing will be returned. */
3865 can_extend_p (to_mode
, from_mode
, unsignedp
)
3866 enum machine_mode to_mode
, from_mode
;
3869 return extendtab
[(int) to_mode
][(int) from_mode
][unsignedp
];
3872 /* Generate the body of an insn to extend Y (with mode MFROM)
3873 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
3876 gen_extend_insn (x
, y
, mto
, mfrom
, unsignedp
)
3878 enum machine_mode mto
, mfrom
;
3881 return (GEN_FCN (extendtab
[(int) mto
][(int) mfrom
][unsignedp
]) (x
, y
));
3884 /* can_fix_p and can_float_p say whether the target machine
3885 can directly convert a given fixed point type to
3886 a given floating point type, or vice versa.
3887 The returned value is the CODE_FOR_... value to use,
3888 or CODE_FOR_nothing if these modes cannot be directly converted.
3890 *TRUNCP_PTR is set to 1 if it is necessary to output
3891 an explicit FTRUNC insn before the fix insn; otherwise 0. */
3893 static enum insn_code
3894 can_fix_p (fixmode
, fltmode
, unsignedp
, truncp_ptr
)
3895 enum machine_mode fltmode
, fixmode
;
3900 if (fixtrunctab
[(int) fltmode
][(int) fixmode
][unsignedp
] != CODE_FOR_nothing
)
3901 return fixtrunctab
[(int) fltmode
][(int) fixmode
][unsignedp
];
3903 if (ftrunc_optab
->handlers
[(int) fltmode
].insn_code
!= CODE_FOR_nothing
)
3906 return fixtab
[(int) fltmode
][(int) fixmode
][unsignedp
];
3908 return CODE_FOR_nothing
;
3911 static enum insn_code
3912 can_float_p (fltmode
, fixmode
, unsignedp
)
3913 enum machine_mode fixmode
, fltmode
;
3916 return floattab
[(int) fltmode
][(int) fixmode
][unsignedp
];
3919 /* Generate code to convert FROM to floating point
3920 and store in TO. FROM must be fixed point and not VOIDmode.
3921 UNSIGNEDP nonzero means regard FROM as unsigned.
3922 Normally this is done by correcting the final value
3923 if it is negative. */
3926 expand_float (to
, from
, unsignedp
)
3930 enum insn_code icode
;
3931 register rtx target
= to
;
3932 enum machine_mode fmode
, imode
;
3934 /* Crash now, because we won't be able to decide which mode to use. */
3935 if (GET_MODE (from
) == VOIDmode
)
3938 /* Look for an insn to do the conversion. Do it in the specified
3939 modes if possible; otherwise convert either input, output or both to
3940 wider mode. If the integer mode is wider than the mode of FROM,
3941 we can do the conversion signed even if the input is unsigned. */
3943 for (imode
= GET_MODE (from
); imode
!= VOIDmode
;
3944 imode
= GET_MODE_WIDER_MODE (imode
))
3945 for (fmode
= GET_MODE (to
); fmode
!= VOIDmode
;
3946 fmode
= GET_MODE_WIDER_MODE (fmode
))
3948 int doing_unsigned
= unsignedp
;
3950 icode
= can_float_p (fmode
, imode
, unsignedp
);
3951 if (icode
== CODE_FOR_nothing
&& imode
!= GET_MODE (from
) && unsignedp
)
3952 icode
= can_float_p (fmode
, imode
, 0), doing_unsigned
= 0;
3954 if (icode
!= CODE_FOR_nothing
)
3956 to
= protect_from_queue (to
, 1);
3957 from
= protect_from_queue (from
, 0);
3959 if (imode
!= GET_MODE (from
))
3960 from
= convert_to_mode (imode
, from
, unsignedp
);
3962 if (fmode
!= GET_MODE (to
))
3963 target
= gen_reg_rtx (fmode
);
3965 emit_unop_insn (icode
, target
, from
,
3966 doing_unsigned
? UNSIGNED_FLOAT
: FLOAT
);
3969 convert_move (to
, target
, 0);
3974 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3976 /* Unsigned integer, and no way to convert directly.
3977 Convert as signed, then conditionally adjust the result. */
3980 rtx label
= gen_label_rtx ();
3982 REAL_VALUE_TYPE offset
;
3986 to
= protect_from_queue (to
, 1);
3987 from
= protect_from_queue (from
, 0);
3990 from
= force_not_mem (from
);
3992 /* Look for a usable floating mode FMODE wider than the source and at
3993 least as wide as the target. Using FMODE will avoid rounding woes
3994 with unsigned values greater than the signed maximum value. */
3996 for (fmode
= GET_MODE (to
); fmode
!= VOIDmode
;
3997 fmode
= GET_MODE_WIDER_MODE (fmode
))
3998 if (GET_MODE_BITSIZE (GET_MODE (from
)) < GET_MODE_BITSIZE (fmode
)
3999 && can_float_p (fmode
, GET_MODE (from
), 0) != CODE_FOR_nothing
)
4002 if (fmode
== VOIDmode
)
4004 /* There is no such mode. Pretend the target is wide enough. */
4005 fmode
= GET_MODE (to
);
4007 /* Avoid double-rounding when TO is narrower than FROM. */
4008 if ((significand_size (fmode
) + 1)
4009 < GET_MODE_BITSIZE (GET_MODE (from
)))
4012 rtx neglabel
= gen_label_rtx ();
4014 /* Don't use TARGET if it isn't a register, is a hard register,
4015 or is the wrong mode. */
4016 if (GET_CODE (target
) != REG
4017 || REGNO (target
) < FIRST_PSEUDO_REGISTER
4018 || GET_MODE (target
) != fmode
)
4019 target
= gen_reg_rtx (fmode
);
4021 imode
= GET_MODE (from
);
4022 do_pending_stack_adjust ();
4024 /* Test whether the sign bit is set. */
4025 emit_cmp_insn (from
, const0_rtx
, GE
, NULL_RTX
, imode
, 0, 0);
4026 emit_jump_insn (gen_blt (neglabel
));
4028 /* The sign bit is not set. Convert as signed. */
4029 expand_float (target
, from
, 0);
4030 emit_jump_insn (gen_jump (label
));
4033 /* The sign bit is set.
4034 Convert to a usable (positive signed) value by shifting right
4035 one bit, while remembering if a nonzero bit was shifted
4036 out; i.e., compute (from & 1) | (from >> 1). */
4038 emit_label (neglabel
);
4039 temp
= expand_binop (imode
, and_optab
, from
, const1_rtx
,
4040 NULL_RTX
, 1, OPTAB_LIB_WIDEN
);
4041 temp1
= expand_shift (RSHIFT_EXPR
, imode
, from
, integer_one_node
,
4043 temp
= expand_binop (imode
, ior_optab
, temp
, temp1
, temp
, 1,
4045 expand_float (target
, temp
, 0);
4047 /* Multiply by 2 to undo the shift above. */
4048 temp
= expand_binop (fmode
, add_optab
, target
, target
,
4049 target
, 0, OPTAB_LIB_WIDEN
);
4051 emit_move_insn (target
, temp
);
4053 do_pending_stack_adjust ();
4059 /* If we are about to do some arithmetic to correct for an
4060 unsigned operand, do it in a pseudo-register. */
4062 if (GET_MODE (to
) != fmode
4063 || GET_CODE (to
) != REG
|| REGNO (to
) < FIRST_PSEUDO_REGISTER
)
4064 target
= gen_reg_rtx (fmode
);
4066 /* Convert as signed integer to floating. */
4067 expand_float (target
, from
, 0);
4069 /* If FROM is negative (and therefore TO is negative),
4070 correct its value by 2**bitwidth. */
4072 do_pending_stack_adjust ();
4073 emit_cmp_and_jump_insns (from
, const0_rtx
, GE
, NULL_RTX
, GET_MODE (from
),
4076 /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
4077 Rather than setting up a dconst_dot_5, let's hope SCO
4079 offset
= REAL_VALUE_LDEXP (dconst1
, GET_MODE_BITSIZE (GET_MODE (from
)));
4080 temp
= expand_binop (fmode
, add_optab
, target
,
4081 CONST_DOUBLE_FROM_REAL_VALUE (offset
, fmode
),
4082 target
, 0, OPTAB_LIB_WIDEN
);
4084 emit_move_insn (target
, temp
);
4086 do_pending_stack_adjust ();
4092 /* No hardware instruction available; call a library routine to convert from
4093 SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */
4099 to
= protect_from_queue (to
, 1);
4100 from
= protect_from_queue (from
, 0);
4102 if (GET_MODE_SIZE (GET_MODE (from
)) < GET_MODE_SIZE (SImode
))
4103 from
= convert_to_mode (SImode
, from
, unsignedp
);
4106 from
= force_not_mem (from
);
4108 if (GET_MODE (to
) == SFmode
)
4110 if (GET_MODE (from
) == SImode
)
4111 libfcn
= floatsisf_libfunc
;
4112 else if (GET_MODE (from
) == DImode
)
4113 libfcn
= floatdisf_libfunc
;
4114 else if (GET_MODE (from
) == TImode
)
4115 libfcn
= floattisf_libfunc
;
4119 else if (GET_MODE (to
) == DFmode
)
4121 if (GET_MODE (from
) == SImode
)
4122 libfcn
= floatsidf_libfunc
;
4123 else if (GET_MODE (from
) == DImode
)
4124 libfcn
= floatdidf_libfunc
;
4125 else if (GET_MODE (from
) == TImode
)
4126 libfcn
= floattidf_libfunc
;
4130 else if (GET_MODE (to
) == XFmode
)
4132 if (GET_MODE (from
) == SImode
)
4133 libfcn
= floatsixf_libfunc
;
4134 else if (GET_MODE (from
) == DImode
)
4135 libfcn
= floatdixf_libfunc
;
4136 else if (GET_MODE (from
) == TImode
)
4137 libfcn
= floattixf_libfunc
;
4141 else if (GET_MODE (to
) == TFmode
)
4143 if (GET_MODE (from
) == SImode
)
4144 libfcn
= floatsitf_libfunc
;
4145 else if (GET_MODE (from
) == DImode
)
4146 libfcn
= floatditf_libfunc
;
4147 else if (GET_MODE (from
) == TImode
)
4148 libfcn
= floattitf_libfunc
;
4157 value
= emit_library_call_value (libfcn
, NULL_RTX
, 1,
4159 1, from
, GET_MODE (from
));
4160 insns
= get_insns ();
4163 emit_libcall_block (insns
, target
, value
,
4164 gen_rtx_FLOAT (GET_MODE (to
), from
));
4169 /* Copy result to requested destination
4170 if we have been computing in a temp location. */
4174 if (GET_MODE (target
) == GET_MODE (to
))
4175 emit_move_insn (to
, target
);
4177 convert_move (to
, target
, 0);
4181 /* expand_fix: generate code to convert FROM to fixed point
4182 and store in TO. FROM must be floating point. */
4188 rtx temp
= gen_reg_rtx (GET_MODE (x
));
4189 return expand_unop (GET_MODE (x
), ftrunc_optab
, x
, temp
, 0);
4193 expand_fix (to
, from
, unsignedp
)
4194 register rtx to
, from
;
4197 enum insn_code icode
;
4198 register rtx target
= to
;
4199 enum machine_mode fmode
, imode
;
4203 /* We first try to find a pair of modes, one real and one integer, at
4204 least as wide as FROM and TO, respectively, in which we can open-code
4205 this conversion. If the integer mode is wider than the mode of TO,
4206 we can do the conversion either signed or unsigned. */
4208 for (imode
= GET_MODE (to
); imode
!= VOIDmode
;
4209 imode
= GET_MODE_WIDER_MODE (imode
))
4210 for (fmode
= GET_MODE (from
); fmode
!= VOIDmode
;
4211 fmode
= GET_MODE_WIDER_MODE (fmode
))
4213 int doing_unsigned
= unsignedp
;
4215 icode
= can_fix_p (imode
, fmode
, unsignedp
, &must_trunc
);
4216 if (icode
== CODE_FOR_nothing
&& imode
!= GET_MODE (to
) && unsignedp
)
4217 icode
= can_fix_p (imode
, fmode
, 0, &must_trunc
), doing_unsigned
= 0;
4219 if (icode
!= CODE_FOR_nothing
)
4221 to
= protect_from_queue (to
, 1);
4222 from
= protect_from_queue (from
, 0);
4224 if (fmode
!= GET_MODE (from
))
4225 from
= convert_to_mode (fmode
, from
, 0);
4228 from
= ftruncify (from
);
4230 if (imode
!= GET_MODE (to
))
4231 target
= gen_reg_rtx (imode
);
4233 emit_unop_insn (icode
, target
, from
,
4234 doing_unsigned
? UNSIGNED_FIX
: FIX
);
4236 convert_move (to
, target
, unsignedp
);
4241 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
4242 /* For an unsigned conversion, there is one more way to do it.
4243 If we have a signed conversion, we generate code that compares
4244 the real value to the largest representable positive number. If if
4245 is smaller, the conversion is done normally. Otherwise, subtract
4246 one plus the highest signed number, convert, and add it back.
4248 We only need to check all real modes, since we know we didn't find
4249 anything with a wider integer mode. */
4251 if (unsignedp
&& GET_MODE_BITSIZE (GET_MODE (to
)) <= HOST_BITS_PER_WIDE_INT
)
4252 for (fmode
= GET_MODE (from
); fmode
!= VOIDmode
;
4253 fmode
= GET_MODE_WIDER_MODE (fmode
))
4254 /* Make sure we won't lose significant bits doing this. */
4255 if (GET_MODE_BITSIZE (fmode
) > GET_MODE_BITSIZE (GET_MODE (to
))
4256 && CODE_FOR_nothing
!= can_fix_p (GET_MODE (to
), fmode
, 0,
4260 REAL_VALUE_TYPE offset
;
4261 rtx limit
, lab1
, lab2
, insn
;
4263 bitsize
= GET_MODE_BITSIZE (GET_MODE (to
));
4264 offset
= REAL_VALUE_LDEXP (dconst1
, bitsize
- 1);
4265 limit
= CONST_DOUBLE_FROM_REAL_VALUE (offset
, fmode
);
4266 lab1
= gen_label_rtx ();
4267 lab2
= gen_label_rtx ();
4270 to
= protect_from_queue (to
, 1);
4271 from
= protect_from_queue (from
, 0);
4274 from
= force_not_mem (from
);
4276 if (fmode
!= GET_MODE (from
))
4277 from
= convert_to_mode (fmode
, from
, 0);
4279 /* See if we need to do the subtraction. */
4280 do_pending_stack_adjust ();
4281 emit_cmp_and_jump_insns (from
, limit
, GE
, NULL_RTX
, GET_MODE (from
),
4284 /* If not, do the signed "fix" and branch around fixup code. */
4285 expand_fix (to
, from
, 0);
4286 emit_jump_insn (gen_jump (lab2
));
4289 /* Otherwise, subtract 2**(N-1), convert to signed number,
4290 then add 2**(N-1). Do the addition using XOR since this
4291 will often generate better code. */
4293 target
= expand_binop (GET_MODE (from
), sub_optab
, from
, limit
,
4294 NULL_RTX
, 0, OPTAB_LIB_WIDEN
);
4295 expand_fix (to
, target
, 0);
4296 target
= expand_binop (GET_MODE (to
), xor_optab
, to
,
4297 GEN_INT ((HOST_WIDE_INT
) 1 << (bitsize
- 1)),
4298 to
, 1, OPTAB_LIB_WIDEN
);
4301 emit_move_insn (to
, target
);
4305 if (mov_optab
->handlers
[(int) GET_MODE (to
)].insn_code
4306 != CODE_FOR_nothing
)
4308 /* Make a place for a REG_NOTE and add it. */
4309 insn
= emit_move_insn (to
, to
);
4310 set_unique_reg_note (insn
,
4312 gen_rtx_fmt_e (UNSIGNED_FIX
,
4320 /* We can't do it with an insn, so use a library call. But first ensure
4321 that the mode of TO is at least as wide as SImode, since those are the
4322 only library calls we know about. */
4324 if (GET_MODE_SIZE (GET_MODE (to
)) < GET_MODE_SIZE (SImode
))
4326 target
= gen_reg_rtx (SImode
);
4328 expand_fix (target
, from
, unsignedp
);
4330 else if (GET_MODE (from
) == SFmode
)
4332 if (GET_MODE (to
) == SImode
)
4333 libfcn
= unsignedp
? fixunssfsi_libfunc
: fixsfsi_libfunc
;
4334 else if (GET_MODE (to
) == DImode
)
4335 libfcn
= unsignedp
? fixunssfdi_libfunc
: fixsfdi_libfunc
;
4336 else if (GET_MODE (to
) == TImode
)
4337 libfcn
= unsignedp
? fixunssfti_libfunc
: fixsfti_libfunc
;
4341 else if (GET_MODE (from
) == DFmode
)
4343 if (GET_MODE (to
) == SImode
)
4344 libfcn
= unsignedp
? fixunsdfsi_libfunc
: fixdfsi_libfunc
;
4345 else if (GET_MODE (to
) == DImode
)
4346 libfcn
= unsignedp
? fixunsdfdi_libfunc
: fixdfdi_libfunc
;
4347 else if (GET_MODE (to
) == TImode
)
4348 libfcn
= unsignedp
? fixunsdfti_libfunc
: fixdfti_libfunc
;
4352 else if (GET_MODE (from
) == XFmode
)
4354 if (GET_MODE (to
) == SImode
)
4355 libfcn
= unsignedp
? fixunsxfsi_libfunc
: fixxfsi_libfunc
;
4356 else if (GET_MODE (to
) == DImode
)
4357 libfcn
= unsignedp
? fixunsxfdi_libfunc
: fixxfdi_libfunc
;
4358 else if (GET_MODE (to
) == TImode
)
4359 libfcn
= unsignedp
? fixunsxfti_libfunc
: fixxfti_libfunc
;
4363 else if (GET_MODE (from
) == TFmode
)
4365 if (GET_MODE (to
) == SImode
)
4366 libfcn
= unsignedp
? fixunstfsi_libfunc
: fixtfsi_libfunc
;
4367 else if (GET_MODE (to
) == DImode
)
4368 libfcn
= unsignedp
? fixunstfdi_libfunc
: fixtfdi_libfunc
;
4369 else if (GET_MODE (to
) == TImode
)
4370 libfcn
= unsignedp
? fixunstfti_libfunc
: fixtfti_libfunc
;
4382 to
= protect_from_queue (to
, 1);
4383 from
= protect_from_queue (from
, 0);
4386 from
= force_not_mem (from
);
4390 value
= emit_library_call_value (libfcn
, NULL_RTX
, 1, GET_MODE (to
),
4392 1, from
, GET_MODE (from
));
4393 insns
= get_insns ();
4396 emit_libcall_block (insns
, target
, value
,
4397 gen_rtx_fmt_e (unsignedp
? UNSIGNED_FIX
: FIX
,
4398 GET_MODE (to
), from
));
4403 if (GET_MODE (to
) == GET_MODE (target
))
4404 emit_move_insn (to
, target
);
4406 convert_move (to
, target
, 0);
4415 optab op
= (optab
) xmalloc (sizeof (struct optab
));
4417 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
4419 op
->handlers
[i
].insn_code
= CODE_FOR_nothing
;
4420 op
->handlers
[i
].libfunc
= 0;
4423 if (code
!= UNKNOWN
)
4424 code_to_optab
[(int) code
] = op
;
4429 /* Initialize the libfunc fields of an entire group of entries in some
4430 optab. Each entry is set equal to a string consisting of a leading
4431 pair of underscores followed by a generic operation name followed by
4432 a mode name (downshifted to lower case) followed by a single character
4433 representing the number of operands for the given operation (which is
4434 usually one of the characters '2', '3', or '4').
4436 OPTABLE is the table in which libfunc fields are to be initialized.
4437 FIRST_MODE is the first machine mode index in the given optab to
4439 LAST_MODE is the last machine mode index in the given optab to
4441 OPNAME is the generic (string) name of the operation.
4442 SUFFIX is the character which specifies the number of operands for
4443 the given generic operation.
4447 init_libfuncs (optable
, first_mode
, last_mode
, opname
, suffix
)
4448 register optab optable
;
4449 register int first_mode
;
4450 register int last_mode
;
4451 register const char *opname
;
4452 register int suffix
;
4455 register unsigned opname_len
= strlen (opname
);
4457 for (mode
= first_mode
; (int) mode
<= (int) last_mode
;
4458 mode
= (enum machine_mode
) ((int) mode
+ 1))
4460 register const char *mname
= GET_MODE_NAME(mode
);
4461 register unsigned mname_len
= strlen (mname
);
4462 register char *libfunc_name
4463 = (char *) xmalloc (2 + opname_len
+ mname_len
+ 1 + 1);
4465 register const char *q
;
4470 for (q
= opname
; *q
; )
4472 for (q
= mname
; *q
; q
++)
4473 *p
++ = tolower ((unsigned char)*q
);
4476 optable
->handlers
[(int) mode
].libfunc
4477 = gen_rtx_SYMBOL_REF (Pmode
, libfunc_name
);
4481 /* Initialize the libfunc fields of an entire group of entries in some
4482 optab which correspond to all integer mode operations. The parameters
4483 have the same meaning as similarly named ones for the `init_libfuncs'
4484 routine. (See above). */
4487 init_integral_libfuncs (optable
, opname
, suffix
)
4488 register optab optable
;
4489 register const char *opname
;
4490 register int suffix
;
4492 init_libfuncs (optable
, SImode
, TImode
, opname
, suffix
);
4495 /* Initialize the libfunc fields of an entire group of entries in some
4496 optab which correspond to all real mode operations. The parameters
4497 have the same meaning as similarly named ones for the `init_libfuncs'
4498 routine. (See above). */
4501 init_floating_libfuncs (optable
, opname
, suffix
)
4502 register optab optable
;
4503 register const char *opname
;
4504 register int suffix
;
4506 init_libfuncs (optable
, SFmode
, TFmode
, opname
, suffix
);
4510 /* Call this once to initialize the contents of the optabs
4511 appropriately for the current target machine. */
4517 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
4523 /* Start by initializing all tables to contain CODE_FOR_nothing. */
4525 for (p
= fixtab
[0][0];
4526 p
< fixtab
[0][0] + sizeof fixtab
/ sizeof (fixtab
[0][0][0]);
4528 *p
= CODE_FOR_nothing
;
4530 for (p
= fixtrunctab
[0][0];
4531 p
< fixtrunctab
[0][0] + sizeof fixtrunctab
/ sizeof (fixtrunctab
[0][0][0]);
4533 *p
= CODE_FOR_nothing
;
4535 for (p
= floattab
[0][0];
4536 p
< floattab
[0][0] + sizeof floattab
/ sizeof (floattab
[0][0][0]);
4538 *p
= CODE_FOR_nothing
;
4540 for (p
= extendtab
[0][0];
4541 p
< extendtab
[0][0] + sizeof extendtab
/ sizeof extendtab
[0][0][0];
4543 *p
= CODE_FOR_nothing
;
4545 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
4546 setcc_gen_code
[i
] = CODE_FOR_nothing
;
4548 #ifdef HAVE_conditional_move
4549 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
4550 movcc_gen_code
[i
] = CODE_FOR_nothing
;
4553 add_optab
= init_optab (PLUS
);
4554 sub_optab
= init_optab (MINUS
);
4555 smul_optab
= init_optab (MULT
);
4556 smul_highpart_optab
= init_optab (UNKNOWN
);
4557 umul_highpart_optab
= init_optab (UNKNOWN
);
4558 smul_widen_optab
= init_optab (UNKNOWN
);
4559 umul_widen_optab
= init_optab (UNKNOWN
);
4560 sdiv_optab
= init_optab (DIV
);
4561 sdivmod_optab
= init_optab (UNKNOWN
);
4562 udiv_optab
= init_optab (UDIV
);
4563 udivmod_optab
= init_optab (UNKNOWN
);
4564 smod_optab
= init_optab (MOD
);
4565 umod_optab
= init_optab (UMOD
);
4566 flodiv_optab
= init_optab (DIV
);
4567 ftrunc_optab
= init_optab (UNKNOWN
);
4568 and_optab
= init_optab (AND
);
4569 ior_optab
= init_optab (IOR
);
4570 xor_optab
= init_optab (XOR
);
4571 ashl_optab
= init_optab (ASHIFT
);
4572 ashr_optab
= init_optab (ASHIFTRT
);
4573 lshr_optab
= init_optab (LSHIFTRT
);
4574 rotl_optab
= init_optab (ROTATE
);
4575 rotr_optab
= init_optab (ROTATERT
);
4576 smin_optab
= init_optab (SMIN
);
4577 smax_optab
= init_optab (SMAX
);
4578 umin_optab
= init_optab (UMIN
);
4579 umax_optab
= init_optab (UMAX
);
4580 mov_optab
= init_optab (UNKNOWN
);
4581 movstrict_optab
= init_optab (UNKNOWN
);
4582 cmp_optab
= init_optab (UNKNOWN
);
4583 ucmp_optab
= init_optab (UNKNOWN
);
4584 tst_optab
= init_optab (UNKNOWN
);
4585 neg_optab
= init_optab (NEG
);
4586 abs_optab
= init_optab (ABS
);
4587 one_cmpl_optab
= init_optab (NOT
);
4588 ffs_optab
= init_optab (FFS
);
4589 sqrt_optab
= init_optab (SQRT
);
4590 sin_optab
= init_optab (UNKNOWN
);
4591 cos_optab
= init_optab (UNKNOWN
);
4592 strlen_optab
= init_optab (UNKNOWN
);
4594 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
4596 movstr_optab
[i
] = CODE_FOR_nothing
;
4597 clrstr_optab
[i
] = CODE_FOR_nothing
;
4599 #ifdef HAVE_SECONDARY_RELOADS
4600 reload_in_optab
[i
] = reload_out_optab
[i
] = CODE_FOR_nothing
;
4604 /* Fill in the optabs with the insns we support. */
4607 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
4608 /* This flag says the same insns that convert to a signed fixnum
4609 also convert validly to an unsigned one. */
4610 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
4611 for (j
= 0; j
< NUM_MACHINE_MODES
; j
++)
4612 fixtrunctab
[i
][j
][1] = fixtrunctab
[i
][j
][0];
4615 #ifdef EXTRA_CC_MODES
4619 /* Initialize the optabs with the names of the library functions. */
4620 init_integral_libfuncs (add_optab
, "add", '3');
4621 init_floating_libfuncs (add_optab
, "add", '3');
4622 init_integral_libfuncs (sub_optab
, "sub", '3');
4623 init_floating_libfuncs (sub_optab
, "sub", '3');
4624 init_integral_libfuncs (smul_optab
, "mul", '3');
4625 init_floating_libfuncs (smul_optab
, "mul", '3');
4626 init_integral_libfuncs (sdiv_optab
, "div", '3');
4627 init_integral_libfuncs (udiv_optab
, "udiv", '3');
4628 init_integral_libfuncs (sdivmod_optab
, "divmod", '4');
4629 init_integral_libfuncs (udivmod_optab
, "udivmod", '4');
4630 init_integral_libfuncs (smod_optab
, "mod", '3');
4631 init_integral_libfuncs (umod_optab
, "umod", '3');
4632 init_floating_libfuncs (flodiv_optab
, "div", '3');
4633 init_floating_libfuncs (ftrunc_optab
, "ftrunc", '2');
4634 init_integral_libfuncs (and_optab
, "and", '3');
4635 init_integral_libfuncs (ior_optab
, "ior", '3');
4636 init_integral_libfuncs (xor_optab
, "xor", '3');
4637 init_integral_libfuncs (ashl_optab
, "ashl", '3');
4638 init_integral_libfuncs (ashr_optab
, "ashr", '3');
4639 init_integral_libfuncs (lshr_optab
, "lshr", '3');
4640 init_integral_libfuncs (smin_optab
, "min", '3');
4641 init_floating_libfuncs (smin_optab
, "min", '3');
4642 init_integral_libfuncs (smax_optab
, "max", '3');
4643 init_floating_libfuncs (smax_optab
, "max", '3');
4644 init_integral_libfuncs (umin_optab
, "umin", '3');
4645 init_integral_libfuncs (umax_optab
, "umax", '3');
4646 init_integral_libfuncs (neg_optab
, "neg", '2');
4647 init_floating_libfuncs (neg_optab
, "neg", '2');
4648 init_integral_libfuncs (one_cmpl_optab
, "one_cmpl", '2');
4649 init_integral_libfuncs (ffs_optab
, "ffs", '2');
4651 /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
4652 init_integral_libfuncs (cmp_optab
, "cmp", '2');
4653 init_integral_libfuncs (ucmp_optab
, "ucmp", '2');
4654 init_floating_libfuncs (cmp_optab
, "cmp", '2');
4656 #ifdef MULSI3_LIBCALL
4657 smul_optab
->handlers
[(int) SImode
].libfunc
4658 = gen_rtx_SYMBOL_REF (Pmode
, MULSI3_LIBCALL
);
4660 #ifdef MULDI3_LIBCALL
4661 smul_optab
->handlers
[(int) DImode
].libfunc
4662 = gen_rtx_SYMBOL_REF (Pmode
, MULDI3_LIBCALL
);
4665 #ifdef DIVSI3_LIBCALL
4666 sdiv_optab
->handlers
[(int) SImode
].libfunc
4667 = gen_rtx_SYMBOL_REF (Pmode
, DIVSI3_LIBCALL
);
4669 #ifdef DIVDI3_LIBCALL
4670 sdiv_optab
->handlers
[(int) DImode
].libfunc
4671 = gen_rtx_SYMBOL_REF (Pmode
, DIVDI3_LIBCALL
);
4674 #ifdef UDIVSI3_LIBCALL
4675 udiv_optab
->handlers
[(int) SImode
].libfunc
4676 = gen_rtx_SYMBOL_REF (Pmode
, UDIVSI3_LIBCALL
);
4678 #ifdef UDIVDI3_LIBCALL
4679 udiv_optab
->handlers
[(int) DImode
].libfunc
4680 = gen_rtx_SYMBOL_REF (Pmode
, UDIVDI3_LIBCALL
);
4683 #ifdef MODSI3_LIBCALL
4684 smod_optab
->handlers
[(int) SImode
].libfunc
4685 = gen_rtx_SYMBOL_REF (Pmode
, MODSI3_LIBCALL
);
4687 #ifdef MODDI3_LIBCALL
4688 smod_optab
->handlers
[(int) DImode
].libfunc
4689 = gen_rtx_SYMBOL_REF (Pmode
, MODDI3_LIBCALL
);
4692 #ifdef UMODSI3_LIBCALL
4693 umod_optab
->handlers
[(int) SImode
].libfunc
4694 = gen_rtx_SYMBOL_REF (Pmode
, UMODSI3_LIBCALL
);
4696 #ifdef UMODDI3_LIBCALL
4697 umod_optab
->handlers
[(int) DImode
].libfunc
4698 = gen_rtx_SYMBOL_REF (Pmode
, UMODDI3_LIBCALL
);
4701 /* Use cabs for DC complex abs, since systems generally have cabs.
4702 Don't define any libcall for SCmode, so that cabs will be used. */
4703 abs_optab
->handlers
[(int) DCmode
].libfunc
4704 = gen_rtx_SYMBOL_REF (Pmode
, "cabs");
4706 /* The ffs function operates on `int'. */
4707 #ifndef INT_TYPE_SIZE
4708 #define INT_TYPE_SIZE BITS_PER_WORD
4710 ffs_optab
->handlers
[(int) mode_for_size (INT_TYPE_SIZE
, MODE_INT
, 0)] .libfunc
4711 = gen_rtx_SYMBOL_REF (Pmode
, "ffs");
4713 extendsfdf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__extendsfdf2");
4714 extendsfxf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__extendsfxf2");
4715 extendsftf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__extendsftf2");
4716 extenddfxf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__extenddfxf2");
4717 extenddftf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__extenddftf2");
4719 truncdfsf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__truncdfsf2");
4720 truncxfsf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__truncxfsf2");
4721 trunctfsf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__trunctfsf2");
4722 truncxfdf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__truncxfdf2");
4723 trunctfdf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__trunctfdf2");
4725 memcpy_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "memcpy");
4726 bcopy_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "bcopy");
4727 memcmp_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "memcmp");
4728 bcmp_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gcc_bcmp");
4729 memset_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "memset");
4730 bzero_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "bzero");
4732 throw_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__throw");
4733 rethrow_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__rethrow");
4734 sjthrow_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__sjthrow");
4735 sjpopnthrow_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__sjpopnthrow");
4736 terminate_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__terminate");
4737 eh_rtime_match_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__eh_rtime_match");
4738 #ifndef DONT_USE_BUILTIN_SETJMP
4739 setjmp_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__builtin_setjmp");
4740 longjmp_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__builtin_longjmp");
4742 setjmp_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "setjmp");
4743 longjmp_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "longjmp");
4746 eqhf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__eqhf2");
4747 nehf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__nehf2");
4748 gthf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gthf2");
4749 gehf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gehf2");
4750 lthf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__lthf2");
4751 lehf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__lehf2");
4753 eqsf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__eqsf2");
4754 nesf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__nesf2");
4755 gtsf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gtsf2");
4756 gesf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gesf2");
4757 ltsf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__ltsf2");
4758 lesf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__lesf2");
4760 eqdf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__eqdf2");
4761 nedf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__nedf2");
4762 gtdf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gtdf2");
4763 gedf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gedf2");
4764 ltdf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__ltdf2");
4765 ledf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__ledf2");
4767 eqxf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__eqxf2");
4768 nexf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__nexf2");
4769 gtxf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gtxf2");
4770 gexf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gexf2");
4771 ltxf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__ltxf2");
4772 lexf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__lexf2");
4774 eqtf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__eqtf2");
4775 netf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__netf2");
4776 gttf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__gttf2");
4777 getf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__getf2");
4778 lttf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__lttf2");
4779 letf2_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__letf2");
4781 floatsisf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatsisf");
4782 floatdisf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatdisf");
4783 floattisf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floattisf");
4785 floatsidf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatsidf");
4786 floatdidf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatdidf");
4787 floattidf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floattidf");
4789 floatsixf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatsixf");
4790 floatdixf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatdixf");
4791 floattixf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floattixf");
4793 floatsitf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatsitf");
4794 floatditf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floatditf");
4795 floattitf_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__floattitf");
4797 fixsfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixsfsi");
4798 fixsfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixsfdi");
4799 fixsfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixsfti");
4801 fixdfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixdfsi");
4802 fixdfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixdfdi");
4803 fixdfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixdfti");
4805 fixxfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixxfsi");
4806 fixxfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixxfdi");
4807 fixxfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixxfti");
4809 fixtfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixtfsi");
4810 fixtfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixtfdi");
4811 fixtfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixtfti");
4813 fixunssfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunssfsi");
4814 fixunssfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunssfdi");
4815 fixunssfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunssfti");
4817 fixunsdfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunsdfsi");
4818 fixunsdfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunsdfdi");
4819 fixunsdfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunsdfti");
4821 fixunsxfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunsxfsi");
4822 fixunsxfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunsxfdi");
4823 fixunsxfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunsxfti");
4825 fixunstfsi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunstfsi");
4826 fixunstfdi_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunstfdi");
4827 fixunstfti_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "__fixunstfti");
4829 /* For check-memory-usage. */
4830 chkr_check_addr_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "chkr_check_addr");
4831 chkr_set_right_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "chkr_set_right");
4832 chkr_copy_bitmap_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "chkr_copy_bitmap");
4833 chkr_check_exec_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "chkr_check_exec");
4834 chkr_check_str_libfunc
= gen_rtx_SYMBOL_REF (Pmode
, "chkr_check_str");
4836 /* For function entry/exit instrumentation. */
4837 profile_function_entry_libfunc
4838 = gen_rtx_SYMBOL_REF (Pmode
, "__cyg_profile_func_enter");
4839 profile_function_exit_libfunc
4840 = gen_rtx_SYMBOL_REF (Pmode
, "__cyg_profile_func_exit");
4842 #ifdef HAVE_conditional_trap
4846 #ifdef INIT_TARGET_OPTABS
4847 /* Allow the target to add more libcalls or rename some, etc. */
4854 /* SCO 3.2 apparently has a broken ldexp. */
4867 #endif /* BROKEN_LDEXP */
4869 #ifdef HAVE_conditional_trap
4870 /* The insn generating function can not take an rtx_code argument.
4871 TRAP_RTX is used as an rtx argument. Its code is replaced with
4872 the code to be used in the trap insn and all other fields are
4875 ??? Will need to change to support garbage collection. */
4876 static rtx trap_rtx
;
4881 if (HAVE_conditional_trap
)
4882 trap_rtx
= gen_rtx_fmt_ee (EQ
, VOIDmode
, NULL_RTX
, NULL_RTX
);
4886 /* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
4887 CODE. Return 0 on failure. */
4890 gen_cond_trap (code
, op1
, op2
, tcode
)
4891 enum rtx_code code ATTRIBUTE_UNUSED
;
4892 rtx op1
, op2 ATTRIBUTE_UNUSED
, tcode ATTRIBUTE_UNUSED
;
4894 enum machine_mode mode
= GET_MODE (op1
);
4896 if (mode
== VOIDmode
)
4899 #ifdef HAVE_conditional_trap
4900 if (HAVE_conditional_trap
4901 && cmp_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
4904 emit_insn (GEN_FCN (cmp_optab
->handlers
[(int) mode
].insn_code
) (op1
, op2
));
4905 PUT_CODE (trap_rtx
, code
);
4906 insn
= gen_conditional_trap (trap_rtx
, tcode
);