1 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2 Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3 2000 Free Software Foundation, Inc.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
27 /* Include insn-config.h before expr.h so that HAVE_conditional_move
28 is properly defined. */
29 #include "insn-config.h"
33 #include "insn-flags.h"
34 #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));
271 /* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
272 the result of operation CODE applied to OP0 (and OP1 if it is a binary
275 If the last insn does not set TARGET, don't do anything, but return 1.
277 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
278 don't add the REG_EQUAL note but return 0. Our caller can then try
279 again, ensuring that TARGET is not one of the operands. */
282 add_equal_note (seq, target, code, op0, op1)
292 if ((GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2'
293 && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<')
294 || GET_CODE (seq) != SEQUENCE
295 || (set = single_set (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))) == 0
296 || GET_CODE (target) == ZERO_EXTRACT
297 || (! rtx_equal_p (SET_DEST (set), target)
298 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
300 && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
301 || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)),
305 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
306 besides the last insn. */
307 if (reg_overlap_mentioned_p (target, op0)
308 || (op1 && reg_overlap_mentioned_p (target, op1)))
309 for (i = XVECLEN (seq, 0) - 2; i >= 0; i--)
310 if (reg_set_p (target, XVECEXP (seq, 0, i)))
313 if (GET_RTX_CLASS (code) == '1')
314 note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0));
316 note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
318 set_unique_reg_note (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1), REG_EQUAL, note);
323 /* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP
324 says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need
325 not actually do a sign-extend or zero-extend, but can leave the
326 higher-order bits of the result rtx undefined, for example, in the case
327 of logical operations, but not right shifts. */
330 widen_operand (op, mode, oldmode, unsignedp, no_extend)
332 enum machine_mode mode, oldmode;
338 /* If we must extend do so. If OP is either a constant or a SUBREG
339 for a promoted object, also extend since it will be more efficient to
342 || GET_MODE (op) == VOIDmode
343 || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op)))
344 return convert_modes (mode, oldmode, op, unsignedp);
346 /* If MODE is no wider than a single word, we return a paradoxical
348 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
349 return gen_rtx_SUBREG (mode, force_reg (GET_MODE (op), op), 0);
351 /* Otherwise, get an object of MODE, clobber it, and set the low-order
354 result = gen_reg_rtx (mode);
355 emit_insn (gen_rtx_CLOBBER (VOIDmode, result));
356 emit_move_insn (gen_lowpart (GET_MODE (op), result), op);
360 /* Generate code to perform a straightforward complex divide. */
363 expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
364 unsignedp, methods, class, binoptab)
365 rtx real0, real1, imag0, imag1, realr, imagr;
366 enum machine_mode submode;
368 enum optab_methods methods;
369 enum mode_class class;
377 /* Don't fetch these from memory more than once. */
378 real0 = force_reg (submode, real0);
379 real1 = force_reg (submode, real1);
382 imag0 = force_reg (submode, imag0);
384 imag1 = force_reg (submode, imag1);
386 /* Divisor: c*c + d*d. */
387 temp1 = expand_binop (submode, smul_optab, real1, real1,
388 NULL_RTX, unsignedp, methods);
390 temp2 = expand_binop (submode, smul_optab, imag1, imag1,
391 NULL_RTX, unsignedp, methods);
393 if (temp1 == 0 || temp2 == 0)
396 divisor = expand_binop (submode, add_optab, temp1, temp2,
397 NULL_RTX, unsignedp, methods);
403 /* Mathematically, ((a)(c-id))/divisor. */
404 /* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)). */
406 /* Calculate the dividend. */
407 real_t = expand_binop (submode, smul_optab, real0, real1,
408 NULL_RTX, unsignedp, methods);
410 imag_t = expand_binop (submode, smul_optab, real0, imag1,
411 NULL_RTX, unsignedp, methods);
413 if (real_t == 0 || imag_t == 0)
416 imag_t = expand_unop (submode, neg_optab, imag_t,
417 NULL_RTX, unsignedp);
421 /* Mathematically, ((a+ib)(c-id))/divider. */
422 /* Calculate the dividend. */
423 temp1 = expand_binop (submode, smul_optab, real0, real1,
424 NULL_RTX, unsignedp, methods);
426 temp2 = expand_binop (submode, smul_optab, imag0, imag1,
427 NULL_RTX, unsignedp, methods);
429 if (temp1 == 0 || temp2 == 0)
432 real_t = expand_binop (submode, add_optab, temp1, temp2,
433 NULL_RTX, unsignedp, methods);
435 temp1 = expand_binop (submode, smul_optab, imag0, real1,
436 NULL_RTX, unsignedp, methods);
438 temp2 = expand_binop (submode, smul_optab, real0, imag1,
439 NULL_RTX, unsignedp, methods);
441 if (temp1 == 0 || temp2 == 0)
444 imag_t = expand_binop (submode, sub_optab, temp1, temp2,
445 NULL_RTX, unsignedp, methods);
447 if (real_t == 0 || imag_t == 0)
451 if (class == MODE_COMPLEX_FLOAT)
452 res = expand_binop (submode, binoptab, real_t, divisor,
453 realr, unsignedp, methods);
455 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
456 real_t, divisor, realr, unsignedp);
462 emit_move_insn (realr, res);
464 if (class == MODE_COMPLEX_FLOAT)
465 res = expand_binop (submode, binoptab, imag_t, divisor,
466 imagr, unsignedp, methods);
468 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
469 imag_t, divisor, imagr, unsignedp);
475 emit_move_insn (imagr, res);
480 /* Generate code to perform a wide-input-range-acceptable complex divide. */
483 expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
484 unsignedp, methods, class, binoptab)
485 rtx real0, real1, imag0, imag1, realr, imagr;
486 enum machine_mode submode;
488 enum optab_methods methods;
489 enum mode_class class;
494 rtx temp1, temp2, lab1, lab2;
495 enum machine_mode mode;
499 /* Don't fetch these from memory more than once. */
500 real0 = force_reg (submode, real0);
501 real1 = force_reg (submode, real1);
504 imag0 = force_reg (submode, imag0);
506 imag1 = force_reg (submode, imag1);
508 /* XXX What's an "unsigned" complex number? */
516 temp1 = expand_abs (submode, real1, NULL_RTX, 1);
517 temp2 = expand_abs (submode, imag1, NULL_RTX, 1);
520 if (temp1 == 0 || temp2 == 0)
523 mode = GET_MODE (temp1);
524 align = GET_MODE_ALIGNMENT (mode);
525 lab1 = gen_label_rtx ();
526 emit_cmp_and_jump_insns (temp1, temp2, LT, NULL_RTX,
527 mode, unsignedp, align, lab1);
529 /* |c| >= |d|; use ratio d/c to scale dividend and divisor. */
531 if (class == MODE_COMPLEX_FLOAT)
532 ratio = expand_binop (submode, binoptab, imag1, real1,
533 NULL_RTX, unsignedp, methods);
535 ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
536 imag1, real1, NULL_RTX, unsignedp);
541 /* Calculate divisor. */
543 temp1 = expand_binop (submode, smul_optab, imag1, ratio,
544 NULL_RTX, unsignedp, methods);
549 divisor = expand_binop (submode, add_optab, temp1, real1,
550 NULL_RTX, unsignedp, methods);
555 /* Calculate dividend. */
561 /* Compute a / (c+id) as a / (c+d(d/c)) + i (-a(d/c)) / (c+d(d/c)). */
563 imag_t = expand_binop (submode, smul_optab, real0, ratio,
564 NULL_RTX, unsignedp, methods);
569 imag_t = expand_unop (submode, neg_optab, imag_t,
570 NULL_RTX, unsignedp);
572 if (real_t == 0 || imag_t == 0)
577 /* Compute (a+ib)/(c+id) as
578 (a+b(d/c))/(c+d(d/c) + i(b-a(d/c))/(c+d(d/c)). */
580 temp1 = expand_binop (submode, smul_optab, imag0, ratio,
581 NULL_RTX, unsignedp, methods);
586 real_t = expand_binop (submode, add_optab, temp1, real0,
587 NULL_RTX, unsignedp, methods);
589 temp1 = expand_binop (submode, smul_optab, real0, ratio,
590 NULL_RTX, unsignedp, methods);
595 imag_t = expand_binop (submode, sub_optab, imag0, temp1,
596 NULL_RTX, unsignedp, methods);
598 if (real_t == 0 || imag_t == 0)
602 if (class == MODE_COMPLEX_FLOAT)
603 res = expand_binop (submode, binoptab, real_t, divisor,
604 realr, unsignedp, methods);
606 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
607 real_t, divisor, realr, unsignedp);
613 emit_move_insn (realr, res);
615 if (class == MODE_COMPLEX_FLOAT)
616 res = expand_binop (submode, binoptab, imag_t, divisor,
617 imagr, unsignedp, methods);
619 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
620 imag_t, divisor, imagr, unsignedp);
626 emit_move_insn (imagr, res);
628 lab2 = gen_label_rtx ();
629 emit_jump_insn (gen_jump (lab2));
634 /* |d| > |c|; use ratio c/d to scale dividend and divisor. */
636 if (class == MODE_COMPLEX_FLOAT)
637 ratio = expand_binop (submode, binoptab, real1, imag1,
638 NULL_RTX, unsignedp, methods);
640 ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
641 real1, imag1, NULL_RTX, unsignedp);
646 /* Calculate divisor. */
648 temp1 = expand_binop (submode, smul_optab, real1, ratio,
649 NULL_RTX, unsignedp, methods);
654 divisor = expand_binop (submode, add_optab, temp1, imag1,
655 NULL_RTX, unsignedp, methods);
660 /* Calculate dividend. */
664 /* Compute a / (c+id) as a(c/d) / (c(c/d)+d) + i (-a) / (c(c/d)+d). */
666 real_t = expand_binop (submode, smul_optab, real0, ratio,
667 NULL_RTX, unsignedp, methods);
669 imag_t = expand_unop (submode, neg_optab, real0,
670 NULL_RTX, unsignedp);
672 if (real_t == 0 || imag_t == 0)
677 /* Compute (a+ib)/(c+id) as
678 (a(c/d)+b)/(c(c/d)+d) + i (b(c/d)-a)/(c(c/d)+d). */
680 temp1 = expand_binop (submode, smul_optab, real0, ratio,
681 NULL_RTX, unsignedp, methods);
686 real_t = expand_binop (submode, add_optab, temp1, imag0,
687 NULL_RTX, unsignedp, methods);
689 temp1 = expand_binop (submode, smul_optab, imag0, ratio,
690 NULL_RTX, unsignedp, methods);
695 imag_t = expand_binop (submode, sub_optab, temp1, real0,
696 NULL_RTX, unsignedp, methods);
698 if (real_t == 0 || imag_t == 0)
702 if (class == MODE_COMPLEX_FLOAT)
703 res = expand_binop (submode, binoptab, real_t, divisor,
704 realr, unsignedp, methods);
706 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
707 real_t, divisor, realr, unsignedp);
713 emit_move_insn (realr, res);
715 if (class == MODE_COMPLEX_FLOAT)
716 res = expand_binop (submode, binoptab, imag_t, divisor,
717 imagr, unsignedp, methods);
719 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
720 imag_t, divisor, imagr, unsignedp);
726 emit_move_insn (imagr, res);
733 /* Generate code to perform an operation specified by BINOPTAB
734 on operands OP0 and OP1, with result having machine-mode MODE.
736 UNSIGNEDP is for the case where we have to widen the operands
737 to perform the operation. It says to use zero-extension.
739 If TARGET is nonzero, the value
740 is generated there, if it is convenient to do so.
741 In all cases an rtx is returned for the locus of the value;
742 this may or may not be TARGET. */
745 expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
746 enum machine_mode mode;
751 enum optab_methods methods;
753 enum optab_methods next_methods
754 = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN
755 ? OPTAB_WIDEN : methods);
756 enum mode_class class;
757 enum machine_mode wider_mode;
759 int commutative_op = 0;
760 int shift_op = (binoptab->code == ASHIFT
761 || binoptab->code == ASHIFTRT
762 || binoptab->code == LSHIFTRT
763 || binoptab->code == ROTATE
764 || binoptab->code == ROTATERT);
765 rtx entry_last = get_last_insn ();
768 class = GET_MODE_CLASS (mode);
770 op0 = protect_from_queue (op0, 0);
771 op1 = protect_from_queue (op1, 0);
773 target = protect_from_queue (target, 1);
777 op0 = force_not_mem (op0);
778 op1 = force_not_mem (op1);
781 /* If subtracting an integer constant, convert this into an addition of
782 the negated constant. */
784 if (binoptab == sub_optab && GET_CODE (op1) == CONST_INT)
786 op1 = negate_rtx (mode, op1);
787 binoptab = add_optab;
790 /* If we are inside an appropriately-short loop and one operand is an
791 expensive constant, force it into a register. */
792 if (CONSTANT_P (op0) && preserve_subexpressions_p ()
793 && rtx_cost (op0, binoptab->code) > 2)
794 op0 = force_reg (mode, op0);
796 if (CONSTANT_P (op1) && preserve_subexpressions_p ()
797 && ! shift_op && rtx_cost (op1, binoptab->code) > 2)
798 op1 = force_reg (mode, op1);
800 /* Record where to delete back to if we backtrack. */
801 last = get_last_insn ();
803 /* If operation is commutative,
804 try to make the first operand a register.
805 Even better, try to make it the same as the target.
806 Also try to make the last operand a constant. */
807 if (GET_RTX_CLASS (binoptab->code) == 'c'
808 || binoptab == smul_widen_optab
809 || binoptab == umul_widen_optab
810 || binoptab == smul_highpart_optab
811 || binoptab == umul_highpart_optab)
815 if (((target == 0 || GET_CODE (target) == REG)
816 ? ((GET_CODE (op1) == REG
817 && GET_CODE (op0) != REG)
819 : rtx_equal_p (op1, target))
820 || GET_CODE (op0) == CONST_INT)
828 /* If we can do it with a three-operand insn, do so. */
830 if (methods != OPTAB_MUST_WIDEN
831 && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
833 int icode = (int) binoptab->handlers[(int) mode].insn_code;
834 enum machine_mode mode0 = insn_operand_mode[icode][1];
835 enum machine_mode mode1 = insn_operand_mode[icode][2];
837 rtx xop0 = op0, xop1 = op1;
842 temp = gen_reg_rtx (mode);
844 /* If it is a commutative operator and the modes would match
845 if we would swap the operands, we can save the conversions. */
848 if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
849 && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
853 tmp = op0; op0 = op1; op1 = tmp;
854 tmp = xop0; xop0 = xop1; xop1 = tmp;
858 /* In case the insn wants input operands in modes different from
859 the result, convert the operands. */
861 if (GET_MODE (op0) != VOIDmode
862 && GET_MODE (op0) != mode0
863 && mode0 != VOIDmode)
864 xop0 = convert_to_mode (mode0, xop0, unsignedp);
866 if (GET_MODE (xop1) != VOIDmode
867 && GET_MODE (xop1) != mode1
868 && mode1 != VOIDmode)
869 xop1 = convert_to_mode (mode1, xop1, unsignedp);
871 /* Now, if insn's predicates don't allow our operands, put them into
874 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0)
875 && mode0 != VOIDmode)
876 xop0 = copy_to_mode_reg (mode0, xop0);
878 if (! (*insn_operand_predicate[icode][2]) (xop1, mode1)
879 && mode1 != VOIDmode)
880 xop1 = copy_to_mode_reg (mode1, xop1);
882 if (! (*insn_operand_predicate[icode][0]) (temp, mode))
883 temp = gen_reg_rtx (mode);
885 pat = GEN_FCN (icode) (temp, xop0, xop1);
888 /* If PAT is a multi-insn sequence, try to add an appropriate
889 REG_EQUAL note to it. If we can't because TEMP conflicts with an
890 operand, call ourselves again, this time without a target. */
891 if (GET_CODE (pat) == SEQUENCE
892 && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
894 delete_insns_since (last);
895 return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
903 delete_insns_since (last);
906 /* If this is a multiply, see if we can do a widening operation that
907 takes operands of this mode and makes a wider mode. */
909 if (binoptab == smul_optab && GET_MODE_WIDER_MODE (mode) != VOIDmode
910 && (((unsignedp ? umul_widen_optab : smul_widen_optab)
911 ->handlers[(int) GET_MODE_WIDER_MODE (mode)].insn_code)
912 != CODE_FOR_nothing))
914 temp = expand_binop (GET_MODE_WIDER_MODE (mode),
915 unsignedp ? umul_widen_optab : smul_widen_optab,
916 op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT);
920 if (GET_MODE_CLASS (mode) == MODE_INT)
921 return gen_lowpart (mode, temp);
923 return convert_to_mode (mode, temp, unsignedp);
927 /* Look for a wider mode of the same class for which we think we
928 can open-code the operation. Check for a widening multiply at the
929 wider mode as well. */
931 if ((class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
932 && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
933 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
934 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
936 if (binoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing
937 || (binoptab == smul_optab
938 && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
939 && (((unsignedp ? umul_widen_optab : smul_widen_optab)
940 ->handlers[(int) GET_MODE_WIDER_MODE (wider_mode)].insn_code)
941 != CODE_FOR_nothing)))
943 rtx xop0 = op0, xop1 = op1;
946 /* For certain integer operations, we need not actually extend
947 the narrow operands, as long as we will truncate
948 the results to the same narrowness. */
950 if ((binoptab == ior_optab || binoptab == and_optab
951 || binoptab == xor_optab
952 || binoptab == add_optab || binoptab == sub_optab
953 || binoptab == smul_optab || binoptab == ashl_optab)
954 && class == MODE_INT)
957 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend);
959 /* The second operand of a shift must always be extended. */
960 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
961 no_extend && binoptab != ashl_optab);
963 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
964 unsignedp, OPTAB_DIRECT);
967 if (class != MODE_INT)
970 target = gen_reg_rtx (mode);
971 convert_move (target, temp, 0);
975 return gen_lowpart (mode, temp);
978 delete_insns_since (last);
982 /* These can be done a word at a time. */
983 if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
985 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
986 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
992 /* If TARGET is the same as one of the operands, the REG_EQUAL note
993 won't be accurate, so use a new target. */
994 if (target == 0 || target == op0 || target == op1)
995 target = gen_reg_rtx (mode);
999 /* Do the actual arithmetic. */
1000 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
1002 rtx target_piece = operand_subword (target, i, 1, mode);
1003 rtx x = expand_binop (word_mode, binoptab,
1004 operand_subword_force (op0, i, mode),
1005 operand_subword_force (op1, i, mode),
1006 target_piece, unsignedp, next_methods);
1011 if (target_piece != x)
1012 emit_move_insn (target_piece, x);
1015 insns = get_insns ();
1018 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
1020 if (binoptab->code != UNKNOWN)
1022 = gen_rtx_fmt_ee (binoptab->code, mode,
1023 copy_rtx (op0), copy_rtx (op1));
1027 emit_no_conflict_block (insns, target, op0, op1, equiv_value);
1032 /* Synthesize double word shifts from single word shifts. */
1033 if ((binoptab == lshr_optab || binoptab == ashl_optab
1034 || binoptab == ashr_optab)
1035 && class == MODE_INT
1036 && GET_CODE (op1) == CONST_INT
1037 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1038 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
1039 && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
1040 && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
1042 rtx insns, inter, equiv_value;
1043 rtx into_target, outof_target;
1044 rtx into_input, outof_input;
1045 int shift_count, left_shift, outof_word;
1047 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1048 won't be accurate, so use a new target. */
1049 if (target == 0 || target == op0 || target == op1)
1050 target = gen_reg_rtx (mode);
1054 shift_count = INTVAL (op1);
1056 /* OUTOF_* is the word we are shifting bits away from, and
1057 INTO_* is the word that we are shifting bits towards, thus
1058 they differ depending on the direction of the shift and
1059 WORDS_BIG_ENDIAN. */
1061 left_shift = binoptab == ashl_optab;
1062 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1064 outof_target = operand_subword (target, outof_word, 1, mode);
1065 into_target = operand_subword (target, 1 - outof_word, 1, mode);
1067 outof_input = operand_subword_force (op0, outof_word, mode);
1068 into_input = operand_subword_force (op0, 1 - outof_word, mode);
1070 if (shift_count >= BITS_PER_WORD)
1072 inter = expand_binop (word_mode, binoptab,
1074 GEN_INT (shift_count - BITS_PER_WORD),
1075 into_target, unsignedp, next_methods);
1077 if (inter != 0 && inter != into_target)
1078 emit_move_insn (into_target, inter);
1080 /* For a signed right shift, we must fill the word we are shifting
1081 out of with copies of the sign bit. Otherwise it is zeroed. */
1082 if (inter != 0 && binoptab != ashr_optab)
1083 inter = CONST0_RTX (word_mode);
1084 else if (inter != 0)
1085 inter = expand_binop (word_mode, binoptab,
1087 GEN_INT (BITS_PER_WORD - 1),
1088 outof_target, unsignedp, next_methods);
1090 if (inter != 0 && inter != outof_target)
1091 emit_move_insn (outof_target, inter);
1096 optab reverse_unsigned_shift, unsigned_shift;
1098 /* For a shift of less then BITS_PER_WORD, to compute the carry,
1099 we must do a logical shift in the opposite direction of the
1102 reverse_unsigned_shift = (left_shift ? lshr_optab : ashl_optab);
1104 /* For a shift of less than BITS_PER_WORD, to compute the word
1105 shifted towards, we need to unsigned shift the orig value of
1108 unsigned_shift = (left_shift ? ashl_optab : lshr_optab);
1110 carries = expand_binop (word_mode, reverse_unsigned_shift,
1112 GEN_INT (BITS_PER_WORD - shift_count),
1113 0, unsignedp, next_methods);
1118 inter = expand_binop (word_mode, unsigned_shift, into_input,
1119 op1, 0, unsignedp, next_methods);
1122 inter = expand_binop (word_mode, ior_optab, carries, inter,
1123 into_target, unsignedp, next_methods);
1125 if (inter != 0 && inter != into_target)
1126 emit_move_insn (into_target, inter);
1129 inter = expand_binop (word_mode, binoptab, outof_input,
1130 op1, outof_target, unsignedp, next_methods);
1132 if (inter != 0 && inter != outof_target)
1133 emit_move_insn (outof_target, inter);
1136 insns = get_insns ();
1141 if (binoptab->code != UNKNOWN)
1142 equiv_value = gen_rtx_fmt_ee (binoptab->code, mode, op0, op1);
1146 emit_no_conflict_block (insns, target, op0, op1, equiv_value);
1151 /* Synthesize double word rotates from single word shifts. */
1152 if ((binoptab == rotl_optab || binoptab == rotr_optab)
1153 && class == MODE_INT
1154 && GET_CODE (op1) == CONST_INT
1155 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1156 && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
1157 && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
1159 rtx insns, equiv_value;
1160 rtx into_target, outof_target;
1161 rtx into_input, outof_input;
1163 int shift_count, left_shift, outof_word;
1165 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1166 won't be accurate, so use a new target. */
1167 if (target == 0 || target == op0 || target == op1)
1168 target = gen_reg_rtx (mode);
1172 shift_count = INTVAL (op1);
1174 /* OUTOF_* is the word we are shifting bits away from, and
1175 INTO_* is the word that we are shifting bits towards, thus
1176 they differ depending on the direction of the shift and
1177 WORDS_BIG_ENDIAN. */
1179 left_shift = (binoptab == rotl_optab);
1180 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1182 outof_target = operand_subword (target, outof_word, 1, mode);
1183 into_target = operand_subword (target, 1 - outof_word, 1, mode);
1185 outof_input = operand_subword_force (op0, outof_word, mode);
1186 into_input = operand_subword_force (op0, 1 - outof_word, mode);
1188 if (shift_count == BITS_PER_WORD)
1190 /* This is just a word swap. */
1191 emit_move_insn (outof_target, into_input);
1192 emit_move_insn (into_target, outof_input);
1197 rtx into_temp1, into_temp2, outof_temp1, outof_temp2;
1198 rtx first_shift_count, second_shift_count;
1199 optab reverse_unsigned_shift, unsigned_shift;
1201 reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1202 ? lshr_optab : ashl_optab);
1204 unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1205 ? ashl_optab : lshr_optab);
1207 if (shift_count > BITS_PER_WORD)
1209 first_shift_count = GEN_INT (shift_count - BITS_PER_WORD);
1210 second_shift_count = GEN_INT (2*BITS_PER_WORD - shift_count);
1214 first_shift_count = GEN_INT (BITS_PER_WORD - shift_count);
1215 second_shift_count = GEN_INT (shift_count);
1218 into_temp1 = expand_binop (word_mode, unsigned_shift,
1219 outof_input, first_shift_count,
1220 NULL_RTX, unsignedp, next_methods);
1221 into_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1222 into_input, second_shift_count,
1223 into_target, unsignedp, next_methods);
1225 if (into_temp1 != 0 && into_temp2 != 0)
1226 inter = expand_binop (word_mode, ior_optab, into_temp1, into_temp2,
1227 into_target, unsignedp, next_methods);
1231 if (inter != 0 && inter != into_target)
1232 emit_move_insn (into_target, inter);
1234 outof_temp1 = expand_binop (word_mode, unsigned_shift,
1235 into_input, first_shift_count,
1236 NULL_RTX, unsignedp, next_methods);
1237 outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1238 outof_input, second_shift_count,
1239 outof_target, unsignedp, next_methods);
1241 if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0)
1242 inter = expand_binop (word_mode, ior_optab,
1243 outof_temp1, outof_temp2,
1244 outof_target, unsignedp, next_methods);
1246 if (inter != 0 && inter != outof_target)
1247 emit_move_insn (outof_target, inter);
1250 insns = get_insns ();
1255 if (binoptab->code != UNKNOWN)
1256 equiv_value = gen_rtx_fmt_ee (binoptab->code, mode, op0, op1);
1260 /* We can't make this a no conflict block if this is a word swap,
1261 because the word swap case fails if the input and output values
1262 are in the same register. */
1263 if (shift_count != BITS_PER_WORD)
1264 emit_no_conflict_block (insns, target, op0, op1, equiv_value);
1273 /* These can be done a word at a time by propagating carries. */
1274 if ((binoptab == add_optab || binoptab == sub_optab)
1275 && class == MODE_INT
1276 && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
1277 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
1280 rtx carry_tmp = gen_reg_rtx (word_mode);
1281 optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
1282 int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
1283 rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
1286 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
1287 value is one of those, use it. Otherwise, use 1 since it is the
1288 one easiest to get. */
1289 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
1290 int normalizep = STORE_FLAG_VALUE;
1295 /* Prepare the operands. */
1296 xop0 = force_reg (mode, op0);
1297 xop1 = force_reg (mode, op1);
1299 if (target == 0 || GET_CODE (target) != REG
1300 || target == xop0 || target == xop1)
1301 target = gen_reg_rtx (mode);
1303 /* Indicate for flow that the entire target reg is being set. */
1304 if (GET_CODE (target) == REG)
1305 emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
1307 /* Do the actual arithmetic. */
1308 for (i = 0; i < nwords; i++)
1310 int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
1311 rtx target_piece = operand_subword (target, index, 1, mode);
1312 rtx op0_piece = operand_subword_force (xop0, index, mode);
1313 rtx op1_piece = operand_subword_force (xop1, index, mode);
1316 /* Main add/subtract of the input operands. */
1317 x = expand_binop (word_mode, binoptab,
1318 op0_piece, op1_piece,
1319 target_piece, unsignedp, next_methods);
1325 /* Store carry from main add/subtract. */
1326 carry_out = gen_reg_rtx (word_mode);
1327 carry_out = emit_store_flag_force (carry_out,
1328 (binoptab == add_optab
1331 word_mode, 1, normalizep);
1336 /* Add/subtract previous carry to main result. */
1337 x = expand_binop (word_mode,
1338 normalizep == 1 ? binoptab : otheroptab,
1340 target_piece, 1, next_methods);
1343 else if (target_piece != x)
1344 emit_move_insn (target_piece, x);
1348 /* THIS CODE HAS NOT BEEN TESTED. */
1349 /* Get out carry from adding/subtracting carry in. */
1350 carry_tmp = emit_store_flag_force (carry_tmp,
1351 binoptab == add_optab
1354 word_mode, 1, normalizep);
1356 /* Logical-ior the two poss. carry together. */
1357 carry_out = expand_binop (word_mode, ior_optab,
1358 carry_out, carry_tmp,
1359 carry_out, 0, next_methods);
1365 carry_in = carry_out;
1368 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
1370 if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1372 rtx temp = emit_move_insn (target, target);
1374 set_unique_reg_note (temp,
1376 gen_rtx_fmt_ee (binoptab->code, mode,
1383 delete_insns_since (last);
1386 /* If we want to multiply two two-word values and have normal and widening
1387 multiplies of single-word values, we can do this with three smaller
1388 multiplications. Note that we do not make a REG_NO_CONFLICT block here
1389 because we are not operating on one word at a time.
1391 The multiplication proceeds as follows:
1392 _______________________
1393 [__op0_high_|__op0_low__]
1394 _______________________
1395 * [__op1_high_|__op1_low__]
1396 _______________________________________________
1397 _______________________
1398 (1) [__op0_low__*__op1_low__]
1399 _______________________
1400 (2a) [__op0_low__*__op1_high_]
1401 _______________________
1402 (2b) [__op0_high_*__op1_low__]
1403 _______________________
1404 (3) [__op0_high_*__op1_high_]
1407 This gives a 4-word result. Since we are only interested in the
1408 lower 2 words, partial result (3) and the upper words of (2a) and
1409 (2b) don't need to be calculated. Hence (2a) and (2b) can be
1410 calculated using non-widening multiplication.
1412 (1), however, needs to be calculated with an unsigned widening
1413 multiplication. If this operation is not directly supported we
1414 try using a signed widening multiplication and adjust the result.
1415 This adjustment works as follows:
1417 If both operands are positive then no adjustment is needed.
1419 If the operands have different signs, for example op0_low < 0 and
1420 op1_low >= 0, the instruction treats the most significant bit of
1421 op0_low as a sign bit instead of a bit with significance
1422 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
1423 with 2**BITS_PER_WORD - op0_low, and two's complements the
1424 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
1427 Similarly, if both operands are negative, we need to add
1428 (op0_low + op1_low) * 2**BITS_PER_WORD.
1430 We use a trick to adjust quickly. We logically shift op0_low right
1431 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
1432 op0_high (op1_high) before it is used to calculate 2b (2a). If no
1433 logical shift exists, we do an arithmetic right shift and subtract
1436 if (binoptab == smul_optab
1437 && class == MODE_INT
1438 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1439 && smul_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
1440 && add_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
1441 && ((umul_widen_optab->handlers[(int) mode].insn_code
1442 != CODE_FOR_nothing)
1443 || (smul_widen_optab->handlers[(int) mode].insn_code
1444 != CODE_FOR_nothing)))
1446 int low = (WORDS_BIG_ENDIAN ? 1 : 0);
1447 int high = (WORDS_BIG_ENDIAN ? 0 : 1);
1448 rtx op0_high = operand_subword_force (op0, high, mode);
1449 rtx op0_low = operand_subword_force (op0, low, mode);
1450 rtx op1_high = operand_subword_force (op1, high, mode);
1451 rtx op1_low = operand_subword_force (op1, low, mode);
1453 rtx op0_xhigh = NULL_RTX;
1454 rtx op1_xhigh = NULL_RTX;
1456 /* If the target is the same as one of the inputs, don't use it. This
1457 prevents problems with the REG_EQUAL note. */
1458 if (target == op0 || target == op1
1459 || (target != 0 && GET_CODE (target) != REG))
1462 /* Multiply the two lower words to get a double-word product.
1463 If unsigned widening multiplication is available, use that;
1464 otherwise use the signed form and compensate. */
1466 if (umul_widen_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1468 product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
1469 target, 1, OPTAB_DIRECT);
1471 /* If we didn't succeed, delete everything we did so far. */
1473 delete_insns_since (last);
1475 op0_xhigh = op0_high, op1_xhigh = op1_high;
1479 && smul_widen_optab->handlers[(int) mode].insn_code
1480 != CODE_FOR_nothing)
1482 rtx wordm1 = GEN_INT (BITS_PER_WORD - 1);
1483 product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
1484 target, 1, OPTAB_DIRECT);
1485 op0_xhigh = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
1486 NULL_RTX, 1, next_methods);
1488 op0_xhigh = expand_binop (word_mode, add_optab, op0_high,
1489 op0_xhigh, op0_xhigh, 0, next_methods);
1492 op0_xhigh = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
1493 NULL_RTX, 0, next_methods);
1495 op0_xhigh = expand_binop (word_mode, sub_optab, op0_high,
1496 op0_xhigh, op0_xhigh, 0,
1500 op1_xhigh = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
1501 NULL_RTX, 1, next_methods);
1503 op1_xhigh = expand_binop (word_mode, add_optab, op1_high,
1504 op1_xhigh, op1_xhigh, 0, next_methods);
1507 op1_xhigh = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
1508 NULL_RTX, 0, next_methods);
1510 op1_xhigh = expand_binop (word_mode, sub_optab, op1_high,
1511 op1_xhigh, op1_xhigh, 0,
1516 /* If we have been able to directly compute the product of the
1517 low-order words of the operands and perform any required adjustments
1518 of the operands, we proceed by trying two more multiplications
1519 and then computing the appropriate sum.
1521 We have checked above that the required addition is provided.
1522 Full-word addition will normally always succeed, especially if
1523 it is provided at all, so we don't worry about its failure. The
1524 multiplication may well fail, however, so we do handle that. */
1526 if (product && op0_xhigh && op1_xhigh)
1528 rtx product_high = operand_subword (product, high, 1, mode);
1529 rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh,
1530 NULL_RTX, 0, OPTAB_DIRECT);
1533 temp = expand_binop (word_mode, add_optab, temp, product_high,
1534 product_high, 0, next_methods);
1536 if (temp != 0 && temp != product_high)
1537 emit_move_insn (product_high, temp);
1540 temp = expand_binop (word_mode, binoptab, op1_low, op0_xhigh,
1541 NULL_RTX, 0, OPTAB_DIRECT);
1544 temp = expand_binop (word_mode, add_optab, temp,
1545 product_high, product_high,
1548 if (temp != 0 && temp != product_high)
1549 emit_move_insn (product_high, temp);
1553 if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1555 temp = emit_move_insn (product, product);
1556 set_unique_reg_note (temp,
1558 gen_rtx_fmt_ee (MULT, mode,
1566 /* If we get here, we couldn't do it for some reason even though we
1567 originally thought we could. Delete anything we've emitted in
1570 delete_insns_since (last);
1573 /* We need to open-code the complex type operations: '+, -, * and /' */
1575 /* At this point we allow operations between two similar complex
1576 numbers, and also if one of the operands is not a complex number
1577 but rather of MODE_FLOAT or MODE_INT. However, the caller
1578 must make sure that the MODE of the non-complex operand matches
1579 the SUBMODE of the complex operand. */
1581 if (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
1583 rtx real0 = 0, imag0 = 0;
1584 rtx real1 = 0, imag1 = 0;
1585 rtx realr, imagr, res;
1590 /* Find the correct mode for the real and imaginary parts */
1591 enum machine_mode submode
1592 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
1593 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
1596 if (submode == BLKmode)
1600 target = gen_reg_rtx (mode);
1604 realr = gen_realpart (submode, target);
1605 imagr = gen_imagpart (submode, target);
1607 if (GET_MODE (op0) == mode)
1609 real0 = gen_realpart (submode, op0);
1610 imag0 = gen_imagpart (submode, op0);
1615 if (GET_MODE (op1) == mode)
1617 real1 = gen_realpart (submode, op1);
1618 imag1 = gen_imagpart (submode, op1);
1623 if (real0 == 0 || real1 == 0 || ! (imag0 != 0|| imag1 != 0))
1626 switch (binoptab->code)
1629 /* (a+ib) + (c+id) = (a+c) + i(b+d) */
1631 /* (a+ib) - (c+id) = (a-c) + i(b-d) */
1632 res = expand_binop (submode, binoptab, real0, real1,
1633 realr, unsignedp, methods);
1637 else if (res != realr)
1638 emit_move_insn (realr, res);
1641 res = expand_binop (submode, binoptab, imag0, imag1,
1642 imagr, unsignedp, methods);
1645 else if (binoptab->code == MINUS)
1646 res = expand_unop (submode, neg_optab, imag1, imagr, unsignedp);
1652 else if (res != imagr)
1653 emit_move_insn (imagr, res);
1659 /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */
1665 /* Don't fetch these from memory more than once. */
1666 real0 = force_reg (submode, real0);
1667 real1 = force_reg (submode, real1);
1668 imag0 = force_reg (submode, imag0);
1669 imag1 = force_reg (submode, imag1);
1671 temp1 = expand_binop (submode, binoptab, real0, real1, NULL_RTX,
1672 unsignedp, methods);
1674 temp2 = expand_binop (submode, binoptab, imag0, imag1, NULL_RTX,
1675 unsignedp, methods);
1677 if (temp1 == 0 || temp2 == 0)
1680 res = expand_binop (submode, sub_optab, temp1, temp2,
1681 realr, unsignedp, methods);
1685 else if (res != realr)
1686 emit_move_insn (realr, res);
1688 temp1 = expand_binop (submode, binoptab, real0, imag1,
1689 NULL_RTX, unsignedp, methods);
1691 temp2 = expand_binop (submode, binoptab, real1, imag0,
1692 NULL_RTX, unsignedp, methods);
1694 if (temp1 == 0 || temp2 == 0)
1697 res = expand_binop (submode, add_optab, temp1, temp2,
1698 imagr, unsignedp, methods);
1702 else if (res != imagr)
1703 emit_move_insn (imagr, res);
1709 /* Don't fetch these from memory more than once. */
1710 real0 = force_reg (submode, real0);
1711 real1 = force_reg (submode, real1);
1713 res = expand_binop (submode, binoptab, real0, real1,
1714 realr, unsignedp, methods);
1717 else if (res != realr)
1718 emit_move_insn (realr, res);
1721 res = expand_binop (submode, binoptab,
1722 real1, imag0, imagr, unsignedp, methods);
1724 res = expand_binop (submode, binoptab,
1725 real0, imag1, imagr, unsignedp, methods);
1729 else if (res != imagr)
1730 emit_move_insn (imagr, res);
1737 /* (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) */
1741 /* (a+ib) / (c+i0) = (a/c) + i(b/c) */
1743 /* Don't fetch these from memory more than once. */
1744 real1 = force_reg (submode, real1);
1746 /* Simply divide the real and imaginary parts by `c' */
1747 if (class == MODE_COMPLEX_FLOAT)
1748 res = expand_binop (submode, binoptab, real0, real1,
1749 realr, unsignedp, methods);
1751 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
1752 real0, real1, realr, unsignedp);
1756 else if (res != realr)
1757 emit_move_insn (realr, res);
1759 if (class == MODE_COMPLEX_FLOAT)
1760 res = expand_binop (submode, binoptab, imag0, real1,
1761 imagr, unsignedp, methods);
1763 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
1764 imag0, real1, imagr, unsignedp);
1768 else if (res != imagr)
1769 emit_move_insn (imagr, res);
1775 switch (flag_complex_divide_method)
1778 ok = expand_cmplxdiv_straight (real0, real1, imag0, imag1,
1779 realr, imagr, submode,
1785 ok = expand_cmplxdiv_wide (real0, real1, imag0, imag1,
1786 realr, imagr, submode,
1806 if (binoptab->code != UNKNOWN)
1808 = gen_rtx_fmt_ee (binoptab->code, mode,
1809 copy_rtx (op0), copy_rtx (op1));
1813 emit_no_conflict_block (seq, target, op0, op1, equiv_value);
1819 /* It can't be open-coded in this mode.
1820 Use a library call if one is available and caller says that's ok. */
1822 if (binoptab->handlers[(int) mode].libfunc
1823 && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
1827 enum machine_mode op1_mode = mode;
1834 op1_mode = word_mode;
1835 /* Specify unsigned here,
1836 since negative shift counts are meaningless. */
1837 op1x = convert_to_mode (word_mode, op1, 1);
1840 if (GET_MODE (op0) != VOIDmode
1841 && GET_MODE (op0) != mode)
1842 op0 = convert_to_mode (mode, op0, unsignedp);
1844 /* Pass 1 for NO_QUEUE so we don't lose any increments
1845 if the libcall is cse'd or moved. */
1846 value = emit_library_call_value (binoptab->handlers[(int) mode].libfunc,
1847 NULL_RTX, 1, mode, 2,
1848 op0, mode, op1x, op1_mode);
1850 insns = get_insns ();
1853 target = gen_reg_rtx (mode);
1854 emit_libcall_block (insns, target, value,
1855 gen_rtx_fmt_ee (binoptab->code, mode, op0, op1));
1860 delete_insns_since (last);
1862 /* It can't be done in this mode. Can we do it in a wider mode? */
1864 if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
1865 || methods == OPTAB_MUST_WIDEN))
1867 /* Caller says, don't even try. */
1868 delete_insns_since (entry_last);
1872 /* Compute the value of METHODS to pass to recursive calls.
1873 Don't allow widening to be tried recursively. */
1875 methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
1877 /* Look for a wider mode of the same class for which it appears we can do
1880 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1882 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1883 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1885 if ((binoptab->handlers[(int) wider_mode].insn_code
1886 != CODE_FOR_nothing)
1887 || (methods == OPTAB_LIB
1888 && binoptab->handlers[(int) wider_mode].libfunc))
1890 rtx xop0 = op0, xop1 = op1;
1893 /* For certain integer operations, we need not actually extend
1894 the narrow operands, as long as we will truncate
1895 the results to the same narrowness. */
1897 if ((binoptab == ior_optab || binoptab == and_optab
1898 || binoptab == xor_optab
1899 || binoptab == add_optab || binoptab == sub_optab
1900 || binoptab == smul_optab || binoptab == ashl_optab)
1901 && class == MODE_INT)
1904 xop0 = widen_operand (xop0, wider_mode, mode,
1905 unsignedp, no_extend);
1907 /* The second operand of a shift must always be extended. */
1908 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
1909 no_extend && binoptab != ashl_optab);
1911 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
1912 unsignedp, methods);
1915 if (class != MODE_INT)
1918 target = gen_reg_rtx (mode);
1919 convert_move (target, temp, 0);
1923 return gen_lowpart (mode, temp);
1926 delete_insns_since (last);
1931 delete_insns_since (entry_last);
1935 /* Expand a binary operator which has both signed and unsigned forms.
1936 UOPTAB is the optab for unsigned operations, and SOPTAB is for
1939 If we widen unsigned operands, we may use a signed wider operation instead
1940 of an unsigned wider operation, since the result would be the same. */
1943 sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods)
1944 enum machine_mode mode;
1945 optab uoptab, soptab;
1946 rtx op0, op1, target;
1948 enum optab_methods methods;
1951 optab direct_optab = unsignedp ? uoptab : soptab;
1952 struct optab wide_soptab;
1954 /* Do it without widening, if possible. */
1955 temp = expand_binop (mode, direct_optab, op0, op1, target,
1956 unsignedp, OPTAB_DIRECT);
1957 if (temp || methods == OPTAB_DIRECT)
1960 /* Try widening to a signed int. Make a fake signed optab that
1961 hides any signed insn for direct use. */
1962 wide_soptab = *soptab;
1963 wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing;
1964 wide_soptab.handlers[(int) mode].libfunc = 0;
1966 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
1967 unsignedp, OPTAB_WIDEN);
1969 /* For unsigned operands, try widening to an unsigned int. */
1970 if (temp == 0 && unsignedp)
1971 temp = expand_binop (mode, uoptab, op0, op1, target,
1972 unsignedp, OPTAB_WIDEN);
1973 if (temp || methods == OPTAB_WIDEN)
1976 /* Use the right width lib call if that exists. */
1977 temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
1978 if (temp || methods == OPTAB_LIB)
1981 /* Must widen and use a lib call, use either signed or unsigned. */
1982 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
1983 unsignedp, methods);
1987 return expand_binop (mode, uoptab, op0, op1, target,
1988 unsignedp, methods);
1992 /* Generate code to perform an operation specified by BINOPTAB
1993 on operands OP0 and OP1, with two results to TARG1 and TARG2.
1994 We assume that the order of the operands for the instruction
1995 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
1996 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
1998 Either TARG0 or TARG1 may be zero, but what that means is that
1999 the result is not actually wanted. We will generate it into
2000 a dummy pseudo-reg and discard it. They may not both be zero.
2002 Returns 1 if this operation can be performed; 0 if not. */
2005 expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
2011 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
2012 enum mode_class class;
2013 enum machine_mode wider_mode;
2014 rtx entry_last = get_last_insn ();
2017 class = GET_MODE_CLASS (mode);
2019 op0 = protect_from_queue (op0, 0);
2020 op1 = protect_from_queue (op1, 0);
2024 op0 = force_not_mem (op0);
2025 op1 = force_not_mem (op1);
2028 /* If we are inside an appropriately-short loop and one operand is an
2029 expensive constant, force it into a register. */
2030 if (CONSTANT_P (op0) && preserve_subexpressions_p ()
2031 && rtx_cost (op0, binoptab->code) > 2)
2032 op0 = force_reg (mode, op0);
2034 if (CONSTANT_P (op1) && preserve_subexpressions_p ()
2035 && rtx_cost (op1, binoptab->code) > 2)
2036 op1 = force_reg (mode, op1);
2039 targ0 = protect_from_queue (targ0, 1);
2041 targ0 = gen_reg_rtx (mode);
2043 targ1 = protect_from_queue (targ1, 1);
2045 targ1 = gen_reg_rtx (mode);
2047 /* Record where to go back to if we fail. */
2048 last = get_last_insn ();
2050 if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2052 int icode = (int) binoptab->handlers[(int) mode].insn_code;
2053 enum machine_mode mode0 = insn_operand_mode[icode][1];
2054 enum machine_mode mode1 = insn_operand_mode[icode][2];
2056 rtx xop0 = op0, xop1 = op1;
2058 /* In case this insn wants input operands in modes different from the
2059 result, convert the operands. */
2060 if (GET_MODE (op0) != VOIDmode && GET_MODE (op0) != mode0)
2061 xop0 = convert_to_mode (mode0, xop0, unsignedp);
2063 if (GET_MODE (op1) != VOIDmode && GET_MODE (op1) != mode1)
2064 xop1 = convert_to_mode (mode1, xop1, unsignedp);
2066 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2067 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
2068 xop0 = copy_to_mode_reg (mode0, xop0);
2070 if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
2071 xop1 = copy_to_mode_reg (mode1, xop1);
2073 /* We could handle this, but we should always be called with a pseudo
2074 for our targets and all insns should take them as outputs. */
2075 if (! (*insn_operand_predicate[icode][0]) (targ0, mode)
2076 || ! (*insn_operand_predicate[icode][3]) (targ1, mode))
2079 pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
2086 delete_insns_since (last);
2089 /* It can't be done in this mode. Can we do it in a wider mode? */
2091 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
2093 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2094 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2096 if (binoptab->handlers[(int) wider_mode].insn_code
2097 != CODE_FOR_nothing)
2099 register rtx t0 = gen_reg_rtx (wider_mode);
2100 register rtx t1 = gen_reg_rtx (wider_mode);
2102 if (expand_twoval_binop (binoptab,
2103 convert_modes (wider_mode, mode, op0,
2105 convert_modes (wider_mode, mode, op1,
2109 convert_move (targ0, t0, unsignedp);
2110 convert_move (targ1, t1, unsignedp);
2114 delete_insns_since (last);
2119 delete_insns_since (entry_last);
2123 /* Generate code to perform an operation specified by UNOPTAB
2124 on operand OP0, with result having machine-mode MODE.
2126 UNSIGNEDP is for the case where we have to widen the operands
2127 to perform the operation. It says to use zero-extension.
2129 If TARGET is nonzero, the value
2130 is generated there, if it is convenient to do so.
2131 In all cases an rtx is returned for the locus of the value;
2132 this may or may not be TARGET. */
2135 expand_unop (mode, unoptab, op0, target, unsignedp)
2136 enum machine_mode mode;
2142 enum mode_class class;
2143 enum machine_mode wider_mode;
2145 rtx last = get_last_insn ();
2148 class = GET_MODE_CLASS (mode);
2150 op0 = protect_from_queue (op0, 0);
2154 op0 = force_not_mem (op0);
2158 target = protect_from_queue (target, 1);
2160 if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2162 int icode = (int) unoptab->handlers[(int) mode].insn_code;
2163 enum machine_mode mode0 = insn_operand_mode[icode][1];
2169 temp = gen_reg_rtx (mode);
2171 if (GET_MODE (xop0) != VOIDmode
2172 && GET_MODE (xop0) != mode0)
2173 xop0 = convert_to_mode (mode0, xop0, unsignedp);
2175 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
2177 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
2178 xop0 = copy_to_mode_reg (mode0, xop0);
2180 if (! (*insn_operand_predicate[icode][0]) (temp, mode))
2181 temp = gen_reg_rtx (mode);
2183 pat = GEN_FCN (icode) (temp, xop0);
2186 if (GET_CODE (pat) == SEQUENCE
2187 && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
2189 delete_insns_since (last);
2190 return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
2198 delete_insns_since (last);
2201 /* It can't be done in this mode. Can we open-code it in a wider mode? */
2203 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
2204 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2205 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2207 if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
2211 /* For certain operations, we need not actually extend
2212 the narrow operand, as long as we will truncate the
2213 results to the same narrowness. */
2215 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
2216 (unoptab == neg_optab
2217 || unoptab == one_cmpl_optab)
2218 && class == MODE_INT);
2220 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
2225 if (class != MODE_INT)
2228 target = gen_reg_rtx (mode);
2229 convert_move (target, temp, 0);
2233 return gen_lowpart (mode, temp);
2236 delete_insns_since (last);
2240 /* These can be done a word at a time. */
2241 if (unoptab == one_cmpl_optab
2242 && class == MODE_INT
2243 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
2244 && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
2249 if (target == 0 || target == op0)
2250 target = gen_reg_rtx (mode);
2254 /* Do the actual arithmetic. */
2255 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
2257 rtx target_piece = operand_subword (target, i, 1, mode);
2258 rtx x = expand_unop (word_mode, unoptab,
2259 operand_subword_force (op0, i, mode),
2260 target_piece, unsignedp);
2261 if (target_piece != x)
2262 emit_move_insn (target_piece, x);
2265 insns = get_insns ();
2268 emit_no_conflict_block (insns, target, op0, NULL_RTX,
2269 gen_rtx_fmt_e (unoptab->code, mode,
2274 /* Open-code the complex negation operation. */
2275 else if (unoptab == neg_optab
2276 && (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT))
2282 /* Find the correct mode for the real and imaginary parts */
2283 enum machine_mode submode
2284 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
2285 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
2288 if (submode == BLKmode)
2292 target = gen_reg_rtx (mode);
2296 target_piece = gen_imagpart (submode, target);
2297 x = expand_unop (submode, unoptab,
2298 gen_imagpart (submode, op0),
2299 target_piece, unsignedp);
2300 if (target_piece != x)
2301 emit_move_insn (target_piece, x);
2303 target_piece = gen_realpart (submode, target);
2304 x = expand_unop (submode, unoptab,
2305 gen_realpart (submode, op0),
2306 target_piece, unsignedp);
2307 if (target_piece != x)
2308 emit_move_insn (target_piece, x);
2313 emit_no_conflict_block (seq, target, op0, 0,
2314 gen_rtx_fmt_e (unoptab->code, mode,
2319 /* Now try a library call in this mode. */
2320 if (unoptab->handlers[(int) mode].libfunc)
2327 /* Pass 1 for NO_QUEUE so we don't lose any increments
2328 if the libcall is cse'd or moved. */
2329 value = emit_library_call_value (unoptab->handlers[(int) mode].libfunc,
2330 NULL_RTX, 1, mode, 1, op0, mode);
2331 insns = get_insns ();
2334 target = gen_reg_rtx (mode);
2335 emit_libcall_block (insns, target, value,
2336 gen_rtx_fmt_e (unoptab->code, mode, op0));
2341 /* It can't be done in this mode. Can we do it in a wider mode? */
2343 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
2345 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2346 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2348 if ((unoptab->handlers[(int) wider_mode].insn_code
2349 != CODE_FOR_nothing)
2350 || unoptab->handlers[(int) wider_mode].libfunc)
2354 /* For certain operations, we need not actually extend
2355 the narrow operand, as long as we will truncate the
2356 results to the same narrowness. */
2358 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
2359 (unoptab == neg_optab
2360 || unoptab == one_cmpl_optab)
2361 && class == MODE_INT);
2363 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
2368 if (class != MODE_INT)
2371 target = gen_reg_rtx (mode);
2372 convert_move (target, temp, 0);
2376 return gen_lowpart (mode, temp);
2379 delete_insns_since (last);
2384 /* If there is no negate operation, try doing a subtract from zero.
2385 The US Software GOFAST library needs this. */
2386 if (unoptab == neg_optab)
2389 temp = expand_binop (mode, sub_optab, CONST0_RTX (mode), op0,
2390 target, unsignedp, OPTAB_LIB_WIDEN);
2398 /* Emit code to compute the absolute value of OP0, with result to
2399 TARGET if convenient. (TARGET may be 0.) The return value says
2400 where the result actually is to be found.
2402 MODE is the mode of the operand; the mode of the result is
2403 different but can be deduced from MODE.
2408 expand_abs (mode, op0, target, safe)
2409 enum machine_mode mode;
2416 /* First try to do it with a special abs instruction. */
2417 temp = expand_unop (mode, abs_optab, op0, target, 0);
2421 /* If this machine has expensive jumps, we can do integer absolute
2422 value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
2423 where W is the width of MODE. */
2425 if (GET_MODE_CLASS (mode) == MODE_INT && BRANCH_COST >= 2)
2427 rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
2428 size_int (GET_MODE_BITSIZE (mode) - 1),
2431 temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
2434 temp = expand_binop (mode, sub_optab, temp, extended, target, 0,
2441 /* If that does not win, use conditional jump and negate. */
2443 /* It is safe to use the target if it is the same
2444 as the source if this is also a pseudo register */
2445 if (op0 == target && GET_CODE (op0) == REG
2446 && REGNO (op0) >= FIRST_PSEUDO_REGISTER)
2449 op1 = gen_label_rtx ();
2450 if (target == 0 || ! safe
2451 || GET_MODE (target) != mode
2452 || (GET_CODE (target) == MEM && MEM_VOLATILE_P (target))
2453 || (GET_CODE (target) == REG
2454 && REGNO (target) < FIRST_PSEUDO_REGISTER))
2455 target = gen_reg_rtx (mode);
2457 emit_move_insn (target, op0);
2460 /* If this mode is an integer too wide to compare properly,
2461 compare word by word. Rely on CSE to optimize constant cases. */
2462 if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode))
2463 do_jump_by_parts_greater_rtx (mode, 0, target, const0_rtx,
2467 temp = compare_from_rtx (target, CONST0_RTX (mode), GE, 0, mode,
2469 if (temp == const1_rtx)
2471 else if (temp != const0_rtx)
2473 if (bcc_gen_fctn[(int) GET_CODE (temp)] != 0)
2474 emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (temp)]) (op1));
2480 op0 = expand_unop (mode, neg_optab, target, target, 0);
2482 emit_move_insn (target, op0);
2488 /* Emit code to compute the absolute value of OP0, with result to
2489 TARGET if convenient. (TARGET may be 0.) The return value says
2490 where the result actually is to be found.
2492 MODE is the mode of the operand; the mode of the result is
2493 different but can be deduced from MODE.
2495 UNSIGNEDP is relevant for complex integer modes. */
2498 expand_complex_abs (mode, op0, target, unsignedp)
2499 enum machine_mode mode;
2504 enum mode_class class = GET_MODE_CLASS (mode);
2505 enum machine_mode wider_mode;
2507 rtx entry_last = get_last_insn ();
2511 /* Find the correct mode for the real and imaginary parts. */
2512 enum machine_mode submode
2513 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
2514 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
2517 if (submode == BLKmode)
2520 op0 = protect_from_queue (op0, 0);
2524 op0 = force_not_mem (op0);
2527 last = get_last_insn ();
2530 target = protect_from_queue (target, 1);
2532 if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2534 int icode = (int) abs_optab->handlers[(int) mode].insn_code;
2535 enum machine_mode mode0 = insn_operand_mode[icode][1];
2541 temp = gen_reg_rtx (submode);
2543 if (GET_MODE (xop0) != VOIDmode
2544 && GET_MODE (xop0) != mode0)
2545 xop0 = convert_to_mode (mode0, xop0, unsignedp);
2547 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
2549 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
2550 xop0 = copy_to_mode_reg (mode0, xop0);
2552 if (! (*insn_operand_predicate[icode][0]) (temp, submode))
2553 temp = gen_reg_rtx (submode);
2555 pat = GEN_FCN (icode) (temp, xop0);
2558 if (GET_CODE (pat) == SEQUENCE
2559 && ! add_equal_note (pat, temp, abs_optab->code, xop0, NULL_RTX))
2561 delete_insns_since (last);
2562 return expand_unop (mode, abs_optab, op0, NULL_RTX, unsignedp);
2570 delete_insns_since (last);
2573 /* It can't be done in this mode. Can we open-code it in a wider mode? */
2575 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2576 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2578 if (abs_optab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
2582 xop0 = convert_modes (wider_mode, mode, xop0, unsignedp);
2583 temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
2587 if (class != MODE_COMPLEX_INT)
2590 target = gen_reg_rtx (submode);
2591 convert_move (target, temp, 0);
2595 return gen_lowpart (submode, temp);
2598 delete_insns_since (last);
2602 /* Open-code the complex absolute-value operation
2603 if we can open-code sqrt. Otherwise it's not worth while. */
2604 if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing)
2606 rtx real, imag, total;
2608 real = gen_realpart (submode, op0);
2609 imag = gen_imagpart (submode, op0);
2611 /* Square both parts. */
2612 real = expand_mult (submode, real, real, NULL_RTX, 0);
2613 imag = expand_mult (submode, imag, imag, NULL_RTX, 0);
2615 /* Sum the parts. */
2616 total = expand_binop (submode, add_optab, real, imag, NULL_RTX,
2617 0, OPTAB_LIB_WIDEN);
2619 /* Get sqrt in TARGET. Set TARGET to where the result is. */
2620 target = expand_unop (submode, sqrt_optab, total, target, 0);
2622 delete_insns_since (last);
2627 /* Now try a library call in this mode. */
2628 if (abs_optab->handlers[(int) mode].libfunc)
2635 /* Pass 1 for NO_QUEUE so we don't lose any increments
2636 if the libcall is cse'd or moved. */
2637 value = emit_library_call_value (abs_optab->handlers[(int) mode].libfunc,
2638 NULL_RTX, 1, submode, 1, op0, mode);
2639 insns = get_insns ();
2642 target = gen_reg_rtx (submode);
2643 emit_libcall_block (insns, target, value,
2644 gen_rtx_fmt_e (abs_optab->code, mode, op0));
2649 /* It can't be done in this mode. Can we do it in a wider mode? */
2651 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2652 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2654 if ((abs_optab->handlers[(int) wider_mode].insn_code
2655 != CODE_FOR_nothing)
2656 || abs_optab->handlers[(int) wider_mode].libfunc)
2660 xop0 = convert_modes (wider_mode, mode, xop0, unsignedp);
2662 temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
2666 if (class != MODE_COMPLEX_INT)
2669 target = gen_reg_rtx (submode);
2670 convert_move (target, temp, 0);
2674 return gen_lowpart (submode, temp);
2677 delete_insns_since (last);
2681 delete_insns_since (entry_last);
2685 /* Generate an instruction whose insn-code is INSN_CODE,
2686 with two operands: an output TARGET and an input OP0.
2687 TARGET *must* be nonzero, and the output is always stored there.
2688 CODE is an rtx code such that (CODE OP0) is an rtx that describes
2689 the value that is stored into TARGET. */
2692 emit_unop_insn (icode, target, op0, code)
2699 enum machine_mode mode0 = insn_operand_mode[icode][1];
2702 temp = target = protect_from_queue (target, 1);
2704 op0 = protect_from_queue (op0, 0);
2706 /* Sign and zero extension from memory is often done specially on
2707 RISC machines, so forcing into a register here can pessimize
2709 if (flag_force_mem && code != SIGN_EXTEND && code != ZERO_EXTEND)
2710 op0 = force_not_mem (op0);
2712 /* Now, if insn does not accept our operands, put them into pseudos. */
2714 if (! (*insn_operand_predicate[icode][1]) (op0, mode0))
2715 op0 = copy_to_mode_reg (mode0, op0);
2717 if (! (*insn_operand_predicate[icode][0]) (temp, GET_MODE (temp))
2718 || (flag_force_mem && GET_CODE (temp) == MEM))
2719 temp = gen_reg_rtx (GET_MODE (temp));
2721 pat = GEN_FCN (icode) (temp, op0);
2723 if (GET_CODE (pat) == SEQUENCE && code != UNKNOWN)
2724 add_equal_note (pat, temp, code, op0, NULL_RTX);
2729 emit_move_insn (target, temp);
2732 /* Emit code to perform a series of operations on a multi-word quantity, one
2735 Such a block is preceded by a CLOBBER of the output, consists of multiple
2736 insns, each setting one word of the output, and followed by a SET copying
2737 the output to itself.
2739 Each of the insns setting words of the output receives a REG_NO_CONFLICT
2740 note indicating that it doesn't conflict with the (also multi-word)
2741 inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
2744 INSNS is a block of code generated to perform the operation, not including
2745 the CLOBBER and final copy. All insns that compute intermediate values
2746 are first emitted, followed by the block as described above.
2748 TARGET, OP0, and OP1 are the output and inputs of the operations,
2749 respectively. OP1 may be zero for a unary operation.
2751 EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
2754 If TARGET is not a register, INSNS is simply emitted with no special
2755 processing. Likewise if anything in INSNS is not an INSN or if
2756 there is a libcall block inside INSNS.
2758 The final insn emitted is returned. */
2761 emit_no_conflict_block (insns, target, op0, op1, equiv)
2767 rtx prev, next, first, last, insn;
2769 if (GET_CODE (target) != REG || reload_in_progress)
2770 return emit_insns (insns);
2772 for (insn = insns; insn; insn = NEXT_INSN (insn))
2773 if (GET_CODE (insn) != INSN
2774 || find_reg_note (insn, REG_LIBCALL, NULL_RTX))
2775 return emit_insns (insns);
2777 /* First emit all insns that do not store into words of the output and remove
2778 these from the list. */
2779 for (insn = insns; insn; insn = next)
2784 next = NEXT_INSN (insn);
2786 if (GET_CODE (PATTERN (insn)) == SET)
2787 set = PATTERN (insn);
2788 else if (GET_CODE (PATTERN (insn)) == PARALLEL)
2790 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
2791 if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
2793 set = XVECEXP (PATTERN (insn), 0, i);
2801 if (! reg_overlap_mentioned_p (target, SET_DEST (set)))
2803 if (PREV_INSN (insn))
2804 NEXT_INSN (PREV_INSN (insn)) = next;
2809 PREV_INSN (next) = PREV_INSN (insn);
2815 prev = get_last_insn ();
2817 /* Now write the CLOBBER of the output, followed by the setting of each
2818 of the words, followed by the final copy. */
2819 if (target != op0 && target != op1)
2820 emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
2822 for (insn = insns; insn; insn = next)
2824 next = NEXT_INSN (insn);
2827 if (op1 && GET_CODE (op1) == REG)
2828 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op1,
2831 if (op0 && GET_CODE (op0) == REG)
2832 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op0,
2836 if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
2837 != CODE_FOR_nothing)
2839 last = emit_move_insn (target, target);
2841 set_unique_reg_note (last, REG_EQUAL, equiv);
2844 last = get_last_insn ();
2847 first = get_insns ();
2849 first = NEXT_INSN (prev);
2851 /* Encapsulate the block so it gets manipulated as a unit. */
2852 REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
2854 REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2859 /* Emit code to make a call to a constant function or a library call.
2861 INSNS is a list containing all insns emitted in the call.
2862 These insns leave the result in RESULT. Our block is to copy RESULT
2863 to TARGET, which is logically equivalent to EQUIV.
2865 We first emit any insns that set a pseudo on the assumption that these are
2866 loading constants into registers; doing so allows them to be safely cse'ed
2867 between blocks. Then we emit all the other insns in the block, followed by
2868 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
2869 note with an operand of EQUIV.
2871 Moving assignments to pseudos outside of the block is done to improve
2872 the generated code, but is not required to generate correct code,
2873 hence being unable to move an assignment is not grounds for not making
2874 a libcall block. There are two reasons why it is safe to leave these
2875 insns inside the block: First, we know that these pseudos cannot be
2876 used in generated RTL outside the block since they are created for
2877 temporary purposes within the block. Second, CSE will not record the
2878 values of anything set inside a libcall block, so we know they must
2879 be dead at the end of the block.
2881 Except for the first group of insns (the ones setting pseudos), the
2882 block is delimited by REG_RETVAL and REG_LIBCALL notes. */
2885 emit_libcall_block (insns, target, result, equiv)
2891 rtx final_dest = target;
2892 rtx prev, next, first, last, insn;
2894 /* If this is a reg with REG_USERVAR_P set, then it could possibly turn
2895 into a MEM later. Protect the libcall block from this change. */
2896 if (! REG_P (target) || REG_USERVAR_P (target))
2897 target = gen_reg_rtx (GET_MODE (target));
2899 /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
2900 reg note to indicate that this call cannot throw. (Unless there is
2901 already a REG_EH_REGION note.) */
2903 for (insn = insns; insn; insn = NEXT_INSN (insn))
2905 if (GET_CODE (insn) == CALL_INSN)
2907 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
2908 if (note == NULL_RTX)
2909 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (-1),
2914 /* First emit all insns that set pseudos. Remove them from the list as
2915 we go. Avoid insns that set pseudos which were referenced in previous
2916 insns. These can be generated by move_by_pieces, for example,
2917 to update an address. Similarly, avoid insns that reference things
2918 set in previous insns. */
2920 for (insn = insns; insn; insn = next)
2922 rtx set = single_set (insn);
2924 next = NEXT_INSN (insn);
2926 if (set != 0 && GET_CODE (SET_DEST (set)) == REG
2927 && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
2929 || (! reg_mentioned_p (SET_DEST (set), PATTERN (insns))
2930 && ! reg_used_between_p (SET_DEST (set), insns, insn)
2931 && ! modified_in_p (SET_SRC (set), insns)
2932 && ! modified_between_p (SET_SRC (set), insns, insn))))
2934 if (PREV_INSN (insn))
2935 NEXT_INSN (PREV_INSN (insn)) = next;
2940 PREV_INSN (next) = PREV_INSN (insn);
2946 prev = get_last_insn ();
2948 /* Write the remaining insns followed by the final copy. */
2950 for (insn = insns; insn; insn = next)
2952 next = NEXT_INSN (insn);
2957 last = emit_move_insn (target, result);
2958 if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
2959 != CODE_FOR_nothing)
2960 set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
2962 if (final_dest != target)
2963 emit_move_insn (final_dest, target);
2966 first = get_insns ();
2968 first = NEXT_INSN (prev);
2970 /* Encapsulate the block so it gets manipulated as a unit. */
2971 REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
2973 REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2976 /* Generate code to store zero in X. */
2982 emit_move_insn (x, const0_rtx);
2985 /* Generate code to store 1 in X
2986 assuming it contains zero beforehand. */
2989 emit_0_to_1_insn (x)
2992 emit_move_insn (x, const1_rtx);
2995 /* Generate code to compare X with Y
2996 so that the condition codes are set.
2998 MODE is the mode of the inputs (in case they are const_int).
2999 UNSIGNEDP nonzero says that X and Y are unsigned;
3000 this matters if they need to be widened.
3002 If they have mode BLKmode, then SIZE specifies the size of both X and Y,
3003 and ALIGN specifies the known shared alignment of X and Y.
3005 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
3006 It is ignored for fixed-point and block comparisons;
3007 it is used only for floating-point comparisons. */
3010 emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
3012 enum rtx_code comparison;
3014 enum machine_mode mode;
3018 enum mode_class class;
3019 enum machine_mode wider_mode;
3021 class = GET_MODE_CLASS (mode);
3023 /* They could both be VOIDmode if both args are immediate constants,
3024 but we should fold that at an earlier stage.
3025 With no special code here, this will call abort,
3026 reminding the programmer to implement such folding. */
3028 if (mode != BLKmode && flag_force_mem)
3030 x = force_not_mem (x);
3031 y = force_not_mem (y);
3034 /* If we are inside an appropriately-short loop and one operand is an
3035 expensive constant, force it into a register. */
3036 if (CONSTANT_P (x) && preserve_subexpressions_p () && rtx_cost (x, COMPARE) > 2)
3037 x = force_reg (mode, x);
3039 if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2)
3040 y = force_reg (mode, y);
3043 /* Abort if we have a non-canonical comparison. The RTL documentation
3044 states that canonical comparisons are required only for targets which
3046 if (CONSTANT_P (x) && ! CONSTANT_P (y))
3050 /* Don't let both operands fail to indicate the mode. */
3051 if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
3052 x = force_reg (mode, x);
3054 /* Handle all BLKmode compares. */
3056 if (mode == BLKmode)
3059 x = protect_from_queue (x, 0);
3060 y = protect_from_queue (y, 0);
3064 #ifdef HAVE_cmpstrqi
3066 && GET_CODE (size) == CONST_INT
3067 && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
3069 enum machine_mode result_mode
3070 = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0];
3071 rtx result = gen_reg_rtx (result_mode);
3072 emit_insn (gen_cmpstrqi (result, x, y, size, GEN_INT (align)));
3073 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
3078 #ifdef HAVE_cmpstrhi
3080 && GET_CODE (size) == CONST_INT
3081 && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
3083 enum machine_mode result_mode
3084 = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0];
3085 rtx result = gen_reg_rtx (result_mode);
3086 emit_insn (gen_cmpstrhi (result, x, y, size, GEN_INT (align)));
3087 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
3092 #ifdef HAVE_cmpstrsi
3095 enum machine_mode result_mode
3096 = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0];
3097 rtx result = gen_reg_rtx (result_mode);
3098 size = protect_from_queue (size, 0);
3099 emit_insn (gen_cmpstrsi (result, x, y,
3100 convert_to_mode (SImode, size, 1),
3102 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
3110 #ifdef TARGET_MEM_FUNCTIONS
3111 emit_library_call (memcmp_libfunc, 0,
3112 TYPE_MODE (integer_type_node), 3,
3113 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
3114 convert_to_mode (TYPE_MODE (sizetype), size,
3115 TREE_UNSIGNED (sizetype)),
3116 TYPE_MODE (sizetype));
3118 emit_library_call (bcmp_libfunc, 0,
3119 TYPE_MODE (integer_type_node), 3,
3120 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
3121 convert_to_mode (TYPE_MODE (integer_type_node),
3123 TREE_UNSIGNED (integer_type_node)),
3124 TYPE_MODE (integer_type_node));
3127 /* Immediately move the result of the libcall into a pseudo
3128 register so reload doesn't clobber the value if it needs
3129 the return register for a spill reg. */
3130 result = gen_reg_rtx (TYPE_MODE (integer_type_node));
3131 emit_move_insn (result,
3132 hard_libcall_value (TYPE_MODE (integer_type_node)));
3133 emit_cmp_insn (result,
3134 const0_rtx, comparison, NULL_RTX,
3135 TYPE_MODE (integer_type_node), 0, 0);
3140 /* Handle some compares against zero. */
3142 if (y == CONST0_RTX (mode)
3143 && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
3145 int icode = (int) tst_optab->handlers[(int) mode].insn_code;
3148 x = protect_from_queue (x, 0);
3149 y = protect_from_queue (y, 0);
3151 /* Now, if insn does accept these operands, put them into pseudos. */
3152 if (! (*insn_operand_predicate[icode][0])
3153 (x, insn_operand_mode[icode][0]))
3154 x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
3156 emit_insn (GEN_FCN (icode) (x));
3160 /* Handle compares for which there is a directly suitable insn. */
3162 if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
3164 int icode = (int) cmp_optab->handlers[(int) mode].insn_code;
3167 x = protect_from_queue (x, 0);
3168 y = protect_from_queue (y, 0);
3170 /* Now, if insn doesn't accept these operands, put them into pseudos. */
3171 if (! (*insn_operand_predicate[icode][0])
3172 (x, insn_operand_mode[icode][0]))
3173 x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
3175 if (! (*insn_operand_predicate[icode][1])
3176 (y, insn_operand_mode[icode][1]))
3177 y = copy_to_mode_reg (insn_operand_mode[icode][1], y);
3179 emit_insn (GEN_FCN (icode) (x, y));
3183 /* Try widening if we can find a direct insn that way. */
3185 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
3187 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
3188 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3190 if (cmp_optab->handlers[(int) wider_mode].insn_code
3191 != CODE_FOR_nothing)
3193 x = protect_from_queue (x, 0);
3194 y = protect_from_queue (y, 0);
3195 x = convert_modes (wider_mode, mode, x, unsignedp);
3196 y = convert_modes (wider_mode, mode, y, unsignedp);
3197 emit_cmp_insn (x, y, comparison, NULL_RTX,
3198 wider_mode, unsignedp, align);
3204 /* Handle a lib call just for the mode we are using. */
3206 if (cmp_optab->handlers[(int) mode].libfunc
3207 && class != MODE_FLOAT)
3209 rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
3212 /* If we want unsigned, and this mode has a distinct unsigned
3213 comparison routine, use that. */
3214 if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
3215 libfunc = ucmp_optab->handlers[(int) mode].libfunc;
3217 emit_library_call (libfunc, 1,
3218 word_mode, 2, x, mode, y, mode);
3220 /* Immediately move the result of the libcall into a pseudo
3221 register so reload doesn't clobber the value if it needs
3222 the return register for a spill reg. */
3223 result = gen_reg_rtx (word_mode);
3224 emit_move_insn (result, hard_libcall_value (word_mode));
3226 /* Integer comparison returns a result that must be compared against 1,
3227 so that even if we do an unsigned compare afterward,
3228 there is still a value that can represent the result "less than". */
3229 emit_cmp_insn (result, const1_rtx,
3230 comparison, NULL_RTX, word_mode, unsignedp, 0);
3234 if (class == MODE_FLOAT)
3235 emit_float_lib_cmp (x, y, comparison);
3241 /* Generate code to compare X with Y so that the condition codes are
3242 set and to jump to LABEL if the condition is true. If X is a
3243 constant and Y is not a constant, then the comparison is swapped to
3244 ensure that the comparison RTL has the canonical form.
3246 UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
3247 need to be widened by emit_cmp_insn. UNSIGNEDP is also used to select
3248 the proper branch condition code.
3250 If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y,
3251 and ALIGN specifies the known shared alignment of X and Y.
3253 MODE is the mode of the inputs (in case they are const_int).
3255 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). It will
3256 be passed unchanged to emit_cmp_insn, then potentially converted into an
3257 unsigned variant based on UNSIGNEDP to select a proper jump instruction. */
3260 emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, label)
3262 enum rtx_code comparison;
3264 enum machine_mode mode;
3274 /* Swap operands and condition to ensure canonical RTL. */
3277 comparison = swap_condition (comparison);
3286 /* If OP0 is still a constant, then both X and Y must be constants. Force
3287 X into a register to avoid aborting in emit_cmp_insn due to non-canonical
3289 if (CONSTANT_P (op0))
3290 op0 = force_reg (mode, op0);
3293 emit_cmp_insn (op0, op1, comparison, size, mode, unsignedp, align);
3296 comparison = unsigned_condition (comparison);
3297 emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
3301 /* Nonzero if a compare of mode MODE can be done straightforwardly
3302 (without splitting it into pieces). */
3305 can_compare_p (mode)
3306 enum machine_mode mode;
3310 if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
3312 mode = GET_MODE_WIDER_MODE (mode);
3313 } while (mode != VOIDmode);
3318 /* Emit a library call comparison between floating point X and Y.
3319 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
3322 emit_float_lib_cmp (x, y, comparison)
3324 enum rtx_code comparison;
3326 enum machine_mode mode = GET_MODE (x);
3334 libfunc = eqhf2_libfunc;
3338 libfunc = nehf2_libfunc;
3342 libfunc = gthf2_libfunc;
3346 libfunc = gehf2_libfunc;
3350 libfunc = lthf2_libfunc;
3354 libfunc = lehf2_libfunc;
3360 else if (mode == SFmode)
3364 libfunc = eqsf2_libfunc;
3368 libfunc = nesf2_libfunc;
3372 libfunc = gtsf2_libfunc;
3376 libfunc = gesf2_libfunc;
3380 libfunc = ltsf2_libfunc;
3384 libfunc = lesf2_libfunc;
3390 else if (mode == DFmode)
3394 libfunc = eqdf2_libfunc;
3398 libfunc = nedf2_libfunc;
3402 libfunc = gtdf2_libfunc;
3406 libfunc = gedf2_libfunc;
3410 libfunc = ltdf2_libfunc;
3414 libfunc = ledf2_libfunc;
3420 else if (mode == XFmode)
3424 libfunc = eqxf2_libfunc;
3428 libfunc = nexf2_libfunc;
3432 libfunc = gtxf2_libfunc;
3436 libfunc = gexf2_libfunc;
3440 libfunc = ltxf2_libfunc;
3444 libfunc = lexf2_libfunc;
3450 else if (mode == TFmode)
3454 libfunc = eqtf2_libfunc;
3458 libfunc = netf2_libfunc;
3462 libfunc = gttf2_libfunc;
3466 libfunc = getf2_libfunc;
3470 libfunc = lttf2_libfunc;
3474 libfunc = letf2_libfunc;
3482 enum machine_mode wider_mode;
3484 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
3485 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3487 if ((cmp_optab->handlers[(int) wider_mode].insn_code
3488 != CODE_FOR_nothing)
3489 || (cmp_optab->handlers[(int) wider_mode].libfunc != 0))
3491 x = protect_from_queue (x, 0);
3492 y = protect_from_queue (y, 0);
3493 x = convert_to_mode (wider_mode, x, 0);
3494 y = convert_to_mode (wider_mode, y, 0);
3495 emit_float_lib_cmp (x, y, comparison);
3505 emit_library_call (libfunc, 1,
3506 word_mode, 2, x, mode, y, mode);
3508 /* Immediately move the result of the libcall into a pseudo
3509 register so reload doesn't clobber the value if it needs
3510 the return register for a spill reg. */
3511 result = gen_reg_rtx (word_mode);
3512 emit_move_insn (result, hard_libcall_value (word_mode));
3514 emit_cmp_insn (result, const0_rtx, comparison,
3515 NULL_RTX, word_mode, 0, 0);
3518 /* Generate code to indirectly jump to a location given in the rtx LOC. */
3521 emit_indirect_jump (loc)
3524 if (! ((*insn_operand_predicate[(int)CODE_FOR_indirect_jump][0])
3526 loc = copy_to_mode_reg (Pmode, loc);
3528 emit_jump_insn (gen_indirect_jump (loc));
3532 #ifdef HAVE_conditional_move
3534 /* Emit a conditional move instruction if the machine supports one for that
3535 condition and machine mode.
3537 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
3538 the mode to use should they be constants. If it is VOIDmode, they cannot
3541 OP2 should be stored in TARGET if the comparison is true, otherwise OP3
3542 should be stored there. MODE is the mode to use should they be constants.
3543 If it is VOIDmode, they cannot both be constants.
3545 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
3546 is not supported. */
3549 emit_conditional_move (target, code, op0, op1, cmode, op2, op3, mode,
3554 enum machine_mode cmode;
3556 enum machine_mode mode;
3559 rtx tem, subtarget, comparison, insn;
3560 enum insn_code icode;
3562 /* If one operand is constant, make it the second one. Only do this
3563 if the other operand is not constant as well. */
3565 if ((CONSTANT_P (op0) && ! CONSTANT_P (op1))
3566 || (GET_CODE (op0) == CONST_INT && GET_CODE (op1) != CONST_INT))
3571 code = swap_condition (code);
3574 if (cmode == VOIDmode)
3575 cmode = GET_MODE (op0);
3577 if (((CONSTANT_P (op2) && ! CONSTANT_P (op3))
3578 || (GET_CODE (op2) == CONST_INT && GET_CODE (op3) != CONST_INT))
3579 && (GET_MODE_CLASS (GET_MODE (op1)) != MODE_FLOAT
3580 || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT || flag_fast_math))
3585 code = reverse_condition (code);
3588 if (mode == VOIDmode)
3589 mode = GET_MODE (op2);
3591 icode = movcc_gen_code[mode];
3593 if (icode == CODE_FOR_nothing)
3598 op2 = force_not_mem (op2);
3599 op3 = force_not_mem (op3);
3603 target = protect_from_queue (target, 1);
3605 target = gen_reg_rtx (mode);
3611 op2 = protect_from_queue (op2, 0);
3612 op3 = protect_from_queue (op3, 0);
3614 /* If the insn doesn't accept these operands, put them in pseudos. */
3616 if (! (*insn_operand_predicate[icode][0])
3617 (subtarget, insn_operand_mode[icode][0]))
3618 subtarget = gen_reg_rtx (insn_operand_mode[icode][0]);
3620 if (! (*insn_operand_predicate[icode][2])
3621 (op2, insn_operand_mode[icode][2]))
3622 op2 = copy_to_mode_reg (insn_operand_mode[icode][2], op2);
3624 if (! (*insn_operand_predicate[icode][3])
3625 (op3, insn_operand_mode[icode][3]))
3626 op3 = copy_to_mode_reg (insn_operand_mode[icode][3], op3);
3628 /* Everything should now be in the suitable form, so emit the compare insn
3629 and then the conditional move. */
3632 = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX, 0);
3634 /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)? */
3635 if (GET_CODE (comparison) != code)
3636 /* This shouldn't happen. */
3639 insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
3641 /* If that failed, then give up. */
3647 if (subtarget != target)
3648 convert_move (target, subtarget, 0);
3653 /* Return non-zero if a conditional move of mode MODE is supported.
3655 This function is for combine so it can tell whether an insn that looks
3656 like a conditional move is actually supported by the hardware. If we
3657 guess wrong we lose a bit on optimization, but that's it. */
3658 /* ??? sparc64 supports conditionally moving integers values based on fp
3659 comparisons, and vice versa. How do we handle them? */
3662 can_conditionally_move_p (mode)
3663 enum machine_mode mode;
3665 if (movcc_gen_code[mode] != CODE_FOR_nothing)
3671 #endif /* HAVE_conditional_move */
3673 /* These three functions generate an insn body and return it
3674 rather than emitting the insn.
3676 They do not protect from queued increments,
3677 because they may be used 1) in protect_from_queue itself
3678 and 2) in other passes where there is no queue. */
3680 /* Generate and return an insn body to add Y to X. */
3683 gen_add2_insn (x, y)
3686 int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code;
3688 if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
3689 || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
3690 || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
3693 return (GEN_FCN (icode) (x, x, y));
3697 have_add2_insn (mode)
3698 enum machine_mode mode;
3700 return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
3703 /* Generate and return an insn body to subtract Y from X. */
3706 gen_sub2_insn (x, y)
3709 int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code;
3711 if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
3712 || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
3713 || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
3716 return (GEN_FCN (icode) (x, x, y));
3720 have_sub2_insn (mode)
3721 enum machine_mode mode;
3723 return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
3726 /* Generate the body of an instruction to copy Y into X.
3727 It may be a SEQUENCE, if one insn isn't enough. */
3730 gen_move_insn (x, y)
3733 register enum machine_mode mode = GET_MODE (x);
3734 enum insn_code insn_code;
3737 if (mode == VOIDmode)
3738 mode = GET_MODE (y);
3740 insn_code = mov_optab->handlers[(int) mode].insn_code;
3742 /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
3743 find a mode to do it in. If we have a movcc, use it. Otherwise,
3744 find the MODE_INT mode of the same width. */
3746 if (GET_MODE_CLASS (mode) == MODE_CC && insn_code == CODE_FOR_nothing)
3748 enum machine_mode tmode = VOIDmode;
3752 && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing)
3755 for (tmode = QImode; tmode != VOIDmode;
3756 tmode = GET_MODE_WIDER_MODE (tmode))
3757 if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode))
3760 if (tmode == VOIDmode)
3763 /* Get X and Y in TMODE. We can't use gen_lowpart here because it
3764 may call change_address which is not appropriate if we were
3765 called when a reload was in progress. We don't have to worry
3766 about changing the address since the size in bytes is supposed to
3767 be the same. Copy the MEM to change the mode and move any
3768 substitutions from the old MEM to the new one. */
3770 if (reload_in_progress)
3772 x = gen_lowpart_common (tmode, x1);
3773 if (x == 0 && GET_CODE (x1) == MEM)
3775 x = gen_rtx_MEM (tmode, XEXP (x1, 0));
3776 RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1);
3777 MEM_COPY_ATTRIBUTES (x, x1);
3778 copy_replacements (x1, x);
3781 y = gen_lowpart_common (tmode, y1);
3782 if (y == 0 && GET_CODE (y1) == MEM)
3784 y = gen_rtx_MEM (tmode, XEXP (y1, 0));
3785 RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1);
3786 MEM_COPY_ATTRIBUTES (y, y1);
3787 copy_replacements (y1, y);
3792 x = gen_lowpart (tmode, x);
3793 y = gen_lowpart (tmode, y);
3796 insn_code = mov_optab->handlers[(int) tmode].insn_code;
3797 return (GEN_FCN (insn_code) (x, y));
3801 emit_move_insn_1 (x, y);
3802 seq = gen_sequence ();
3807 /* Return the insn code used to extend FROM_MODE to TO_MODE.
3808 UNSIGNEDP specifies zero-extension instead of sign-extension. If
3809 no such operation exists, CODE_FOR_nothing will be returned. */
3812 can_extend_p (to_mode, from_mode, unsignedp)
3813 enum machine_mode to_mode, from_mode;
3816 return extendtab[(int) to_mode][(int) from_mode][unsignedp];
3819 /* Generate the body of an insn to extend Y (with mode MFROM)
3820 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
3823 gen_extend_insn (x, y, mto, mfrom, unsignedp)
3825 enum machine_mode mto, mfrom;
3828 return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp]) (x, y));
3831 /* can_fix_p and can_float_p say whether the target machine
3832 can directly convert a given fixed point type to
3833 a given floating point type, or vice versa.
3834 The returned value is the CODE_FOR_... value to use,
3835 or CODE_FOR_nothing if these modes cannot be directly converted.
3837 *TRUNCP_PTR is set to 1 if it is necessary to output
3838 an explicit FTRUNC insn before the fix insn; otherwise 0. */
3840 static enum insn_code
3841 can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
3842 enum machine_mode fltmode, fixmode;
3847 if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp] != CODE_FOR_nothing)
3848 return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp];
3850 if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
3853 return fixtab[(int) fltmode][(int) fixmode][unsignedp];
3855 return CODE_FOR_nothing;
3858 static enum insn_code
3859 can_float_p (fltmode, fixmode, unsignedp)
3860 enum machine_mode fixmode, fltmode;
3863 return floattab[(int) fltmode][(int) fixmode][unsignedp];
3866 /* Generate code to convert FROM to floating point
3867 and store in TO. FROM must be fixed point and not VOIDmode.
3868 UNSIGNEDP nonzero means regard FROM as unsigned.
3869 Normally this is done by correcting the final value
3870 if it is negative. */
3873 expand_float (to, from, unsignedp)
3877 enum insn_code icode;
3878 register rtx target = to;
3879 enum machine_mode fmode, imode;
3881 /* Crash now, because we won't be able to decide which mode to use. */
3882 if (GET_MODE (from) == VOIDmode)
3885 /* Look for an insn to do the conversion. Do it in the specified
3886 modes if possible; otherwise convert either input, output or both to
3887 wider mode. If the integer mode is wider than the mode of FROM,
3888 we can do the conversion signed even if the input is unsigned. */
3890 for (imode = GET_MODE (from); imode != VOIDmode;
3891 imode = GET_MODE_WIDER_MODE (imode))
3892 for (fmode = GET_MODE (to); fmode != VOIDmode;
3893 fmode = GET_MODE_WIDER_MODE (fmode))
3895 int doing_unsigned = unsignedp;
3897 icode = can_float_p (fmode, imode, unsignedp);
3898 if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
3899 icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;
3901 if (icode != CODE_FOR_nothing)
3903 to = protect_from_queue (to, 1);
3904 from = protect_from_queue (from, 0);
3906 if (imode != GET_MODE (from))
3907 from = convert_to_mode (imode, from, unsignedp);
3909 if (fmode != GET_MODE (to))
3910 target = gen_reg_rtx (fmode);
3912 emit_unop_insn (icode, target, from,
3913 doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
3916 convert_move (to, target, 0);
3921 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3923 /* Unsigned integer, and no way to convert directly.
3924 Convert as signed, then conditionally adjust the result. */
3927 rtx label = gen_label_rtx ();
3929 REAL_VALUE_TYPE offset;
3933 to = protect_from_queue (to, 1);
3934 from = protect_from_queue (from, 0);
3937 from = force_not_mem (from);
3939 /* Look for a usable floating mode FMODE wider than the source and at
3940 least as wide as the target. Using FMODE will avoid rounding woes
3941 with unsigned values greater than the signed maximum value. */
3943 for (fmode = GET_MODE (to); fmode != VOIDmode;
3944 fmode = GET_MODE_WIDER_MODE (fmode))
3945 if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
3946 && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
3949 if (fmode == VOIDmode)
3951 /* There is no such mode. Pretend the target is wide enough. */
3952 fmode = GET_MODE (to);
3954 /* Avoid double-rounding when TO is narrower than FROM. */
3955 if ((significand_size (fmode) + 1)
3956 < GET_MODE_BITSIZE (GET_MODE (from)))
3959 rtx neglabel = gen_label_rtx ();
3961 /* Don't use TARGET if it isn't a register, is a hard register,
3962 or is the wrong mode. */
3963 if (GET_CODE (target) != REG
3964 || REGNO (target) < FIRST_PSEUDO_REGISTER
3965 || GET_MODE (target) != fmode)
3966 target = gen_reg_rtx (fmode);
3968 imode = GET_MODE (from);
3969 do_pending_stack_adjust ();
3971 /* Test whether the sign bit is set. */
3972 emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, imode, 0, 0);
3973 emit_jump_insn (gen_blt (neglabel));
3975 /* The sign bit is not set. Convert as signed. */
3976 expand_float (target, from, 0);
3977 emit_jump_insn (gen_jump (label));
3980 /* The sign bit is set.
3981 Convert to a usable (positive signed) value by shifting right
3982 one bit, while remembering if a nonzero bit was shifted
3983 out; i.e., compute (from & 1) | (from >> 1). */
3985 emit_label (neglabel);
3986 temp = expand_binop (imode, and_optab, from, const1_rtx,
3987 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3988 temp1 = expand_shift (RSHIFT_EXPR, imode, from, integer_one_node,
3990 temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1,
3992 expand_float (target, temp, 0);
3994 /* Multiply by 2 to undo the shift above. */
3995 temp = expand_binop (fmode, add_optab, target, target,
3996 target, 0, OPTAB_LIB_WIDEN);
3998 emit_move_insn (target, temp);
4000 do_pending_stack_adjust ();
4006 /* If we are about to do some arithmetic to correct for an
4007 unsigned operand, do it in a pseudo-register. */
4009 if (GET_MODE (to) != fmode
4010 || GET_CODE (to) != REG || REGNO (to) < FIRST_PSEUDO_REGISTER)
4011 target = gen_reg_rtx (fmode);
4013 /* Convert as signed integer to floating. */
4014 expand_float (target, from, 0);
4016 /* If FROM is negative (and therefore TO is negative),
4017 correct its value by 2**bitwidth. */
4019 do_pending_stack_adjust ();
4020 emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
4023 /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
4024 Rather than setting up a dconst_dot_5, let's hope SCO
4026 offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from)));
4027 temp = expand_binop (fmode, add_optab, target,
4028 CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
4029 target, 0, OPTAB_LIB_WIDEN);
4031 emit_move_insn (target, temp);
4033 do_pending_stack_adjust ();
4039 /* No hardware instruction available; call a library routine to convert from
4040 SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */
4046 to = protect_from_queue (to, 1);
4047 from = protect_from_queue (from, 0);
4049 if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
4050 from = convert_to_mode (SImode, from, unsignedp);
4053 from = force_not_mem (from);
4055 if (GET_MODE (to) == SFmode)
4057 if (GET_MODE (from) == SImode)
4058 libfcn = floatsisf_libfunc;
4059 else if (GET_MODE (from) == DImode)
4060 libfcn = floatdisf_libfunc;
4061 else if (GET_MODE (from) == TImode)
4062 libfcn = floattisf_libfunc;
4066 else if (GET_MODE (to) == DFmode)
4068 if (GET_MODE (from) == SImode)
4069 libfcn = floatsidf_libfunc;
4070 else if (GET_MODE (from) == DImode)
4071 libfcn = floatdidf_libfunc;
4072 else if (GET_MODE (from) == TImode)
4073 libfcn = floattidf_libfunc;
4077 else if (GET_MODE (to) == XFmode)
4079 if (GET_MODE (from) == SImode)
4080 libfcn = floatsixf_libfunc;
4081 else if (GET_MODE (from) == DImode)
4082 libfcn = floatdixf_libfunc;
4083 else if (GET_MODE (from) == TImode)
4084 libfcn = floattixf_libfunc;
4088 else if (GET_MODE (to) == TFmode)
4090 if (GET_MODE (from) == SImode)
4091 libfcn = floatsitf_libfunc;
4092 else if (GET_MODE (from) == DImode)
4093 libfcn = floatditf_libfunc;
4094 else if (GET_MODE (from) == TImode)
4095 libfcn = floattitf_libfunc;
4104 value = emit_library_call_value (libfcn, NULL_RTX, 1,
4106 1, from, GET_MODE (from));
4107 insns = get_insns ();
4110 emit_libcall_block (insns, target, value,
4111 gen_rtx_FLOAT (GET_MODE (to), from));
4116 /* Copy result to requested destination
4117 if we have been computing in a temp location. */
4121 if (GET_MODE (target) == GET_MODE (to))
4122 emit_move_insn (to, target);
4124 convert_move (to, target, 0);
4128 /* expand_fix: generate code to convert FROM to fixed point
4129 and store in TO. FROM must be floating point. */
4135 rtx temp = gen_reg_rtx (GET_MODE (x));
4136 return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0);
4140 expand_fix (to, from, unsignedp)
4141 register rtx to, from;
4144 enum insn_code icode;
4145 register rtx target = to;
4146 enum machine_mode fmode, imode;
4150 /* We first try to find a pair of modes, one real and one integer, at
4151 least as wide as FROM and TO, respectively, in which we can open-code
4152 this conversion. If the integer mode is wider than the mode of TO,
4153 we can do the conversion either signed or unsigned. */
4155 for (imode = GET_MODE (to); imode != VOIDmode;
4156 imode = GET_MODE_WIDER_MODE (imode))
4157 for (fmode = GET_MODE (from); fmode != VOIDmode;
4158 fmode = GET_MODE_WIDER_MODE (fmode))
4160 int doing_unsigned = unsignedp;
4162 icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
4163 if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
4164 icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
4166 if (icode != CODE_FOR_nothing)
4168 to = protect_from_queue (to, 1);
4169 from = protect_from_queue (from, 0);
4171 if (fmode != GET_MODE (from))
4172 from = convert_to_mode (fmode, from, 0);
4175 from = ftruncify (from);
4177 if (imode != GET_MODE (to))
4178 target = gen_reg_rtx (imode);
4180 emit_unop_insn (icode, target, from,
4181 doing_unsigned ? UNSIGNED_FIX : FIX);
4183 convert_move (to, target, unsignedp);
4188 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
4189 /* For an unsigned conversion, there is one more way to do it.
4190 If we have a signed conversion, we generate code that compares
4191 the real value to the largest representable positive number. If if
4192 is smaller, the conversion is done normally. Otherwise, subtract
4193 one plus the highest signed number, convert, and add it back.
4195 We only need to check all real modes, since we know we didn't find
4196 anything with a wider integer mode. */
4198 if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
4199 for (fmode = GET_MODE (from); fmode != VOIDmode;
4200 fmode = GET_MODE_WIDER_MODE (fmode))
4201 /* Make sure we won't lose significant bits doing this. */
4202 if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))
4203 && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
4207 REAL_VALUE_TYPE offset;
4208 rtx limit, lab1, lab2, insn;
4210 bitsize = GET_MODE_BITSIZE (GET_MODE (to));
4211 offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1);
4212 limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
4213 lab1 = gen_label_rtx ();
4214 lab2 = gen_label_rtx ();
4217 to = protect_from_queue (to, 1);
4218 from = protect_from_queue (from, 0);
4221 from = force_not_mem (from);
4223 if (fmode != GET_MODE (from))
4224 from = convert_to_mode (fmode, from, 0);
4226 /* See if we need to do the subtraction. */
4227 do_pending_stack_adjust ();
4228 emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
4231 /* If not, do the signed "fix" and branch around fixup code. */
4232 expand_fix (to, from, 0);
4233 emit_jump_insn (gen_jump (lab2));
4236 /* Otherwise, subtract 2**(N-1), convert to signed number,
4237 then add 2**(N-1). Do the addition using XOR since this
4238 will often generate better code. */
4240 target = expand_binop (GET_MODE (from), sub_optab, from, limit,
4241 NULL_RTX, 0, OPTAB_LIB_WIDEN);
4242 expand_fix (to, target, 0);
4243 target = expand_binop (GET_MODE (to), xor_optab, to,
4244 GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)),
4245 to, 1, OPTAB_LIB_WIDEN);
4248 emit_move_insn (to, target);
4252 if (mov_optab->handlers[(int) GET_MODE (to)].insn_code
4253 != CODE_FOR_nothing)
4255 /* Make a place for a REG_NOTE and add it. */
4256 insn = emit_move_insn (to, to);
4257 set_unique_reg_note (insn,
4259 gen_rtx_fmt_e (UNSIGNED_FIX,
4267 /* We can't do it with an insn, so use a library call. But first ensure
4268 that the mode of TO is at least as wide as SImode, since those are the
4269 only library calls we know about. */
4271 if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
4273 target = gen_reg_rtx (SImode);
4275 expand_fix (target, from, unsignedp);
4277 else if (GET_MODE (from) == SFmode)
4279 if (GET_MODE (to) == SImode)
4280 libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc;
4281 else if (GET_MODE (to) == DImode)
4282 libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc;
4283 else if (GET_MODE (to) == TImode)
4284 libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc;
4288 else if (GET_MODE (from) == DFmode)
4290 if (GET_MODE (to) == SImode)
4291 libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc;
4292 else if (GET_MODE (to) == DImode)
4293 libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc;
4294 else if (GET_MODE (to) == TImode)
4295 libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc;
4299 else if (GET_MODE (from) == XFmode)
4301 if (GET_MODE (to) == SImode)
4302 libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc;
4303 else if (GET_MODE (to) == DImode)
4304 libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc;
4305 else if (GET_MODE (to) == TImode)
4306 libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc;
4310 else if (GET_MODE (from) == TFmode)
4312 if (GET_MODE (to) == SImode)
4313 libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc;
4314 else if (GET_MODE (to) == DImode)
4315 libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc;
4316 else if (GET_MODE (to) == TImode)
4317 libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc;
4329 to = protect_from_queue (to, 1);
4330 from = protect_from_queue (from, 0);
4333 from = force_not_mem (from);
4337 value = emit_library_call_value (libfcn, NULL_RTX, 1, GET_MODE (to),
4339 1, from, GET_MODE (from));
4340 insns = get_insns ();
4343 emit_libcall_block (insns, target, value,
4344 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX,
4345 GET_MODE (to), from));
4350 if (GET_MODE (to) == GET_MODE (target))
4351 emit_move_insn (to, target);
4353 convert_move (to, target, 0);
4362 optab op = (optab) xmalloc (sizeof (struct optab));
4364 for (i = 0; i < NUM_MACHINE_MODES; i++)
4366 op->handlers[i].insn_code = CODE_FOR_nothing;
4367 op->handlers[i].libfunc = 0;
4370 if (code != UNKNOWN)
4371 code_to_optab[(int) code] = op;
4376 /* Initialize the libfunc fields of an entire group of entries in some
4377 optab. Each entry is set equal to a string consisting of a leading
4378 pair of underscores followed by a generic operation name followed by
4379 a mode name (downshifted to lower case) followed by a single character
4380 representing the number of operands for the given operation (which is
4381 usually one of the characters '2', '3', or '4').
4383 OPTABLE is the table in which libfunc fields are to be initialized.
4384 FIRST_MODE is the first machine mode index in the given optab to
4386 LAST_MODE is the last machine mode index in the given optab to
4388 OPNAME is the generic (string) name of the operation.
4389 SUFFIX is the character which specifies the number of operands for
4390 the given generic operation.
4394 init_libfuncs (optable, first_mode, last_mode, opname, suffix)
4395 register optab optable;
4396 register int first_mode;
4397 register int last_mode;
4398 register const char *opname;
4399 register int suffix;
4402 register unsigned opname_len = strlen (opname);
4404 for (mode = first_mode; (int) mode <= (int) last_mode;
4405 mode = (enum machine_mode) ((int) mode + 1))
4407 register char *mname = mode_name[(int) mode];
4408 register unsigned mname_len = strlen (mname);
4409 register char *libfunc_name
4410 = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1);
4412 register const char *q;
4417 for (q = opname; *q; )
4419 for (q = mname; *q; q++)
4420 *p++ = tolower ((unsigned char)*q);
4423 optable->handlers[(int) mode].libfunc
4424 = gen_rtx_SYMBOL_REF (Pmode, libfunc_name);
4428 /* Initialize the libfunc fields of an entire group of entries in some
4429 optab which correspond to all integer mode operations. The parameters
4430 have the same meaning as similarly named ones for the `init_libfuncs'
4431 routine. (See above). */
4434 init_integral_libfuncs (optable, opname, suffix)
4435 register optab optable;
4436 register const char *opname;
4437 register int suffix;
4439 init_libfuncs (optable, SImode, TImode, opname, suffix);
4442 /* Initialize the libfunc fields of an entire group of entries in some
4443 optab which correspond to all real mode operations. The parameters
4444 have the same meaning as similarly named ones for the `init_libfuncs'
4445 routine. (See above). */
4448 init_floating_libfuncs (optable, opname, suffix)
4449 register optab optable;
4450 register const char *opname;
4451 register int suffix;
4453 init_libfuncs (optable, SFmode, TFmode, opname, suffix);
4457 /* Call this once to initialize the contents of the optabs
4458 appropriately for the current target machine. */
4464 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
4470 /* Start by initializing all tables to contain CODE_FOR_nothing. */
4472 for (p = fixtab[0][0];
4473 p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]);
4475 *p = CODE_FOR_nothing;
4477 for (p = fixtrunctab[0][0];
4478 p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]);
4480 *p = CODE_FOR_nothing;
4482 for (p = floattab[0][0];
4483 p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]);
4485 *p = CODE_FOR_nothing;
4487 for (p = extendtab[0][0];
4488 p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0];
4490 *p = CODE_FOR_nothing;
4492 for (i = 0; i < NUM_RTX_CODE; i++)
4493 setcc_gen_code[i] = CODE_FOR_nothing;
4495 #ifdef HAVE_conditional_move
4496 for (i = 0; i < NUM_MACHINE_MODES; i++)
4497 movcc_gen_code[i] = CODE_FOR_nothing;
4500 add_optab = init_optab (PLUS);
4501 sub_optab = init_optab (MINUS);
4502 smul_optab = init_optab (MULT);
4503 smul_highpart_optab = init_optab (UNKNOWN);
4504 umul_highpart_optab = init_optab (UNKNOWN);
4505 smul_widen_optab = init_optab (UNKNOWN);
4506 umul_widen_optab = init_optab (UNKNOWN);
4507 sdiv_optab = init_optab (DIV);
4508 sdivmod_optab = init_optab (UNKNOWN);
4509 udiv_optab = init_optab (UDIV);
4510 udivmod_optab = init_optab (UNKNOWN);
4511 smod_optab = init_optab (MOD);
4512 umod_optab = init_optab (UMOD);
4513 flodiv_optab = init_optab (DIV);
4514 ftrunc_optab = init_optab (UNKNOWN);
4515 and_optab = init_optab (AND);
4516 ior_optab = init_optab (IOR);
4517 xor_optab = init_optab (XOR);
4518 ashl_optab = init_optab (ASHIFT);
4519 ashr_optab = init_optab (ASHIFTRT);
4520 lshr_optab = init_optab (LSHIFTRT);
4521 rotl_optab = init_optab (ROTATE);
4522 rotr_optab = init_optab (ROTATERT);
4523 smin_optab = init_optab (SMIN);
4524 smax_optab = init_optab (SMAX);
4525 umin_optab = init_optab (UMIN);
4526 umax_optab = init_optab (UMAX);
4527 mov_optab = init_optab (UNKNOWN);
4528 movstrict_optab = init_optab (UNKNOWN);
4529 cmp_optab = init_optab (UNKNOWN);
4530 ucmp_optab = init_optab (UNKNOWN);
4531 tst_optab = init_optab (UNKNOWN);
4532 neg_optab = init_optab (NEG);
4533 abs_optab = init_optab (ABS);
4534 one_cmpl_optab = init_optab (NOT);
4535 ffs_optab = init_optab (FFS);
4536 sqrt_optab = init_optab (SQRT);
4537 sin_optab = init_optab (UNKNOWN);
4538 cos_optab = init_optab (UNKNOWN);
4539 strlen_optab = init_optab (UNKNOWN);
4541 for (i = 0; i < NUM_MACHINE_MODES; i++)
4543 movstr_optab[i] = CODE_FOR_nothing;
4544 clrstr_optab[i] = CODE_FOR_nothing;
4546 #ifdef HAVE_SECONDARY_RELOADS
4547 reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
4551 /* Fill in the optabs with the insns we support. */
4554 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
4555 /* This flag says the same insns that convert to a signed fixnum
4556 also convert validly to an unsigned one. */
4557 for (i = 0; i < NUM_MACHINE_MODES; i++)
4558 for (j = 0; j < NUM_MACHINE_MODES; j++)
4559 fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
4562 #ifdef EXTRA_CC_MODES
4566 /* Initialize the optabs with the names of the library functions. */
4567 init_integral_libfuncs (add_optab, "add", '3');
4568 init_floating_libfuncs (add_optab, "add", '3');
4569 init_integral_libfuncs (sub_optab, "sub", '3');
4570 init_floating_libfuncs (sub_optab, "sub", '3');
4571 init_integral_libfuncs (smul_optab, "mul", '3');
4572 init_floating_libfuncs (smul_optab, "mul", '3');
4573 init_integral_libfuncs (sdiv_optab, "div", '3');
4574 init_integral_libfuncs (udiv_optab, "udiv", '3');
4575 init_integral_libfuncs (sdivmod_optab, "divmod", '4');
4576 init_integral_libfuncs (udivmod_optab, "udivmod", '4');
4577 init_integral_libfuncs (smod_optab, "mod", '3');
4578 init_integral_libfuncs (umod_optab, "umod", '3');
4579 init_floating_libfuncs (flodiv_optab, "div", '3');
4580 init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
4581 init_integral_libfuncs (and_optab, "and", '3');
4582 init_integral_libfuncs (ior_optab, "ior", '3');
4583 init_integral_libfuncs (xor_optab, "xor", '3');
4584 init_integral_libfuncs (ashl_optab, "ashl", '3');
4585 init_integral_libfuncs (ashr_optab, "ashr", '3');
4586 init_integral_libfuncs (lshr_optab, "lshr", '3');
4587 init_integral_libfuncs (smin_optab, "min", '3');
4588 init_floating_libfuncs (smin_optab, "min", '3');
4589 init_integral_libfuncs (smax_optab, "max", '3');
4590 init_floating_libfuncs (smax_optab, "max", '3');
4591 init_integral_libfuncs (umin_optab, "umin", '3');
4592 init_integral_libfuncs (umax_optab, "umax", '3');
4593 init_integral_libfuncs (neg_optab, "neg", '2');
4594 init_floating_libfuncs (neg_optab, "neg", '2');
4595 init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
4596 init_integral_libfuncs (ffs_optab, "ffs", '2');
4598 /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
4599 init_integral_libfuncs (cmp_optab, "cmp", '2');
4600 init_integral_libfuncs (ucmp_optab, "ucmp", '2');
4601 init_floating_libfuncs (cmp_optab, "cmp", '2');
4603 #ifdef MULSI3_LIBCALL
4604 smul_optab->handlers[(int) SImode].libfunc
4605 = gen_rtx_SYMBOL_REF (Pmode, MULSI3_LIBCALL);
4607 #ifdef MULDI3_LIBCALL
4608 smul_optab->handlers[(int) DImode].libfunc
4609 = gen_rtx_SYMBOL_REF (Pmode, MULDI3_LIBCALL);
4612 #ifdef DIVSI3_LIBCALL
4613 sdiv_optab->handlers[(int) SImode].libfunc
4614 = gen_rtx_SYMBOL_REF (Pmode, DIVSI3_LIBCALL);
4616 #ifdef DIVDI3_LIBCALL
4617 sdiv_optab->handlers[(int) DImode].libfunc
4618 = gen_rtx_SYMBOL_REF (Pmode, DIVDI3_LIBCALL);
4621 #ifdef UDIVSI3_LIBCALL
4622 udiv_optab->handlers[(int) SImode].libfunc
4623 = gen_rtx_SYMBOL_REF (Pmode, UDIVSI3_LIBCALL);
4625 #ifdef UDIVDI3_LIBCALL
4626 udiv_optab->handlers[(int) DImode].libfunc
4627 = gen_rtx_SYMBOL_REF (Pmode, UDIVDI3_LIBCALL);
4630 #ifdef MODSI3_LIBCALL
4631 smod_optab->handlers[(int) SImode].libfunc
4632 = gen_rtx_SYMBOL_REF (Pmode, MODSI3_LIBCALL);
4634 #ifdef MODDI3_LIBCALL
4635 smod_optab->handlers[(int) DImode].libfunc
4636 = gen_rtx_SYMBOL_REF (Pmode, MODDI3_LIBCALL);
4639 #ifdef UMODSI3_LIBCALL
4640 umod_optab->handlers[(int) SImode].libfunc
4641 = gen_rtx_SYMBOL_REF (Pmode, UMODSI3_LIBCALL);
4643 #ifdef UMODDI3_LIBCALL
4644 umod_optab->handlers[(int) DImode].libfunc
4645 = gen_rtx_SYMBOL_REF (Pmode, UMODDI3_LIBCALL);
4648 /* Use cabs for DC complex abs, since systems generally have cabs.
4649 Don't define any libcall for SCmode, so that cabs will be used. */
4650 abs_optab->handlers[(int) DCmode].libfunc
4651 = gen_rtx_SYMBOL_REF (Pmode, "cabs");
4653 /* The ffs function operates on `int'. */
4654 #ifndef INT_TYPE_SIZE
4655 #define INT_TYPE_SIZE BITS_PER_WORD
4657 ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)] .libfunc
4658 = gen_rtx_SYMBOL_REF (Pmode, "ffs");
4660 extendsfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsfdf2");
4661 extendsfxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsfxf2");
4662 extendsftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsftf2");
4663 extenddfxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extenddfxf2");
4664 extenddftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extenddftf2");
4666 truncdfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncdfsf2");
4667 truncxfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncxfsf2");
4668 trunctfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__trunctfsf2");
4669 truncxfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncxfdf2");
4670 trunctfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__trunctfdf2");
4672 memcpy_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memcpy");
4673 bcopy_libfunc = gen_rtx_SYMBOL_REF (Pmode, "bcopy");
4674 memcmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memcmp");
4675 bcmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gcc_bcmp");
4676 memset_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memset");
4677 bzero_libfunc = gen_rtx_SYMBOL_REF (Pmode, "bzero");
4679 throw_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__throw");
4680 rethrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__rethrow");
4681 sjthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjthrow");
4682 sjpopnthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjpopnthrow");
4683 terminate_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__terminate");
4684 eh_rtime_match_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eh_rtime_match");
4685 #ifndef DONT_USE_BUILTIN_SETJMP
4686 setjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__builtin_setjmp");
4687 longjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__builtin_longjmp");
4689 setjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "setjmp");
4690 longjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "longjmp");
4693 eqhf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqhf2");
4694 nehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nehf2");
4695 gthf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gthf2");
4696 gehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gehf2");
4697 lthf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lthf2");
4698 lehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lehf2");
4700 eqsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqsf2");
4701 nesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nesf2");
4702 gtsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtsf2");
4703 gesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gesf2");
4704 ltsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltsf2");
4705 lesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lesf2");
4707 eqdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqdf2");
4708 nedf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nedf2");
4709 gtdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtdf2");
4710 gedf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gedf2");
4711 ltdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltdf2");
4712 ledf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ledf2");
4714 eqxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqxf2");
4715 nexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nexf2");
4716 gtxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtxf2");
4717 gexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gexf2");
4718 ltxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltxf2");
4719 lexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lexf2");
4721 eqtf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqtf2");
4722 netf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__netf2");
4723 gttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gttf2");
4724 getf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__getf2");
4725 lttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lttf2");
4726 letf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__letf2");
4728 floatsisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsisf");
4729 floatdisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdisf");
4730 floattisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattisf");
4732 floatsidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsidf");
4733 floatdidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdidf");
4734 floattidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattidf");
4736 floatsixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsixf");
4737 floatdixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdixf");
4738 floattixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattixf");
4740 floatsitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsitf");
4741 floatditf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatditf");
4742 floattitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattitf");
4744 fixsfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfsi");
4745 fixsfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfdi");
4746 fixsfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfti");
4748 fixdfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfsi");
4749 fixdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfdi");
4750 fixdfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfti");
4752 fixxfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfsi");
4753 fixxfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfdi");
4754 fixxfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfti");
4756 fixtfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfsi");
4757 fixtfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfdi");
4758 fixtfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfti");
4760 fixunssfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfsi");
4761 fixunssfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfdi");
4762 fixunssfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfti");
4764 fixunsdfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfsi");
4765 fixunsdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfdi");
4766 fixunsdfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfti");
4768 fixunsxfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfsi");
4769 fixunsxfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfdi");
4770 fixunsxfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfti");
4772 fixunstfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfsi");
4773 fixunstfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfdi");
4774 fixunstfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfti");
4776 /* For check-memory-usage. */
4777 chkr_check_addr_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_addr");
4778 chkr_set_right_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_set_right");
4779 chkr_copy_bitmap_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_copy_bitmap");
4780 chkr_check_exec_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_exec");
4781 chkr_check_str_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_str");
4783 /* For function entry/exit instrumentation. */
4784 profile_function_entry_libfunc
4785 = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_enter");
4786 profile_function_exit_libfunc
4787 = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_exit");
4789 #ifdef HAVE_conditional_trap
4793 #ifdef INIT_TARGET_OPTABS
4794 /* Allow the target to add more libcalls or rename some, etc. */
4801 /* SCO 3.2 apparently has a broken ldexp. */
4814 #endif /* BROKEN_LDEXP */
4816 #ifdef HAVE_conditional_trap
4817 /* The insn generating function can not take an rtx_code argument.
4818 TRAP_RTX is used as an rtx argument. Its code is replaced with
4819 the code to be used in the trap insn and all other fields are
4822 ??? Will need to change to support garbage collection. */
4823 static rtx trap_rtx;
4828 if (HAVE_conditional_trap)
4829 trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);
4833 /* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
4834 CODE. Return 0 on failure. */
4837 gen_cond_trap (code, op1, op2, tcode)
4838 enum rtx_code code ATTRIBUTE_UNUSED;
4839 rtx op1, op2 ATTRIBUTE_UNUSED, tcode ATTRIBUTE_UNUSED;
4841 enum machine_mode mode = GET_MODE (op1);
4843 if (mode == VOIDmode)
4846 #ifdef HAVE_conditional_trap
4847 if (HAVE_conditional_trap
4848 && cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
4851 emit_insn (GEN_FCN (cmp_optab->handlers[(int) mode].insn_code) (op1, op2));
4852 PUT_CODE (trap_rtx, code);
4853 insn = gen_conditional_trap (trap_rtx, tcode);