2000-05-02 Jeff Sturm <jsturm@one-point.com>
[official-gcc.git] / gcc / optabs.c
blobc28b4d97c77cba4557e69fdd30d5522cc7c4a789
1 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2 Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000, 2001 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)
10 any later version.
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. */
23 #include "config.h"
24 #include "system.h"
25 #include "toplev.h"
27 /* Include insn-config.h before expr.h so that HAVE_conditional_move
28 is properly defined. */
29 #include "insn-config.h"
30 #include "rtl.h"
31 #include "tree.h"
32 #include "tm_p.h"
33 #include "flags.h"
34 #include "function.h"
35 #include "except.h"
36 #include "expr.h"
37 #include "recog.h"
38 #include "reload.h"
39 #include "ggc.h"
40 #include "real.h"
42 /* Each optab contains info on how this target machine
43 can perform a particular operation
44 for all sizes and kinds of operands.
46 The operation to be performed is often specified
47 by passing one of these optabs as an argument.
49 See expr.h for documentation of these optabs. */
51 optab optab_table[OTI_MAX];
53 rtx libfunc_table[LTI_MAX];
55 /* Tables of patterns for extending one integer mode to another. */
56 enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2];
58 /* Tables of patterns for converting between fixed and floating point. */
59 enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
60 enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
61 enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
63 /* Contains the optab used for each rtx code. */
64 optab code_to_optab[NUM_RTX_CODE + 1];
66 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
67 gives the gen_function to make a branch to test that condition. */
69 rtxfun bcc_gen_fctn[NUM_RTX_CODE];
71 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
72 gives the insn code to make a store-condition insn
73 to test that condition. */
75 enum insn_code setcc_gen_code[NUM_RTX_CODE];
77 #ifdef HAVE_conditional_move
78 /* Indexed by the machine mode, gives the insn code to make a conditional
79 move insn. This is not indexed by the rtx-code like bcc_gen_fctn and
80 setcc_gen_code to cut down on the number of named patterns. Consider a day
81 when a lot more rtx codes are conditional (eg: for the ARM). */
83 enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
84 #endif
86 static int add_equal_note PARAMS ((rtx, rtx, enum rtx_code, rtx, rtx));
87 static rtx widen_operand PARAMS ((rtx, enum machine_mode,
88 enum machine_mode, int, int));
89 static int expand_cmplxdiv_straight PARAMS ((rtx, rtx, rtx, rtx,
90 rtx, rtx, enum machine_mode,
91 int, enum optab_methods,
92 enum mode_class, optab));
93 static int expand_cmplxdiv_wide PARAMS ((rtx, rtx, rtx, rtx,
94 rtx, rtx, enum machine_mode,
95 int, enum optab_methods,
96 enum mode_class, optab));
97 static enum insn_code can_fix_p PARAMS ((enum machine_mode, enum machine_mode,
98 int, int *));
99 static enum insn_code can_float_p PARAMS ((enum machine_mode, enum machine_mode,
100 int));
101 static rtx ftruncify PARAMS ((rtx));
102 static optab init_optab PARAMS ((enum rtx_code));
103 static void init_libfuncs PARAMS ((optab, int, int, const char *, int));
104 static void init_integral_libfuncs PARAMS ((optab, const char *, int));
105 static void init_floating_libfuncs PARAMS ((optab, const char *, int));
106 #ifdef HAVE_conditional_trap
107 static void init_traps PARAMS ((void));
108 #endif
109 static void emit_cmp_and_jump_insn_1 PARAMS ((rtx, rtx, enum machine_mode,
110 enum rtx_code, int, rtx));
111 static void prepare_float_lib_cmp PARAMS ((rtx *, rtx *, enum rtx_code *,
112 enum machine_mode *, int *));
114 /* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
115 the result of operation CODE applied to OP0 (and OP1 if it is a binary
116 operation).
118 If the last insn does not set TARGET, don't do anything, but return 1.
120 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
121 don't add the REG_EQUAL note but return 0. Our caller can then try
122 again, ensuring that TARGET is not one of the operands. */
124 static int
125 add_equal_note (seq, target, code, op0, op1)
126 rtx seq;
127 rtx target;
128 enum rtx_code code;
129 rtx op0, op1;
131 rtx set;
132 int i;
133 rtx note;
135 if ((GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2'
136 && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<')
137 || GET_CODE (seq) != SEQUENCE
138 || (set = single_set (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))) == 0
139 || GET_CODE (target) == ZERO_EXTRACT
140 || (! rtx_equal_p (SET_DEST (set), target)
141 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
142 SUBREG. */
143 && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
144 || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)),
145 target))))
146 return 1;
148 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
149 besides the last insn. */
150 if (reg_overlap_mentioned_p (target, op0)
151 || (op1 && reg_overlap_mentioned_p (target, op1)))
152 for (i = XVECLEN (seq, 0) - 2; i >= 0; i--)
153 if (reg_set_p (target, XVECEXP (seq, 0, i)))
154 return 0;
156 if (GET_RTX_CLASS (code) == '1')
157 note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0));
158 else
159 note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
161 set_unique_reg_note (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1), REG_EQUAL, note);
163 return 1;
166 /* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP
167 says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need
168 not actually do a sign-extend or zero-extend, but can leave the
169 higher-order bits of the result rtx undefined, for example, in the case
170 of logical operations, but not right shifts. */
172 static rtx
173 widen_operand (op, mode, oldmode, unsignedp, no_extend)
174 rtx op;
175 enum machine_mode mode, oldmode;
176 int unsignedp;
177 int no_extend;
179 rtx result;
181 /* If we must extend do so. If OP is either a constant or a SUBREG
182 for a promoted object, also extend since it will be more efficient to
183 do so. */
184 if (! no_extend
185 || GET_MODE (op) == VOIDmode
186 || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op)))
187 return convert_modes (mode, oldmode, op, unsignedp);
189 /* If MODE is no wider than a single word, we return a paradoxical
190 SUBREG. */
191 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
192 return gen_rtx_SUBREG (mode, force_reg (GET_MODE (op), op), 0);
194 /* Otherwise, get an object of MODE, clobber it, and set the low-order
195 part to OP. */
197 result = gen_reg_rtx (mode);
198 emit_insn (gen_rtx_CLOBBER (VOIDmode, result));
199 emit_move_insn (gen_lowpart (GET_MODE (op), result), op);
200 return result;
203 /* Generate code to perform a straightforward complex divide. */
205 static int
206 expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
207 unsignedp, methods, class, binoptab)
208 rtx real0, real1, imag0, imag1, realr, imagr;
209 enum machine_mode submode;
210 int unsignedp;
211 enum optab_methods methods;
212 enum mode_class class;
213 optab binoptab;
215 rtx divisor;
216 rtx real_t, imag_t;
217 rtx temp1, temp2;
218 rtx res;
219 optab this_add_optab = add_optab;
220 optab this_sub_optab = sub_optab;
221 optab this_neg_optab = neg_optab;
222 optab this_mul_optab = smul_optab;
224 if (binoptab == sdivv_optab)
226 this_add_optab = addv_optab;
227 this_sub_optab = subv_optab;
228 this_neg_optab = negv_optab;
229 this_mul_optab = smulv_optab;
232 /* Don't fetch these from memory more than once. */
233 real0 = force_reg (submode, real0);
234 real1 = force_reg (submode, real1);
236 if (imag0 != 0)
237 imag0 = force_reg (submode, imag0);
239 imag1 = force_reg (submode, imag1);
241 /* Divisor: c*c + d*d. */
242 temp1 = expand_binop (submode, this_mul_optab, real1, real1,
243 NULL_RTX, unsignedp, methods);
245 temp2 = expand_binop (submode, this_mul_optab, imag1, imag1,
246 NULL_RTX, unsignedp, methods);
248 if (temp1 == 0 || temp2 == 0)
249 return 0;
251 divisor = expand_binop (submode, this_add_optab, temp1, temp2,
252 NULL_RTX, unsignedp, methods);
253 if (divisor == 0)
254 return 0;
256 if (imag0 == 0)
258 /* Mathematically, ((a)(c-id))/divisor. */
259 /* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)). */
261 /* Calculate the dividend. */
262 real_t = expand_binop (submode, this_mul_optab, real0, real1,
263 NULL_RTX, unsignedp, methods);
265 imag_t = expand_binop (submode, this_mul_optab, real0, imag1,
266 NULL_RTX, unsignedp, methods);
268 if (real_t == 0 || imag_t == 0)
269 return 0;
271 imag_t = expand_unop (submode, this_neg_optab, imag_t,
272 NULL_RTX, unsignedp);
274 else
276 /* Mathematically, ((a+ib)(c-id))/divider. */
277 /* Calculate the dividend. */
278 temp1 = expand_binop (submode, this_mul_optab, real0, real1,
279 NULL_RTX, unsignedp, methods);
281 temp2 = expand_binop (submode, this_mul_optab, imag0, imag1,
282 NULL_RTX, unsignedp, methods);
284 if (temp1 == 0 || temp2 == 0)
285 return 0;
287 real_t = expand_binop (submode, this_add_optab, temp1, temp2,
288 NULL_RTX, unsignedp, methods);
290 temp1 = expand_binop (submode, this_mul_optab, imag0, real1,
291 NULL_RTX, unsignedp, methods);
293 temp2 = expand_binop (submode, this_mul_optab, real0, imag1,
294 NULL_RTX, unsignedp, methods);
296 if (temp1 == 0 || temp2 == 0)
297 return 0;
299 imag_t = expand_binop (submode, this_sub_optab, temp1, temp2,
300 NULL_RTX, unsignedp, methods);
302 if (real_t == 0 || imag_t == 0)
303 return 0;
306 if (class == MODE_COMPLEX_FLOAT)
307 res = expand_binop (submode, binoptab, real_t, divisor,
308 realr, unsignedp, methods);
309 else
310 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
311 real_t, divisor, realr, unsignedp);
313 if (res == 0)
314 return 0;
316 if (res != realr)
317 emit_move_insn (realr, res);
319 if (class == MODE_COMPLEX_FLOAT)
320 res = expand_binop (submode, binoptab, imag_t, divisor,
321 imagr, unsignedp, methods);
322 else
323 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
324 imag_t, divisor, imagr, unsignedp);
326 if (res == 0)
327 return 0;
329 if (res != imagr)
330 emit_move_insn (imagr, res);
332 return 1;
335 /* Generate code to perform a wide-input-range-acceptable complex divide. */
337 static int
338 expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
339 unsignedp, methods, class, binoptab)
340 rtx real0, real1, imag0, imag1, realr, imagr;
341 enum machine_mode submode;
342 int unsignedp;
343 enum optab_methods methods;
344 enum mode_class class;
345 optab binoptab;
347 rtx ratio, divisor;
348 rtx real_t, imag_t;
349 rtx temp1, temp2, lab1, lab2;
350 enum machine_mode mode;
351 int align;
352 rtx res;
353 optab this_add_optab = add_optab;
354 optab this_sub_optab = sub_optab;
355 optab this_neg_optab = neg_optab;
356 optab this_mul_optab = smul_optab;
358 if (binoptab == sdivv_optab)
360 this_add_optab = addv_optab;
361 this_sub_optab = subv_optab;
362 this_neg_optab = negv_optab;
363 this_mul_optab = smulv_optab;
366 /* Don't fetch these from memory more than once. */
367 real0 = force_reg (submode, real0);
368 real1 = force_reg (submode, real1);
370 if (imag0 != 0)
371 imag0 = force_reg (submode, imag0);
373 imag1 = force_reg (submode, imag1);
375 /* XXX What's an "unsigned" complex number? */
376 if (unsignedp)
378 temp1 = real1;
379 temp2 = imag1;
381 else
383 temp1 = expand_abs (submode, real1, NULL_RTX, unsignedp, 1);
384 temp2 = expand_abs (submode, imag1, NULL_RTX, unsignedp, 1);
387 if (temp1 == 0 || temp2 == 0)
388 return 0;
390 mode = GET_MODE (temp1);
391 align = GET_MODE_ALIGNMENT (mode);
392 lab1 = gen_label_rtx ();
393 emit_cmp_and_jump_insns (temp1, temp2, LT, NULL_RTX,
394 mode, unsignedp, align, lab1);
396 /* |c| >= |d|; use ratio d/c to scale dividend and divisor. */
398 if (class == MODE_COMPLEX_FLOAT)
399 ratio = expand_binop (submode, binoptab, imag1, real1,
400 NULL_RTX, unsignedp, methods);
401 else
402 ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
403 imag1, real1, NULL_RTX, unsignedp);
405 if (ratio == 0)
406 return 0;
408 /* Calculate divisor. */
410 temp1 = expand_binop (submode, this_mul_optab, imag1, ratio,
411 NULL_RTX, unsignedp, methods);
413 if (temp1 == 0)
414 return 0;
416 divisor = expand_binop (submode, this_add_optab, temp1, real1,
417 NULL_RTX, unsignedp, methods);
419 if (divisor == 0)
420 return 0;
422 /* Calculate dividend. */
424 if (imag0 == 0)
426 real_t = real0;
428 /* Compute a / (c+id) as a / (c+d(d/c)) + i (-a(d/c)) / (c+d(d/c)). */
430 imag_t = expand_binop (submode, this_mul_optab, real0, ratio,
431 NULL_RTX, unsignedp, methods);
433 if (imag_t == 0)
434 return 0;
436 imag_t = expand_unop (submode, this_neg_optab, imag_t,
437 NULL_RTX, unsignedp);
439 if (real_t == 0 || imag_t == 0)
440 return 0;
442 else
444 /* Compute (a+ib)/(c+id) as
445 (a+b(d/c))/(c+d(d/c) + i(b-a(d/c))/(c+d(d/c)). */
447 temp1 = expand_binop (submode, this_mul_optab, imag0, ratio,
448 NULL_RTX, unsignedp, methods);
450 if (temp1 == 0)
451 return 0;
453 real_t = expand_binop (submode, this_add_optab, temp1, real0,
454 NULL_RTX, unsignedp, methods);
456 temp1 = expand_binop (submode, this_mul_optab, real0, ratio,
457 NULL_RTX, unsignedp, methods);
459 if (temp1 == 0)
460 return 0;
462 imag_t = expand_binop (submode, this_sub_optab, imag0, temp1,
463 NULL_RTX, unsignedp, methods);
465 if (real_t == 0 || imag_t == 0)
466 return 0;
469 if (class == MODE_COMPLEX_FLOAT)
470 res = expand_binop (submode, binoptab, real_t, divisor,
471 realr, unsignedp, methods);
472 else
473 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
474 real_t, divisor, realr, unsignedp);
476 if (res == 0)
477 return 0;
479 if (res != realr)
480 emit_move_insn (realr, res);
482 if (class == MODE_COMPLEX_FLOAT)
483 res = expand_binop (submode, binoptab, imag_t, divisor,
484 imagr, unsignedp, methods);
485 else
486 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
487 imag_t, divisor, imagr, unsignedp);
489 if (res == 0)
490 return 0;
492 if (res != imagr)
493 emit_move_insn (imagr, res);
495 lab2 = gen_label_rtx ();
496 emit_jump_insn (gen_jump (lab2));
497 emit_barrier ();
499 emit_label (lab1);
501 /* |d| > |c|; use ratio c/d to scale dividend and divisor. */
503 if (class == MODE_COMPLEX_FLOAT)
504 ratio = expand_binop (submode, binoptab, real1, imag1,
505 NULL_RTX, unsignedp, methods);
506 else
507 ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
508 real1, imag1, NULL_RTX, unsignedp);
510 if (ratio == 0)
511 return 0;
513 /* Calculate divisor. */
515 temp1 = expand_binop (submode, this_mul_optab, real1, ratio,
516 NULL_RTX, unsignedp, methods);
518 if (temp1 == 0)
519 return 0;
521 divisor = expand_binop (submode, this_add_optab, temp1, imag1,
522 NULL_RTX, unsignedp, methods);
524 if (divisor == 0)
525 return 0;
527 /* Calculate dividend. */
529 if (imag0 == 0)
531 /* Compute a / (c+id) as a(c/d) / (c(c/d)+d) + i (-a) / (c(c/d)+d). */
533 real_t = expand_binop (submode, this_mul_optab, real0, ratio,
534 NULL_RTX, unsignedp, methods);
536 imag_t = expand_unop (submode, this_neg_optab, real0,
537 NULL_RTX, unsignedp);
539 if (real_t == 0 || imag_t == 0)
540 return 0;
542 else
544 /* Compute (a+ib)/(c+id) as
545 (a(c/d)+b)/(c(c/d)+d) + i (b(c/d)-a)/(c(c/d)+d). */
547 temp1 = expand_binop (submode, this_mul_optab, real0, ratio,
548 NULL_RTX, unsignedp, methods);
550 if (temp1 == 0)
551 return 0;
553 real_t = expand_binop (submode, this_add_optab, temp1, imag0,
554 NULL_RTX, unsignedp, methods);
556 temp1 = expand_binop (submode, this_mul_optab, imag0, ratio,
557 NULL_RTX, unsignedp, methods);
559 if (temp1 == 0)
560 return 0;
562 imag_t = expand_binop (submode, this_sub_optab, temp1, real0,
563 NULL_RTX, unsignedp, methods);
565 if (real_t == 0 || imag_t == 0)
566 return 0;
569 if (class == MODE_COMPLEX_FLOAT)
570 res = expand_binop (submode, binoptab, real_t, divisor,
571 realr, unsignedp, methods);
572 else
573 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
574 real_t, divisor, realr, unsignedp);
576 if (res == 0)
577 return 0;
579 if (res != realr)
580 emit_move_insn (realr, res);
582 if (class == MODE_COMPLEX_FLOAT)
583 res = expand_binop (submode, binoptab, imag_t, divisor,
584 imagr, unsignedp, methods);
585 else
586 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
587 imag_t, divisor, imagr, unsignedp);
589 if (res == 0)
590 return 0;
592 if (res != imagr)
593 emit_move_insn (imagr, res);
595 emit_label (lab2);
597 return 1;
600 /* Generate code to perform an operation specified by BINOPTAB
601 on operands OP0 and OP1, with result having machine-mode MODE.
603 UNSIGNEDP is for the case where we have to widen the operands
604 to perform the operation. It says to use zero-extension.
606 If TARGET is nonzero, the value
607 is generated there, if it is convenient to do so.
608 In all cases an rtx is returned for the locus of the value;
609 this may or may not be TARGET. */
612 expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
613 enum machine_mode mode;
614 optab binoptab;
615 rtx op0, op1;
616 rtx target;
617 int unsignedp;
618 enum optab_methods methods;
620 enum optab_methods next_methods
621 = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN
622 ? OPTAB_WIDEN : methods);
623 enum mode_class class;
624 enum machine_mode wider_mode;
625 register rtx temp;
626 int commutative_op = 0;
627 int shift_op = (binoptab->code == ASHIFT
628 || binoptab->code == ASHIFTRT
629 || binoptab->code == LSHIFTRT
630 || binoptab->code == ROTATE
631 || binoptab->code == ROTATERT);
632 rtx entry_last = get_last_insn ();
633 rtx last;
635 class = GET_MODE_CLASS (mode);
637 op0 = protect_from_queue (op0, 0);
638 op1 = protect_from_queue (op1, 0);
639 if (target)
640 target = protect_from_queue (target, 1);
642 if (flag_force_mem)
644 op0 = force_not_mem (op0);
645 op1 = force_not_mem (op1);
648 /* If subtracting an integer constant, convert this into an addition of
649 the negated constant. */
651 if (binoptab == sub_optab && GET_CODE (op1) == CONST_INT)
653 op1 = negate_rtx (mode, op1);
654 binoptab = add_optab;
657 /* If we are inside an appropriately-short loop and one operand is an
658 expensive constant, force it into a register. */
659 if (CONSTANT_P (op0) && preserve_subexpressions_p ()
660 && rtx_cost (op0, binoptab->code) > COSTS_N_INSNS (1))
661 op0 = force_reg (mode, op0);
663 if (CONSTANT_P (op1) && preserve_subexpressions_p ()
664 && ! shift_op && rtx_cost (op1, binoptab->code) > COSTS_N_INSNS (1))
665 op1 = force_reg (mode, op1);
667 /* Record where to delete back to if we backtrack. */
668 last = get_last_insn ();
670 /* If operation is commutative,
671 try to make the first operand a register.
672 Even better, try to make it the same as the target.
673 Also try to make the last operand a constant. */
674 if (GET_RTX_CLASS (binoptab->code) == 'c'
675 || binoptab == smul_widen_optab
676 || binoptab == umul_widen_optab
677 || binoptab == smul_highpart_optab
678 || binoptab == umul_highpart_optab)
680 commutative_op = 1;
682 if (((target == 0 || GET_CODE (target) == REG)
683 ? ((GET_CODE (op1) == REG
684 && GET_CODE (op0) != REG)
685 || target == op1)
686 : rtx_equal_p (op1, target))
687 || GET_CODE (op0) == CONST_INT)
689 temp = op1;
690 op1 = op0;
691 op0 = temp;
695 /* If we can do it with a three-operand insn, do so. */
697 if (methods != OPTAB_MUST_WIDEN
698 && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
700 int icode = (int) binoptab->handlers[(int) mode].insn_code;
701 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
702 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
703 rtx pat;
704 rtx xop0 = op0, xop1 = op1;
706 if (target)
707 temp = target;
708 else
709 temp = gen_reg_rtx (mode);
711 /* If it is a commutative operator and the modes would match
712 if we would swap the operands, we can save the conversions. */
713 if (commutative_op)
715 if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
716 && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
718 register rtx tmp;
720 tmp = op0; op0 = op1; op1 = tmp;
721 tmp = xop0; xop0 = xop1; xop1 = tmp;
725 /* In case the insn wants input operands in modes different from
726 the result, convert the operands. It would seem that we
727 don't need to convert CONST_INTs, but we do, so that they're
728 a properly sign-extended for their modes; we choose the
729 widest mode between mode and mode[01], so that, in a widening
730 operation, we call convert_modes with different FROM and TO
731 modes, which ensures the value is sign-extended. Shift
732 operations are an exception, because the second operand needs
733 not be extended to the mode of the result. */
735 if (GET_MODE (op0) != mode0
736 && mode0 != VOIDmode)
737 xop0 = convert_modes (mode0,
738 GET_MODE (op0) != VOIDmode
739 ? GET_MODE (op0)
740 : GET_MODE_SIZE (mode) > GET_MODE_SIZE (mode0)
741 ? mode
742 : mode0,
743 xop0, unsignedp);
745 if (GET_MODE (xop1) != mode1
746 && mode1 != VOIDmode)
747 xop1 = convert_modes (mode1,
748 GET_MODE (op1) != VOIDmode
749 ? GET_MODE (op1)
750 : (GET_MODE_SIZE (mode) > GET_MODE_SIZE (mode1)
751 && ! shift_op)
752 ? mode
753 : mode1,
754 xop1, unsignedp);
756 /* Now, if insn's predicates don't allow our operands, put them into
757 pseudo regs. */
759 if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0)
760 && mode0 != VOIDmode)
761 xop0 = copy_to_mode_reg (mode0, xop0);
763 if (! (*insn_data[icode].operand[2].predicate) (xop1, mode1)
764 && mode1 != VOIDmode)
765 xop1 = copy_to_mode_reg (mode1, xop1);
767 if (! (*insn_data[icode].operand[0].predicate) (temp, mode))
768 temp = gen_reg_rtx (mode);
770 pat = GEN_FCN (icode) (temp, xop0, xop1);
771 if (pat)
773 /* If PAT is a multi-insn sequence, try to add an appropriate
774 REG_EQUAL note to it. If we can't because TEMP conflicts with an
775 operand, call ourselves again, this time without a target. */
776 if (GET_CODE (pat) == SEQUENCE
777 && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
779 delete_insns_since (last);
780 return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
781 unsignedp, methods);
784 emit_insn (pat);
785 return temp;
787 else
788 delete_insns_since (last);
791 /* If this is a multiply, see if we can do a widening operation that
792 takes operands of this mode and makes a wider mode. */
794 if (binoptab == smul_optab && GET_MODE_WIDER_MODE (mode) != VOIDmode
795 && (((unsignedp ? umul_widen_optab : smul_widen_optab)
796 ->handlers[(int) GET_MODE_WIDER_MODE (mode)].insn_code)
797 != CODE_FOR_nothing))
799 temp = expand_binop (GET_MODE_WIDER_MODE (mode),
800 unsignedp ? umul_widen_optab : smul_widen_optab,
801 op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT);
803 if (temp != 0)
805 if (GET_MODE_CLASS (mode) == MODE_INT)
806 return gen_lowpart (mode, temp);
807 else
808 return convert_to_mode (mode, temp, unsignedp);
812 /* Look for a wider mode of the same class for which we think we
813 can open-code the operation. Check for a widening multiply at the
814 wider mode as well. */
816 if ((class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
817 && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
818 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
819 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
821 if (binoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing
822 || (binoptab == smul_optab
823 && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
824 && (((unsignedp ? umul_widen_optab : smul_widen_optab)
825 ->handlers[(int) GET_MODE_WIDER_MODE (wider_mode)].insn_code)
826 != CODE_FOR_nothing)))
828 rtx xop0 = op0, xop1 = op1;
829 int no_extend = 0;
831 /* For certain integer operations, we need not actually extend
832 the narrow operands, as long as we will truncate
833 the results to the same narrowness. */
835 if ((binoptab == ior_optab || binoptab == and_optab
836 || binoptab == xor_optab
837 || binoptab == add_optab || binoptab == sub_optab
838 || binoptab == smul_optab || binoptab == ashl_optab)
839 && class == MODE_INT)
840 no_extend = 1;
842 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend);
844 /* The second operand of a shift must always be extended. */
845 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
846 no_extend && binoptab != ashl_optab);
848 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
849 unsignedp, OPTAB_DIRECT);
850 if (temp)
852 if (class != MODE_INT)
854 if (target == 0)
855 target = gen_reg_rtx (mode);
856 convert_move (target, temp, 0);
857 return target;
859 else
860 return gen_lowpart (mode, temp);
862 else
863 delete_insns_since (last);
867 /* These can be done a word at a time. */
868 if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
869 && class == MODE_INT
870 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
871 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
873 unsigned int i;
874 rtx insns;
875 rtx equiv_value;
877 /* If TARGET is the same as one of the operands, the REG_EQUAL note
878 won't be accurate, so use a new target. */
879 if (target == 0 || target == op0 || target == op1)
880 target = gen_reg_rtx (mode);
882 start_sequence ();
884 /* Do the actual arithmetic. */
885 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
887 rtx target_piece = operand_subword (target, i, 1, mode);
888 rtx x = expand_binop (word_mode, binoptab,
889 operand_subword_force (op0, i, mode),
890 operand_subword_force (op1, i, mode),
891 target_piece, unsignedp, next_methods);
893 if (x == 0)
894 break;
896 if (target_piece != x)
897 emit_move_insn (target_piece, x);
900 insns = get_insns ();
901 end_sequence ();
903 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
905 if (binoptab->code != UNKNOWN)
906 equiv_value
907 = gen_rtx_fmt_ee (binoptab->code, mode,
908 copy_rtx (op0), copy_rtx (op1));
909 else
910 equiv_value = 0;
912 emit_no_conflict_block (insns, target, op0, op1, equiv_value);
913 return target;
917 /* Synthesize double word shifts from single word shifts. */
918 if ((binoptab == lshr_optab || binoptab == ashl_optab
919 || binoptab == ashr_optab)
920 && class == MODE_INT
921 && GET_CODE (op1) == CONST_INT
922 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
923 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
924 && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
925 && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
927 rtx insns, inter, equiv_value;
928 rtx into_target, outof_target;
929 rtx into_input, outof_input;
930 int shift_count, left_shift, outof_word;
932 /* If TARGET is the same as one of the operands, the REG_EQUAL note
933 won't be accurate, so use a new target. */
934 if (target == 0 || target == op0 || target == op1)
935 target = gen_reg_rtx (mode);
937 start_sequence ();
939 shift_count = INTVAL (op1);
941 /* OUTOF_* is the word we are shifting bits away from, and
942 INTO_* is the word that we are shifting bits towards, thus
943 they differ depending on the direction of the shift and
944 WORDS_BIG_ENDIAN. */
946 left_shift = binoptab == ashl_optab;
947 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
949 outof_target = operand_subword (target, outof_word, 1, mode);
950 into_target = operand_subword (target, 1 - outof_word, 1, mode);
952 outof_input = operand_subword_force (op0, outof_word, mode);
953 into_input = operand_subword_force (op0, 1 - outof_word, mode);
955 if (shift_count >= BITS_PER_WORD)
957 inter = expand_binop (word_mode, binoptab,
958 outof_input,
959 GEN_INT (shift_count - BITS_PER_WORD),
960 into_target, unsignedp, next_methods);
962 if (inter != 0 && inter != into_target)
963 emit_move_insn (into_target, inter);
965 /* For a signed right shift, we must fill the word we are shifting
966 out of with copies of the sign bit. Otherwise it is zeroed. */
967 if (inter != 0 && binoptab != ashr_optab)
968 inter = CONST0_RTX (word_mode);
969 else if (inter != 0)
970 inter = expand_binop (word_mode, binoptab,
971 outof_input,
972 GEN_INT (BITS_PER_WORD - 1),
973 outof_target, unsignedp, next_methods);
975 if (inter != 0 && inter != outof_target)
976 emit_move_insn (outof_target, inter);
978 else
980 rtx carries;
981 optab reverse_unsigned_shift, unsigned_shift;
983 /* For a shift of less then BITS_PER_WORD, to compute the carry,
984 we must do a logical shift in the opposite direction of the
985 desired shift. */
987 reverse_unsigned_shift = (left_shift ? lshr_optab : ashl_optab);
989 /* For a shift of less than BITS_PER_WORD, to compute the word
990 shifted towards, we need to unsigned shift the orig value of
991 that word. */
993 unsigned_shift = (left_shift ? ashl_optab : lshr_optab);
995 carries = expand_binop (word_mode, reverse_unsigned_shift,
996 outof_input,
997 GEN_INT (BITS_PER_WORD - shift_count),
998 0, unsignedp, next_methods);
1000 if (carries == 0)
1001 inter = 0;
1002 else
1003 inter = expand_binop (word_mode, unsigned_shift, into_input,
1004 op1, 0, unsignedp, next_methods);
1006 if (inter != 0)
1007 inter = expand_binop (word_mode, ior_optab, carries, inter,
1008 into_target, unsignedp, next_methods);
1010 if (inter != 0 && inter != into_target)
1011 emit_move_insn (into_target, inter);
1013 if (inter != 0)
1014 inter = expand_binop (word_mode, binoptab, outof_input,
1015 op1, outof_target, unsignedp, next_methods);
1017 if (inter != 0 && inter != outof_target)
1018 emit_move_insn (outof_target, inter);
1021 insns = get_insns ();
1022 end_sequence ();
1024 if (inter != 0)
1026 if (binoptab->code != UNKNOWN)
1027 equiv_value = gen_rtx_fmt_ee (binoptab->code, mode, op0, op1);
1028 else
1029 equiv_value = 0;
1031 emit_no_conflict_block (insns, target, op0, op1, equiv_value);
1032 return target;
1036 /* Synthesize double word rotates from single word shifts. */
1037 if ((binoptab == rotl_optab || binoptab == rotr_optab)
1038 && class == MODE_INT
1039 && GET_CODE (op1) == CONST_INT
1040 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1041 && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
1042 && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
1044 rtx insns, equiv_value;
1045 rtx into_target, outof_target;
1046 rtx into_input, outof_input;
1047 rtx inter;
1048 int shift_count, left_shift, outof_word;
1050 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1051 won't be accurate, so use a new target. */
1052 if (target == 0 || target == op0 || target == op1)
1053 target = gen_reg_rtx (mode);
1055 start_sequence ();
1057 shift_count = INTVAL (op1);
1059 /* OUTOF_* is the word we are shifting bits away from, and
1060 INTO_* is the word that we are shifting bits towards, thus
1061 they differ depending on the direction of the shift and
1062 WORDS_BIG_ENDIAN. */
1064 left_shift = (binoptab == rotl_optab);
1065 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1067 outof_target = operand_subword (target, outof_word, 1, mode);
1068 into_target = operand_subword (target, 1 - outof_word, 1, mode);
1070 outof_input = operand_subword_force (op0, outof_word, mode);
1071 into_input = operand_subword_force (op0, 1 - outof_word, mode);
1073 if (shift_count == BITS_PER_WORD)
1075 /* This is just a word swap. */
1076 emit_move_insn (outof_target, into_input);
1077 emit_move_insn (into_target, outof_input);
1078 inter = const0_rtx;
1080 else
1082 rtx into_temp1, into_temp2, outof_temp1, outof_temp2;
1083 rtx first_shift_count, second_shift_count;
1084 optab reverse_unsigned_shift, unsigned_shift;
1086 reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1087 ? lshr_optab : ashl_optab);
1089 unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1090 ? ashl_optab : lshr_optab);
1092 if (shift_count > BITS_PER_WORD)
1094 first_shift_count = GEN_INT (shift_count - BITS_PER_WORD);
1095 second_shift_count = GEN_INT (2*BITS_PER_WORD - shift_count);
1097 else
1099 first_shift_count = GEN_INT (BITS_PER_WORD - shift_count);
1100 second_shift_count = GEN_INT (shift_count);
1103 into_temp1 = expand_binop (word_mode, unsigned_shift,
1104 outof_input, first_shift_count,
1105 NULL_RTX, unsignedp, next_methods);
1106 into_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1107 into_input, second_shift_count,
1108 into_target, unsignedp, next_methods);
1110 if (into_temp1 != 0 && into_temp2 != 0)
1111 inter = expand_binop (word_mode, ior_optab, into_temp1, into_temp2,
1112 into_target, unsignedp, next_methods);
1113 else
1114 inter = 0;
1116 if (inter != 0 && inter != into_target)
1117 emit_move_insn (into_target, inter);
1119 outof_temp1 = expand_binop (word_mode, unsigned_shift,
1120 into_input, first_shift_count,
1121 NULL_RTX, unsignedp, next_methods);
1122 outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1123 outof_input, second_shift_count,
1124 outof_target, unsignedp, next_methods);
1126 if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0)
1127 inter = expand_binop (word_mode, ior_optab,
1128 outof_temp1, outof_temp2,
1129 outof_target, unsignedp, next_methods);
1131 if (inter != 0 && inter != outof_target)
1132 emit_move_insn (outof_target, inter);
1135 insns = get_insns ();
1136 end_sequence ();
1138 if (inter != 0)
1140 if (binoptab->code != UNKNOWN)
1141 equiv_value = gen_rtx_fmt_ee (binoptab->code, mode, op0, op1);
1142 else
1143 equiv_value = 0;
1145 /* We can't make this a no conflict block if this is a word swap,
1146 because the word swap case fails if the input and output values
1147 are in the same register. */
1148 if (shift_count != BITS_PER_WORD)
1149 emit_no_conflict_block (insns, target, op0, op1, equiv_value);
1150 else
1151 emit_insns (insns);
1154 return target;
1158 /* These can be done a word at a time by propagating carries. */
1159 if ((binoptab == add_optab || binoptab == sub_optab)
1160 && class == MODE_INT
1161 && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
1162 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
1164 unsigned int i;
1165 rtx carry_tmp = gen_reg_rtx (word_mode);
1166 optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
1167 unsigned int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
1168 rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
1169 rtx xop0, xop1;
1171 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
1172 value is one of those, use it. Otherwise, use 1 since it is the
1173 one easiest to get. */
1174 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
1175 int normalizep = STORE_FLAG_VALUE;
1176 #else
1177 int normalizep = 1;
1178 #endif
1180 /* Prepare the operands. */
1181 xop0 = force_reg (mode, op0);
1182 xop1 = force_reg (mode, op1);
1184 if (target == 0 || GET_CODE (target) != REG
1185 || target == xop0 || target == xop1)
1186 target = gen_reg_rtx (mode);
1188 /* Indicate for flow that the entire target reg is being set. */
1189 if (GET_CODE (target) == REG)
1190 emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
1192 /* Do the actual arithmetic. */
1193 for (i = 0; i < nwords; i++)
1195 int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
1196 rtx target_piece = operand_subword (target, index, 1, mode);
1197 rtx op0_piece = operand_subword_force (xop0, index, mode);
1198 rtx op1_piece = operand_subword_force (xop1, index, mode);
1199 rtx x;
1201 /* Main add/subtract of the input operands. */
1202 x = expand_binop (word_mode, binoptab,
1203 op0_piece, op1_piece,
1204 target_piece, unsignedp, next_methods);
1205 if (x == 0)
1206 break;
1208 if (i + 1 < nwords)
1210 /* Store carry from main add/subtract. */
1211 carry_out = gen_reg_rtx (word_mode);
1212 carry_out = emit_store_flag_force (carry_out,
1213 (binoptab == add_optab
1214 ? LT : GT),
1215 x, op0_piece,
1216 word_mode, 1, normalizep);
1219 if (i > 0)
1221 /* Add/subtract previous carry to main result. */
1222 x = expand_binop (word_mode,
1223 normalizep == 1 ? binoptab : otheroptab,
1224 x, carry_in,
1225 target_piece, 1, next_methods);
1226 if (x == 0)
1227 break;
1228 else if (target_piece != x)
1229 emit_move_insn (target_piece, x);
1231 if (i + 1 < nwords)
1233 /* THIS CODE HAS NOT BEEN TESTED. */
1234 /* Get out carry from adding/subtracting carry in. */
1235 carry_tmp = emit_store_flag_force (carry_tmp,
1236 binoptab == add_optab
1237 ? LT : GT,
1238 x, carry_in,
1239 word_mode, 1, normalizep);
1241 /* Logical-ior the two poss. carry together. */
1242 carry_out = expand_binop (word_mode, ior_optab,
1243 carry_out, carry_tmp,
1244 carry_out, 0, next_methods);
1245 if (carry_out == 0)
1246 break;
1250 carry_in = carry_out;
1253 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
1255 if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1257 rtx temp = emit_move_insn (target, target);
1259 set_unique_reg_note (temp,
1260 REG_EQUAL,
1261 gen_rtx_fmt_ee (binoptab->code, mode,
1262 copy_rtx (xop0),
1263 copy_rtx (xop1)));
1266 return target;
1269 else
1270 delete_insns_since (last);
1273 /* If we want to multiply two two-word values and have normal and widening
1274 multiplies of single-word values, we can do this with three smaller
1275 multiplications. Note that we do not make a REG_NO_CONFLICT block here
1276 because we are not operating on one word at a time.
1278 The multiplication proceeds as follows:
1279 _______________________
1280 [__op0_high_|__op0_low__]
1281 _______________________
1282 * [__op1_high_|__op1_low__]
1283 _______________________________________________
1284 _______________________
1285 (1) [__op0_low__*__op1_low__]
1286 _______________________
1287 (2a) [__op0_low__*__op1_high_]
1288 _______________________
1289 (2b) [__op0_high_*__op1_low__]
1290 _______________________
1291 (3) [__op0_high_*__op1_high_]
1294 This gives a 4-word result. Since we are only interested in the
1295 lower 2 words, partial result (3) and the upper words of (2a) and
1296 (2b) don't need to be calculated. Hence (2a) and (2b) can be
1297 calculated using non-widening multiplication.
1299 (1), however, needs to be calculated with an unsigned widening
1300 multiplication. If this operation is not directly supported we
1301 try using a signed widening multiplication and adjust the result.
1302 This adjustment works as follows:
1304 If both operands are positive then no adjustment is needed.
1306 If the operands have different signs, for example op0_low < 0 and
1307 op1_low >= 0, the instruction treats the most significant bit of
1308 op0_low as a sign bit instead of a bit with significance
1309 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
1310 with 2**BITS_PER_WORD - op0_low, and two's complements the
1311 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
1312 the result.
1314 Similarly, if both operands are negative, we need to add
1315 (op0_low + op1_low) * 2**BITS_PER_WORD.
1317 We use a trick to adjust quickly. We logically shift op0_low right
1318 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
1319 op0_high (op1_high) before it is used to calculate 2b (2a). If no
1320 logical shift exists, we do an arithmetic right shift and subtract
1321 the 0 or -1. */
1323 if (binoptab == smul_optab
1324 && class == MODE_INT
1325 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1326 && smul_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
1327 && add_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
1328 && ((umul_widen_optab->handlers[(int) mode].insn_code
1329 != CODE_FOR_nothing)
1330 || (smul_widen_optab->handlers[(int) mode].insn_code
1331 != CODE_FOR_nothing)))
1333 int low = (WORDS_BIG_ENDIAN ? 1 : 0);
1334 int high = (WORDS_BIG_ENDIAN ? 0 : 1);
1335 rtx op0_high = operand_subword_force (op0, high, mode);
1336 rtx op0_low = operand_subword_force (op0, low, mode);
1337 rtx op1_high = operand_subword_force (op1, high, mode);
1338 rtx op1_low = operand_subword_force (op1, low, mode);
1339 rtx product = 0;
1340 rtx op0_xhigh = NULL_RTX;
1341 rtx op1_xhigh = NULL_RTX;
1343 /* If the target is the same as one of the inputs, don't use it. This
1344 prevents problems with the REG_EQUAL note. */
1345 if (target == op0 || target == op1
1346 || (target != 0 && GET_CODE (target) != REG))
1347 target = 0;
1349 /* Multiply the two lower words to get a double-word product.
1350 If unsigned widening multiplication is available, use that;
1351 otherwise use the signed form and compensate. */
1353 if (umul_widen_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1355 product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
1356 target, 1, OPTAB_DIRECT);
1358 /* If we didn't succeed, delete everything we did so far. */
1359 if (product == 0)
1360 delete_insns_since (last);
1361 else
1362 op0_xhigh = op0_high, op1_xhigh = op1_high;
1365 if (product == 0
1366 && smul_widen_optab->handlers[(int) mode].insn_code
1367 != CODE_FOR_nothing)
1369 rtx wordm1 = GEN_INT (BITS_PER_WORD - 1);
1370 product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
1371 target, 1, OPTAB_DIRECT);
1372 op0_xhigh = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
1373 NULL_RTX, 1, next_methods);
1374 if (op0_xhigh)
1375 op0_xhigh = expand_binop (word_mode, add_optab, op0_high,
1376 op0_xhigh, op0_xhigh, 0, next_methods);
1377 else
1379 op0_xhigh = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
1380 NULL_RTX, 0, next_methods);
1381 if (op0_xhigh)
1382 op0_xhigh = expand_binop (word_mode, sub_optab, op0_high,
1383 op0_xhigh, op0_xhigh, 0,
1384 next_methods);
1387 op1_xhigh = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
1388 NULL_RTX, 1, next_methods);
1389 if (op1_xhigh)
1390 op1_xhigh = expand_binop (word_mode, add_optab, op1_high,
1391 op1_xhigh, op1_xhigh, 0, next_methods);
1392 else
1394 op1_xhigh = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
1395 NULL_RTX, 0, next_methods);
1396 if (op1_xhigh)
1397 op1_xhigh = expand_binop (word_mode, sub_optab, op1_high,
1398 op1_xhigh, op1_xhigh, 0,
1399 next_methods);
1403 /* If we have been able to directly compute the product of the
1404 low-order words of the operands and perform any required adjustments
1405 of the operands, we proceed by trying two more multiplications
1406 and then computing the appropriate sum.
1408 We have checked above that the required addition is provided.
1409 Full-word addition will normally always succeed, especially if
1410 it is provided at all, so we don't worry about its failure. The
1411 multiplication may well fail, however, so we do handle that. */
1413 if (product && op0_xhigh && op1_xhigh)
1415 rtx product_high = operand_subword (product, high, 1, mode);
1416 rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh,
1417 NULL_RTX, 0, OPTAB_DIRECT);
1419 if (temp != 0)
1420 temp = expand_binop (word_mode, add_optab, temp, product_high,
1421 product_high, 0, next_methods);
1423 if (temp != 0 && temp != product_high)
1424 emit_move_insn (product_high, temp);
1426 if (temp != 0)
1427 temp = expand_binop (word_mode, binoptab, op1_low, op0_xhigh,
1428 NULL_RTX, 0, OPTAB_DIRECT);
1430 if (temp != 0)
1431 temp = expand_binop (word_mode, add_optab, temp,
1432 product_high, product_high,
1433 0, next_methods);
1435 if (temp != 0 && temp != product_high)
1436 emit_move_insn (product_high, temp);
1438 if (temp != 0)
1440 if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1442 temp = emit_move_insn (product, product);
1443 set_unique_reg_note (temp,
1444 REG_EQUAL,
1445 gen_rtx_fmt_ee (MULT, mode,
1446 copy_rtx (op0),
1447 copy_rtx (op1)));
1450 return product;
1454 /* If we get here, we couldn't do it for some reason even though we
1455 originally thought we could. Delete anything we've emitted in
1456 trying to do it. */
1458 delete_insns_since (last);
1461 /* We need to open-code the complex type operations: '+, -, * and /' */
1463 /* At this point we allow operations between two similar complex
1464 numbers, and also if one of the operands is not a complex number
1465 but rather of MODE_FLOAT or MODE_INT. However, the caller
1466 must make sure that the MODE of the non-complex operand matches
1467 the SUBMODE of the complex operand. */
1469 if (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
1471 rtx real0 = 0, imag0 = 0;
1472 rtx real1 = 0, imag1 = 0;
1473 rtx realr, imagr, res;
1474 rtx seq;
1475 rtx equiv_value;
1476 int ok = 0;
1478 /* Find the correct mode for the real and imaginary parts */
1479 enum machine_mode submode
1480 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
1481 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
1484 if (submode == BLKmode)
1485 abort ();
1487 if (! target)
1488 target = gen_reg_rtx (mode);
1490 start_sequence ();
1492 realr = gen_realpart (submode, target);
1493 imagr = gen_imagpart (submode, target);
1495 if (GET_MODE (op0) == mode)
1497 real0 = gen_realpart (submode, op0);
1498 imag0 = gen_imagpart (submode, op0);
1500 else
1501 real0 = op0;
1503 if (GET_MODE (op1) == mode)
1505 real1 = gen_realpart (submode, op1);
1506 imag1 = gen_imagpart (submode, op1);
1508 else
1509 real1 = op1;
1511 if (real0 == 0 || real1 == 0 || ! (imag0 != 0|| imag1 != 0))
1512 abort ();
1514 switch (binoptab->code)
1516 case PLUS:
1517 /* (a+ib) + (c+id) = (a+c) + i(b+d) */
1518 case MINUS:
1519 /* (a+ib) - (c+id) = (a-c) + i(b-d) */
1520 res = expand_binop (submode, binoptab, real0, real1,
1521 realr, unsignedp, methods);
1523 if (res == 0)
1524 break;
1525 else if (res != realr)
1526 emit_move_insn (realr, res);
1528 if (imag0 && imag1)
1529 res = expand_binop (submode, binoptab, imag0, imag1,
1530 imagr, unsignedp, methods);
1531 else if (imag0)
1532 res = imag0;
1533 else if (binoptab->code == MINUS)
1534 res = expand_unop (submode,
1535 binoptab == subv_optab ? negv_optab : neg_optab,
1536 imag1, imagr, unsignedp);
1537 else
1538 res = imag1;
1540 if (res == 0)
1541 break;
1542 else if (res != imagr)
1543 emit_move_insn (imagr, res);
1545 ok = 1;
1546 break;
1548 case MULT:
1549 /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */
1551 if (imag0 && imag1)
1553 rtx temp1, temp2;
1555 /* Don't fetch these from memory more than once. */
1556 real0 = force_reg (submode, real0);
1557 real1 = force_reg (submode, real1);
1558 imag0 = force_reg (submode, imag0);
1559 imag1 = force_reg (submode, imag1);
1561 temp1 = expand_binop (submode, binoptab, real0, real1, NULL_RTX,
1562 unsignedp, methods);
1564 temp2 = expand_binop (submode, binoptab, imag0, imag1, NULL_RTX,
1565 unsignedp, methods);
1567 if (temp1 == 0 || temp2 == 0)
1568 break;
1570 res = (expand_binop
1571 (submode,
1572 binoptab == smulv_optab ? subv_optab : sub_optab,
1573 temp1, temp2, realr, unsignedp, methods));
1575 if (res == 0)
1576 break;
1577 else if (res != realr)
1578 emit_move_insn (realr, res);
1580 temp1 = expand_binop (submode, binoptab, real0, imag1,
1581 NULL_RTX, unsignedp, methods);
1583 temp2 = expand_binop (submode, binoptab, real1, imag0,
1584 NULL_RTX, unsignedp, methods);
1586 if (temp1 == 0 || temp2 == 0)
1587 break;
1589 res = (expand_binop
1590 (submode,
1591 binoptab == smulv_optab ? addv_optab : add_optab,
1592 temp1, temp2, imagr, unsignedp, methods));
1594 if (res == 0)
1595 break;
1596 else if (res != imagr)
1597 emit_move_insn (imagr, res);
1599 ok = 1;
1601 else
1603 /* Don't fetch these from memory more than once. */
1604 real0 = force_reg (submode, real0);
1605 real1 = force_reg (submode, real1);
1607 res = expand_binop (submode, binoptab, real0, real1,
1608 realr, unsignedp, methods);
1609 if (res == 0)
1610 break;
1611 else if (res != realr)
1612 emit_move_insn (realr, res);
1614 if (imag0 != 0)
1615 res = expand_binop (submode, binoptab,
1616 real1, imag0, imagr, unsignedp, methods);
1617 else
1618 res = expand_binop (submode, binoptab,
1619 real0, imag1, imagr, unsignedp, methods);
1621 if (res == 0)
1622 break;
1623 else if (res != imagr)
1624 emit_move_insn (imagr, res);
1626 ok = 1;
1628 break;
1630 case DIV:
1631 /* (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) */
1633 if (imag1 == 0)
1635 /* (a+ib) / (c+i0) = (a/c) + i(b/c) */
1637 /* Don't fetch these from memory more than once. */
1638 real1 = force_reg (submode, real1);
1640 /* Simply divide the real and imaginary parts by `c' */
1641 if (class == MODE_COMPLEX_FLOAT)
1642 res = expand_binop (submode, binoptab, real0, real1,
1643 realr, unsignedp, methods);
1644 else
1645 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
1646 real0, real1, realr, unsignedp);
1648 if (res == 0)
1649 break;
1650 else if (res != realr)
1651 emit_move_insn (realr, res);
1653 if (class == MODE_COMPLEX_FLOAT)
1654 res = expand_binop (submode, binoptab, imag0, real1,
1655 imagr, unsignedp, methods);
1656 else
1657 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
1658 imag0, real1, imagr, unsignedp);
1660 if (res == 0)
1661 break;
1662 else if (res != imagr)
1663 emit_move_insn (imagr, res);
1665 ok = 1;
1667 else
1669 switch (flag_complex_divide_method)
1671 case 0:
1672 ok = expand_cmplxdiv_straight (real0, real1, imag0, imag1,
1673 realr, imagr, submode,
1674 unsignedp, methods,
1675 class, binoptab);
1676 break;
1678 case 1:
1679 ok = expand_cmplxdiv_wide (real0, real1, imag0, imag1,
1680 realr, imagr, submode,
1681 unsignedp, methods,
1682 class, binoptab);
1683 break;
1685 default:
1686 abort ();
1689 break;
1691 default:
1692 abort ();
1695 seq = get_insns ();
1696 end_sequence ();
1698 if (ok)
1700 if (binoptab->code != UNKNOWN)
1701 equiv_value
1702 = gen_rtx_fmt_ee (binoptab->code, mode,
1703 copy_rtx (op0), copy_rtx (op1));
1704 else
1705 equiv_value = 0;
1707 emit_no_conflict_block (seq, target, op0, op1, equiv_value);
1709 return target;
1713 /* It can't be open-coded in this mode.
1714 Use a library call if one is available and caller says that's ok. */
1716 if (binoptab->handlers[(int) mode].libfunc
1717 && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
1719 rtx insns;
1720 rtx op1x = op1;
1721 enum machine_mode op1_mode = mode;
1722 rtx value;
1724 start_sequence ();
1726 if (shift_op)
1728 op1_mode = word_mode;
1729 /* Specify unsigned here,
1730 since negative shift counts are meaningless. */
1731 op1x = convert_to_mode (word_mode, op1, 1);
1734 if (GET_MODE (op0) != VOIDmode
1735 && GET_MODE (op0) != mode)
1736 op0 = convert_to_mode (mode, op0, unsignedp);
1738 /* Pass 1 for NO_QUEUE so we don't lose any increments
1739 if the libcall is cse'd or moved. */
1740 value = emit_library_call_value (binoptab->handlers[(int) mode].libfunc,
1741 NULL_RTX, LCT_CONST, mode, 2,
1742 op0, mode, op1x, op1_mode);
1744 insns = get_insns ();
1745 end_sequence ();
1747 target = gen_reg_rtx (mode);
1748 emit_libcall_block (insns, target, value,
1749 gen_rtx_fmt_ee (binoptab->code, mode, op0, op1));
1751 return target;
1754 delete_insns_since (last);
1756 /* It can't be done in this mode. Can we do it in a wider mode? */
1758 if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
1759 || methods == OPTAB_MUST_WIDEN))
1761 /* Caller says, don't even try. */
1762 delete_insns_since (entry_last);
1763 return 0;
1766 /* Compute the value of METHODS to pass to recursive calls.
1767 Don't allow widening to be tried recursively. */
1769 methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
1771 /* Look for a wider mode of the same class for which it appears we can do
1772 the operation. */
1774 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1776 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1777 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1779 if ((binoptab->handlers[(int) wider_mode].insn_code
1780 != CODE_FOR_nothing)
1781 || (methods == OPTAB_LIB
1782 && binoptab->handlers[(int) wider_mode].libfunc))
1784 rtx xop0 = op0, xop1 = op1;
1785 int no_extend = 0;
1787 /* For certain integer operations, we need not actually extend
1788 the narrow operands, as long as we will truncate
1789 the results to the same narrowness. */
1791 if ((binoptab == ior_optab || binoptab == and_optab
1792 || binoptab == xor_optab
1793 || binoptab == add_optab || binoptab == sub_optab
1794 || binoptab == smul_optab || binoptab == ashl_optab)
1795 && class == MODE_INT)
1796 no_extend = 1;
1798 xop0 = widen_operand (xop0, wider_mode, mode,
1799 unsignedp, no_extend);
1801 /* The second operand of a shift must always be extended. */
1802 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
1803 no_extend && binoptab != ashl_optab);
1805 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
1806 unsignedp, methods);
1807 if (temp)
1809 if (class != MODE_INT)
1811 if (target == 0)
1812 target = gen_reg_rtx (mode);
1813 convert_move (target, temp, 0);
1814 return target;
1816 else
1817 return gen_lowpart (mode, temp);
1819 else
1820 delete_insns_since (last);
1825 delete_insns_since (entry_last);
1826 return 0;
1829 /* Expand a binary operator which has both signed and unsigned forms.
1830 UOPTAB is the optab for unsigned operations, and SOPTAB is for
1831 signed operations.
1833 If we widen unsigned operands, we may use a signed wider operation instead
1834 of an unsigned wider operation, since the result would be the same. */
1837 sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods)
1838 enum machine_mode mode;
1839 optab uoptab, soptab;
1840 rtx op0, op1, target;
1841 int unsignedp;
1842 enum optab_methods methods;
1844 register rtx temp;
1845 optab direct_optab = unsignedp ? uoptab : soptab;
1846 struct optab wide_soptab;
1848 /* Do it without widening, if possible. */
1849 temp = expand_binop (mode, direct_optab, op0, op1, target,
1850 unsignedp, OPTAB_DIRECT);
1851 if (temp || methods == OPTAB_DIRECT)
1852 return temp;
1854 /* Try widening to a signed int. Make a fake signed optab that
1855 hides any signed insn for direct use. */
1856 wide_soptab = *soptab;
1857 wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing;
1858 wide_soptab.handlers[(int) mode].libfunc = 0;
1860 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
1861 unsignedp, OPTAB_WIDEN);
1863 /* For unsigned operands, try widening to an unsigned int. */
1864 if (temp == 0 && unsignedp)
1865 temp = expand_binop (mode, uoptab, op0, op1, target,
1866 unsignedp, OPTAB_WIDEN);
1867 if (temp || methods == OPTAB_WIDEN)
1868 return temp;
1870 /* Use the right width lib call if that exists. */
1871 temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
1872 if (temp || methods == OPTAB_LIB)
1873 return temp;
1875 /* Must widen and use a lib call, use either signed or unsigned. */
1876 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
1877 unsignedp, methods);
1878 if (temp != 0)
1879 return temp;
1880 if (unsignedp)
1881 return expand_binop (mode, uoptab, op0, op1, target,
1882 unsignedp, methods);
1883 return 0;
1886 /* Generate code to perform an operation specified by BINOPTAB
1887 on operands OP0 and OP1, with two results to TARG1 and TARG2.
1888 We assume that the order of the operands for the instruction
1889 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
1890 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
1892 Either TARG0 or TARG1 may be zero, but what that means is that
1893 the result is not actually wanted. We will generate it into
1894 a dummy pseudo-reg and discard it. They may not both be zero.
1896 Returns 1 if this operation can be performed; 0 if not. */
1899 expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
1900 optab binoptab;
1901 rtx op0, op1;
1902 rtx targ0, targ1;
1903 int unsignedp;
1905 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
1906 enum mode_class class;
1907 enum machine_mode wider_mode;
1908 rtx entry_last = get_last_insn ();
1909 rtx last;
1911 class = GET_MODE_CLASS (mode);
1913 op0 = protect_from_queue (op0, 0);
1914 op1 = protect_from_queue (op1, 0);
1916 if (flag_force_mem)
1918 op0 = force_not_mem (op0);
1919 op1 = force_not_mem (op1);
1922 /* If we are inside an appropriately-short loop and one operand is an
1923 expensive constant, force it into a register. */
1924 if (CONSTANT_P (op0) && preserve_subexpressions_p ()
1925 && rtx_cost (op0, binoptab->code) > COSTS_N_INSNS (1))
1926 op0 = force_reg (mode, op0);
1928 if (CONSTANT_P (op1) && preserve_subexpressions_p ()
1929 && rtx_cost (op1, binoptab->code) > COSTS_N_INSNS (1))
1930 op1 = force_reg (mode, op1);
1932 if (targ0)
1933 targ0 = protect_from_queue (targ0, 1);
1934 else
1935 targ0 = gen_reg_rtx (mode);
1936 if (targ1)
1937 targ1 = protect_from_queue (targ1, 1);
1938 else
1939 targ1 = gen_reg_rtx (mode);
1941 /* Record where to go back to if we fail. */
1942 last = get_last_insn ();
1944 if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1946 int icode = (int) binoptab->handlers[(int) mode].insn_code;
1947 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
1948 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
1949 rtx pat;
1950 rtx xop0 = op0, xop1 = op1;
1952 /* In case this insn wants input operands in modes different from the
1953 result, convert the operands. */
1954 if (GET_MODE (op0) != VOIDmode && GET_MODE (op0) != mode0)
1955 xop0 = convert_to_mode (mode0, xop0, unsignedp);
1957 if (GET_MODE (op1) != VOIDmode && GET_MODE (op1) != mode1)
1958 xop1 = convert_to_mode (mode1, xop1, unsignedp);
1960 /* Now, if insn doesn't accept these operands, put them into pseudos. */
1961 if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0))
1962 xop0 = copy_to_mode_reg (mode0, xop0);
1964 if (! (*insn_data[icode].operand[2].predicate) (xop1, mode1))
1965 xop1 = copy_to_mode_reg (mode1, xop1);
1967 /* We could handle this, but we should always be called with a pseudo
1968 for our targets and all insns should take them as outputs. */
1969 if (! (*insn_data[icode].operand[0].predicate) (targ0, mode)
1970 || ! (*insn_data[icode].operand[3].predicate) (targ1, mode))
1971 abort ();
1973 pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
1974 if (pat)
1976 emit_insn (pat);
1977 return 1;
1979 else
1980 delete_insns_since (last);
1983 /* It can't be done in this mode. Can we do it in a wider mode? */
1985 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1987 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1988 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1990 if (binoptab->handlers[(int) wider_mode].insn_code
1991 != CODE_FOR_nothing)
1993 register rtx t0 = gen_reg_rtx (wider_mode);
1994 register rtx t1 = gen_reg_rtx (wider_mode);
1996 if (expand_twoval_binop (binoptab,
1997 convert_modes (wider_mode, mode, op0,
1998 unsignedp),
1999 convert_modes (wider_mode, mode, op1,
2000 unsignedp),
2001 t0, t1, unsignedp))
2003 convert_move (targ0, t0, unsignedp);
2004 convert_move (targ1, t1, unsignedp);
2005 return 1;
2007 else
2008 delete_insns_since (last);
2013 delete_insns_since (entry_last);
2014 return 0;
2017 /* Generate code to perform an operation specified by UNOPTAB
2018 on operand OP0, with result having machine-mode MODE.
2020 UNSIGNEDP is for the case where we have to widen the operands
2021 to perform the operation. It says to use zero-extension.
2023 If TARGET is nonzero, the value
2024 is generated there, if it is convenient to do so.
2025 In all cases an rtx is returned for the locus of the value;
2026 this may or may not be TARGET. */
2029 expand_unop (mode, unoptab, op0, target, unsignedp)
2030 enum machine_mode mode;
2031 optab unoptab;
2032 rtx op0;
2033 rtx target;
2034 int unsignedp;
2036 enum mode_class class;
2037 enum machine_mode wider_mode;
2038 register rtx temp;
2039 rtx last = get_last_insn ();
2040 rtx pat;
2042 class = GET_MODE_CLASS (mode);
2044 op0 = protect_from_queue (op0, 0);
2046 if (flag_force_mem)
2048 op0 = force_not_mem (op0);
2051 if (target)
2052 target = protect_from_queue (target, 1);
2054 if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2056 int icode = (int) unoptab->handlers[(int) mode].insn_code;
2057 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
2058 rtx xop0 = op0;
2060 if (target)
2061 temp = target;
2062 else
2063 temp = gen_reg_rtx (mode);
2065 if (GET_MODE (xop0) != VOIDmode
2066 && GET_MODE (xop0) != mode0)
2067 xop0 = convert_to_mode (mode0, xop0, unsignedp);
2069 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
2071 if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0))
2072 xop0 = copy_to_mode_reg (mode0, xop0);
2074 if (! (*insn_data[icode].operand[0].predicate) (temp, mode))
2075 temp = gen_reg_rtx (mode);
2077 pat = GEN_FCN (icode) (temp, xop0);
2078 if (pat)
2080 if (GET_CODE (pat) == SEQUENCE
2081 && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
2083 delete_insns_since (last);
2084 return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
2087 emit_insn (pat);
2089 return temp;
2091 else
2092 delete_insns_since (last);
2095 /* It can't be done in this mode. Can we open-code it in a wider mode? */
2097 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
2098 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2099 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2101 if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
2103 rtx xop0 = op0;
2105 /* For certain operations, we need not actually extend
2106 the narrow operand, as long as we will truncate the
2107 results to the same narrowness. */
2109 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
2110 (unoptab == neg_optab
2111 || unoptab == one_cmpl_optab)
2112 && class == MODE_INT);
2114 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
2115 unsignedp);
2117 if (temp)
2119 if (class != MODE_INT)
2121 if (target == 0)
2122 target = gen_reg_rtx (mode);
2123 convert_move (target, temp, 0);
2124 return target;
2126 else
2127 return gen_lowpart (mode, temp);
2129 else
2130 delete_insns_since (last);
2134 /* These can be done a word at a time. */
2135 if (unoptab == one_cmpl_optab
2136 && class == MODE_INT
2137 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
2138 && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
2140 unsigned int i;
2141 rtx insns;
2143 if (target == 0 || target == op0)
2144 target = gen_reg_rtx (mode);
2146 start_sequence ();
2148 /* Do the actual arithmetic. */
2149 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
2151 rtx target_piece = operand_subword (target, i, 1, mode);
2152 rtx x = expand_unop (word_mode, unoptab,
2153 operand_subword_force (op0, i, mode),
2154 target_piece, unsignedp);
2155 if (target_piece != x)
2156 emit_move_insn (target_piece, x);
2159 insns = get_insns ();
2160 end_sequence ();
2162 emit_no_conflict_block (insns, target, op0, NULL_RTX,
2163 gen_rtx_fmt_e (unoptab->code, mode,
2164 copy_rtx (op0)));
2165 return target;
2168 /* Open-code the complex negation operation. */
2169 else if (unoptab->code == NEG
2170 && (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT))
2172 rtx target_piece;
2173 rtx x;
2174 rtx seq;
2176 /* Find the correct mode for the real and imaginary parts */
2177 enum machine_mode submode
2178 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
2179 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
2182 if (submode == BLKmode)
2183 abort ();
2185 if (target == 0)
2186 target = gen_reg_rtx (mode);
2188 start_sequence ();
2190 target_piece = gen_imagpart (submode, target);
2191 x = expand_unop (submode, unoptab,
2192 gen_imagpart (submode, op0),
2193 target_piece, unsignedp);
2194 if (target_piece != x)
2195 emit_move_insn (target_piece, x);
2197 target_piece = gen_realpart (submode, target);
2198 x = expand_unop (submode, unoptab,
2199 gen_realpart (submode, op0),
2200 target_piece, unsignedp);
2201 if (target_piece != x)
2202 emit_move_insn (target_piece, x);
2204 seq = get_insns ();
2205 end_sequence ();
2207 emit_no_conflict_block (seq, target, op0, 0,
2208 gen_rtx_fmt_e (unoptab->code, mode,
2209 copy_rtx (op0)));
2210 return target;
2213 /* Now try a library call in this mode. */
2214 if (unoptab->handlers[(int) mode].libfunc)
2216 rtx insns;
2217 rtx value;
2219 start_sequence ();
2221 /* Pass 1 for NO_QUEUE so we don't lose any increments
2222 if the libcall is cse'd or moved. */
2223 value = emit_library_call_value (unoptab->handlers[(int) mode].libfunc,
2224 NULL_RTX, LCT_CONST, mode, 1, op0, mode);
2225 insns = get_insns ();
2226 end_sequence ();
2228 target = gen_reg_rtx (mode);
2229 emit_libcall_block (insns, target, value,
2230 gen_rtx_fmt_e (unoptab->code, mode, op0));
2232 return target;
2235 /* It can't be done in this mode. Can we do it in a wider mode? */
2237 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
2239 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2240 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2242 if ((unoptab->handlers[(int) wider_mode].insn_code
2243 != CODE_FOR_nothing)
2244 || unoptab->handlers[(int) wider_mode].libfunc)
2246 rtx xop0 = op0;
2248 /* For certain operations, we need not actually extend
2249 the narrow operand, as long as we will truncate the
2250 results to the same narrowness. */
2252 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
2253 (unoptab == neg_optab
2254 || unoptab == one_cmpl_optab)
2255 && class == MODE_INT);
2257 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
2258 unsignedp);
2260 if (temp)
2262 if (class != MODE_INT)
2264 if (target == 0)
2265 target = gen_reg_rtx (mode);
2266 convert_move (target, temp, 0);
2267 return target;
2269 else
2270 return gen_lowpart (mode, temp);
2272 else
2273 delete_insns_since (last);
2278 /* If there is no negate operation, try doing a subtract from zero.
2279 The US Software GOFAST library needs this. */
2280 if (unoptab->code == NEG)
2282 rtx temp;
2283 temp = expand_binop (mode,
2284 unoptab == negv_optab ? subv_optab : sub_optab,
2285 CONST0_RTX (mode), op0,
2286 target, unsignedp, OPTAB_LIB_WIDEN);
2287 if (temp)
2288 return temp;
2291 return 0;
2294 /* Emit code to compute the absolute value of OP0, with result to
2295 TARGET if convenient. (TARGET may be 0.) The return value says
2296 where the result actually is to be found.
2298 MODE is the mode of the operand; the mode of the result is
2299 different but can be deduced from MODE.
2304 expand_abs (mode, op0, target, result_unsignedp, safe)
2305 enum machine_mode mode;
2306 rtx op0;
2307 rtx target;
2308 int result_unsignedp;
2309 int safe;
2311 rtx temp, op1;
2313 if (! flag_trapv)
2314 result_unsignedp = 1;
2316 /* First try to do it with a special abs instruction. */
2317 temp = expand_unop (mode, result_unsignedp ? abs_optab : absv_optab,
2318 op0, target, 0);
2319 if (temp != 0)
2320 return temp;
2322 /* If we have a MAX insn, we can do this as MAX (x, -x). */
2323 if (smax_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2325 rtx last = get_last_insn ();
2327 temp = expand_unop (mode, neg_optab, op0, NULL_RTX, 0);
2328 if (temp != 0)
2329 temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
2330 OPTAB_WIDEN);
2332 if (temp != 0)
2333 return temp;
2335 delete_insns_since (last);
2338 /* If this machine has expensive jumps, we can do integer absolute
2339 value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
2340 where W is the width of MODE. */
2342 if (GET_MODE_CLASS (mode) == MODE_INT && BRANCH_COST >= 2)
2344 rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
2345 size_int (GET_MODE_BITSIZE (mode) - 1),
2346 NULL_RTX, 0);
2348 temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
2349 OPTAB_LIB_WIDEN);
2350 if (temp != 0)
2351 temp = expand_binop (mode, result_unsignedp ? sub_optab : subv_optab,
2352 temp, extended, target, 0, OPTAB_LIB_WIDEN);
2354 if (temp != 0)
2355 return temp;
2358 /* If that does not win, use conditional jump and negate. */
2360 /* It is safe to use the target if it is the same
2361 as the source if this is also a pseudo register */
2362 if (op0 == target && GET_CODE (op0) == REG
2363 && REGNO (op0) >= FIRST_PSEUDO_REGISTER)
2364 safe = 1;
2366 op1 = gen_label_rtx ();
2367 if (target == 0 || ! safe
2368 || GET_MODE (target) != mode
2369 || (GET_CODE (target) == MEM && MEM_VOLATILE_P (target))
2370 || (GET_CODE (target) == REG
2371 && REGNO (target) < FIRST_PSEUDO_REGISTER))
2372 target = gen_reg_rtx (mode);
2374 emit_move_insn (target, op0);
2375 NO_DEFER_POP;
2377 /* If this mode is an integer too wide to compare properly,
2378 compare word by word. Rely on CSE to optimize constant cases. */
2379 if (GET_MODE_CLASS (mode) == MODE_INT
2380 && ! can_compare_p (GE, mode, ccp_jump))
2381 do_jump_by_parts_greater_rtx (mode, 0, target, const0_rtx,
2382 NULL_RTX, op1);
2383 else
2384 do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
2385 NULL_RTX, 0, NULL_RTX, op1);
2387 op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
2388 target, target, 0);
2389 if (op0 != target)
2390 emit_move_insn (target, op0);
2391 emit_label (op1);
2392 OK_DEFER_POP;
2393 return target;
2396 /* Emit code to compute the absolute value of OP0, with result to
2397 TARGET if convenient. (TARGET may be 0.) The return value says
2398 where the result actually is to be found.
2400 MODE is the mode of the operand; the mode of the result is
2401 different but can be deduced from MODE.
2403 UNSIGNEDP is relevant for complex integer modes. */
2406 expand_complex_abs (mode, op0, target, unsignedp)
2407 enum machine_mode mode;
2408 rtx op0;
2409 rtx target;
2410 int unsignedp;
2412 enum mode_class class = GET_MODE_CLASS (mode);
2413 enum machine_mode wider_mode;
2414 register rtx temp;
2415 rtx entry_last = get_last_insn ();
2416 rtx last;
2417 rtx pat;
2418 optab this_abs_optab;
2420 /* Find the correct mode for the real and imaginary parts. */
2421 enum machine_mode submode
2422 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
2423 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
2426 if (submode == BLKmode)
2427 abort ();
2429 op0 = protect_from_queue (op0, 0);
2431 if (flag_force_mem)
2433 op0 = force_not_mem (op0);
2436 last = get_last_insn ();
2438 if (target)
2439 target = protect_from_queue (target, 1);
2441 this_abs_optab = ! unsignedp && flag_trapv
2442 && (GET_MODE_CLASS(mode) == MODE_INT)
2443 ? absv_optab : abs_optab;
2445 if (this_abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2447 int icode = (int) this_abs_optab->handlers[(int) mode].insn_code;
2448 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
2449 rtx xop0 = op0;
2451 if (target)
2452 temp = target;
2453 else
2454 temp = gen_reg_rtx (submode);
2456 if (GET_MODE (xop0) != VOIDmode
2457 && GET_MODE (xop0) != mode0)
2458 xop0 = convert_to_mode (mode0, xop0, unsignedp);
2460 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
2462 if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0))
2463 xop0 = copy_to_mode_reg (mode0, xop0);
2465 if (! (*insn_data[icode].operand[0].predicate) (temp, submode))
2466 temp = gen_reg_rtx (submode);
2468 pat = GEN_FCN (icode) (temp, xop0);
2469 if (pat)
2471 if (GET_CODE (pat) == SEQUENCE
2472 && ! add_equal_note (pat, temp, this_abs_optab->code, xop0,
2473 NULL_RTX))
2475 delete_insns_since (last);
2476 return expand_unop (mode, this_abs_optab, op0, NULL_RTX,
2477 unsignedp);
2480 emit_insn (pat);
2482 return temp;
2484 else
2485 delete_insns_since (last);
2488 /* It can't be done in this mode. Can we open-code it in a wider mode? */
2490 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2491 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2493 if (this_abs_optab->handlers[(int) wider_mode].insn_code
2494 != CODE_FOR_nothing)
2496 rtx xop0 = op0;
2498 xop0 = convert_modes (wider_mode, mode, xop0, unsignedp);
2499 temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
2501 if (temp)
2503 if (class != MODE_COMPLEX_INT)
2505 if (target == 0)
2506 target = gen_reg_rtx (submode);
2507 convert_move (target, temp, 0);
2508 return target;
2510 else
2511 return gen_lowpart (submode, temp);
2513 else
2514 delete_insns_since (last);
2518 /* Open-code the complex absolute-value operation
2519 if we can open-code sqrt. Otherwise it's not worth while. */
2520 if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing
2521 && ! flag_trapv)
2523 rtx real, imag, total;
2525 real = gen_realpart (submode, op0);
2526 imag = gen_imagpart (submode, op0);
2528 /* Square both parts. */
2529 real = expand_mult (submode, real, real, NULL_RTX, 0);
2530 imag = expand_mult (submode, imag, imag, NULL_RTX, 0);
2532 /* Sum the parts. */
2533 total = expand_binop (submode, add_optab, real, imag, NULL_RTX,
2534 0, OPTAB_LIB_WIDEN);
2536 /* Get sqrt in TARGET. Set TARGET to where the result is. */
2537 target = expand_unop (submode, sqrt_optab, total, target, 0);
2538 if (target == 0)
2539 delete_insns_since (last);
2540 else
2541 return target;
2544 /* Now try a library call in this mode. */
2545 if (this_abs_optab->handlers[(int) mode].libfunc)
2547 rtx insns;
2548 rtx value;
2550 start_sequence ();
2552 /* Pass 1 for NO_QUEUE so we don't lose any increments
2553 if the libcall is cse'd or moved. */
2554 value = emit_library_call_value (abs_optab->handlers[(int) mode].libfunc,
2555 NULL_RTX, LCT_CONST, submode, 1, op0, mode);
2556 insns = get_insns ();
2557 end_sequence ();
2559 target = gen_reg_rtx (submode);
2560 emit_libcall_block (insns, target, value,
2561 gen_rtx_fmt_e (this_abs_optab->code, mode, op0));
2563 return target;
2566 /* It can't be done in this mode. Can we do it in a wider mode? */
2568 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2569 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2571 if ((this_abs_optab->handlers[(int) wider_mode].insn_code
2572 != CODE_FOR_nothing)
2573 || this_abs_optab->handlers[(int) wider_mode].libfunc)
2575 rtx xop0 = op0;
2577 xop0 = convert_modes (wider_mode, mode, xop0, unsignedp);
2579 temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
2581 if (temp)
2583 if (class != MODE_COMPLEX_INT)
2585 if (target == 0)
2586 target = gen_reg_rtx (submode);
2587 convert_move (target, temp, 0);
2588 return target;
2590 else
2591 return gen_lowpart (submode, temp);
2593 else
2594 delete_insns_since (last);
2598 delete_insns_since (entry_last);
2599 return 0;
2602 /* Generate an instruction whose insn-code is INSN_CODE,
2603 with two operands: an output TARGET and an input OP0.
2604 TARGET *must* be nonzero, and the output is always stored there.
2605 CODE is an rtx code such that (CODE OP0) is an rtx that describes
2606 the value that is stored into TARGET. */
2608 void
2609 emit_unop_insn (icode, target, op0, code)
2610 int icode;
2611 rtx target;
2612 rtx op0;
2613 enum rtx_code code;
2615 register rtx temp;
2616 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
2617 rtx pat;
2619 temp = target = protect_from_queue (target, 1);
2621 op0 = protect_from_queue (op0, 0);
2623 /* Sign and zero extension from memory is often done specially on
2624 RISC machines, so forcing into a register here can pessimize
2625 code. */
2626 if (flag_force_mem && code != SIGN_EXTEND && code != ZERO_EXTEND)
2627 op0 = force_not_mem (op0);
2629 /* Now, if insn does not accept our operands, put them into pseudos. */
2631 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
2632 op0 = copy_to_mode_reg (mode0, op0);
2634 if (! (*insn_data[icode].operand[0].predicate) (temp, GET_MODE (temp))
2635 || (flag_force_mem && GET_CODE (temp) == MEM))
2636 temp = gen_reg_rtx (GET_MODE (temp));
2638 pat = GEN_FCN (icode) (temp, op0);
2640 if (GET_CODE (pat) == SEQUENCE && code != UNKNOWN)
2641 add_equal_note (pat, temp, code, op0, NULL_RTX);
2643 emit_insn (pat);
2645 if (temp != target)
2646 emit_move_insn (target, temp);
2649 /* Emit code to perform a series of operations on a multi-word quantity, one
2650 word at a time.
2652 Such a block is preceded by a CLOBBER of the output, consists of multiple
2653 insns, each setting one word of the output, and followed by a SET copying
2654 the output to itself.
2656 Each of the insns setting words of the output receives a REG_NO_CONFLICT
2657 note indicating that it doesn't conflict with the (also multi-word)
2658 inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
2659 notes.
2661 INSNS is a block of code generated to perform the operation, not including
2662 the CLOBBER and final copy. All insns that compute intermediate values
2663 are first emitted, followed by the block as described above.
2665 TARGET, OP0, and OP1 are the output and inputs of the operations,
2666 respectively. OP1 may be zero for a unary operation.
2668 EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
2669 on the last insn.
2671 If TARGET is not a register, INSNS is simply emitted with no special
2672 processing. Likewise if anything in INSNS is not an INSN or if
2673 there is a libcall block inside INSNS.
2675 The final insn emitted is returned. */
2678 emit_no_conflict_block (insns, target, op0, op1, equiv)
2679 rtx insns;
2680 rtx target;
2681 rtx op0, op1;
2682 rtx equiv;
2684 rtx prev, next, first, last, insn;
2686 if (GET_CODE (target) != REG || reload_in_progress)
2687 return emit_insns (insns);
2688 else
2689 for (insn = insns; insn; insn = NEXT_INSN (insn))
2690 if (GET_CODE (insn) != INSN
2691 || find_reg_note (insn, REG_LIBCALL, NULL_RTX))
2692 return emit_insns (insns);
2694 /* First emit all insns that do not store into words of the output and remove
2695 these from the list. */
2696 for (insn = insns; insn; insn = next)
2698 rtx set = 0;
2699 int i;
2701 next = NEXT_INSN (insn);
2703 if (GET_CODE (PATTERN (insn)) == SET || GET_CODE (PATTERN (insn)) == USE
2704 || GET_CODE (PATTERN (insn)) == CLOBBER)
2705 set = PATTERN (insn);
2706 else if (GET_CODE (PATTERN (insn)) == PARALLEL)
2708 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
2709 if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
2711 set = XVECEXP (PATTERN (insn), 0, i);
2712 break;
2716 if (set == 0)
2717 abort ();
2719 if (! reg_overlap_mentioned_p (target, SET_DEST (set)))
2721 if (PREV_INSN (insn))
2722 NEXT_INSN (PREV_INSN (insn)) = next;
2723 else
2724 insns = next;
2726 if (next)
2727 PREV_INSN (next) = PREV_INSN (insn);
2729 add_insn (insn);
2733 prev = get_last_insn ();
2735 /* Now write the CLOBBER of the output, followed by the setting of each
2736 of the words, followed by the final copy. */
2737 if (target != op0 && target != op1)
2738 emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
2740 for (insn = insns; insn; insn = next)
2742 next = NEXT_INSN (insn);
2743 add_insn (insn);
2745 if (op1 && GET_CODE (op1) == REG)
2746 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op1,
2747 REG_NOTES (insn));
2749 if (op0 && GET_CODE (op0) == REG)
2750 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op0,
2751 REG_NOTES (insn));
2754 if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
2755 != CODE_FOR_nothing)
2757 last = emit_move_insn (target, target);
2758 if (equiv)
2759 set_unique_reg_note (last, REG_EQUAL, equiv);
2761 else
2763 last = get_last_insn ();
2765 /* Remove any existing REG_EQUAL note from "last", or else it will
2766 be mistaken for a note referring to the full contents of the
2767 alleged libcall value when found together with the REG_RETVAL
2768 note added below. An existing note can come from an insn
2769 expansion at "last". */
2770 remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
2773 if (prev == 0)
2774 first = get_insns ();
2775 else
2776 first = NEXT_INSN (prev);
2778 /* Encapsulate the block so it gets manipulated as a unit. */
2779 REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
2780 REG_NOTES (first));
2781 REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2783 return last;
2786 /* Emit code to make a call to a constant function or a library call.
2788 INSNS is a list containing all insns emitted in the call.
2789 These insns leave the result in RESULT. Our block is to copy RESULT
2790 to TARGET, which is logically equivalent to EQUIV.
2792 We first emit any insns that set a pseudo on the assumption that these are
2793 loading constants into registers; doing so allows them to be safely cse'ed
2794 between blocks. Then we emit all the other insns in the block, followed by
2795 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
2796 note with an operand of EQUIV.
2798 Moving assignments to pseudos outside of the block is done to improve
2799 the generated code, but is not required to generate correct code,
2800 hence being unable to move an assignment is not grounds for not making
2801 a libcall block. There are two reasons why it is safe to leave these
2802 insns inside the block: First, we know that these pseudos cannot be
2803 used in generated RTL outside the block since they are created for
2804 temporary purposes within the block. Second, CSE will not record the
2805 values of anything set inside a libcall block, so we know they must
2806 be dead at the end of the block.
2808 Except for the first group of insns (the ones setting pseudos), the
2809 block is delimited by REG_RETVAL and REG_LIBCALL notes. */
2811 void
2812 emit_libcall_block (insns, target, result, equiv)
2813 rtx insns;
2814 rtx target;
2815 rtx result;
2816 rtx equiv;
2818 rtx final_dest = target;
2819 rtx prev, next, first, last, insn;
2821 /* If this is a reg with REG_USERVAR_P set, then it could possibly turn
2822 into a MEM later. Protect the libcall block from this change. */
2823 if (! REG_P (target) || REG_USERVAR_P (target))
2824 target = gen_reg_rtx (GET_MODE (target));
2826 /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
2827 reg note to indicate that this call cannot throw or execute a nonlocal
2828 goto (unless there is already a REG_EH_REGION note, in which case
2829 we update it). */
2831 for (insn = insns; insn; insn = NEXT_INSN (insn))
2832 if (GET_CODE (insn) == CALL_INSN)
2834 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
2836 if (note != 0)
2837 XEXP (note, 0) = GEN_INT (-1);
2838 else
2839 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (-1),
2840 REG_NOTES (insn));
2843 /* First emit all insns that set pseudos. Remove them from the list as
2844 we go. Avoid insns that set pseudos which were referenced in previous
2845 insns. These can be generated by move_by_pieces, for example,
2846 to update an address. Similarly, avoid insns that reference things
2847 set in previous insns. */
2849 for (insn = insns; insn; insn = next)
2851 rtx set = single_set (insn);
2853 next = NEXT_INSN (insn);
2855 if (set != 0 && GET_CODE (SET_DEST (set)) == REG
2856 && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
2857 && (insn == insns
2858 || ((! INSN_P(insns)
2859 || ! reg_mentioned_p (SET_DEST (set), PATTERN (insns)))
2860 && ! reg_used_between_p (SET_DEST (set), insns, insn)
2861 && ! modified_in_p (SET_SRC (set), insns)
2862 && ! modified_between_p (SET_SRC (set), insns, insn))))
2864 if (PREV_INSN (insn))
2865 NEXT_INSN (PREV_INSN (insn)) = next;
2866 else
2867 insns = next;
2869 if (next)
2870 PREV_INSN (next) = PREV_INSN (insn);
2872 add_insn (insn);
2876 prev = get_last_insn ();
2878 /* Write the remaining insns followed by the final copy. */
2880 for (insn = insns; insn; insn = next)
2882 next = NEXT_INSN (insn);
2884 add_insn (insn);
2887 last = emit_move_insn (target, result);
2888 if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
2889 != CODE_FOR_nothing)
2890 set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
2891 else
2893 /* Remove any existing REG_EQUAL note from "last", or else it will
2894 be mistaken for a note referring to the full contents of the
2895 libcall value when found together with the REG_RETVAL note added
2896 below. An existing note can come from an insn expansion at
2897 "last". */
2898 remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
2901 if (final_dest != target)
2902 emit_move_insn (final_dest, target);
2904 if (prev == 0)
2905 first = get_insns ();
2906 else
2907 first = NEXT_INSN (prev);
2909 /* Encapsulate the block so it gets manipulated as a unit. */
2910 REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
2911 REG_NOTES (first));
2912 REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2915 /* Generate code to store zero in X. */
2917 void
2918 emit_clr_insn (x)
2919 rtx x;
2921 emit_move_insn (x, const0_rtx);
2924 /* Generate code to store 1 in X
2925 assuming it contains zero beforehand. */
2927 void
2928 emit_0_to_1_insn (x)
2929 rtx x;
2931 emit_move_insn (x, const1_rtx);
2934 /* Nonzero if we can perform a comparison of mode MODE straightforwardly.
2935 PURPOSE describes how this comparison will be used. CODE is the rtx
2936 comparison code we will be using.
2938 ??? Actually, CODE is slightly weaker than that. A target is still
2939 required to implement all of the normal bcc operations, but not
2940 required to implement all (or any) of the unordered bcc operations. */
2943 can_compare_p (code, mode, purpose)
2944 enum rtx_code code;
2945 enum machine_mode mode;
2946 enum can_compare_purpose purpose;
2950 if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
2952 if (purpose == ccp_jump)
2953 return bcc_gen_fctn[(int)code] != NULL;
2954 else if (purpose == ccp_store_flag)
2955 return setcc_gen_code[(int)code] != CODE_FOR_nothing;
2956 else
2957 /* There's only one cmov entry point, and it's allowed to fail. */
2958 return 1;
2960 if (purpose == ccp_jump
2961 && cbranch_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
2962 return 1;
2963 if (purpose == ccp_cmov
2964 && cmov_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
2965 return 1;
2966 if (purpose == ccp_store_flag
2967 && cstore_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
2968 return 1;
2970 mode = GET_MODE_WIDER_MODE (mode);
2972 while (mode != VOIDmode);
2974 return 0;
2977 /* This function is called when we are going to emit a compare instruction that
2978 compares the values found in *PX and *PY, using the rtl operator COMPARISON.
2980 *PMODE is the mode of the inputs (in case they are const_int).
2981 *PUNSIGNEDP nonzero says that the operands are unsigned;
2982 this matters if they need to be widened.
2984 If they have mode BLKmode, then SIZE specifies the size of both operands,
2985 and ALIGN specifies the known shared alignment of the operands.
2987 This function performs all the setup necessary so that the caller only has
2988 to emit a single comparison insn. This setup can involve doing a BLKmode
2989 comparison or emitting a library call to perform the comparison if no insn
2990 is available to handle it.
2991 The values which are passed in through pointers can be modified; the caller
2992 should perform the comparison on the modified values. */
2994 void
2995 prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align,
2996 purpose)
2997 rtx *px, *py;
2998 enum rtx_code *pcomparison;
2999 rtx size;
3000 enum machine_mode *pmode;
3001 int *punsignedp;
3002 int align ATTRIBUTE_UNUSED;
3003 enum can_compare_purpose purpose;
3005 enum machine_mode mode = *pmode;
3006 rtx x = *px, y = *py;
3007 int unsignedp = *punsignedp;
3008 enum mode_class class;
3009 rtx opalign ATTRIBUTE_UNUSED = GEN_INT (align / BITS_PER_UNIT);;
3011 class = GET_MODE_CLASS (mode);
3013 /* They could both be VOIDmode if both args are immediate constants,
3014 but we should fold that at an earlier stage.
3015 With no special code here, this will call abort,
3016 reminding the programmer to implement such folding. */
3018 if (mode != BLKmode && flag_force_mem)
3020 x = force_not_mem (x);
3021 y = force_not_mem (y);
3024 /* If we are inside an appropriately-short loop and one operand is an
3025 expensive constant, force it into a register. */
3026 if (CONSTANT_P (x) && preserve_subexpressions_p ()
3027 && rtx_cost (x, COMPARE) > COSTS_N_INSNS (1))
3028 x = force_reg (mode, x);
3030 if (CONSTANT_P (y) && preserve_subexpressions_p ()
3031 && rtx_cost (y, COMPARE) > COSTS_N_INSNS (1))
3032 y = force_reg (mode, y);
3034 #ifdef HAVE_cc0
3035 /* Abort if we have a non-canonical comparison. The RTL documentation
3036 states that canonical comparisons are required only for targets which
3037 have cc0. */
3038 if (CONSTANT_P (x) && ! CONSTANT_P (y))
3039 abort();
3040 #endif
3042 /* Don't let both operands fail to indicate the mode. */
3043 if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
3044 x = force_reg (mode, x);
3046 /* Handle all BLKmode compares. */
3048 if (mode == BLKmode)
3050 rtx result;
3051 enum machine_mode result_mode;
3053 emit_queue ();
3054 x = protect_from_queue (x, 0);
3055 y = protect_from_queue (y, 0);
3057 if (size == 0)
3058 abort ();
3059 #ifdef HAVE_cmpstrqi
3060 if (HAVE_cmpstrqi
3061 && GET_CODE (size) == CONST_INT
3062 && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
3064 result_mode = insn_data[(int) CODE_FOR_cmpstrqi].operand[0].mode;
3065 result = gen_reg_rtx (result_mode);
3066 emit_insn (gen_cmpstrqi (result, x, y, size, opalign));
3068 else
3069 #endif
3070 #ifdef HAVE_cmpstrhi
3071 if (HAVE_cmpstrhi
3072 && GET_CODE (size) == CONST_INT
3073 && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
3075 result_mode = insn_data[(int) CODE_FOR_cmpstrhi].operand[0].mode;
3076 result = gen_reg_rtx (result_mode);
3077 emit_insn (gen_cmpstrhi (result, x, y, size, opalign));
3079 else
3080 #endif
3081 #ifdef HAVE_cmpstrsi
3082 if (HAVE_cmpstrsi)
3084 result_mode = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3085 result = gen_reg_rtx (result_mode);
3086 size = protect_from_queue (size, 0);
3087 emit_insn (gen_cmpstrsi (result, x, y,
3088 convert_to_mode (SImode, size, 1),
3089 opalign));
3091 else
3092 #endif
3094 #ifdef TARGET_MEM_FUNCTIONS
3095 emit_library_call (memcmp_libfunc, LCT_PURE_MAKE_BLOCK,
3096 TYPE_MODE (integer_type_node), 3,
3097 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
3098 convert_to_mode (TYPE_MODE (sizetype), size,
3099 TREE_UNSIGNED (sizetype)),
3100 TYPE_MODE (sizetype));
3101 #else
3102 emit_library_call (bcmp_libfunc, LCT_PURE_MAKE_BLOCK,
3103 TYPE_MODE (integer_type_node), 3,
3104 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
3105 convert_to_mode (TYPE_MODE (integer_type_node),
3106 size,
3107 TREE_UNSIGNED (integer_type_node)),
3108 TYPE_MODE (integer_type_node));
3109 #endif
3111 /* Immediately move the result of the libcall into a pseudo
3112 register so reload doesn't clobber the value if it needs
3113 the return register for a spill reg. */
3114 result = gen_reg_rtx (TYPE_MODE (integer_type_node));
3115 result_mode = TYPE_MODE (integer_type_node);
3116 emit_move_insn (result,
3117 hard_libcall_value (result_mode));
3119 *px = result;
3120 *py = const0_rtx;
3121 *pmode = result_mode;
3122 return;
3125 *px = x;
3126 *py = y;
3127 if (can_compare_p (*pcomparison, mode, purpose))
3128 return;
3130 /* Handle a lib call just for the mode we are using. */
3132 if (cmp_optab->handlers[(int) mode].libfunc && class != MODE_FLOAT)
3134 rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
3135 rtx result;
3137 /* If we want unsigned, and this mode has a distinct unsigned
3138 comparison routine, use that. */
3139 if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
3140 libfunc = ucmp_optab->handlers[(int) mode].libfunc;
3142 emit_library_call (libfunc, 1,
3143 word_mode, 2, x, mode, y, mode);
3145 /* Immediately move the result of the libcall into a pseudo
3146 register so reload doesn't clobber the value if it needs
3147 the return register for a spill reg. */
3148 result = gen_reg_rtx (word_mode);
3149 emit_move_insn (result, hard_libcall_value (word_mode));
3151 /* Integer comparison returns a result that must be compared against 1,
3152 so that even if we do an unsigned compare afterward,
3153 there is still a value that can represent the result "less than". */
3154 *px = result;
3155 *py = const1_rtx;
3156 *pmode = word_mode;
3157 return;
3160 if (class == MODE_FLOAT)
3161 prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp);
3163 else
3164 abort ();
3167 /* Before emitting an insn with code ICODE, make sure that X, which is going
3168 to be used for operand OPNUM of the insn, is converted from mode MODE to
3169 WIDER_MODE (UNSIGNEDP determines whether it is a unsigned conversion), and
3170 that it is accepted by the operand predicate. Return the new value. */
3173 prepare_operand (icode, x, opnum, mode, wider_mode, unsignedp)
3174 int icode;
3175 rtx x;
3176 int opnum;
3177 enum machine_mode mode, wider_mode;
3178 int unsignedp;
3180 x = protect_from_queue (x, 0);
3182 if (mode != wider_mode)
3183 x = convert_modes (wider_mode, mode, x, unsignedp);
3185 if (! (*insn_data[icode].operand[opnum].predicate)
3186 (x, insn_data[icode].operand[opnum].mode))
3187 x = copy_to_mode_reg (insn_data[icode].operand[opnum].mode, x);
3188 return x;
3191 /* Subroutine of emit_cmp_and_jump_insns; this function is called when we know
3192 we can do the comparison.
3193 The arguments are the same as for emit_cmp_and_jump_insns; but LABEL may
3194 be NULL_RTX which indicates that only a comparison is to be generated. */
3196 static void
3197 emit_cmp_and_jump_insn_1 (x, y, mode, comparison, unsignedp, label)
3198 rtx x, y;
3199 enum machine_mode mode;
3200 enum rtx_code comparison;
3201 int unsignedp;
3202 rtx label;
3204 rtx test = gen_rtx_fmt_ee (comparison, mode, x, y);
3205 enum mode_class class = GET_MODE_CLASS (mode);
3206 enum machine_mode wider_mode = mode;
3208 /* Try combined insns first. */
3211 enum insn_code icode;
3212 PUT_MODE (test, wider_mode);
3214 if (label)
3216 icode = cbranch_optab->handlers[(int)wider_mode].insn_code;
3218 if (icode != CODE_FOR_nothing
3219 && (*insn_data[icode].operand[0].predicate) (test, wider_mode))
3221 x = prepare_operand (icode, x, 1, mode, wider_mode, unsignedp);
3222 y = prepare_operand (icode, y, 2, mode, wider_mode, unsignedp);
3223 emit_jump_insn (GEN_FCN (icode) (test, x, y, label));
3224 return;
3228 /* Handle some compares against zero. */
3229 icode = (int) tst_optab->handlers[(int) wider_mode].insn_code;
3230 if (y == CONST0_RTX (mode) && icode != CODE_FOR_nothing)
3232 x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp);
3233 emit_insn (GEN_FCN (icode) (x));
3234 if (label)
3235 emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
3236 return;
3239 /* Handle compares for which there is a directly suitable insn. */
3241 icode = (int) cmp_optab->handlers[(int) wider_mode].insn_code;
3242 if (icode != CODE_FOR_nothing)
3244 x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp);
3245 y = prepare_operand (icode, y, 1, mode, wider_mode, unsignedp);
3246 emit_insn (GEN_FCN (icode) (x, y));
3247 if (label)
3248 emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
3249 return;
3252 if (class != MODE_INT && class != MODE_FLOAT
3253 && class != MODE_COMPLEX_FLOAT)
3254 break;
3256 wider_mode = GET_MODE_WIDER_MODE (wider_mode);
3257 } while (wider_mode != VOIDmode);
3259 abort ();
3262 /* Generate code to compare X with Y so that the condition codes are
3263 set and to jump to LABEL if the condition is true. If X is a
3264 constant and Y is not a constant, then the comparison is swapped to
3265 ensure that the comparison RTL has the canonical form.
3267 UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
3268 need to be widened by emit_cmp_insn. UNSIGNEDP is also used to select
3269 the proper branch condition code.
3271 If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y,
3272 and ALIGN specifies the known shared alignment of X and Y.
3274 MODE is the mode of the inputs (in case they are const_int).
3276 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). It will
3277 be passed unchanged to emit_cmp_insn, then potentially converted into an
3278 unsigned variant based on UNSIGNEDP to select a proper jump instruction. */
3280 void
3281 emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, label)
3282 rtx x, y;
3283 enum rtx_code comparison;
3284 rtx size;
3285 enum machine_mode mode;
3286 int unsignedp;
3287 unsigned int align;
3288 rtx label;
3290 rtx op0;
3291 rtx op1;
3293 if ((CONSTANT_P (x) && ! CONSTANT_P (y))
3294 || (GET_CODE (x) == CONST_INT && GET_CODE (y) != CONST_INT))
3296 /* Swap operands and condition to ensure canonical RTL. */
3297 op0 = y;
3298 op1 = x;
3299 comparison = swap_condition (comparison);
3301 else
3303 op0 = x;
3304 op1 = y;
3307 #ifdef HAVE_cc0
3308 /* If OP0 is still a constant, then both X and Y must be constants. Force
3309 X into a register to avoid aborting in emit_cmp_insn due to non-canonical
3310 RTL. */
3311 if (CONSTANT_P (op0))
3312 op0 = force_reg (mode, op0);
3313 #endif
3315 emit_queue ();
3316 if (unsignedp)
3317 comparison = unsigned_condition (comparison);
3318 prepare_cmp_insn (&op0, &op1, &comparison, size, &mode, &unsignedp, align,
3319 ccp_jump);
3320 emit_cmp_and_jump_insn_1 (op0, op1, mode, comparison, unsignedp, label);
3323 /* Like emit_cmp_and_jump_insns, but generate only the comparison. */
3325 void
3326 emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
3327 rtx x, y;
3328 enum rtx_code comparison;
3329 rtx size;
3330 enum machine_mode mode;
3331 int unsignedp;
3332 unsigned int align;
3334 emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, 0);
3337 /* Emit a library call comparison between floating point X and Y.
3338 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
3340 static void
3341 prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
3342 rtx *px, *py;
3343 enum rtx_code *pcomparison;
3344 enum machine_mode *pmode;
3345 int *punsignedp;
3347 enum rtx_code comparison = *pcomparison;
3348 rtx x = *px = protect_from_queue (*px, 0);
3349 rtx y = *py = protect_from_queue (*py, 0);
3350 enum machine_mode mode = GET_MODE (x);
3351 rtx libfunc = 0;
3352 rtx result;
3354 if (mode == HFmode)
3355 switch (comparison)
3357 case EQ:
3358 libfunc = eqhf2_libfunc;
3359 break;
3361 case NE:
3362 libfunc = nehf2_libfunc;
3363 break;
3365 case GT:
3366 libfunc = gthf2_libfunc;
3367 break;
3369 case GE:
3370 libfunc = gehf2_libfunc;
3371 break;
3373 case LT:
3374 libfunc = lthf2_libfunc;
3375 break;
3377 case LE:
3378 libfunc = lehf2_libfunc;
3379 break;
3381 case UNORDERED:
3382 libfunc = unordhf2_libfunc;
3383 break;
3385 default:
3386 break;
3388 else if (mode == SFmode)
3389 switch (comparison)
3391 case EQ:
3392 libfunc = eqsf2_libfunc;
3393 break;
3395 case NE:
3396 libfunc = nesf2_libfunc;
3397 break;
3399 case GT:
3400 libfunc = gtsf2_libfunc;
3401 break;
3403 case GE:
3404 libfunc = gesf2_libfunc;
3405 break;
3407 case LT:
3408 libfunc = ltsf2_libfunc;
3409 break;
3411 case LE:
3412 libfunc = lesf2_libfunc;
3413 break;
3415 case UNORDERED:
3416 libfunc = unordsf2_libfunc;
3417 break;
3419 default:
3420 break;
3422 else if (mode == DFmode)
3423 switch (comparison)
3425 case EQ:
3426 libfunc = eqdf2_libfunc;
3427 break;
3429 case NE:
3430 libfunc = nedf2_libfunc;
3431 break;
3433 case GT:
3434 libfunc = gtdf2_libfunc;
3435 break;
3437 case GE:
3438 libfunc = gedf2_libfunc;
3439 break;
3441 case LT:
3442 libfunc = ltdf2_libfunc;
3443 break;
3445 case LE:
3446 libfunc = ledf2_libfunc;
3447 break;
3449 case UNORDERED:
3450 libfunc = unorddf2_libfunc;
3451 break;
3453 default:
3454 break;
3456 else if (mode == XFmode)
3457 switch (comparison)
3459 case EQ:
3460 libfunc = eqxf2_libfunc;
3461 break;
3463 case NE:
3464 libfunc = nexf2_libfunc;
3465 break;
3467 case GT:
3468 libfunc = gtxf2_libfunc;
3469 break;
3471 case GE:
3472 libfunc = gexf2_libfunc;
3473 break;
3475 case LT:
3476 libfunc = ltxf2_libfunc;
3477 break;
3479 case LE:
3480 libfunc = lexf2_libfunc;
3481 break;
3483 case UNORDERED:
3484 libfunc = unordxf2_libfunc;
3485 break;
3487 default:
3488 break;
3490 else if (mode == TFmode)
3491 switch (comparison)
3493 case EQ:
3494 libfunc = eqtf2_libfunc;
3495 break;
3497 case NE:
3498 libfunc = netf2_libfunc;
3499 break;
3501 case GT:
3502 libfunc = gttf2_libfunc;
3503 break;
3505 case GE:
3506 libfunc = getf2_libfunc;
3507 break;
3509 case LT:
3510 libfunc = lttf2_libfunc;
3511 break;
3513 case LE:
3514 libfunc = letf2_libfunc;
3515 break;
3517 case UNORDERED:
3518 libfunc = unordtf2_libfunc;
3519 break;
3521 default:
3522 break;
3524 else
3526 enum machine_mode wider_mode;
3528 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
3529 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3531 if ((cmp_optab->handlers[(int) wider_mode].insn_code
3532 != CODE_FOR_nothing)
3533 || (cmp_optab->handlers[(int) wider_mode].libfunc != 0))
3535 x = protect_from_queue (x, 0);
3536 y = protect_from_queue (y, 0);
3537 *px = convert_to_mode (wider_mode, x, 0);
3538 *py = convert_to_mode (wider_mode, y, 0);
3539 prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp);
3540 return;
3543 abort ();
3546 if (libfunc == 0)
3547 abort ();
3549 emit_library_call (libfunc, LCT_CONST_MAKE_BLOCK, word_mode, 2, x, mode, y,
3550 mode);
3552 /* Immediately move the result of the libcall into a pseudo
3553 register so reload doesn't clobber the value if it needs
3554 the return register for a spill reg. */
3555 result = gen_reg_rtx (word_mode);
3556 emit_move_insn (result, hard_libcall_value (word_mode));
3557 *px = result;
3558 *py = const0_rtx;
3559 *pmode = word_mode;
3560 if (comparison == UNORDERED)
3561 *pcomparison = NE;
3562 #ifdef FLOAT_LIB_COMPARE_RETURNS_BOOL
3563 else if (FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
3564 *pcomparison = NE;
3565 #endif
3566 *punsignedp = 0;
3569 /* Generate code to indirectly jump to a location given in the rtx LOC. */
3571 void
3572 emit_indirect_jump (loc)
3573 rtx loc;
3575 if (! ((*insn_data[(int)CODE_FOR_indirect_jump].operand[0].predicate)
3576 (loc, Pmode)))
3577 loc = copy_to_mode_reg (Pmode, loc);
3579 emit_jump_insn (gen_indirect_jump (loc));
3580 emit_barrier ();
3583 #ifdef HAVE_conditional_move
3585 /* Emit a conditional move instruction if the machine supports one for that
3586 condition and machine mode.
3588 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
3589 the mode to use should they be constants. If it is VOIDmode, they cannot
3590 both be constants.
3592 OP2 should be stored in TARGET if the comparison is true, otherwise OP3
3593 should be stored there. MODE is the mode to use should they be constants.
3594 If it is VOIDmode, they cannot both be constants.
3596 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
3597 is not supported. */
3600 emit_conditional_move (target, code, op0, op1, cmode, op2, op3, mode,
3601 unsignedp)
3602 rtx target;
3603 enum rtx_code code;
3604 rtx op0, op1;
3605 enum machine_mode cmode;
3606 rtx op2, op3;
3607 enum machine_mode mode;
3608 int unsignedp;
3610 rtx tem, subtarget, comparison, insn;
3611 enum insn_code icode;
3613 /* If one operand is constant, make it the second one. Only do this
3614 if the other operand is not constant as well. */
3616 if ((CONSTANT_P (op0) && ! CONSTANT_P (op1))
3617 || (GET_CODE (op0) == CONST_INT && GET_CODE (op1) != CONST_INT))
3619 tem = op0;
3620 op0 = op1;
3621 op1 = tem;
3622 code = swap_condition (code);
3625 /* get_condition will prefer to generate LT and GT even if the old
3626 comparison was against zero, so undo that canonicalization here since
3627 comparisons against zero are cheaper. */
3628 if (code == LT && GET_CODE (op1) == CONST_INT && INTVAL (op1) == 1)
3629 code = LE, op1 = const0_rtx;
3630 else if (code == GT && GET_CODE (op1) == CONST_INT && INTVAL (op1) == -1)
3631 code = GE, op1 = const0_rtx;
3633 if (cmode == VOIDmode)
3634 cmode = GET_MODE (op0);
3636 if (((CONSTANT_P (op2) && ! CONSTANT_P (op3))
3637 || (GET_CODE (op2) == CONST_INT && GET_CODE (op3) != CONST_INT))
3638 && (GET_MODE_CLASS (GET_MODE (op1)) != MODE_FLOAT
3639 || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
3640 || flag_unsafe_math_optimizations))
3642 tem = op2;
3643 op2 = op3;
3644 op3 = tem;
3645 code = reverse_condition (code);
3648 if (mode == VOIDmode)
3649 mode = GET_MODE (op2);
3651 icode = movcc_gen_code[mode];
3653 if (icode == CODE_FOR_nothing)
3654 return 0;
3656 if (flag_force_mem)
3658 op2 = force_not_mem (op2);
3659 op3 = force_not_mem (op3);
3662 if (target)
3663 target = protect_from_queue (target, 1);
3664 else
3665 target = gen_reg_rtx (mode);
3667 subtarget = target;
3669 emit_queue ();
3671 op2 = protect_from_queue (op2, 0);
3672 op3 = protect_from_queue (op3, 0);
3674 /* If the insn doesn't accept these operands, put them in pseudos. */
3676 if (! (*insn_data[icode].operand[0].predicate)
3677 (subtarget, insn_data[icode].operand[0].mode))
3678 subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
3680 if (! (*insn_data[icode].operand[2].predicate)
3681 (op2, insn_data[icode].operand[2].mode))
3682 op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
3684 if (! (*insn_data[icode].operand[3].predicate)
3685 (op3, insn_data[icode].operand[3].mode))
3686 op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);
3688 /* Everything should now be in the suitable form, so emit the compare insn
3689 and then the conditional move. */
3691 comparison
3692 = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX, 0);
3694 /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)? */
3695 /* We can get const0_rtx or const_true_rtx in some circumstances. Just
3696 return NULL and let the caller figure out how best to deal with this
3697 situation. */
3698 if (GET_CODE (comparison) != code)
3699 return NULL_RTX;
3701 insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
3703 /* If that failed, then give up. */
3704 if (insn == 0)
3705 return 0;
3707 emit_insn (insn);
3709 if (subtarget != target)
3710 convert_move (target, subtarget, 0);
3712 return target;
3715 /* Return non-zero if a conditional move of mode MODE is supported.
3717 This function is for combine so it can tell whether an insn that looks
3718 like a conditional move is actually supported by the hardware. If we
3719 guess wrong we lose a bit on optimization, but that's it. */
3720 /* ??? sparc64 supports conditionally moving integers values based on fp
3721 comparisons, and vice versa. How do we handle them? */
3724 can_conditionally_move_p (mode)
3725 enum machine_mode mode;
3727 if (movcc_gen_code[mode] != CODE_FOR_nothing)
3728 return 1;
3730 return 0;
3733 #endif /* HAVE_conditional_move */
3735 /* These three functions generate an insn body and return it
3736 rather than emitting the insn.
3738 They do not protect from queued increments,
3739 because they may be used 1) in protect_from_queue itself
3740 and 2) in other passes where there is no queue. */
3742 /* Generate and return an insn body to add Y to X. */
3745 gen_add2_insn (x, y)
3746 rtx x, y;
3748 int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code;
3750 if (! ((*insn_data[icode].operand[0].predicate)
3751 (x, insn_data[icode].operand[0].mode))
3752 || ! ((*insn_data[icode].operand[1].predicate)
3753 (x, insn_data[icode].operand[1].mode))
3754 || ! ((*insn_data[icode].operand[2].predicate)
3755 (y, insn_data[icode].operand[2].mode)))
3756 abort ();
3758 return (GEN_FCN (icode) (x, x, y));
3762 have_add2_insn (mode)
3763 enum machine_mode mode;
3765 return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
3768 /* Generate and return an insn body to subtract Y from X. */
3771 gen_sub2_insn (x, y)
3772 rtx x, y;
3774 int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code;
3776 if (! ((*insn_data[icode].operand[0].predicate)
3777 (x, insn_data[icode].operand[0].mode))
3778 || ! ((*insn_data[icode].operand[1].predicate)
3779 (x, insn_data[icode].operand[1].mode))
3780 || ! ((*insn_data[icode].operand[2].predicate)
3781 (y, insn_data[icode].operand[2].mode)))
3782 abort ();
3784 return (GEN_FCN (icode) (x, x, y));
3788 have_sub2_insn (mode)
3789 enum machine_mode mode;
3791 return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
3794 /* Generate the body of an instruction to copy Y into X.
3795 It may be a SEQUENCE, if one insn isn't enough. */
3798 gen_move_insn (x, y)
3799 rtx x, y;
3801 register enum machine_mode mode = GET_MODE (x);
3802 enum insn_code insn_code;
3803 rtx seq;
3805 if (mode == VOIDmode)
3806 mode = GET_MODE (y);
3808 insn_code = mov_optab->handlers[(int) mode].insn_code;
3810 /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
3811 find a mode to do it in. If we have a movcc, use it. Otherwise,
3812 find the MODE_INT mode of the same width. */
3814 if (GET_MODE_CLASS (mode) == MODE_CC && insn_code == CODE_FOR_nothing)
3816 enum machine_mode tmode = VOIDmode;
3817 rtx x1 = x, y1 = y;
3819 if (mode != CCmode
3820 && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing)
3821 tmode = CCmode;
3822 else
3823 for (tmode = QImode; tmode != VOIDmode;
3824 tmode = GET_MODE_WIDER_MODE (tmode))
3825 if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode))
3826 break;
3828 if (tmode == VOIDmode)
3829 abort ();
3831 /* Get X and Y in TMODE. We can't use gen_lowpart here because it
3832 may call change_address which is not appropriate if we were
3833 called when a reload was in progress. We don't have to worry
3834 about changing the address since the size in bytes is supposed to
3835 be the same. Copy the MEM to change the mode and move any
3836 substitutions from the old MEM to the new one. */
3838 if (reload_in_progress)
3840 x = gen_lowpart_common (tmode, x1);
3841 if (x == 0 && GET_CODE (x1) == MEM)
3843 x = gen_rtx_MEM (tmode, XEXP (x1, 0));
3844 MEM_COPY_ATTRIBUTES (x, x1);
3845 copy_replacements (x1, x);
3848 y = gen_lowpart_common (tmode, y1);
3849 if (y == 0 && GET_CODE (y1) == MEM)
3851 y = gen_rtx_MEM (tmode, XEXP (y1, 0));
3852 MEM_COPY_ATTRIBUTES (y, y1);
3853 copy_replacements (y1, y);
3856 else
3858 x = gen_lowpart (tmode, x);
3859 y = gen_lowpart (tmode, y);
3862 insn_code = mov_optab->handlers[(int) tmode].insn_code;
3863 return (GEN_FCN (insn_code) (x, y));
3866 start_sequence ();
3867 emit_move_insn_1 (x, y);
3868 seq = gen_sequence ();
3869 end_sequence ();
3870 return seq;
3873 /* Return the insn code used to extend FROM_MODE to TO_MODE.
3874 UNSIGNEDP specifies zero-extension instead of sign-extension. If
3875 no such operation exists, CODE_FOR_nothing will be returned. */
3877 enum insn_code
3878 can_extend_p (to_mode, from_mode, unsignedp)
3879 enum machine_mode to_mode, from_mode;
3880 int unsignedp;
3882 return extendtab[(int) to_mode][(int) from_mode][unsignedp != 0];
3885 /* Generate the body of an insn to extend Y (with mode MFROM)
3886 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
3889 gen_extend_insn (x, y, mto, mfrom, unsignedp)
3890 rtx x, y;
3891 enum machine_mode mto, mfrom;
3892 int unsignedp;
3894 return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp != 0]) (x, y));
3897 /* can_fix_p and can_float_p say whether the target machine
3898 can directly convert a given fixed point type to
3899 a given floating point type, or vice versa.
3900 The returned value is the CODE_FOR_... value to use,
3901 or CODE_FOR_nothing if these modes cannot be directly converted.
3903 *TRUNCP_PTR is set to 1 if it is necessary to output
3904 an explicit FTRUNC insn before the fix insn; otherwise 0. */
3906 static enum insn_code
3907 can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
3908 enum machine_mode fltmode, fixmode;
3909 int unsignedp;
3910 int *truncp_ptr;
3912 *truncp_ptr = 0;
3913 if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp != 0]
3914 != CODE_FOR_nothing)
3915 return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp != 0];
3917 if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
3919 *truncp_ptr = 1;
3920 return fixtab[(int) fltmode][(int) fixmode][unsignedp != 0];
3922 return CODE_FOR_nothing;
3925 static enum insn_code
3926 can_float_p (fltmode, fixmode, unsignedp)
3927 enum machine_mode fixmode, fltmode;
3928 int unsignedp;
3930 return floattab[(int) fltmode][(int) fixmode][unsignedp != 0];
3933 /* Generate code to convert FROM to floating point
3934 and store in TO. FROM must be fixed point and not VOIDmode.
3935 UNSIGNEDP nonzero means regard FROM as unsigned.
3936 Normally this is done by correcting the final value
3937 if it is negative. */
3939 void
3940 expand_float (to, from, unsignedp)
3941 rtx to, from;
3942 int unsignedp;
3944 enum insn_code icode;
3945 register rtx target = to;
3946 enum machine_mode fmode, imode;
3948 /* Crash now, because we won't be able to decide which mode to use. */
3949 if (GET_MODE (from) == VOIDmode)
3950 abort ();
3952 /* Look for an insn to do the conversion. Do it in the specified
3953 modes if possible; otherwise convert either input, output or both to
3954 wider mode. If the integer mode is wider than the mode of FROM,
3955 we can do the conversion signed even if the input is unsigned. */
3957 for (imode = GET_MODE (from); imode != VOIDmode;
3958 imode = GET_MODE_WIDER_MODE (imode))
3959 for (fmode = GET_MODE (to); fmode != VOIDmode;
3960 fmode = GET_MODE_WIDER_MODE (fmode))
3962 int doing_unsigned = unsignedp;
3964 if (fmode != GET_MODE (to)
3965 && significand_size (fmode) < GET_MODE_BITSIZE (GET_MODE (from)))
3966 continue;
3968 icode = can_float_p (fmode, imode, unsignedp);
3969 if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
3970 icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;
3972 if (icode != CODE_FOR_nothing)
3974 to = protect_from_queue (to, 1);
3975 from = protect_from_queue (from, 0);
3977 if (imode != GET_MODE (from))
3978 from = convert_to_mode (imode, from, unsignedp);
3980 if (fmode != GET_MODE (to))
3981 target = gen_reg_rtx (fmode);
3983 emit_unop_insn (icode, target, from,
3984 doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
3986 if (target != to)
3987 convert_move (to, target, 0);
3988 return;
3992 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3994 /* Unsigned integer, and no way to convert directly.
3995 Convert as signed, then conditionally adjust the result. */
3996 if (unsignedp)
3998 rtx label = gen_label_rtx ();
3999 rtx temp;
4000 REAL_VALUE_TYPE offset;
4002 emit_queue ();
4004 to = protect_from_queue (to, 1);
4005 from = protect_from_queue (from, 0);
4007 if (flag_force_mem)
4008 from = force_not_mem (from);
4010 /* Look for a usable floating mode FMODE wider than the source and at
4011 least as wide as the target. Using FMODE will avoid rounding woes
4012 with unsigned values greater than the signed maximum value. */
4014 for (fmode = GET_MODE (to); fmode != VOIDmode;
4015 fmode = GET_MODE_WIDER_MODE (fmode))
4016 if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
4017 && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
4018 break;
4020 if (fmode == VOIDmode)
4022 /* There is no such mode. Pretend the target is wide enough. */
4023 fmode = GET_MODE (to);
4025 /* Avoid double-rounding when TO is narrower than FROM. */
4026 if ((significand_size (fmode) + 1)
4027 < GET_MODE_BITSIZE (GET_MODE (from)))
4029 rtx temp1;
4030 rtx neglabel = gen_label_rtx ();
4032 /* Don't use TARGET if it isn't a register, is a hard register,
4033 or is the wrong mode. */
4034 if (GET_CODE (target) != REG
4035 || REGNO (target) < FIRST_PSEUDO_REGISTER
4036 || GET_MODE (target) != fmode)
4037 target = gen_reg_rtx (fmode);
4039 imode = GET_MODE (from);
4040 do_pending_stack_adjust ();
4042 /* Test whether the sign bit is set. */
4043 emit_cmp_and_jump_insns (from, const0_rtx, LT, NULL_RTX, imode,
4044 0, 0, neglabel);
4046 /* The sign bit is not set. Convert as signed. */
4047 expand_float (target, from, 0);
4048 emit_jump_insn (gen_jump (label));
4049 emit_barrier ();
4051 /* The sign bit is set.
4052 Convert to a usable (positive signed) value by shifting right
4053 one bit, while remembering if a nonzero bit was shifted
4054 out; i.e., compute (from & 1) | (from >> 1). */
4056 emit_label (neglabel);
4057 temp = expand_binop (imode, and_optab, from, const1_rtx,
4058 NULL_RTX, 1, OPTAB_LIB_WIDEN);
4059 temp1 = expand_shift (RSHIFT_EXPR, imode, from, integer_one_node,
4060 NULL_RTX, 1);
4061 temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1,
4062 OPTAB_LIB_WIDEN);
4063 expand_float (target, temp, 0);
4065 /* Multiply by 2 to undo the shift above. */
4066 temp = expand_binop (fmode, add_optab, target, target,
4067 target, 0, OPTAB_LIB_WIDEN);
4068 if (temp != target)
4069 emit_move_insn (target, temp);
4071 do_pending_stack_adjust ();
4072 emit_label (label);
4073 goto done;
4077 /* If we are about to do some arithmetic to correct for an
4078 unsigned operand, do it in a pseudo-register. */
4080 if (GET_MODE (to) != fmode
4081 || GET_CODE (to) != REG || REGNO (to) < FIRST_PSEUDO_REGISTER)
4082 target = gen_reg_rtx (fmode);
4084 /* Convert as signed integer to floating. */
4085 expand_float (target, from, 0);
4087 /* If FROM is negative (and therefore TO is negative),
4088 correct its value by 2**bitwidth. */
4090 do_pending_stack_adjust ();
4091 emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
4092 0, 0, label);
4094 /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
4095 Rather than setting up a dconst_dot_5, let's hope SCO
4096 fixes the bug. */
4097 offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from)));
4098 temp = expand_binop (fmode, add_optab, target,
4099 CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
4100 target, 0, OPTAB_LIB_WIDEN);
4101 if (temp != target)
4102 emit_move_insn (target, temp);
4104 do_pending_stack_adjust ();
4105 emit_label (label);
4106 goto done;
4108 #endif
4110 /* No hardware instruction available; call a library routine to convert from
4111 SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */
4113 rtx libfcn;
4114 rtx insns;
4115 rtx value;
4117 to = protect_from_queue (to, 1);
4118 from = protect_from_queue (from, 0);
4120 if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
4121 from = convert_to_mode (SImode, from, unsignedp);
4123 if (flag_force_mem)
4124 from = force_not_mem (from);
4126 if (GET_MODE (to) == SFmode)
4128 if (GET_MODE (from) == SImode)
4129 libfcn = floatsisf_libfunc;
4130 else if (GET_MODE (from) == DImode)
4131 libfcn = floatdisf_libfunc;
4132 else if (GET_MODE (from) == TImode)
4133 libfcn = floattisf_libfunc;
4134 else
4135 abort ();
4137 else if (GET_MODE (to) == DFmode)
4139 if (GET_MODE (from) == SImode)
4140 libfcn = floatsidf_libfunc;
4141 else if (GET_MODE (from) == DImode)
4142 libfcn = floatdidf_libfunc;
4143 else if (GET_MODE (from) == TImode)
4144 libfcn = floattidf_libfunc;
4145 else
4146 abort ();
4148 else if (GET_MODE (to) == XFmode)
4150 if (GET_MODE (from) == SImode)
4151 libfcn = floatsixf_libfunc;
4152 else if (GET_MODE (from) == DImode)
4153 libfcn = floatdixf_libfunc;
4154 else if (GET_MODE (from) == TImode)
4155 libfcn = floattixf_libfunc;
4156 else
4157 abort ();
4159 else if (GET_MODE (to) == TFmode)
4161 if (GET_MODE (from) == SImode)
4162 libfcn = floatsitf_libfunc;
4163 else if (GET_MODE (from) == DImode)
4164 libfcn = floatditf_libfunc;
4165 else if (GET_MODE (from) == TImode)
4166 libfcn = floattitf_libfunc;
4167 else
4168 abort ();
4170 else
4171 abort ();
4173 start_sequence ();
4175 value = emit_library_call_value (libfcn, NULL_RTX, LCT_CONST,
4176 GET_MODE (to), 1, from,
4177 GET_MODE (from));
4178 insns = get_insns ();
4179 end_sequence ();
4181 emit_libcall_block (insns, target, value,
4182 gen_rtx_FLOAT (GET_MODE (to), from));
4185 done:
4187 /* Copy result to requested destination
4188 if we have been computing in a temp location. */
4190 if (target != to)
4192 if (GET_MODE (target) == GET_MODE (to))
4193 emit_move_insn (to, target);
4194 else
4195 convert_move (to, target, 0);
4199 /* expand_fix: generate code to convert FROM to fixed point
4200 and store in TO. FROM must be floating point. */
4202 static rtx
4203 ftruncify (x)
4204 rtx x;
4206 rtx temp = gen_reg_rtx (GET_MODE (x));
4207 return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0);
4210 void
4211 expand_fix (to, from, unsignedp)
4212 register rtx to, from;
4213 int unsignedp;
4215 enum insn_code icode;
4216 register rtx target = to;
4217 enum machine_mode fmode, imode;
4218 int must_trunc = 0;
4219 rtx libfcn = 0;
4221 /* We first try to find a pair of modes, one real and one integer, at
4222 least as wide as FROM and TO, respectively, in which we can open-code
4223 this conversion. If the integer mode is wider than the mode of TO,
4224 we can do the conversion either signed or unsigned. */
4226 for (imode = GET_MODE (to); imode != VOIDmode;
4227 imode = GET_MODE_WIDER_MODE (imode))
4228 for (fmode = GET_MODE (from); fmode != VOIDmode;
4229 fmode = GET_MODE_WIDER_MODE (fmode))
4231 int doing_unsigned = unsignedp;
4233 icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
4234 if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
4235 icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
4237 if (icode != CODE_FOR_nothing)
4239 to = protect_from_queue (to, 1);
4240 from = protect_from_queue (from, 0);
4242 if (fmode != GET_MODE (from))
4243 from = convert_to_mode (fmode, from, 0);
4245 if (must_trunc)
4246 from = ftruncify (from);
4248 if (imode != GET_MODE (to))
4249 target = gen_reg_rtx (imode);
4251 emit_unop_insn (icode, target, from,
4252 doing_unsigned ? UNSIGNED_FIX : FIX);
4253 if (target != to)
4254 convert_move (to, target, unsignedp);
4255 return;
4259 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
4260 /* For an unsigned conversion, there is one more way to do it.
4261 If we have a signed conversion, we generate code that compares
4262 the real value to the largest representable positive number. If if
4263 is smaller, the conversion is done normally. Otherwise, subtract
4264 one plus the highest signed number, convert, and add it back.
4266 We only need to check all real modes, since we know we didn't find
4267 anything with a wider integer mode. */
4269 if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
4270 for (fmode = GET_MODE (from); fmode != VOIDmode;
4271 fmode = GET_MODE_WIDER_MODE (fmode))
4272 /* Make sure we won't lose significant bits doing this. */
4273 if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))
4274 && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
4275 &must_trunc))
4277 int bitsize;
4278 REAL_VALUE_TYPE offset;
4279 rtx limit, lab1, lab2, insn;
4281 bitsize = GET_MODE_BITSIZE (GET_MODE (to));
4282 offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1);
4283 limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
4284 lab1 = gen_label_rtx ();
4285 lab2 = gen_label_rtx ();
4287 emit_queue ();
4288 to = protect_from_queue (to, 1);
4289 from = protect_from_queue (from, 0);
4291 if (flag_force_mem)
4292 from = force_not_mem (from);
4294 if (fmode != GET_MODE (from))
4295 from = convert_to_mode (fmode, from, 0);
4297 /* See if we need to do the subtraction. */
4298 do_pending_stack_adjust ();
4299 emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
4300 0, 0, lab1);
4302 /* If not, do the signed "fix" and branch around fixup code. */
4303 expand_fix (to, from, 0);
4304 emit_jump_insn (gen_jump (lab2));
4305 emit_barrier ();
4307 /* Otherwise, subtract 2**(N-1), convert to signed number,
4308 then add 2**(N-1). Do the addition using XOR since this
4309 will often generate better code. */
4310 emit_label (lab1);
4311 target = expand_binop (GET_MODE (from), sub_optab, from, limit,
4312 NULL_RTX, 0, OPTAB_LIB_WIDEN);
4313 expand_fix (to, target, 0);
4314 target = expand_binop (GET_MODE (to), xor_optab, to,
4315 GEN_INT (trunc_int_for_mode
4316 ((HOST_WIDE_INT) 1 << (bitsize - 1),
4317 GET_MODE (to))),
4318 to, 1, OPTAB_LIB_WIDEN);
4320 if (target != to)
4321 emit_move_insn (to, target);
4323 emit_label (lab2);
4325 if (mov_optab->handlers[(int) GET_MODE (to)].insn_code
4326 != CODE_FOR_nothing)
4328 /* Make a place for a REG_NOTE and add it. */
4329 insn = emit_move_insn (to, to);
4330 set_unique_reg_note (insn,
4331 REG_EQUAL,
4332 gen_rtx_fmt_e (UNSIGNED_FIX,
4333 GET_MODE (to),
4334 copy_rtx (from)));
4337 return;
4339 #endif
4341 /* We can't do it with an insn, so use a library call. But first ensure
4342 that the mode of TO is at least as wide as SImode, since those are the
4343 only library calls we know about. */
4345 if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
4347 target = gen_reg_rtx (SImode);
4349 expand_fix (target, from, unsignedp);
4351 else if (GET_MODE (from) == SFmode)
4353 if (GET_MODE (to) == SImode)
4354 libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc;
4355 else if (GET_MODE (to) == DImode)
4356 libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc;
4357 else if (GET_MODE (to) == TImode)
4358 libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc;
4359 else
4360 abort ();
4362 else if (GET_MODE (from) == DFmode)
4364 if (GET_MODE (to) == SImode)
4365 libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc;
4366 else if (GET_MODE (to) == DImode)
4367 libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc;
4368 else if (GET_MODE (to) == TImode)
4369 libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc;
4370 else
4371 abort ();
4373 else if (GET_MODE (from) == XFmode)
4375 if (GET_MODE (to) == SImode)
4376 libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc;
4377 else if (GET_MODE (to) == DImode)
4378 libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc;
4379 else if (GET_MODE (to) == TImode)
4380 libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc;
4381 else
4382 abort ();
4384 else if (GET_MODE (from) == TFmode)
4386 if (GET_MODE (to) == SImode)
4387 libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc;
4388 else if (GET_MODE (to) == DImode)
4389 libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc;
4390 else if (GET_MODE (to) == TImode)
4391 libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc;
4392 else
4393 abort ();
4395 else
4396 abort ();
4398 if (libfcn)
4400 rtx insns;
4401 rtx value;
4403 to = protect_from_queue (to, 1);
4404 from = protect_from_queue (from, 0);
4406 if (flag_force_mem)
4407 from = force_not_mem (from);
4409 start_sequence ();
4411 value = emit_library_call_value (libfcn, NULL_RTX, LCT_CONST,
4412 GET_MODE (to), 1, from,
4413 GET_MODE (from));
4414 insns = get_insns ();
4415 end_sequence ();
4417 emit_libcall_block (insns, target, value,
4418 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX,
4419 GET_MODE (to), from));
4422 if (target != to)
4424 if (GET_MODE (to) == GET_MODE (target))
4425 emit_move_insn (to, target);
4426 else
4427 convert_move (to, target, 0);
4431 static optab
4432 init_optab (code)
4433 enum rtx_code code;
4435 int i;
4436 optab op = (optab) xmalloc (sizeof (struct optab));
4437 op->code = code;
4438 for (i = 0; i < NUM_MACHINE_MODES; i++)
4440 op->handlers[i].insn_code = CODE_FOR_nothing;
4441 op->handlers[i].libfunc = 0;
4444 if (code != UNKNOWN)
4445 code_to_optab[(int) code] = op;
4447 return op;
4450 /* Initialize the libfunc fields of an entire group of entries in some
4451 optab. Each entry is set equal to a string consisting of a leading
4452 pair of underscores followed by a generic operation name followed by
4453 a mode name (downshifted to lower case) followed by a single character
4454 representing the number of operands for the given operation (which is
4455 usually one of the characters '2', '3', or '4').
4457 OPTABLE is the table in which libfunc fields are to be initialized.
4458 FIRST_MODE is the first machine mode index in the given optab to
4459 initialize.
4460 LAST_MODE is the last machine mode index in the given optab to
4461 initialize.
4462 OPNAME is the generic (string) name of the operation.
4463 SUFFIX is the character which specifies the number of operands for
4464 the given generic operation.
4467 static void
4468 init_libfuncs (optable, first_mode, last_mode, opname, suffix)
4469 register optab optable;
4470 register int first_mode;
4471 register int last_mode;
4472 register const char *opname;
4473 register int suffix;
4475 register int mode;
4476 register unsigned opname_len = strlen (opname);
4478 for (mode = first_mode; (int) mode <= (int) last_mode;
4479 mode = (enum machine_mode) ((int) mode + 1))
4481 register const char *mname = GET_MODE_NAME(mode);
4482 register unsigned mname_len = strlen (mname);
4483 register char *libfunc_name = alloca (2 + opname_len + mname_len + 1 + 1);
4484 register char *p;
4485 register const char *q;
4487 p = libfunc_name;
4488 *p++ = '_';
4489 *p++ = '_';
4490 for (q = opname; *q; )
4491 *p++ = *q++;
4492 for (q = mname; *q; q++)
4493 *p++ = TOLOWER (*q);
4494 *p++ = suffix;
4495 *p = '\0';
4497 optable->handlers[(int) mode].libfunc
4498 = gen_rtx_SYMBOL_REF (Pmode, ggc_alloc_string (libfunc_name,
4499 p - libfunc_name));
4503 /* Initialize the libfunc fields of an entire group of entries in some
4504 optab which correspond to all integer mode operations. The parameters
4505 have the same meaning as similarly named ones for the `init_libfuncs'
4506 routine. (See above). */
4508 static void
4509 init_integral_libfuncs (optable, opname, suffix)
4510 register optab optable;
4511 register const char *opname;
4512 register int suffix;
4514 init_libfuncs (optable, SImode, TImode, opname, suffix);
4517 /* Initialize the libfunc fields of an entire group of entries in some
4518 optab which correspond to all real mode operations. The parameters
4519 have the same meaning as similarly named ones for the `init_libfuncs'
4520 routine. (See above). */
4522 static void
4523 init_floating_libfuncs (optable, opname, suffix)
4524 register optab optable;
4525 register const char *opname;
4526 register int suffix;
4528 init_libfuncs (optable, SFmode, TFmode, opname, suffix);
4532 init_one_libfunc (name)
4533 register const char *name;
4535 name = ggc_strdup (name);
4537 return gen_rtx_SYMBOL_REF (Pmode, name);
4540 /* Mark ARG (which is really an OPTAB *) for GC. */
4542 void
4543 mark_optab (arg)
4544 void *arg;
4546 optab o = *(optab *) arg;
4547 int i;
4549 for (i = 0; i < NUM_MACHINE_MODES; ++i)
4550 ggc_mark_rtx (o->handlers[i].libfunc);
4553 /* Call this once to initialize the contents of the optabs
4554 appropriately for the current target machine. */
4556 void
4557 init_optabs ()
4559 unsigned int i, j, k;
4561 /* Start by initializing all tables to contain CODE_FOR_nothing. */
4563 for (i = 0; i < ARRAY_SIZE (fixtab); i++)
4564 for (j = 0; j < ARRAY_SIZE (fixtab[0]); j++)
4565 for (k = 0; k < ARRAY_SIZE (fixtab[0][0]); k++)
4566 fixtab[i][j][k] = CODE_FOR_nothing;
4568 for (i = 0; i < ARRAY_SIZE (fixtrunctab); i++)
4569 for (j = 0; j < ARRAY_SIZE (fixtrunctab[0]); j++)
4570 for (k = 0; k < ARRAY_SIZE (fixtrunctab[0][0]); k++)
4571 fixtrunctab[i][j][k] = CODE_FOR_nothing;
4573 for (i = 0; i < ARRAY_SIZE (floattab); i++)
4574 for (j = 0; j < ARRAY_SIZE (floattab[0]); j++)
4575 for (k = 0; k < ARRAY_SIZE (floattab[0][0]); k++)
4576 floattab[i][j][k] = CODE_FOR_nothing;
4578 for (i = 0; i < ARRAY_SIZE (extendtab); i++)
4579 for (j = 0; j < ARRAY_SIZE (extendtab[0]); j++)
4580 for (k = 0; k < ARRAY_SIZE (extendtab[0][0]); k++)
4581 extendtab[i][j][k] = CODE_FOR_nothing;
4583 for (i = 0; i < NUM_RTX_CODE; i++)
4584 setcc_gen_code[i] = CODE_FOR_nothing;
4586 #ifdef HAVE_conditional_move
4587 for (i = 0; i < NUM_MACHINE_MODES; i++)
4588 movcc_gen_code[i] = CODE_FOR_nothing;
4589 #endif
4591 add_optab = init_optab (PLUS);
4592 addv_optab = init_optab (PLUS);
4593 sub_optab = init_optab (MINUS);
4594 subv_optab = init_optab (MINUS);
4595 smul_optab = init_optab (MULT);
4596 smulv_optab = init_optab (MULT);
4597 smul_highpart_optab = init_optab (UNKNOWN);
4598 umul_highpart_optab = init_optab (UNKNOWN);
4599 smul_widen_optab = init_optab (UNKNOWN);
4600 umul_widen_optab = init_optab (UNKNOWN);
4601 sdiv_optab = init_optab (DIV);
4602 sdivv_optab = init_optab (DIV);
4603 sdivmod_optab = init_optab (UNKNOWN);
4604 udiv_optab = init_optab (UDIV);
4605 udivmod_optab = init_optab (UNKNOWN);
4606 smod_optab = init_optab (MOD);
4607 umod_optab = init_optab (UMOD);
4608 flodiv_optab = init_optab (DIV);
4609 ftrunc_optab = init_optab (UNKNOWN);
4610 and_optab = init_optab (AND);
4611 ior_optab = init_optab (IOR);
4612 xor_optab = init_optab (XOR);
4613 ashl_optab = init_optab (ASHIFT);
4614 ashr_optab = init_optab (ASHIFTRT);
4615 lshr_optab = init_optab (LSHIFTRT);
4616 rotl_optab = init_optab (ROTATE);
4617 rotr_optab = init_optab (ROTATERT);
4618 smin_optab = init_optab (SMIN);
4619 smax_optab = init_optab (SMAX);
4620 umin_optab = init_optab (UMIN);
4621 umax_optab = init_optab (UMAX);
4622 mov_optab = init_optab (UNKNOWN);
4623 movstrict_optab = init_optab (UNKNOWN);
4624 cmp_optab = init_optab (UNKNOWN);
4625 ucmp_optab = init_optab (UNKNOWN);
4626 tst_optab = init_optab (UNKNOWN);
4627 neg_optab = init_optab (NEG);
4628 negv_optab = init_optab (NEG);
4629 abs_optab = init_optab (ABS);
4630 absv_optab = init_optab (ABS);
4631 one_cmpl_optab = init_optab (NOT);
4632 ffs_optab = init_optab (FFS);
4633 sqrt_optab = init_optab (SQRT);
4634 sin_optab = init_optab (UNKNOWN);
4635 cos_optab = init_optab (UNKNOWN);
4636 strlen_optab = init_optab (UNKNOWN);
4637 cbranch_optab = init_optab (UNKNOWN);
4638 cmov_optab = init_optab (UNKNOWN);
4639 cstore_optab = init_optab (UNKNOWN);
4641 for (i = 0; i < NUM_MACHINE_MODES; i++)
4643 movstr_optab[i] = CODE_FOR_nothing;
4644 clrstr_optab[i] = CODE_FOR_nothing;
4646 #ifdef HAVE_SECONDARY_RELOADS
4647 reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
4648 #endif
4651 /* Fill in the optabs with the insns we support. */
4652 init_all_optabs ();
4654 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
4655 /* This flag says the same insns that convert to a signed fixnum
4656 also convert validly to an unsigned one. */
4657 for (i = 0; i < NUM_MACHINE_MODES; i++)
4658 for (j = 0; j < NUM_MACHINE_MODES; j++)
4659 fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
4660 #endif
4662 /* Initialize the optabs with the names of the library functions. */
4663 init_integral_libfuncs (add_optab, "add", '3');
4664 init_floating_libfuncs (add_optab, "add", '3');
4665 init_integral_libfuncs (addv_optab, "addv", '3');
4666 init_floating_libfuncs (addv_optab, "add", '3');
4667 init_integral_libfuncs (sub_optab, "sub", '3');
4668 init_floating_libfuncs (sub_optab, "sub", '3');
4669 init_integral_libfuncs (subv_optab, "subv", '3');
4670 init_floating_libfuncs (subv_optab, "sub", '3');
4671 init_integral_libfuncs (smul_optab, "mul", '3');
4672 init_floating_libfuncs (smul_optab, "mul", '3');
4673 init_integral_libfuncs (smulv_optab, "mulv", '3');
4674 init_floating_libfuncs (smulv_optab, "mul", '3');
4675 init_integral_libfuncs (sdiv_optab, "div", '3');
4676 init_integral_libfuncs (sdivv_optab, "divv", '3');
4677 init_integral_libfuncs (udiv_optab, "udiv", '3');
4678 init_integral_libfuncs (sdivmod_optab, "divmod", '4');
4679 init_integral_libfuncs (udivmod_optab, "udivmod", '4');
4680 init_integral_libfuncs (smod_optab, "mod", '3');
4681 init_integral_libfuncs (umod_optab, "umod", '3');
4682 init_floating_libfuncs (flodiv_optab, "div", '3');
4683 init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
4684 init_integral_libfuncs (and_optab, "and", '3');
4685 init_integral_libfuncs (ior_optab, "ior", '3');
4686 init_integral_libfuncs (xor_optab, "xor", '3');
4687 init_integral_libfuncs (ashl_optab, "ashl", '3');
4688 init_integral_libfuncs (ashr_optab, "ashr", '3');
4689 init_integral_libfuncs (lshr_optab, "lshr", '3');
4690 init_integral_libfuncs (smin_optab, "min", '3');
4691 init_floating_libfuncs (smin_optab, "min", '3');
4692 init_integral_libfuncs (smax_optab, "max", '3');
4693 init_floating_libfuncs (smax_optab, "max", '3');
4694 init_integral_libfuncs (umin_optab, "umin", '3');
4695 init_integral_libfuncs (umax_optab, "umax", '3');
4696 init_integral_libfuncs (neg_optab, "neg", '2');
4697 init_floating_libfuncs (neg_optab, "neg", '2');
4698 init_integral_libfuncs (negv_optab, "negv", '2');
4699 init_floating_libfuncs (negv_optab, "neg", '2');
4700 init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
4701 init_integral_libfuncs (ffs_optab, "ffs", '2');
4703 /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
4704 init_integral_libfuncs (cmp_optab, "cmp", '2');
4705 init_integral_libfuncs (ucmp_optab, "ucmp", '2');
4706 init_floating_libfuncs (cmp_optab, "cmp", '2');
4708 #ifdef MULSI3_LIBCALL
4709 smul_optab->handlers[(int) SImode].libfunc
4710 = init_one_libfunc (MULSI3_LIBCALL);
4711 #endif
4712 #ifdef MULDI3_LIBCALL
4713 smul_optab->handlers[(int) DImode].libfunc
4714 = init_one_libfunc (MULDI3_LIBCALL);
4715 #endif
4717 #ifdef DIVSI3_LIBCALL
4718 sdiv_optab->handlers[(int) SImode].libfunc
4719 = init_one_libfunc (DIVSI3_LIBCALL);
4720 #endif
4721 #ifdef DIVDI3_LIBCALL
4722 sdiv_optab->handlers[(int) DImode].libfunc
4723 = init_one_libfunc (DIVDI3_LIBCALL);
4724 #endif
4726 #ifdef UDIVSI3_LIBCALL
4727 udiv_optab->handlers[(int) SImode].libfunc
4728 = init_one_libfunc (UDIVSI3_LIBCALL);
4729 #endif
4730 #ifdef UDIVDI3_LIBCALL
4731 udiv_optab->handlers[(int) DImode].libfunc
4732 = init_one_libfunc (UDIVDI3_LIBCALL);
4733 #endif
4735 #ifdef MODSI3_LIBCALL
4736 smod_optab->handlers[(int) SImode].libfunc
4737 = init_one_libfunc (MODSI3_LIBCALL);
4738 #endif
4739 #ifdef MODDI3_LIBCALL
4740 smod_optab->handlers[(int) DImode].libfunc
4741 = init_one_libfunc (MODDI3_LIBCALL);
4742 #endif
4744 #ifdef UMODSI3_LIBCALL
4745 umod_optab->handlers[(int) SImode].libfunc
4746 = init_one_libfunc (UMODSI3_LIBCALL);
4747 #endif
4748 #ifdef UMODDI3_LIBCALL
4749 umod_optab->handlers[(int) DImode].libfunc
4750 = init_one_libfunc (UMODDI3_LIBCALL);
4751 #endif
4753 /* Use cabs for DC complex abs, since systems generally have cabs.
4754 Don't define any libcall for SCmode, so that cabs will be used. */
4755 abs_optab->handlers[(int) DCmode].libfunc
4756 = init_one_libfunc ("cabs");
4758 /* The ffs function operates on `int'. */
4759 ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)].libfunc
4760 = init_one_libfunc ("ffs");
4762 extendsfdf2_libfunc = init_one_libfunc ("__extendsfdf2");
4763 extendsfxf2_libfunc = init_one_libfunc ("__extendsfxf2");
4764 extendsftf2_libfunc = init_one_libfunc ("__extendsftf2");
4765 extenddfxf2_libfunc = init_one_libfunc ("__extenddfxf2");
4766 extenddftf2_libfunc = init_one_libfunc ("__extenddftf2");
4768 truncdfsf2_libfunc = init_one_libfunc ("__truncdfsf2");
4769 truncxfsf2_libfunc = init_one_libfunc ("__truncxfsf2");
4770 trunctfsf2_libfunc = init_one_libfunc ("__trunctfsf2");
4771 truncxfdf2_libfunc = init_one_libfunc ("__truncxfdf2");
4772 trunctfdf2_libfunc = init_one_libfunc ("__trunctfdf2");
4774 memcpy_libfunc = init_one_libfunc ("memcpy");
4775 memmove_libfunc = init_one_libfunc ("memmove");
4776 bcopy_libfunc = init_one_libfunc ("bcopy");
4777 memcmp_libfunc = init_one_libfunc ("memcmp");
4778 bcmp_libfunc = init_one_libfunc ("__gcc_bcmp");
4779 memset_libfunc = init_one_libfunc ("memset");
4780 bzero_libfunc = init_one_libfunc ("bzero");
4782 unwind_resume_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
4783 ? "_Unwind_SjLj_Resume"
4784 : "_Unwind_Resume");
4785 #ifndef DONT_USE_BUILTIN_SETJMP
4786 setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
4787 longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
4788 #else
4789 setjmp_libfunc = init_one_libfunc ("setjmp");
4790 longjmp_libfunc = init_one_libfunc ("longjmp");
4791 #endif
4792 unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
4793 unwind_sjlj_unregister_libfunc
4794 = init_one_libfunc ("_Unwind_SjLj_Unregister");
4796 eqhf2_libfunc = init_one_libfunc ("__eqhf2");
4797 nehf2_libfunc = init_one_libfunc ("__nehf2");
4798 gthf2_libfunc = init_one_libfunc ("__gthf2");
4799 gehf2_libfunc = init_one_libfunc ("__gehf2");
4800 lthf2_libfunc = init_one_libfunc ("__lthf2");
4801 lehf2_libfunc = init_one_libfunc ("__lehf2");
4802 unordhf2_libfunc = init_one_libfunc ("__unordhf2");
4804 eqsf2_libfunc = init_one_libfunc ("__eqsf2");
4805 nesf2_libfunc = init_one_libfunc ("__nesf2");
4806 gtsf2_libfunc = init_one_libfunc ("__gtsf2");
4807 gesf2_libfunc = init_one_libfunc ("__gesf2");
4808 ltsf2_libfunc = init_one_libfunc ("__ltsf2");
4809 lesf2_libfunc = init_one_libfunc ("__lesf2");
4810 unordsf2_libfunc = init_one_libfunc ("__unordsf2");
4812 eqdf2_libfunc = init_one_libfunc ("__eqdf2");
4813 nedf2_libfunc = init_one_libfunc ("__nedf2");
4814 gtdf2_libfunc = init_one_libfunc ("__gtdf2");
4815 gedf2_libfunc = init_one_libfunc ("__gedf2");
4816 ltdf2_libfunc = init_one_libfunc ("__ltdf2");
4817 ledf2_libfunc = init_one_libfunc ("__ledf2");
4818 unorddf2_libfunc = init_one_libfunc ("__unorddf2");
4820 eqxf2_libfunc = init_one_libfunc ("__eqxf2");
4821 nexf2_libfunc = init_one_libfunc ("__nexf2");
4822 gtxf2_libfunc = init_one_libfunc ("__gtxf2");
4823 gexf2_libfunc = init_one_libfunc ("__gexf2");
4824 ltxf2_libfunc = init_one_libfunc ("__ltxf2");
4825 lexf2_libfunc = init_one_libfunc ("__lexf2");
4826 unordxf2_libfunc = init_one_libfunc ("__unordxf2");
4828 eqtf2_libfunc = init_one_libfunc ("__eqtf2");
4829 netf2_libfunc = init_one_libfunc ("__netf2");
4830 gttf2_libfunc = init_one_libfunc ("__gttf2");
4831 getf2_libfunc = init_one_libfunc ("__getf2");
4832 lttf2_libfunc = init_one_libfunc ("__lttf2");
4833 letf2_libfunc = init_one_libfunc ("__letf2");
4834 unordtf2_libfunc = init_one_libfunc ("__unordtf2");
4836 floatsisf_libfunc = init_one_libfunc ("__floatsisf");
4837 floatdisf_libfunc = init_one_libfunc ("__floatdisf");
4838 floattisf_libfunc = init_one_libfunc ("__floattisf");
4840 floatsidf_libfunc = init_one_libfunc ("__floatsidf");
4841 floatdidf_libfunc = init_one_libfunc ("__floatdidf");
4842 floattidf_libfunc = init_one_libfunc ("__floattidf");
4844 floatsixf_libfunc = init_one_libfunc ("__floatsixf");
4845 floatdixf_libfunc = init_one_libfunc ("__floatdixf");
4846 floattixf_libfunc = init_one_libfunc ("__floattixf");
4848 floatsitf_libfunc = init_one_libfunc ("__floatsitf");
4849 floatditf_libfunc = init_one_libfunc ("__floatditf");
4850 floattitf_libfunc = init_one_libfunc ("__floattitf");
4852 fixsfsi_libfunc = init_one_libfunc ("__fixsfsi");
4853 fixsfdi_libfunc = init_one_libfunc ("__fixsfdi");
4854 fixsfti_libfunc = init_one_libfunc ("__fixsfti");
4856 fixdfsi_libfunc = init_one_libfunc ("__fixdfsi");
4857 fixdfdi_libfunc = init_one_libfunc ("__fixdfdi");
4858 fixdfti_libfunc = init_one_libfunc ("__fixdfti");
4860 fixxfsi_libfunc = init_one_libfunc ("__fixxfsi");
4861 fixxfdi_libfunc = init_one_libfunc ("__fixxfdi");
4862 fixxfti_libfunc = init_one_libfunc ("__fixxfti");
4864 fixtfsi_libfunc = init_one_libfunc ("__fixtfsi");
4865 fixtfdi_libfunc = init_one_libfunc ("__fixtfdi");
4866 fixtfti_libfunc = init_one_libfunc ("__fixtfti");
4868 fixunssfsi_libfunc = init_one_libfunc ("__fixunssfsi");
4869 fixunssfdi_libfunc = init_one_libfunc ("__fixunssfdi");
4870 fixunssfti_libfunc = init_one_libfunc ("__fixunssfti");
4872 fixunsdfsi_libfunc = init_one_libfunc ("__fixunsdfsi");
4873 fixunsdfdi_libfunc = init_one_libfunc ("__fixunsdfdi");
4874 fixunsdfti_libfunc = init_one_libfunc ("__fixunsdfti");
4876 fixunsxfsi_libfunc = init_one_libfunc ("__fixunsxfsi");
4877 fixunsxfdi_libfunc = init_one_libfunc ("__fixunsxfdi");
4878 fixunsxfti_libfunc = init_one_libfunc ("__fixunsxfti");
4880 fixunstfsi_libfunc = init_one_libfunc ("__fixunstfsi");
4881 fixunstfdi_libfunc = init_one_libfunc ("__fixunstfdi");
4882 fixunstfti_libfunc = init_one_libfunc ("__fixunstfti");
4884 /* For check-memory-usage. */
4885 chkr_check_addr_libfunc = init_one_libfunc ("chkr_check_addr");
4886 chkr_set_right_libfunc = init_one_libfunc ("chkr_set_right");
4887 chkr_copy_bitmap_libfunc = init_one_libfunc ("chkr_copy_bitmap");
4888 chkr_check_exec_libfunc = init_one_libfunc ("chkr_check_exec");
4889 chkr_check_str_libfunc = init_one_libfunc ("chkr_check_str");
4891 /* For function entry/exit instrumentation. */
4892 profile_function_entry_libfunc
4893 = init_one_libfunc ("__cyg_profile_func_enter");
4894 profile_function_exit_libfunc
4895 = init_one_libfunc ("__cyg_profile_func_exit");
4897 #ifdef HAVE_conditional_trap
4898 init_traps ();
4899 #endif
4901 #ifdef INIT_TARGET_OPTABS
4902 /* Allow the target to add more libcalls or rename some, etc. */
4903 INIT_TARGET_OPTABS;
4904 #endif
4906 /* Add these GC roots. */
4907 ggc_add_root (optab_table, OTI_MAX, sizeof(optab), mark_optab);
4908 ggc_add_rtx_root (libfunc_table, LTI_MAX);
4911 #ifdef HAVE_conditional_trap
4912 /* The insn generating function can not take an rtx_code argument.
4913 TRAP_RTX is used as an rtx argument. Its code is replaced with
4914 the code to be used in the trap insn and all other fields are
4915 ignored. */
4916 static rtx trap_rtx;
4918 static void
4919 init_traps ()
4921 if (HAVE_conditional_trap)
4923 trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);
4924 ggc_add_rtx_root (&trap_rtx, 1);
4927 #endif
4929 /* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
4930 CODE. Return 0 on failure. */
4933 gen_cond_trap (code, op1, op2, tcode)
4934 enum rtx_code code ATTRIBUTE_UNUSED;
4935 rtx op1, op2 ATTRIBUTE_UNUSED, tcode ATTRIBUTE_UNUSED;
4937 enum machine_mode mode = GET_MODE (op1);
4939 if (mode == VOIDmode)
4940 return 0;
4942 #ifdef HAVE_conditional_trap
4943 if (HAVE_conditional_trap
4944 && cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
4946 rtx insn;
4947 start_sequence();
4948 emit_insn (GEN_FCN (cmp_optab->handlers[(int) mode].insn_code) (op1, op2));
4949 PUT_CODE (trap_rtx, code);
4950 insn = gen_conditional_trap (trap_rtx, tcode);
4951 if (insn)
4953 emit_insn (insn);
4954 insn = gen_sequence ();
4956 end_sequence();
4957 return insn;
4959 #endif
4961 return 0;