[official-gcc.git] / gcc / optabs.c
blob2b9091bcf4e05c0f59aa876dd8db646f7310a484
1 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2 Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
22 #include "config.h"
23 #include "system.h"
24 #include "toplev.h"
26 /* Include insn-config.h before expr.h so that HAVE_conditional_move
27 is properly defined. */
28 #include "insn-config.h"
29 #include "rtl.h"
30 #include "tree.h"
31 #include "flags.h"
32 #include "insn-flags.h"
33 #include "insn-codes.h"
34 #include "expr.h"
35 #include "recog.h"
36 #include "reload.h"
38 /* Each optab contains info on how this target machine
39 can perform a particular operation
40 for all sizes and kinds of operands.
42 The operation to be performed is often specified
43 by passing one of these optabs as an argument.
45 See expr.h for documentation of these optabs. */
47 optab add_optab;
48 optab sub_optab;
49 optab smul_optab;
50 optab smul_highpart_optab;
51 optab umul_highpart_optab;
52 optab smul_widen_optab;
53 optab umul_widen_optab;
54 optab sdiv_optab;
55 optab sdivmod_optab;
56 optab udiv_optab;
57 optab udivmod_optab;
58 optab smod_optab;
59 optab umod_optab;
60 optab flodiv_optab;
61 optab ftrunc_optab;
62 optab and_optab;
63 optab ior_optab;
64 optab xor_optab;
65 optab ashl_optab;
66 optab lshr_optab;
67 optab ashr_optab;
68 optab rotl_optab;
69 optab rotr_optab;
70 optab smin_optab;
71 optab smax_optab;
72 optab umin_optab;
73 optab umax_optab;
75 optab mov_optab;
76 optab movstrict_optab;
78 optab neg_optab;
79 optab abs_optab;
80 optab one_cmpl_optab;
81 optab ffs_optab;
82 optab sqrt_optab;
83 optab sin_optab;
84 optab cos_optab;
86 optab cmp_optab;
87 optab ucmp_optab; /* Used only for libcalls for unsigned comparisons. */
88 optab tst_optab;
90 optab strlen_optab;
92 /* Tables of patterns for extending one integer mode to another. */
93 enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2];
95 /* Tables of patterns for converting between fixed and floating point. */
96 enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
97 enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
98 enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
100 /* Contains the optab used for each rtx code. */
101 optab code_to_optab[NUM_RTX_CODE + 1];
103 /* SYMBOL_REF rtx's for the library functions that are called
104 implicitly and not via optabs. */
106 rtx extendsfdf2_libfunc;
107 rtx extendsfxf2_libfunc;
108 rtx extendsftf2_libfunc;
109 rtx extenddfxf2_libfunc;
110 rtx extenddftf2_libfunc;
112 rtx truncdfsf2_libfunc;
113 rtx truncxfsf2_libfunc;
114 rtx trunctfsf2_libfunc;
115 rtx truncxfdf2_libfunc;
116 rtx trunctfdf2_libfunc;
118 rtx memcpy_libfunc;
119 rtx bcopy_libfunc;
120 rtx memcmp_libfunc;
121 rtx bcmp_libfunc;
122 rtx memset_libfunc;
123 rtx bzero_libfunc;
125 rtx throw_libfunc;
126 rtx rethrow_libfunc;
127 rtx sjthrow_libfunc;
128 rtx sjpopnthrow_libfunc;
129 rtx terminate_libfunc;
130 rtx setjmp_libfunc;
131 rtx longjmp_libfunc;
132 rtx eh_rtime_match_libfunc;
134 rtx eqhf2_libfunc;
135 rtx nehf2_libfunc;
136 rtx gthf2_libfunc;
137 rtx gehf2_libfunc;
138 rtx lthf2_libfunc;
139 rtx lehf2_libfunc;
141 rtx eqsf2_libfunc;
142 rtx nesf2_libfunc;
143 rtx gtsf2_libfunc;
144 rtx gesf2_libfunc;
145 rtx ltsf2_libfunc;
146 rtx lesf2_libfunc;
148 rtx eqdf2_libfunc;
149 rtx nedf2_libfunc;
150 rtx gtdf2_libfunc;
151 rtx gedf2_libfunc;
152 rtx ltdf2_libfunc;
153 rtx ledf2_libfunc;
155 rtx eqxf2_libfunc;
156 rtx nexf2_libfunc;
157 rtx gtxf2_libfunc;
158 rtx gexf2_libfunc;
159 rtx ltxf2_libfunc;
160 rtx lexf2_libfunc;
162 rtx eqtf2_libfunc;
163 rtx netf2_libfunc;
164 rtx gttf2_libfunc;
165 rtx getf2_libfunc;
166 rtx lttf2_libfunc;
167 rtx letf2_libfunc;
169 rtx floatsisf_libfunc;
170 rtx floatdisf_libfunc;
171 rtx floattisf_libfunc;
173 rtx floatsidf_libfunc;
174 rtx floatdidf_libfunc;
175 rtx floattidf_libfunc;
177 rtx floatsixf_libfunc;
178 rtx floatdixf_libfunc;
179 rtx floattixf_libfunc;
181 rtx floatsitf_libfunc;
182 rtx floatditf_libfunc;
183 rtx floattitf_libfunc;
185 rtx fixsfsi_libfunc;
186 rtx fixsfdi_libfunc;
187 rtx fixsfti_libfunc;
189 rtx fixdfsi_libfunc;
190 rtx fixdfdi_libfunc;
191 rtx fixdfti_libfunc;
193 rtx fixxfsi_libfunc;
194 rtx fixxfdi_libfunc;
195 rtx fixxfti_libfunc;
197 rtx fixtfsi_libfunc;
198 rtx fixtfdi_libfunc;
199 rtx fixtfti_libfunc;
201 rtx fixunssfsi_libfunc;
202 rtx fixunssfdi_libfunc;
203 rtx fixunssfti_libfunc;
205 rtx fixunsdfsi_libfunc;
206 rtx fixunsdfdi_libfunc;
207 rtx fixunsdfti_libfunc;
209 rtx fixunsxfsi_libfunc;
210 rtx fixunsxfdi_libfunc;
211 rtx fixunsxfti_libfunc;
213 rtx fixunstfsi_libfunc;
214 rtx fixunstfdi_libfunc;
215 rtx fixunstfti_libfunc;
217 rtx chkr_check_addr_libfunc;
218 rtx chkr_set_right_libfunc;
219 rtx chkr_copy_bitmap_libfunc;
220 rtx chkr_check_exec_libfunc;
221 rtx chkr_check_str_libfunc;
223 rtx profile_function_entry_libfunc;
224 rtx profile_function_exit_libfunc;
226 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
227 gives the gen_function to make a branch to test that condition. */
229 rtxfun bcc_gen_fctn[NUM_RTX_CODE];
231 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
232 gives the insn code to make a store-condition insn
233 to test that condition. */
235 enum insn_code setcc_gen_code[NUM_RTX_CODE];
237 #ifdef HAVE_conditional_move
238 /* Indexed by the machine mode, gives the insn code to make a conditional
239 move insn. This is not indexed by the rtx-code like bcc_gen_fctn and
240 setcc_gen_code to cut down on the number of named patterns. Consider a day
241 when a lot more rtx codes are conditional (eg: for the ARM). */
243 enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
244 #endif
246 static int add_equal_note PROTO((rtx, rtx, enum rtx_code, rtx, rtx));
247 static rtx widen_operand PROTO((rtx, enum machine_mode,
248 enum machine_mode, int, int));
249 static int expand_cmplxdiv_straight PROTO((rtx, rtx, rtx, rtx,
250 rtx, rtx, enum machine_mode,
251 int, enum optab_methods,
252 enum mode_class, optab));
253 static int expand_cmplxdiv_wide PROTO((rtx, rtx, rtx, rtx,
254 rtx, rtx, enum machine_mode,
255 int, enum optab_methods,
256 enum mode_class, optab));
257 static enum insn_code can_fix_p PROTO((enum machine_mode, enum machine_mode,
258 int, int *));
259 static enum insn_code can_float_p PROTO((enum machine_mode, enum machine_mode,
260 int));
261 static rtx ftruncify PROTO((rtx));
262 static optab init_optab PROTO((enum rtx_code));
263 static void init_libfuncs PROTO((optab, int, int, const char *, int));
264 static void init_integral_libfuncs PROTO((optab, const char *, int));
265 static void init_floating_libfuncs PROTO((optab, const char *, int));
266 #ifdef HAVE_conditional_trap
267 static void init_traps PROTO((void));
268 #endif
270 /* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
271 the result of operation CODE applied to OP0 (and OP1 if it is a binary
272 operation).
274 If the last insn does not set TARGET, don't do anything, but return 1.
276 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
277 don't add the REG_EQUAL note but return 0. Our caller can then try
278 again, ensuring that TARGET is not one of the operands. */
280 static int
281 add_equal_note (seq, target, code, op0, op1)
282 rtx seq;
283 rtx target;
284 enum rtx_code code;
285 rtx op0, op1;
287 rtx set;
288 int i;
289 rtx note;
291 if ((GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2'
292 && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<')
293 || GET_CODE (seq) != SEQUENCE
294 || (set = single_set (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))) == 0
295 || GET_CODE (target) == ZERO_EXTRACT
296 || (! rtx_equal_p (SET_DEST (set), target)
297 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
298 SUBREG. */
299 && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
300 || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)),
301 target))))
302 return 1;
304 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
305 besides the last insn. */
306 if (reg_overlap_mentioned_p (target, op0)
307 || (op1 && reg_overlap_mentioned_p (target, op1)))
308 for (i = XVECLEN (seq, 0) - 2; i >= 0; i--)
309 if (reg_set_p (target, XVECEXP (seq, 0, i)))
310 return 0;
312 if (GET_RTX_CLASS (code) == '1')
313 note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0));
314 else
315 note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
317 set_unique_reg_note (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1), REG_EQUAL, note);
319 return 1;
322 /* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP
323 says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need
324 not actually do a sign-extend or zero-extend, but can leave the
325 higher-order bits of the result rtx undefined, for example, in the case
326 of logical operations, but not right shifts. */
328 static rtx
329 widen_operand (op, mode, oldmode, unsignedp, no_extend)
330 rtx op;
331 enum machine_mode mode, oldmode;
332 int unsignedp;
333 int no_extend;
335 rtx result;
337 /* If we must extend do so. If OP is either a constant or a SUBREG
338 for a promoted object, also extend since it will be more efficient to
339 do so. */
340 if (! no_extend
341 || GET_MODE (op) == VOIDmode
342 || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op)))
343 return convert_modes (mode, oldmode, op, unsignedp);
345 /* If MODE is no wider than a single word, we return a paradoxical
346 SUBREG. */
347 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
348 return gen_rtx_SUBREG (mode, force_reg (GET_MODE (op), op), 0);
350 /* Otherwise, get an object of MODE, clobber it, and set the low-order
351 part to OP. */
353 result = gen_reg_rtx (mode);
354 emit_insn (gen_rtx_CLOBBER (VOIDmode, result));
355 emit_move_insn (gen_lowpart (GET_MODE (op), result), op);
356 return result;
359 /* Generate code to perform a straightforward complex divide. */
361 static int
362 expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
363 unsignedp, methods, class, binoptab)
364 rtx real0, real1, imag0, imag1, realr, imagr;
365 enum machine_mode submode;
366 int unsignedp;
367 enum optab_methods methods;
368 enum mode_class class;
369 optab binoptab;
371 rtx divisor;
372 rtx real_t, imag_t;
373 rtx temp1, temp2;
374 rtx res;
376 /* Don't fetch these from memory more than once. */
377 real0 = force_reg (submode, real0);
378 real1 = force_reg (submode, real1);
380 if (imag0 != 0)
381 imag0 = force_reg (submode, imag0);
383 imag1 = force_reg (submode, imag1);
385 /* Divisor: c*c + d*d. */
386 temp1 = expand_binop (submode, smul_optab, real1, real1,
387 NULL_RTX, unsignedp, methods);
389 temp2 = expand_binop (submode, smul_optab, imag1, imag1,
390 NULL_RTX, unsignedp, methods);
392 if (temp1 == 0 || temp2 == 0)
393 return 0;
395 divisor = expand_binop (submode, add_optab, temp1, temp2,
396 NULL_RTX, unsignedp, methods);
397 if (divisor == 0)
398 return 0;
400 if (imag0 == 0)
402 /* Mathematically, ((a)(c-id))/divisor. */
403 /* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)). */
405 /* Calculate the dividend. */
406 real_t = expand_binop (submode, smul_optab, real0, real1,
407 NULL_RTX, unsignedp, methods);
409 imag_t = expand_binop (submode, smul_optab, real0, imag1,
410 NULL_RTX, unsignedp, methods);
412 if (real_t == 0 || imag_t == 0)
413 return 0;
415 imag_t = expand_unop (submode, neg_optab, imag_t,
416 NULL_RTX, unsignedp);
418 else
420 /* Mathematically, ((a+ib)(c-id))/divider. */
421 /* Calculate the dividend. */
422 temp1 = expand_binop (submode, smul_optab, real0, real1,
423 NULL_RTX, unsignedp, methods);
425 temp2 = expand_binop (submode, smul_optab, imag0, imag1,
426 NULL_RTX, unsignedp, methods);
428 if (temp1 == 0 || temp2 == 0)
429 return 0;
431 real_t = expand_binop (submode, add_optab, temp1, temp2,
432 NULL_RTX, unsignedp, methods);
434 temp1 = expand_binop (submode, smul_optab, imag0, real1,
435 NULL_RTX, unsignedp, methods);
437 temp2 = expand_binop (submode, smul_optab, real0, imag1,
438 NULL_RTX, unsignedp, methods);
440 if (temp1 == 0 || temp2 == 0)
441 return 0;
443 imag_t = expand_binop (submode, sub_optab, temp1, temp2,
444 NULL_RTX, unsignedp, methods);
446 if (real_t == 0 || imag_t == 0)
447 return 0;
450 if (class == MODE_COMPLEX_FLOAT)
451 res = expand_binop (submode, binoptab, real_t, divisor,
452 realr, unsignedp, methods);
453 else
454 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
455 real_t, divisor, realr, unsignedp);
457 if (res == 0)
458 return 0;
460 if (res != realr)
461 emit_move_insn (realr, res);
463 if (class == MODE_COMPLEX_FLOAT)
464 res = expand_binop (submode, binoptab, imag_t, divisor,
465 imagr, unsignedp, methods);
466 else
467 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
468 imag_t, divisor, imagr, unsignedp);
470 if (res == 0)
471 return 0;
473 if (res != imagr)
474 emit_move_insn (imagr, res);
476 return 1;
479 /* Generate code to perform a wide-input-range-acceptable complex divide. */
481 static int
482 expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
483 unsignedp, methods, class, binoptab)
484 rtx real0, real1, imag0, imag1, realr, imagr;
485 enum machine_mode submode;
486 int unsignedp;
487 enum optab_methods methods;
488 enum mode_class class;
489 optab binoptab;
491 rtx ratio, divisor;
492 rtx real_t, imag_t;
493 rtx temp1, temp2, lab1, lab2;
494 enum machine_mode mode;
495 int align;
496 rtx res;
498 /* Don't fetch these from memory more than once. */
499 real0 = force_reg (submode, real0);
500 real1 = force_reg (submode, real1);
502 if (imag0 != 0)
503 imag0 = force_reg (submode, imag0);
505 imag1 = force_reg (submode, imag1);
507 /* XXX What's an "unsigned" complex number? */
508 if (unsignedp)
510 temp1 = real1;
511 temp2 = imag1;
513 else
515 temp1 = expand_abs (submode, real1, NULL_RTX, 1);
516 temp2 = expand_abs (submode, imag1, NULL_RTX, 1);
519 if (temp1 == 0 || temp2 == 0)
520 return 0;
522 mode = GET_MODE (temp1);
523 align = GET_MODE_ALIGNMENT (mode);
524 lab1 = gen_label_rtx ();
525 emit_cmp_and_jump_insns (temp1, temp2, LT, NULL_RTX,
526 mode, unsignedp, align, lab1);
528 /* |c| >= |d|; use ratio d/c to scale dividend and divisor. */
530 if (class == MODE_COMPLEX_FLOAT)
531 ratio = expand_binop (submode, binoptab, imag1, real1,
532 NULL_RTX, unsignedp, methods);
533 else
534 ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
535 imag1, real1, NULL_RTX, unsignedp);
537 if (ratio == 0)
538 return 0;
540 /* Calculate divisor. */
542 temp1 = expand_binop (submode, smul_optab, imag1, ratio,
543 NULL_RTX, unsignedp, methods);
545 if (temp1 == 0)
546 return 0;
548 divisor = expand_binop (submode, add_optab, temp1, real1,
549 NULL_RTX, unsignedp, methods);
551 if (divisor == 0)
552 return 0;
554 /* Calculate dividend. */
556 if (imag0 == 0)
558 real_t = real0;
560 /* Compute a / (c+id) as a / (c+d(d/c)) + i (-a(d/c)) / (c+d(d/c)). */
562 imag_t = expand_binop (submode, smul_optab, real0, ratio,
563 NULL_RTX, unsignedp, methods);
565 if (imag_t == 0)
566 return 0;
568 imag_t = expand_unop (submode, neg_optab, imag_t,
569 NULL_RTX, unsignedp);
571 if (real_t == 0 || imag_t == 0)
572 return 0;
574 else
576 /* Compute (a+ib)/(c+id) as
577 (a+b(d/c))/(c+d(d/c) + i(b-a(d/c))/(c+d(d/c)). */
579 temp1 = expand_binop (submode, smul_optab, imag0, ratio,
580 NULL_RTX, unsignedp, methods);
582 if (temp1 == 0)
583 return 0;
585 real_t = expand_binop (submode, add_optab, temp1, real0,
586 NULL_RTX, unsignedp, methods);
588 temp1 = expand_binop (submode, smul_optab, real0, ratio,
589 NULL_RTX, unsignedp, methods);
591 if (temp1 == 0)
592 return 0;
594 imag_t = expand_binop (submode, sub_optab, imag0, temp1,
595 NULL_RTX, unsignedp, methods);
597 if (real_t == 0 || imag_t == 0)
598 return 0;
601 if (class == MODE_COMPLEX_FLOAT)
602 res = expand_binop (submode, binoptab, real_t, divisor,
603 realr, unsignedp, methods);
604 else
605 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
606 real_t, divisor, realr, unsignedp);
608 if (res == 0)
609 return 0;
611 if (res != realr)
612 emit_move_insn (realr, res);
614 if (class == MODE_COMPLEX_FLOAT)
615 res = expand_binop (submode, binoptab, imag_t, divisor,
616 imagr, unsignedp, methods);
617 else
618 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
619 imag_t, divisor, imagr, unsignedp);
621 if (res == 0)
622 return 0;
624 if (res != imagr)
625 emit_move_insn (imagr, res);
627 lab2 = gen_label_rtx ();
628 emit_jump_insn (gen_jump (lab2));
629 emit_barrier ();
631 emit_label (lab1);
633 /* |d| > |c|; use ratio c/d to scale dividend and divisor. */
635 if (class == MODE_COMPLEX_FLOAT)
636 ratio = expand_binop (submode, binoptab, real1, imag1,
637 NULL_RTX, unsignedp, methods);
638 else
639 ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
640 real1, imag1, NULL_RTX, unsignedp);
642 if (ratio == 0)
643 return 0;
645 /* Calculate divisor. */
647 temp1 = expand_binop (submode, smul_optab, real1, ratio,
648 NULL_RTX, unsignedp, methods);
650 if (temp1 == 0)
651 return 0;
653 divisor = expand_binop (submode, add_optab, temp1, imag1,
654 NULL_RTX, unsignedp, methods);
656 if (divisor == 0)
657 return 0;
659 /* Calculate dividend. */
661 if (imag0 == 0)
663 /* Compute a / (c+id) as a(c/d) / (c(c/d)+d) + i (-a) / (c(c/d)+d). */
665 real_t = expand_binop (submode, smul_optab, real0, ratio,
666 NULL_RTX, unsignedp, methods);
668 imag_t = expand_unop (submode, neg_optab, real0,
669 NULL_RTX, unsignedp);
671 if (real_t == 0 || imag_t == 0)
672 return 0;
674 else
676 /* Compute (a+ib)/(c+id) as
677 (a(c/d)+b)/(c(c/d)+d) + i (b(c/d)-a)/(c(c/d)+d). */
679 temp1 = expand_binop (submode, smul_optab, real0, ratio,
680 NULL_RTX, unsignedp, methods);
682 if (temp1 == 0)
683 return 0;
685 real_t = expand_binop (submode, add_optab, temp1, imag0,
686 NULL_RTX, unsignedp, methods);
688 temp1 = expand_binop (submode, smul_optab, imag0, ratio,
689 NULL_RTX, unsignedp, methods);
691 if (temp1 == 0)
692 return 0;
694 imag_t = expand_binop (submode, sub_optab, temp1, real0,
695 NULL_RTX, unsignedp, methods);
697 if (real_t == 0 || imag_t == 0)
698 return 0;
701 if (class == MODE_COMPLEX_FLOAT)
702 res = expand_binop (submode, binoptab, real_t, divisor,
703 realr, unsignedp, methods);
704 else
705 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
706 real_t, divisor, realr, unsignedp);
708 if (res == 0)
709 return 0;
711 if (res != realr)
712 emit_move_insn (realr, res);
714 if (class == MODE_COMPLEX_FLOAT)
715 res = expand_binop (submode, binoptab, imag_t, divisor,
716 imagr, unsignedp, methods);
717 else
718 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
719 imag_t, divisor, imagr, unsignedp);
721 if (res == 0)
722 return 0;
724 if (res != imagr)
725 emit_move_insn (imagr, res);
727 emit_label (lab2);
729 return 1;
732 /* Generate code to perform an operation specified by BINOPTAB
733 on operands OP0 and OP1, with result having machine-mode MODE.
735 UNSIGNEDP is for the case where we have to widen the operands
736 to perform the operation. It says to use zero-extension.
738 If TARGET is nonzero, the value
739 is generated there, if it is convenient to do so.
740 In all cases an rtx is returned for the locus of the value;
741 this may or may not be TARGET. */
744 expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
745 enum machine_mode mode;
746 optab binoptab;
747 rtx op0, op1;
748 rtx target;
749 int unsignedp;
750 enum optab_methods methods;
752 enum optab_methods next_methods
753 = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN
754 ? OPTAB_WIDEN : methods);
755 enum mode_class class;
756 enum machine_mode wider_mode;
757 register rtx temp;
758 int commutative_op = 0;
759 int shift_op = (binoptab->code == ASHIFT
760 || binoptab->code == ASHIFTRT
761 || binoptab->code == LSHIFTRT
762 || binoptab->code == ROTATE
763 || binoptab->code == ROTATERT);
764 rtx entry_last = get_last_insn ();
765 rtx last;
767 class = GET_MODE_CLASS (mode);
769 op0 = protect_from_queue (op0, 0);
770 op1 = protect_from_queue (op1, 0);
771 if (target)
772 target = protect_from_queue (target, 1);
774 if (flag_force_mem)
776 op0 = force_not_mem (op0);
777 op1 = force_not_mem (op1);
780 /* If subtracting an integer constant, convert this into an addition of
781 the negated constant. */
783 if (binoptab == sub_optab && GET_CODE (op1) == CONST_INT)
785 op1 = negate_rtx (mode, op1);
786 binoptab = add_optab;
789 /* If we are inside an appropriately-short loop and one operand is an
790 expensive constant, force it into a register. */
791 if (CONSTANT_P (op0) && preserve_subexpressions_p ()
792 && rtx_cost (op0, binoptab->code) > 2)
793 op0 = force_reg (mode, op0);
795 if (CONSTANT_P (op1) && preserve_subexpressions_p ()
796 && ! shift_op && rtx_cost (op1, binoptab->code) > 2)
797 op1 = force_reg (mode, op1);
799 /* Record where to delete back to if we backtrack. */
800 last = get_last_insn ();
802 /* If operation is commutative,
803 try to make the first operand a register.
804 Even better, try to make it the same as the target.
805 Also try to make the last operand a constant. */
806 if (GET_RTX_CLASS (binoptab->code) == 'c'
807 || binoptab == smul_widen_optab
808 || binoptab == umul_widen_optab
809 || binoptab == smul_highpart_optab
810 || binoptab == umul_highpart_optab)
812 commutative_op = 1;
814 if (((target == 0 || GET_CODE (target) == REG)
815 ? ((GET_CODE (op1) == REG
816 && GET_CODE (op0) != REG)
817 || target == op1)
818 : rtx_equal_p (op1, target))
819 || GET_CODE (op0) == CONST_INT)
821 temp = op1;
822 op1 = op0;
823 op0 = temp;
827 /* If we can do it with a three-operand insn, do so. */
829 if (methods != OPTAB_MUST_WIDEN
830 && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
832 int icode = (int) binoptab->handlers[(int) mode].insn_code;
833 enum machine_mode mode0 = insn_operand_mode[icode][1];
834 enum machine_mode mode1 = insn_operand_mode[icode][2];
835 rtx pat;
836 rtx xop0 = op0, xop1 = op1;
838 if (target)
839 temp = target;
840 else
841 temp = gen_reg_rtx (mode);
843 /* If it is a commutative operator and the modes would match
844 if we would swap the operands, we can save the conversions. */
845 if (commutative_op)
847 if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
848 && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
850 register rtx tmp;
852 tmp = op0; op0 = op1; op1 = tmp;
853 tmp = xop0; xop0 = xop1; xop1 = tmp;
857 /* In case the insn wants input operands in modes different from
858 the result, convert the operands. */
860 if (GET_MODE (op0) != VOIDmode
861 && GET_MODE (op0) != mode0
862 && mode0 != VOIDmode)
863 xop0 = convert_to_mode (mode0, xop0, unsignedp);
865 if (GET_MODE (xop1) != VOIDmode
866 && GET_MODE (xop1) != mode1
867 && mode1 != VOIDmode)
868 xop1 = convert_to_mode (mode1, xop1, unsignedp);
870 /* Now, if insn's predicates don't allow our operands, put them into
871 pseudo regs. */
873 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0)
874 && mode0 != VOIDmode)
875 xop0 = copy_to_mode_reg (mode0, xop0);
877 if (! (*insn_operand_predicate[icode][2]) (xop1, mode1)
878 && mode1 != VOIDmode)
879 xop1 = copy_to_mode_reg (mode1, xop1);
881 if (! (*insn_operand_predicate[icode][0]) (temp, mode))
882 temp = gen_reg_rtx (mode);
884 pat = GEN_FCN (icode) (temp, xop0, xop1);
885 if (pat)
887 /* If PAT is a multi-insn sequence, try to add an appropriate
888 REG_EQUAL note to it. If we can't because TEMP conflicts with an
889 operand, call ourselves again, this time without a target. */
890 if (GET_CODE (pat) == SEQUENCE
891 && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
893 delete_insns_since (last);
894 return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
895 unsignedp, methods);
898 emit_insn (pat);
899 return temp;
901 else
902 delete_insns_since (last);
905 /* If this is a multiply, see if we can do a widening operation that
906 takes operands of this mode and makes a wider mode. */
908 if (binoptab == smul_optab && GET_MODE_WIDER_MODE (mode) != VOIDmode
909 && (((unsignedp ? umul_widen_optab : smul_widen_optab)
910 ->handlers[(int) GET_MODE_WIDER_MODE (mode)].insn_code)
911 != CODE_FOR_nothing))
913 temp = expand_binop (GET_MODE_WIDER_MODE (mode),
914 unsignedp ? umul_widen_optab : smul_widen_optab,
915 op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT);
917 if (temp != 0)
919 if (GET_MODE_CLASS (mode) == MODE_INT)
920 return gen_lowpart (mode, temp);
921 else
922 return convert_to_mode (mode, temp, unsignedp);
926 /* Look for a wider mode of the same class for which we think we
927 can open-code the operation. Check for a widening multiply at the
928 wider mode as well. */
930 if ((class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
931 && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
932 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
933 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
935 if (binoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing
936 || (binoptab == smul_optab
937 && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
938 && (((unsignedp ? umul_widen_optab : smul_widen_optab)
939 ->handlers[(int) GET_MODE_WIDER_MODE (wider_mode)].insn_code)
940 != CODE_FOR_nothing)))
942 rtx xop0 = op0, xop1 = op1;
943 int no_extend = 0;
945 /* For certain integer operations, we need not actually extend
946 the narrow operands, as long as we will truncate
947 the results to the same narrowness. */
949 if ((binoptab == ior_optab || binoptab == and_optab
950 || binoptab == xor_optab
951 || binoptab == add_optab || binoptab == sub_optab
952 || binoptab == smul_optab || binoptab == ashl_optab)
953 && class == MODE_INT)
954 no_extend = 1;
956 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend);
958 /* The second operand of a shift must always be extended. */
959 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
960 no_extend && binoptab != ashl_optab);
962 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
963 unsignedp, OPTAB_DIRECT);
964 if (temp)
966 if (class != MODE_INT)
968 if (target == 0)
969 target = gen_reg_rtx (mode);
970 convert_move (target, temp, 0);
971 return target;
973 else
974 return gen_lowpart (mode, temp);
976 else
977 delete_insns_since (last);
981 /* These can be done a word at a time. */
982 if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
983 && class == MODE_INT
984 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
985 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
987 int i;
988 rtx insns;
989 rtx equiv_value;
991 /* If TARGET is the same as one of the operands, the REG_EQUAL note
992 won't be accurate, so use a new target. */
993 if (target == 0 || target == op0 || target == op1)
994 target = gen_reg_rtx (mode);
996 start_sequence ();
998 /* Do the actual arithmetic. */
999 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
1001 rtx target_piece = operand_subword (target, i, 1, mode);
1002 rtx x = expand_binop (word_mode, binoptab,
1003 operand_subword_force (op0, i, mode),
1004 operand_subword_force (op1, i, mode),
1005 target_piece, unsignedp, next_methods);
1007 if (x == 0)
1008 break;
1010 if (target_piece != x)
1011 emit_move_insn (target_piece, x);
1014 insns = get_insns ();
1015 end_sequence ();
1017 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
1019 if (binoptab->code != UNKNOWN)
1020 equiv_value
1021 = gen_rtx_fmt_ee (binoptab->code, mode,
1022 copy_rtx (op0), copy_rtx (op1));
1023 else
1024 equiv_value = 0;
1026 emit_no_conflict_block (insns, target, op0, op1, equiv_value);
1027 return target;
1031 /* Synthesize double word shifts from single word shifts. */
1032 if ((binoptab == lshr_optab || binoptab == ashl_optab
1033 || binoptab == ashr_optab)
1034 && class == MODE_INT
1035 && GET_CODE (op1) == CONST_INT
1036 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1037 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
1038 && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
1039 && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
1041 rtx insns, inter, equiv_value;
1042 rtx into_target, outof_target;
1043 rtx into_input, outof_input;
1044 int shift_count, left_shift, outof_word;
1046 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1047 won't be accurate, so use a new target. */
1048 if (target == 0 || target == op0 || target == op1)
1049 target = gen_reg_rtx (mode);
1051 start_sequence ();
1053 shift_count = INTVAL (op1);
1055 /* OUTOF_* is the word we are shifting bits away from, and
1056 INTO_* is the word that we are shifting bits towards, thus
1057 they differ depending on the direction of the shift and
1058 WORDS_BIG_ENDIAN. */
1060 left_shift = binoptab == ashl_optab;
1061 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1063 outof_target = operand_subword (target, outof_word, 1, mode);
1064 into_target = operand_subword (target, 1 - outof_word, 1, mode);
1066 outof_input = operand_subword_force (op0, outof_word, mode);
1067 into_input = operand_subword_force (op0, 1 - outof_word, mode);
1069 if (shift_count >= BITS_PER_WORD)
1071 inter = expand_binop (word_mode, binoptab,
1072 outof_input,
1073 GEN_INT (shift_count - BITS_PER_WORD),
1074 into_target, unsignedp, next_methods);
1076 if (inter != 0 && inter != into_target)
1077 emit_move_insn (into_target, inter);
1079 /* For a signed right shift, we must fill the word we are shifting
1080 out of with copies of the sign bit. Otherwise it is zeroed. */
1081 if (inter != 0 && binoptab != ashr_optab)
1082 inter = CONST0_RTX (word_mode);
1083 else if (inter != 0)
1084 inter = expand_binop (word_mode, binoptab,
1085 outof_input,
1086 GEN_INT (BITS_PER_WORD - 1),
1087 outof_target, unsignedp, next_methods);
1089 if (inter != 0 && inter != outof_target)
1090 emit_move_insn (outof_target, inter);
1092 else
1094 rtx carries;
1095 optab reverse_unsigned_shift, unsigned_shift;
1097 /* For a shift of less then BITS_PER_WORD, to compute the carry,
1098 we must do a logical shift in the opposite direction of the
1099 desired shift. */
1101 reverse_unsigned_shift = (left_shift ? lshr_optab : ashl_optab);
1103 /* For a shift of less than BITS_PER_WORD, to compute the word
1104 shifted towards, we need to unsigned shift the orig value of
1105 that word. */
1107 unsigned_shift = (left_shift ? ashl_optab : lshr_optab);
1109 carries = expand_binop (word_mode, reverse_unsigned_shift,
1110 outof_input,
1111 GEN_INT (BITS_PER_WORD - shift_count),
1112 0, unsignedp, next_methods);
1114 if (carries == 0)
1115 inter = 0;
1116 else
1117 inter = expand_binop (word_mode, unsigned_shift, into_input,
1118 op1, 0, unsignedp, next_methods);
1120 if (inter != 0)
1121 inter = expand_binop (word_mode, ior_optab, carries, inter,
1122 into_target, unsignedp, next_methods);
1124 if (inter != 0 && inter != into_target)
1125 emit_move_insn (into_target, inter);
1127 if (inter != 0)
1128 inter = expand_binop (word_mode, binoptab, outof_input,
1129 op1, outof_target, unsignedp, next_methods);
1131 if (inter != 0 && inter != outof_target)
1132 emit_move_insn (outof_target, inter);
1135 insns = get_insns ();
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 emit_no_conflict_block (insns, target, op0, op1, equiv_value);
1146 return target;
1150 /* Synthesize double word rotates from single word shifts. */
1151 if ((binoptab == rotl_optab || binoptab == rotr_optab)
1152 && class == MODE_INT
1153 && GET_CODE (op1) == CONST_INT
1154 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1155 && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
1156 && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
1158 rtx insns, equiv_value;
1159 rtx into_target, outof_target;
1160 rtx into_input, outof_input;
1161 rtx inter;
1162 int shift_count, left_shift, outof_word;
1164 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1165 won't be accurate, so use a new target. */
1166 if (target == 0 || target == op0 || target == op1)
1167 target = gen_reg_rtx (mode);
1169 start_sequence ();
1171 shift_count = INTVAL (op1);
1173 /* OUTOF_* is the word we are shifting bits away from, and
1174 INTO_* is the word that we are shifting bits towards, thus
1175 they differ depending on the direction of the shift and
1176 WORDS_BIG_ENDIAN. */
1178 left_shift = (binoptab == rotl_optab);
1179 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1181 outof_target = operand_subword (target, outof_word, 1, mode);
1182 into_target = operand_subword (target, 1 - outof_word, 1, mode);
1184 outof_input = operand_subword_force (op0, outof_word, mode);
1185 into_input = operand_subword_force (op0, 1 - outof_word, mode);
1187 if (shift_count == BITS_PER_WORD)
1189 /* This is just a word swap. */
1190 emit_move_insn (outof_target, into_input);
1191 emit_move_insn (into_target, outof_input);
1192 inter = const0_rtx;
1194 else
1196 rtx into_temp1, into_temp2, outof_temp1, outof_temp2;
1197 rtx first_shift_count, second_shift_count;
1198 optab reverse_unsigned_shift, unsigned_shift;
1200 reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1201 ? lshr_optab : ashl_optab);
1203 unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1204 ? ashl_optab : lshr_optab);
1206 if (shift_count > BITS_PER_WORD)
1208 first_shift_count = GEN_INT (shift_count - BITS_PER_WORD);
1209 second_shift_count = GEN_INT (2*BITS_PER_WORD - shift_count);
1211 else
1213 first_shift_count = GEN_INT (BITS_PER_WORD - shift_count);
1214 second_shift_count = GEN_INT (shift_count);
1217 into_temp1 = expand_binop (word_mode, unsigned_shift,
1218 outof_input, first_shift_count,
1219 NULL_RTX, unsignedp, next_methods);
1220 into_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1221 into_input, second_shift_count,
1222 into_target, unsignedp, next_methods);
1224 if (into_temp1 != 0 && into_temp2 != 0)
1225 inter = expand_binop (word_mode, ior_optab, into_temp1, into_temp2,
1226 into_target, unsignedp, next_methods);
1227 else
1228 inter = 0;
1230 if (inter != 0 && inter != into_target)
1231 emit_move_insn (into_target, inter);
1233 outof_temp1 = expand_binop (word_mode, unsigned_shift,
1234 into_input, first_shift_count,
1235 NULL_RTX, unsignedp, next_methods);
1236 outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1237 outof_input, second_shift_count,
1238 outof_target, unsignedp, next_methods);
1240 if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0)
1241 inter = expand_binop (word_mode, ior_optab,
1242 outof_temp1, outof_temp2,
1243 outof_target, unsignedp, next_methods);
1245 if (inter != 0 && inter != outof_target)
1246 emit_move_insn (outof_target, inter);
1249 insns = get_insns ();
1250 end_sequence ();
1252 if (inter != 0)
1254 if (binoptab->code != UNKNOWN)
1255 equiv_value = gen_rtx_fmt_ee (binoptab->code, mode, op0, op1);
1256 else
1257 equiv_value = 0;
1259 /* We can't make this a no conflict block if this is a word swap,
1260 because the word swap case fails if the input and output values
1261 are in the same register. */
1262 if (shift_count != BITS_PER_WORD)
1263 emit_no_conflict_block (insns, target, op0, op1, equiv_value);
1264 else
1265 emit_insns (insns);
1268 return target;
1272 /* These can be done a word at a time by propagating carries. */
1273 if ((binoptab == add_optab || binoptab == sub_optab)
1274 && class == MODE_INT
1275 && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
1276 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
1278 int i;
1279 rtx carry_tmp = gen_reg_rtx (word_mode);
1280 optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
1281 int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
1282 rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
1283 rtx xop0, xop1;
1285 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
1286 value is one of those, use it. Otherwise, use 1 since it is the
1287 one easiest to get. */
1288 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
1289 int normalizep = STORE_FLAG_VALUE;
1290 #else
1291 int normalizep = 1;
1292 #endif
1294 /* Prepare the operands. */
1295 xop0 = force_reg (mode, op0);
1296 xop1 = force_reg (mode, op1);
1298 if (target == 0 || GET_CODE (target) != REG
1299 || target == xop0 || target == xop1)
1300 target = gen_reg_rtx (mode);
1302 /* Indicate for flow that the entire target reg is being set. */
1303 if (GET_CODE (target) == REG)
1304 emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
1306 /* Do the actual arithmetic. */
1307 for (i = 0; i < nwords; i++)
1309 int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
1310 rtx target_piece = operand_subword (target, index, 1, mode);
1311 rtx op0_piece = operand_subword_force (xop0, index, mode);
1312 rtx op1_piece = operand_subword_force (xop1, index, mode);
1313 rtx x;
1315 /* Main add/subtract of the input operands. */
1316 x = expand_binop (word_mode, binoptab,
1317 op0_piece, op1_piece,
1318 target_piece, unsignedp, next_methods);
1319 if (x == 0)
1320 break;
1322 if (i + 1 < nwords)
1324 /* Store carry from main add/subtract. */
1325 carry_out = gen_reg_rtx (word_mode);
1326 carry_out = emit_store_flag_force (carry_out,
1327 (binoptab == add_optab
1328 ? LTU : GTU),
1329 x, op0_piece,
1330 word_mode, 1, normalizep);
1333 if (i > 0)
1335 /* Add/subtract previous carry to main result. */
1336 x = expand_binop (word_mode,
1337 normalizep == 1 ? binoptab : otheroptab,
1338 x, carry_in,
1339 target_piece, 1, next_methods);
1340 if (x == 0)
1341 break;
1342 else if (target_piece != x)
1343 emit_move_insn (target_piece, x);
1345 if (i + 1 < nwords)
1347 /* THIS CODE HAS NOT BEEN TESTED. */
1348 /* Get out carry from adding/subtracting carry in. */
1349 carry_tmp = emit_store_flag_force (carry_tmp,
1350 binoptab == add_optab
1351 ? LTU : GTU,
1352 x, carry_in,
1353 word_mode, 1, normalizep);
1355 /* Logical-ior the two poss. carry together. */
1356 carry_out = expand_binop (word_mode, ior_optab,
1357 carry_out, carry_tmp,
1358 carry_out, 0, next_methods);
1359 if (carry_out == 0)
1360 break;
1364 carry_in = carry_out;
1367 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
1369 if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1371 rtx temp = emit_move_insn (target, target);
1373 set_unique_reg_note (temp,
1374 REG_EQUAL,
1375 gen_rtx_fmt_ee (binoptab->code, mode,
1376 copy_rtx (xop0),
1377 copy_rtx (xop1)));
1379 return target;
1381 else
1382 delete_insns_since (last);
1385 /* If we want to multiply two two-word values and have normal and widening
1386 multiplies of single-word values, we can do this with three smaller
1387 multiplications. Note that we do not make a REG_NO_CONFLICT block here
1388 because we are not operating on one word at a time.
1390 The multiplication proceeds as follows:
1391 _______________________
1392 [__op0_high_|__op0_low__]
1393 _______________________
1394 * [__op1_high_|__op1_low__]
1395 _______________________________________________
1396 _______________________
1397 (1) [__op0_low__*__op1_low__]
1398 _______________________
1399 (2a) [__op0_low__*__op1_high_]
1400 _______________________
1401 (2b) [__op0_high_*__op1_low__]
1402 _______________________
1403 (3) [__op0_high_*__op1_high_]
1406 This gives a 4-word result. Since we are only interested in the
1407 lower 2 words, partial result (3) and the upper words of (2a) and
1408 (2b) don't need to be calculated. Hence (2a) and (2b) can be
1409 calculated using non-widening multiplication.
1411 (1), however, needs to be calculated with an unsigned widening
1412 multiplication. If this operation is not directly supported we
1413 try using a signed widening multiplication and adjust the result.
1414 This adjustment works as follows:
1416 If both operands are positive then no adjustment is needed.
1418 If the operands have different signs, for example op0_low < 0 and
1419 op1_low >= 0, the instruction treats the most significant bit of
1420 op0_low as a sign bit instead of a bit with significance
1421 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
1422 with 2**BITS_PER_WORD - op0_low, and two's complements the
1423 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
1424 the result.
1426 Similarly, if both operands are negative, we need to add
1427 (op0_low + op1_low) * 2**BITS_PER_WORD.
1429 We use a trick to adjust quickly. We logically shift op0_low right
1430 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
1431 op0_high (op1_high) before it is used to calculate 2b (2a). If no
1432 logical shift exists, we do an arithmetic right shift and subtract
1433 the 0 or -1. */
1435 if (binoptab == smul_optab
1436 && class == MODE_INT
1437 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1438 && smul_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
1439 && add_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
1440 && ((umul_widen_optab->handlers[(int) mode].insn_code
1441 != CODE_FOR_nothing)
1442 || (smul_widen_optab->handlers[(int) mode].insn_code
1443 != CODE_FOR_nothing)))
1445 int low = (WORDS_BIG_ENDIAN ? 1 : 0);
1446 int high = (WORDS_BIG_ENDIAN ? 0 : 1);
1447 rtx op0_high = operand_subword_force (op0, high, mode);
1448 rtx op0_low = operand_subword_force (op0, low, mode);
1449 rtx op1_high = operand_subword_force (op1, high, mode);
1450 rtx op1_low = operand_subword_force (op1, low, mode);
1451 rtx product = 0;
1452 rtx op0_xhigh = NULL_RTX;
1453 rtx op1_xhigh = NULL_RTX;
1455 /* If the target is the same as one of the inputs, don't use it. This
1456 prevents problems with the REG_EQUAL note. */
1457 if (target == op0 || target == op1
1458 || (target != 0 && GET_CODE (target) != REG))
1459 target = 0;
1461 /* Multiply the two lower words to get a double-word product.
1462 If unsigned widening multiplication is available, use that;
1463 otherwise use the signed form and compensate. */
1465 if (umul_widen_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1467 product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
1468 target, 1, OPTAB_DIRECT);
1470 /* If we didn't succeed, delete everything we did so far. */
1471 if (product == 0)
1472 delete_insns_since (last);
1473 else
1474 op0_xhigh = op0_high, op1_xhigh = op1_high;
1477 if (product == 0
1478 && smul_widen_optab->handlers[(int) mode].insn_code
1479 != CODE_FOR_nothing)
1481 rtx wordm1 = GEN_INT (BITS_PER_WORD - 1);
1482 product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
1483 target, 1, OPTAB_DIRECT);
1484 op0_xhigh = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
1485 NULL_RTX, 1, next_methods);
1486 if (op0_xhigh)
1487 op0_xhigh = expand_binop (word_mode, add_optab, op0_high,
1488 op0_xhigh, op0_xhigh, 0, next_methods);
1489 else
1491 op0_xhigh = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
1492 NULL_RTX, 0, next_methods);
1493 if (op0_xhigh)
1494 op0_xhigh = expand_binop (word_mode, sub_optab, op0_high,
1495 op0_xhigh, op0_xhigh, 0,
1496 next_methods);
1499 op1_xhigh = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
1500 NULL_RTX, 1, next_methods);
1501 if (op1_xhigh)
1502 op1_xhigh = expand_binop (word_mode, add_optab, op1_high,
1503 op1_xhigh, op1_xhigh, 0, next_methods);
1504 else
1506 op1_xhigh = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
1507 NULL_RTX, 0, next_methods);
1508 if (op1_xhigh)
1509 op1_xhigh = expand_binop (word_mode, sub_optab, op1_high,
1510 op1_xhigh, op1_xhigh, 0,
1511 next_methods);
1515 /* If we have been able to directly compute the product of the
1516 low-order words of the operands and perform any required adjustments
1517 of the operands, we proceed by trying two more multiplications
1518 and then computing the appropriate sum.
1520 We have checked above that the required addition is provided.
1521 Full-word addition will normally always succeed, especially if
1522 it is provided at all, so we don't worry about its failure. The
1523 multiplication may well fail, however, so we do handle that. */
1525 if (product && op0_xhigh && op1_xhigh)
1527 rtx product_high = operand_subword (product, high, 1, mode);
1528 rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh,
1529 NULL_RTX, 0, OPTAB_DIRECT);
1531 if (temp != 0)
1532 temp = expand_binop (word_mode, add_optab, temp, product_high,
1533 product_high, 0, next_methods);
1535 if (temp != 0 && temp != product_high)
1536 emit_move_insn (product_high, temp);
1538 if (temp != 0)
1539 temp = expand_binop (word_mode, binoptab, op1_low, op0_xhigh,
1540 NULL_RTX, 0, OPTAB_DIRECT);
1542 if (temp != 0)
1543 temp = expand_binop (word_mode, add_optab, temp,
1544 product_high, product_high,
1545 0, next_methods);
1547 if (temp != 0 && temp != product_high)
1548 emit_move_insn (product_high, temp);
1550 if (temp != 0)
1552 if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1554 temp = emit_move_insn (product, product);
1555 set_unique_reg_note (temp,
1556 REG_EQUAL,
1557 gen_rtx_fmt_ee (MULT, mode,
1558 copy_rtx (op0),
1559 copy_rtx (op1)));
1561 return product;
1565 /* If we get here, we couldn't do it for some reason even though we
1566 originally thought we could. Delete anything we've emitted in
1567 trying to do it. */
1569 delete_insns_since (last);
1572 /* We need to open-code the complex type operations: '+, -, * and /' */
1574 /* At this point we allow operations between two similar complex
1575 numbers, and also if one of the operands is not a complex number
1576 but rather of MODE_FLOAT or MODE_INT. However, the caller
1577 must make sure that the MODE of the non-complex operand matches
1578 the SUBMODE of the complex operand. */
1580 if (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
1582 rtx real0 = 0, imag0 = 0;
1583 rtx real1 = 0, imag1 = 0;
1584 rtx realr, imagr, res;
1585 rtx seq;
1586 rtx equiv_value;
1587 int ok = 0;
1589 /* Find the correct mode for the real and imaginary parts */
1590 enum machine_mode submode
1591 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
1592 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
1595 if (submode == BLKmode)
1596 abort ();
1598 if (! target)
1599 target = gen_reg_rtx (mode);
1601 start_sequence ();
1603 realr = gen_realpart (submode, target);
1604 imagr = gen_imagpart (submode, target);
1606 if (GET_MODE (op0) == mode)
1608 real0 = gen_realpart (submode, op0);
1609 imag0 = gen_imagpart (submode, op0);
1611 else
1612 real0 = op0;
1614 if (GET_MODE (op1) == mode)
1616 real1 = gen_realpart (submode, op1);
1617 imag1 = gen_imagpart (submode, op1);
1619 else
1620 real1 = op1;
1622 if (real0 == 0 || real1 == 0 || ! (imag0 != 0|| imag1 != 0))
1623 abort ();
1625 switch (binoptab->code)
1627 case PLUS:
1628 /* (a+ib) + (c+id) = (a+c) + i(b+d) */
1629 case MINUS:
1630 /* (a+ib) - (c+id) = (a-c) + i(b-d) */
1631 res = expand_binop (submode, binoptab, real0, real1,
1632 realr, unsignedp, methods);
1634 if (res == 0)
1635 break;
1636 else if (res != realr)
1637 emit_move_insn (realr, res);
1639 if (imag0 && imag1)
1640 res = expand_binop (submode, binoptab, imag0, imag1,
1641 imagr, unsignedp, methods);
1642 else if (imag0)
1643 res = imag0;
1644 else if (binoptab->code == MINUS)
1645 res = expand_unop (submode, neg_optab, imag1, imagr, unsignedp);
1646 else
1647 res = imag1;
1649 if (res == 0)
1650 break;
1651 else if (res != imagr)
1652 emit_move_insn (imagr, res);
1654 ok = 1;
1655 break;
1657 case MULT:
1658 /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */
1660 if (imag0 && imag1)
1662 rtx temp1, temp2;
1664 /* Don't fetch these from memory more than once. */
1665 real0 = force_reg (submode, real0);
1666 real1 = force_reg (submode, real1);
1667 imag0 = force_reg (submode, imag0);
1668 imag1 = force_reg (submode, imag1);
1670 temp1 = expand_binop (submode, binoptab, real0, real1, NULL_RTX,
1671 unsignedp, methods);
1673 temp2 = expand_binop (submode, binoptab, imag0, imag1, NULL_RTX,
1674 unsignedp, methods);
1676 if (temp1 == 0 || temp2 == 0)
1677 break;
1679 res = expand_binop (submode, sub_optab, temp1, temp2,
1680 realr, unsignedp, methods);
1682 if (res == 0)
1683 break;
1684 else if (res != realr)
1685 emit_move_insn (realr, res);
1687 temp1 = expand_binop (submode, binoptab, real0, imag1,
1688 NULL_RTX, unsignedp, methods);
1690 temp2 = expand_binop (submode, binoptab, real1, imag0,
1691 NULL_RTX, unsignedp, methods);
1693 if (temp1 == 0 || temp2 == 0)
1694 break;
1696 res = expand_binop (submode, add_optab, temp1, temp2,
1697 imagr, unsignedp, methods);
1699 if (res == 0)
1700 break;
1701 else if (res != imagr)
1702 emit_move_insn (imagr, res);
1704 ok = 1;
1706 else
1708 /* Don't fetch these from memory more than once. */
1709 real0 = force_reg (submode, real0);
1710 real1 = force_reg (submode, real1);
1712 res = expand_binop (submode, binoptab, real0, real1,
1713 realr, unsignedp, methods);
1714 if (res == 0)
1715 break;
1716 else if (res != realr)
1717 emit_move_insn (realr, res);
1719 if (imag0 != 0)
1720 res = expand_binop (submode, binoptab,
1721 real1, imag0, imagr, unsignedp, methods);
1722 else
1723 res = expand_binop (submode, binoptab,
1724 real0, imag1, imagr, unsignedp, methods);
1726 if (res == 0)
1727 break;
1728 else if (res != imagr)
1729 emit_move_insn (imagr, res);
1731 ok = 1;
1733 break;
1735 case DIV:
1736 /* (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) */
1738 if (imag1 == 0)
1740 /* (a+ib) / (c+i0) = (a/c) + i(b/c) */
1742 /* Don't fetch these from memory more than once. */
1743 real1 = force_reg (submode, real1);
1745 /* Simply divide the real and imaginary parts by `c' */
1746 if (class == MODE_COMPLEX_FLOAT)
1747 res = expand_binop (submode, binoptab, real0, real1,
1748 realr, unsignedp, methods);
1749 else
1750 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
1751 real0, real1, realr, unsignedp);
1753 if (res == 0)
1754 break;
1755 else if (res != realr)
1756 emit_move_insn (realr, res);
1758 if (class == MODE_COMPLEX_FLOAT)
1759 res = expand_binop (submode, binoptab, imag0, real1,
1760 imagr, unsignedp, methods);
1761 else
1762 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
1763 imag0, real1, imagr, unsignedp);
1765 if (res == 0)
1766 break;
1767 else if (res != imagr)
1768 emit_move_insn (imagr, res);
1770 ok = 1;
1772 else
1774 switch (flag_complex_divide_method)
1776 case 0:
1777 ok = expand_cmplxdiv_straight (real0, real1, imag0, imag1,
1778 realr, imagr, submode,
1779 unsignedp, methods,
1780 class, binoptab);
1781 break;
1783 case 1:
1784 ok = expand_cmplxdiv_wide (real0, real1, imag0, imag1,
1785 realr, imagr, submode,
1786 unsignedp, methods,
1787 class, binoptab);
1788 break;
1790 default:
1791 abort ();
1794 break;
1796 default:
1797 abort ();
1800 seq = get_insns ();
1801 end_sequence ();
1803 if (ok)
1805 if (binoptab->code != UNKNOWN)
1806 equiv_value
1807 = gen_rtx_fmt_ee (binoptab->code, mode,
1808 copy_rtx (op0), copy_rtx (op1));
1809 else
1810 equiv_value = 0;
1812 emit_no_conflict_block (seq, target, op0, op1, equiv_value);
1814 return target;
1818 /* It can't be open-coded in this mode.
1819 Use a library call if one is available and caller says that's ok. */
1821 if (binoptab->handlers[(int) mode].libfunc
1822 && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
1824 rtx insns;
1825 rtx op1x = op1;
1826 enum machine_mode op1_mode = mode;
1827 rtx value;
1829 start_sequence ();
1831 if (shift_op)
1833 op1_mode = word_mode;
1834 /* Specify unsigned here,
1835 since negative shift counts are meaningless. */
1836 op1x = convert_to_mode (word_mode, op1, 1);
1839 if (GET_MODE (op0) != VOIDmode
1840 && GET_MODE (op0) != mode)
1841 op0 = convert_to_mode (mode, op0, unsignedp);
1843 /* Pass 1 for NO_QUEUE so we don't lose any increments
1844 if the libcall is cse'd or moved. */
1845 value = emit_library_call_value (binoptab->handlers[(int) mode].libfunc,
1846 NULL_RTX, 1, mode, 2,
1847 op0, mode, op1x, op1_mode);
1849 insns = get_insns ();
1850 end_sequence ();
1852 target = gen_reg_rtx (mode);
1853 emit_libcall_block (insns, target, value,
1854 gen_rtx_fmt_ee (binoptab->code, mode, op0, op1));
1856 return target;
1859 delete_insns_since (last);
1861 /* It can't be done in this mode. Can we do it in a wider mode? */
1863 if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
1864 || methods == OPTAB_MUST_WIDEN))
1866 /* Caller says, don't even try. */
1867 delete_insns_since (entry_last);
1868 return 0;
1871 /* Compute the value of METHODS to pass to recursive calls.
1872 Don't allow widening to be tried recursively. */
1874 methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
1876 /* Look for a wider mode of the same class for which it appears we can do
1877 the operation. */
1879 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1881 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1882 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1884 if ((binoptab->handlers[(int) wider_mode].insn_code
1885 != CODE_FOR_nothing)
1886 || (methods == OPTAB_LIB
1887 && binoptab->handlers[(int) wider_mode].libfunc))
1889 rtx xop0 = op0, xop1 = op1;
1890 int no_extend = 0;
1892 /* For certain integer operations, we need not actually extend
1893 the narrow operands, as long as we will truncate
1894 the results to the same narrowness. */
1896 if ((binoptab == ior_optab || binoptab == and_optab
1897 || binoptab == xor_optab
1898 || binoptab == add_optab || binoptab == sub_optab
1899 || binoptab == smul_optab || binoptab == ashl_optab)
1900 && class == MODE_INT)
1901 no_extend = 1;
1903 xop0 = widen_operand (xop0, wider_mode, mode,
1904 unsignedp, no_extend);
1906 /* The second operand of a shift must always be extended. */
1907 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
1908 no_extend && binoptab != ashl_optab);
1910 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
1911 unsignedp, methods);
1912 if (temp)
1914 if (class != MODE_INT)
1916 if (target == 0)
1917 target = gen_reg_rtx (mode);
1918 convert_move (target, temp, 0);
1919 return target;
1921 else
1922 return gen_lowpart (mode, temp);
1924 else
1925 delete_insns_since (last);
1930 delete_insns_since (entry_last);
1931 return 0;
1934 /* Expand a binary operator which has both signed and unsigned forms.
1935 UOPTAB is the optab for unsigned operations, and SOPTAB is for
1936 signed operations.
1938 If we widen unsigned operands, we may use a signed wider operation instead
1939 of an unsigned wider operation, since the result would be the same. */
1942 sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods)
1943 enum machine_mode mode;
1944 optab uoptab, soptab;
1945 rtx op0, op1, target;
1946 int unsignedp;
1947 enum optab_methods methods;
1949 register rtx temp;
1950 optab direct_optab = unsignedp ? uoptab : soptab;
1951 struct optab wide_soptab;
1953 /* Do it without widening, if possible. */
1954 temp = expand_binop (mode, direct_optab, op0, op1, target,
1955 unsignedp, OPTAB_DIRECT);
1956 if (temp || methods == OPTAB_DIRECT)
1957 return temp;
1959 /* Try widening to a signed int. Make a fake signed optab that
1960 hides any signed insn for direct use. */
1961 wide_soptab = *soptab;
1962 wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing;
1963 wide_soptab.handlers[(int) mode].libfunc = 0;
1965 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
1966 unsignedp, OPTAB_WIDEN);
1968 /* For unsigned operands, try widening to an unsigned int. */
1969 if (temp == 0 && unsignedp)
1970 temp = expand_binop (mode, uoptab, op0, op1, target,
1971 unsignedp, OPTAB_WIDEN);
1972 if (temp || methods == OPTAB_WIDEN)
1973 return temp;
1975 /* Use the right width lib call if that exists. */
1976 temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
1977 if (temp || methods == OPTAB_LIB)
1978 return temp;
1980 /* Must widen and use a lib call, use either signed or unsigned. */
1981 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
1982 unsignedp, methods);
1983 if (temp != 0)
1984 return temp;
1985 if (unsignedp)
1986 return expand_binop (mode, uoptab, op0, op1, target,
1987 unsignedp, methods);
1988 return 0;
1991 /* Generate code to perform an operation specified by BINOPTAB
1992 on operands OP0 and OP1, with two results to TARG1 and TARG2.
1993 We assume that the order of the operands for the instruction
1994 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
1995 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
1997 Either TARG0 or TARG1 may be zero, but what that means is that
1998 the result is not actually wanted. We will generate it into
1999 a dummy pseudo-reg and discard it. They may not both be zero.
2001 Returns 1 if this operation can be performed; 0 if not. */
2004 expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
2005 optab binoptab;
2006 rtx op0, op1;
2007 rtx targ0, targ1;
2008 int unsignedp;
2010 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
2011 enum mode_class class;
2012 enum machine_mode wider_mode;
2013 rtx entry_last = get_last_insn ();
2014 rtx last;
2016 class = GET_MODE_CLASS (mode);
2018 op0 = protect_from_queue (op0, 0);
2019 op1 = protect_from_queue (op1, 0);
2021 if (flag_force_mem)
2023 op0 = force_not_mem (op0);
2024 op1 = force_not_mem (op1);
2027 /* If we are inside an appropriately-short loop and one operand is an
2028 expensive constant, force it into a register. */
2029 if (CONSTANT_P (op0) && preserve_subexpressions_p ()
2030 && rtx_cost (op0, binoptab->code) > 2)
2031 op0 = force_reg (mode, op0);
2033 if (CONSTANT_P (op1) && preserve_subexpressions_p ()
2034 && rtx_cost (op1, binoptab->code) > 2)
2035 op1 = force_reg (mode, op1);
2037 if (targ0)
2038 targ0 = protect_from_queue (targ0, 1);
2039 else
2040 targ0 = gen_reg_rtx (mode);
2041 if (targ1)
2042 targ1 = protect_from_queue (targ1, 1);
2043 else
2044 targ1 = gen_reg_rtx (mode);
2046 /* Record where to go back to if we fail. */
2047 last = get_last_insn ();
2049 if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2051 int icode = (int) binoptab->handlers[(int) mode].insn_code;
2052 enum machine_mode mode0 = insn_operand_mode[icode][1];
2053 enum machine_mode mode1 = insn_operand_mode[icode][2];
2054 rtx pat;
2055 rtx xop0 = op0, xop1 = op1;
2057 /* In case this insn wants input operands in modes different from the
2058 result, convert the operands. */
2059 if (GET_MODE (op0) != VOIDmode && GET_MODE (op0) != mode0)
2060 xop0 = convert_to_mode (mode0, xop0, unsignedp);
2062 if (GET_MODE (op1) != VOIDmode && GET_MODE (op1) != mode1)
2063 xop1 = convert_to_mode (mode1, xop1, unsignedp);
2065 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2066 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
2067 xop0 = copy_to_mode_reg (mode0, xop0);
2069 if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
2070 xop1 = copy_to_mode_reg (mode1, xop1);
2072 /* We could handle this, but we should always be called with a pseudo
2073 for our targets and all insns should take them as outputs. */
2074 if (! (*insn_operand_predicate[icode][0]) (targ0, mode)
2075 || ! (*insn_operand_predicate[icode][3]) (targ1, mode))
2076 abort ();
2078 pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
2079 if (pat)
2081 emit_insn (pat);
2082 return 1;
2084 else
2085 delete_insns_since (last);
2088 /* It can't be done in this mode. Can we do it in a wider mode? */
2090 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
2092 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2093 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2095 if (binoptab->handlers[(int) wider_mode].insn_code
2096 != CODE_FOR_nothing)
2098 register rtx t0 = gen_reg_rtx (wider_mode);
2099 register rtx t1 = gen_reg_rtx (wider_mode);
2101 if (expand_twoval_binop (binoptab,
2102 convert_modes (wider_mode, mode, op0,
2103 unsignedp),
2104 convert_modes (wider_mode, mode, op1,
2105 unsignedp),
2106 t0, t1, unsignedp))
2108 convert_move (targ0, t0, unsignedp);
2109 convert_move (targ1, t1, unsignedp);
2110 return 1;
2112 else
2113 delete_insns_since (last);
2118 delete_insns_since (entry_last);
2119 return 0;
2122 /* Generate code to perform an operation specified by UNOPTAB
2123 on operand OP0, with result having machine-mode MODE.
2125 UNSIGNEDP is for the case where we have to widen the operands
2126 to perform the operation. It says to use zero-extension.
2128 If TARGET is nonzero, the value
2129 is generated there, if it is convenient to do so.
2130 In all cases an rtx is returned for the locus of the value;
2131 this may or may not be TARGET. */
2134 expand_unop (mode, unoptab, op0, target, unsignedp)
2135 enum machine_mode mode;
2136 optab unoptab;
2137 rtx op0;
2138 rtx target;
2139 int unsignedp;
2141 enum mode_class class;
2142 enum machine_mode wider_mode;
2143 register rtx temp;
2144 rtx last = get_last_insn ();
2145 rtx pat;
2147 class = GET_MODE_CLASS (mode);
2149 op0 = protect_from_queue (op0, 0);
2151 if (flag_force_mem)
2153 op0 = force_not_mem (op0);
2156 if (target)
2157 target = protect_from_queue (target, 1);
2159 if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2161 int icode = (int) unoptab->handlers[(int) mode].insn_code;
2162 enum machine_mode mode0 = insn_operand_mode[icode][1];
2163 rtx xop0 = op0;
2165 if (target)
2166 temp = target;
2167 else
2168 temp = gen_reg_rtx (mode);
2170 if (GET_MODE (xop0) != VOIDmode
2171 && GET_MODE (xop0) != mode0)
2172 xop0 = convert_to_mode (mode0, xop0, unsignedp);
2174 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
2176 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
2177 xop0 = copy_to_mode_reg (mode0, xop0);
2179 if (! (*insn_operand_predicate[icode][0]) (temp, mode))
2180 temp = gen_reg_rtx (mode);
2182 pat = GEN_FCN (icode) (temp, xop0);
2183 if (pat)
2185 if (GET_CODE (pat) == SEQUENCE
2186 && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
2188 delete_insns_since (last);
2189 return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
2192 emit_insn (pat);
2194 return temp;
2196 else
2197 delete_insns_since (last);
2200 /* It can't be done in this mode. Can we open-code it in a wider mode? */
2202 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
2203 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2204 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2206 if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
2208 rtx xop0 = op0;
2210 /* For certain operations, we need not actually extend
2211 the narrow operand, as long as we will truncate the
2212 results to the same narrowness. */
2214 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
2215 (unoptab == neg_optab
2216 || unoptab == one_cmpl_optab)
2217 && class == MODE_INT);
2219 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
2220 unsignedp);
2222 if (temp)
2224 if (class != MODE_INT)
2226 if (target == 0)
2227 target = gen_reg_rtx (mode);
2228 convert_move (target, temp, 0);
2229 return target;
2231 else
2232 return gen_lowpart (mode, temp);
2234 else
2235 delete_insns_since (last);
2239 /* These can be done a word at a time. */
2240 if (unoptab == one_cmpl_optab
2241 && class == MODE_INT
2242 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
2243 && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
2245 int i;
2246 rtx insns;
2248 if (target == 0 || target == op0)
2249 target = gen_reg_rtx (mode);
2251 start_sequence ();
2253 /* Do the actual arithmetic. */
2254 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
2256 rtx target_piece = operand_subword (target, i, 1, mode);
2257 rtx x = expand_unop (word_mode, unoptab,
2258 operand_subword_force (op0, i, mode),
2259 target_piece, unsignedp);
2260 if (target_piece != x)
2261 emit_move_insn (target_piece, x);
2264 insns = get_insns ();
2265 end_sequence ();
2267 emit_no_conflict_block (insns, target, op0, NULL_RTX,
2268 gen_rtx_fmt_e (unoptab->code, mode,
2269 copy_rtx (op0)));
2270 return target;
2273 /* Open-code the complex negation operation. */
2274 else if (unoptab == neg_optab
2275 && (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT))
2277 rtx target_piece;
2278 rtx x;
2279 rtx seq;
2281 /* Find the correct mode for the real and imaginary parts */
2282 enum machine_mode submode
2283 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
2284 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
2287 if (submode == BLKmode)
2288 abort ();
2290 if (target == 0)
2291 target = gen_reg_rtx (mode);
2293 start_sequence ();
2295 target_piece = gen_imagpart (submode, target);
2296 x = expand_unop (submode, unoptab,
2297 gen_imagpart (submode, op0),
2298 target_piece, unsignedp);
2299 if (target_piece != x)
2300 emit_move_insn (target_piece, x);
2302 target_piece = gen_realpart (submode, target);
2303 x = expand_unop (submode, unoptab,
2304 gen_realpart (submode, op0),
2305 target_piece, unsignedp);
2306 if (target_piece != x)
2307 emit_move_insn (target_piece, x);
2309 seq = get_insns ();
2310 end_sequence ();
2312 emit_no_conflict_block (seq, target, op0, 0,
2313 gen_rtx_fmt_e (unoptab->code, mode,
2314 copy_rtx (op0)));
2315 return target;
2318 /* Now try a library call in this mode. */
2319 if (unoptab->handlers[(int) mode].libfunc)
2321 rtx insns;
2322 rtx value;
2324 start_sequence ();
2326 /* Pass 1 for NO_QUEUE so we don't lose any increments
2327 if the libcall is cse'd or moved. */
2328 value = emit_library_call_value (unoptab->handlers[(int) mode].libfunc,
2329 NULL_RTX, 1, mode, 1, op0, mode);
2330 insns = get_insns ();
2331 end_sequence ();
2333 target = gen_reg_rtx (mode);
2334 emit_libcall_block (insns, target, value,
2335 gen_rtx_fmt_e (unoptab->code, mode, op0));
2337 return target;
2340 /* It can't be done in this mode. Can we do it in a wider mode? */
2342 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
2344 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2345 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2347 if ((unoptab->handlers[(int) wider_mode].insn_code
2348 != CODE_FOR_nothing)
2349 || unoptab->handlers[(int) wider_mode].libfunc)
2351 rtx xop0 = op0;
2353 /* For certain operations, we need not actually extend
2354 the narrow operand, as long as we will truncate the
2355 results to the same narrowness. */
2357 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
2358 (unoptab == neg_optab
2359 || unoptab == one_cmpl_optab)
2360 && class == MODE_INT);
2362 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
2363 unsignedp);
2365 if (temp)
2367 if (class != MODE_INT)
2369 if (target == 0)
2370 target = gen_reg_rtx (mode);
2371 convert_move (target, temp, 0);
2372 return target;
2374 else
2375 return gen_lowpart (mode, temp);
2377 else
2378 delete_insns_since (last);
2383 /* If there is no negate operation, try doing a subtract from zero.
2384 The US Software GOFAST library needs this. */
2385 if (unoptab == neg_optab)
2387 rtx temp;
2388 temp = expand_binop (mode, sub_optab, CONST0_RTX (mode), op0,
2389 target, unsignedp, OPTAB_LIB_WIDEN);
2390 if (temp)
2391 return temp;
2394 return 0;
2397 /* Emit code to compute the absolute value of OP0, with result to
2398 TARGET if convenient. (TARGET may be 0.) The return value says
2399 where the result actually is to be found.
2401 MODE is the mode of the operand; the mode of the result is
2402 different but can be deduced from MODE.
2407 expand_abs (mode, op0, target, safe)
2408 enum machine_mode mode;
2409 rtx op0;
2410 rtx target;
2411 int safe;
2413 rtx temp, op1;
2415 /* First try to do it with a special abs instruction. */
2416 temp = expand_unop (mode, abs_optab, op0, target, 0);
2417 if (temp != 0)
2418 return temp;
2420 /* If this machine has expensive jumps, we can do integer absolute
2421 value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
2422 where W is the width of MODE. */
2424 if (GET_MODE_CLASS (mode) == MODE_INT && BRANCH_COST >= 2)
2426 rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
2427 size_int (GET_MODE_BITSIZE (mode) - 1),
2428 NULL_RTX, 0);
2430 temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
2431 OPTAB_LIB_WIDEN);
2432 if (temp != 0)
2433 temp = expand_binop (mode, sub_optab, temp, extended, target, 0,
2434 OPTAB_LIB_WIDEN);
2436 if (temp != 0)
2437 return temp;
2440 /* If that does not win, use conditional jump and negate. */
2442 /* It is safe to use the target if it is the same
2443 as the source if this is also a pseudo register */
2444 if (op0 == target && GET_CODE (op0) == REG
2445 && REGNO (op0) >= FIRST_PSEUDO_REGISTER)
2446 safe = 1;
2448 op1 = gen_label_rtx ();
2449 if (target == 0 || ! safe
2450 || GET_MODE (target) != mode
2451 || (GET_CODE (target) == MEM && MEM_VOLATILE_P (target))
2452 || (GET_CODE (target) == REG
2453 && REGNO (target) < FIRST_PSEUDO_REGISTER))
2454 target = gen_reg_rtx (mode);
2456 emit_move_insn (target, op0);
2457 NO_DEFER_POP;
2459 /* If this mode is an integer too wide to compare properly,
2460 compare word by word. Rely on CSE to optimize constant cases. */
2461 if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode))
2462 do_jump_by_parts_greater_rtx (mode, 0, target, const0_rtx,
2463 NULL_RTX, op1);
2464 else
2466 temp = compare_from_rtx (target, CONST0_RTX (mode), GE, 0, mode,
2467 NULL_RTX, 0);
2468 if (temp == const1_rtx)
2469 return target;
2470 else if (temp != const0_rtx)
2472 if (bcc_gen_fctn[(int) GET_CODE (temp)] != 0)
2473 emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (temp)]) (op1));
2474 else
2475 abort ();
2479 op0 = expand_unop (mode, neg_optab, target, target, 0);
2480 if (op0 != target)
2481 emit_move_insn (target, op0);
2482 emit_label (op1);
2483 OK_DEFER_POP;
2484 return target;
2487 /* Emit code to compute the absolute value of OP0, with result to
2488 TARGET if convenient. (TARGET may be 0.) The return value says
2489 where the result actually is to be found.
2491 MODE is the mode of the operand; the mode of the result is
2492 different but can be deduced from MODE.
2494 UNSIGNEDP is relevant for complex integer modes. */
2497 expand_complex_abs (mode, op0, target, unsignedp)
2498 enum machine_mode mode;
2499 rtx op0;
2500 rtx target;
2501 int unsignedp;
2503 enum mode_class class = GET_MODE_CLASS (mode);
2504 enum machine_mode wider_mode;
2505 register rtx temp;
2506 rtx entry_last = get_last_insn ();
2507 rtx last;
2508 rtx pat;
2510 /* Find the correct mode for the real and imaginary parts. */
2511 enum machine_mode submode
2512 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
2513 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
2516 if (submode == BLKmode)
2517 abort ();
2519 op0 = protect_from_queue (op0, 0);
2521 if (flag_force_mem)
2523 op0 = force_not_mem (op0);
2526 last = get_last_insn ();
2528 if (target)
2529 target = protect_from_queue (target, 1);
2531 if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2533 int icode = (int) abs_optab->handlers[(int) mode].insn_code;
2534 enum machine_mode mode0 = insn_operand_mode[icode][1];
2535 rtx xop0 = op0;
2537 if (target)
2538 temp = target;
2539 else
2540 temp = gen_reg_rtx (submode);
2542 if (GET_MODE (xop0) != VOIDmode
2543 && GET_MODE (xop0) != mode0)
2544 xop0 = convert_to_mode (mode0, xop0, unsignedp);
2546 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
2548 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
2549 xop0 = copy_to_mode_reg (mode0, xop0);
2551 if (! (*insn_operand_predicate[icode][0]) (temp, submode))
2552 temp = gen_reg_rtx (submode);
2554 pat = GEN_FCN (icode) (temp, xop0);
2555 if (pat)
2557 if (GET_CODE (pat) == SEQUENCE
2558 && ! add_equal_note (pat, temp, abs_optab->code, xop0, NULL_RTX))
2560 delete_insns_since (last);
2561 return expand_unop (mode, abs_optab, op0, NULL_RTX, unsignedp);
2564 emit_insn (pat);
2566 return temp;
2568 else
2569 delete_insns_since (last);
2572 /* It can't be done in this mode. Can we open-code it in a wider mode? */
2574 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2575 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2577 if (abs_optab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
2579 rtx xop0 = op0;
2581 xop0 = convert_modes (wider_mode, mode, xop0, unsignedp);
2582 temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
2584 if (temp)
2586 if (class != MODE_COMPLEX_INT)
2588 if (target == 0)
2589 target = gen_reg_rtx (submode);
2590 convert_move (target, temp, 0);
2591 return target;
2593 else
2594 return gen_lowpart (submode, temp);
2596 else
2597 delete_insns_since (last);
2601 /* Open-code the complex absolute-value operation
2602 if we can open-code sqrt. Otherwise it's not worth while. */
2603 if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing)
2605 rtx real, imag, total;
2607 real = gen_realpart (submode, op0);
2608 imag = gen_imagpart (submode, op0);
2610 /* Square both parts. */
2611 real = expand_mult (submode, real, real, NULL_RTX, 0);
2612 imag = expand_mult (submode, imag, imag, NULL_RTX, 0);
2614 /* Sum the parts. */
2615 total = expand_binop (submode, add_optab, real, imag, NULL_RTX,
2616 0, OPTAB_LIB_WIDEN);
2618 /* Get sqrt in TARGET. Set TARGET to where the result is. */
2619 target = expand_unop (submode, sqrt_optab, total, target, 0);
2620 if (target == 0)
2621 delete_insns_since (last);
2622 else
2623 return target;
2626 /* Now try a library call in this mode. */
2627 if (abs_optab->handlers[(int) mode].libfunc)
2629 rtx insns;
2630 rtx value;
2632 start_sequence ();
2634 /* Pass 1 for NO_QUEUE so we don't lose any increments
2635 if the libcall is cse'd or moved. */
2636 value = emit_library_call_value (abs_optab->handlers[(int) mode].libfunc,
2637 NULL_RTX, 1, submode, 1, op0, mode);
2638 insns = get_insns ();
2639 end_sequence ();
2641 target = gen_reg_rtx (submode);
2642 emit_libcall_block (insns, target, value,
2643 gen_rtx_fmt_e (abs_optab->code, mode, op0));
2645 return target;
2648 /* It can't be done in this mode. Can we do it in a wider mode? */
2650 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2651 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2653 if ((abs_optab->handlers[(int) wider_mode].insn_code
2654 != CODE_FOR_nothing)
2655 || abs_optab->handlers[(int) wider_mode].libfunc)
2657 rtx xop0 = op0;
2659 xop0 = convert_modes (wider_mode, mode, xop0, unsignedp);
2661 temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
2663 if (temp)
2665 if (class != MODE_COMPLEX_INT)
2667 if (target == 0)
2668 target = gen_reg_rtx (submode);
2669 convert_move (target, temp, 0);
2670 return target;
2672 else
2673 return gen_lowpart (submode, temp);
2675 else
2676 delete_insns_since (last);
2680 delete_insns_since (entry_last);
2681 return 0;
2684 /* Generate an instruction whose insn-code is INSN_CODE,
2685 with two operands: an output TARGET and an input OP0.
2686 TARGET *must* be nonzero, and the output is always stored there.
2687 CODE is an rtx code such that (CODE OP0) is an rtx that describes
2688 the value that is stored into TARGET. */
2690 void
2691 emit_unop_insn (icode, target, op0, code)
2692 int icode;
2693 rtx target;
2694 rtx op0;
2695 enum rtx_code code;
2697 register rtx temp;
2698 enum machine_mode mode0 = insn_operand_mode[icode][1];
2699 rtx pat;
2701 temp = target = protect_from_queue (target, 1);
2703 op0 = protect_from_queue (op0, 0);
2705 /* Sign and zero extension from memory is often done specially on
2706 RISC machines, so forcing into a register here can pessimize
2707 code. */
2708 if (flag_force_mem && code != SIGN_EXTEND && code != ZERO_EXTEND)
2709 op0 = force_not_mem (op0);
2711 /* Now, if insn does not accept our operands, put them into pseudos. */
2713 if (! (*insn_operand_predicate[icode][1]) (op0, mode0))
2714 op0 = copy_to_mode_reg (mode0, op0);
2716 if (! (*insn_operand_predicate[icode][0]) (temp, GET_MODE (temp))
2717 || (flag_force_mem && GET_CODE (temp) == MEM))
2718 temp = gen_reg_rtx (GET_MODE (temp));
2720 pat = GEN_FCN (icode) (temp, op0);
2722 if (GET_CODE (pat) == SEQUENCE && code != UNKNOWN)
2723 add_equal_note (pat, temp, code, op0, NULL_RTX);
2725 emit_insn (pat);
2727 if (temp != target)
2728 emit_move_insn (target, temp);
2731 /* Emit code to perform a series of operations on a multi-word quantity, one
2732 word at a time.
2734 Such a block is preceded by a CLOBBER of the output, consists of multiple
2735 insns, each setting one word of the output, and followed by a SET copying
2736 the output to itself.
2738 Each of the insns setting words of the output receives a REG_NO_CONFLICT
2739 note indicating that it doesn't conflict with the (also multi-word)
2740 inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
2741 notes.
2743 INSNS is a block of code generated to perform the operation, not including
2744 the CLOBBER and final copy. All insns that compute intermediate values
2745 are first emitted, followed by the block as described above.
2747 TARGET, OP0, and OP1 are the output and inputs of the operations,
2748 respectively. OP1 may be zero for a unary operation.
2750 EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
2751 on the last insn.
2753 If TARGET is not a register, INSNS is simply emitted with no special
2754 processing. Likewise if anything in INSNS is not an INSN or if
2755 there is a libcall block inside INSNS.
2757 The final insn emitted is returned. */
2760 emit_no_conflict_block (insns, target, op0, op1, equiv)
2761 rtx insns;
2762 rtx target;
2763 rtx op0, op1;
2764 rtx equiv;
2766 rtx prev, next, first, last, insn;
2768 if (GET_CODE (target) != REG || reload_in_progress)
2769 return emit_insns (insns);
2770 else
2771 for (insn = insns; insn; insn = NEXT_INSN (insn))
2772 if (GET_CODE (insn) != INSN
2773 || find_reg_note (insn, REG_LIBCALL, NULL_RTX))
2774 return emit_insns (insns);
2776 /* First emit all insns that do not store into words of the output and remove
2777 these from the list. */
2778 for (insn = insns; insn; insn = next)
2780 rtx set = 0;
2781 int i;
2783 next = NEXT_INSN (insn);
2785 if (GET_CODE (PATTERN (insn)) == SET)
2786 set = PATTERN (insn);
2787 else if (GET_CODE (PATTERN (insn)) == PARALLEL)
2789 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
2790 if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
2792 set = XVECEXP (PATTERN (insn), 0, i);
2793 break;
2797 if (set == 0)
2798 abort ();
2800 if (! reg_overlap_mentioned_p (target, SET_DEST (set)))
2802 if (PREV_INSN (insn))
2803 NEXT_INSN (PREV_INSN (insn)) = next;
2804 else
2805 insns = next;
2807 if (next)
2808 PREV_INSN (next) = PREV_INSN (insn);
2810 add_insn (insn);
2814 prev = get_last_insn ();
2816 /* Now write the CLOBBER of the output, followed by the setting of each
2817 of the words, followed by the final copy. */
2818 if (target != op0 && target != op1)
2819 emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
2821 for (insn = insns; insn; insn = next)
2823 next = NEXT_INSN (insn);
2824 add_insn (insn);
2826 if (op1 && GET_CODE (op1) == REG)
2827 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op1,
2828 REG_NOTES (insn));
2830 if (op0 && GET_CODE (op0) == REG)
2831 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op0,
2832 REG_NOTES (insn));
2835 if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
2836 != CODE_FOR_nothing)
2838 last = emit_move_insn (target, target);
2839 if (equiv)
2840 set_unique_reg_note (last, REG_EQUAL, equiv);
2842 else
2843 last = get_last_insn ();
2845 if (prev == 0)
2846 first = get_insns ();
2847 else
2848 first = NEXT_INSN (prev);
2850 /* Encapsulate the block so it gets manipulated as a unit. */
2851 REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
2852 REG_NOTES (first));
2853 REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2855 return last;
2858 /* Emit code to make a call to a constant function or a library call.
2860 INSNS is a list containing all insns emitted in the call.
2861 These insns leave the result in RESULT. Our block is to copy RESULT
2862 to TARGET, which is logically equivalent to EQUIV.
2864 We first emit any insns that set a pseudo on the assumption that these are
2865 loading constants into registers; doing so allows them to be safely cse'ed
2866 between blocks. Then we emit all the other insns in the block, followed by
2867 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
2868 note with an operand of EQUIV.
2870 Moving assignments to pseudos outside of the block is done to improve
2871 the generated code, but is not required to generate correct code,
2872 hence being unable to move an assignment is not grounds for not making
2873 a libcall block. There are two reasons why it is safe to leave these
2874 insns inside the block: First, we know that these pseudos cannot be
2875 used in generated RTL outside the block since they are created for
2876 temporary purposes within the block. Second, CSE will not record the
2877 values of anything set inside a libcall block, so we know they must
2878 be dead at the end of the block.
2880 Except for the first group of insns (the ones setting pseudos), the
2881 block is delimited by REG_RETVAL and REG_LIBCALL notes. */
2883 void
2884 emit_libcall_block (insns, target, result, equiv)
2885 rtx insns;
2886 rtx target;
2887 rtx result;
2888 rtx equiv;
2890 rtx prev, next, first, last, insn;
2892 /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
2893 reg note to indicate that this call cannot throw. (Unless there is
2894 already a REG_EH_REGION note.) */
2896 for (insn = insns; insn; insn = NEXT_INSN (insn))
2898 if (GET_CODE (insn) == CALL_INSN)
2900 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
2901 if (note == NULL_RTX)
2902 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (-1),
2903 REG_NOTES (insn));
2907 /* First emit all insns that set pseudos. Remove them from the list as
2908 we go. Avoid insns that set pseudos which were referenced in previous
2909 insns. These can be generated by move_by_pieces, for example,
2910 to update an address. Similarly, avoid insns that reference things
2911 set in previous insns. */
2913 for (insn = insns; insn; insn = next)
2915 rtx set = single_set (insn);
2917 next = NEXT_INSN (insn);
2919 if (set != 0 && GET_CODE (SET_DEST (set)) == REG
2920 && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
2921 && (insn == insns
2922 || (! reg_mentioned_p (SET_DEST (set), PATTERN (insns))
2923 && ! reg_used_between_p (SET_DEST (set), insns, insn)
2924 && ! modified_in_p (SET_SRC (set), insns)
2925 && ! modified_between_p (SET_SRC (set), insns, insn))))
2927 if (PREV_INSN (insn))
2928 NEXT_INSN (PREV_INSN (insn)) = next;
2929 else
2930 insns = next;
2932 if (next)
2933 PREV_INSN (next) = PREV_INSN (insn);
2935 add_insn (insn);
2939 prev = get_last_insn ();
2941 /* Write the remaining insns followed by the final copy. */
2943 for (insn = insns; insn; insn = next)
2945 next = NEXT_INSN (insn);
2947 add_insn (insn);
2950 last = emit_move_insn (target, result);
2951 if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
2952 != CODE_FOR_nothing)
2953 set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
2955 if (prev == 0)
2956 first = get_insns ();
2957 else
2958 first = NEXT_INSN (prev);
2960 /* Encapsulate the block so it gets manipulated as a unit. */
2961 REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
2962 REG_NOTES (first));
2963 REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2966 /* Generate code to store zero in X. */
2968 void
2969 emit_clr_insn (x)
2970 rtx x;
2972 emit_move_insn (x, const0_rtx);
2975 /* Generate code to store 1 in X
2976 assuming it contains zero beforehand. */
2978 void
2979 emit_0_to_1_insn (x)
2980 rtx x;
2982 emit_move_insn (x, const1_rtx);
2985 /* Generate code to compare X with Y
2986 so that the condition codes are set.
2988 MODE is the mode of the inputs (in case they are const_int).
2989 UNSIGNEDP nonzero says that X and Y are unsigned;
2990 this matters if they need to be widened.
2992 If they have mode BLKmode, then SIZE specifies the size of both X and Y,
2993 and ALIGN specifies the known shared alignment of X and Y.
2995 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
2996 It is ignored for fixed-point and block comparisons;
2997 it is used only for floating-point comparisons. */
2999 void
3000 emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
3001 rtx x, y;
3002 enum rtx_code comparison;
3003 rtx size;
3004 enum machine_mode mode;
3005 int unsignedp;
3006 int align;
3008 enum mode_class class;
3009 enum machine_mode wider_mode;
3011 class = GET_MODE_CLASS (mode);
3013 /* They could both be VOIDmode if both args are immediate constants,
3014 but we should fold that at an earlier stage.
3015 With no special code here, this will call abort,
3016 reminding the programmer to implement such folding. */
3018 if (mode != BLKmode && flag_force_mem)
3020 x = force_not_mem (x);
3021 y = force_not_mem (y);
3024 /* If we are inside an appropriately-short loop and one operand is an
3025 expensive constant, force it into a register. */
3026 if (CONSTANT_P (x) && preserve_subexpressions_p () && rtx_cost (x, COMPARE) > 2)
3027 x = force_reg (mode, x);
3029 if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2)
3030 y = force_reg (mode, y);
3032 #ifdef HAVE_cc0
3033 /* Abort if we have a non-canonical comparison. The RTL documentation
3034 states that canonical comparisons are required only for targets which
3035 have cc0. */
3036 if (CONSTANT_P (x) && ! CONSTANT_P (y))
3037 abort();
3038 #endif
3040 /* Don't let both operands fail to indicate the mode. */
3041 if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
3042 x = force_reg (mode, x);
3044 /* Handle all BLKmode compares. */
3046 if (mode == BLKmode)
3048 emit_queue ();
3049 x = protect_from_queue (x, 0);
3050 y = protect_from_queue (y, 0);
3052 if (size == 0)
3053 abort ();
3054 #ifdef HAVE_cmpstrqi
3055 if (HAVE_cmpstrqi
3056 && GET_CODE (size) == CONST_INT
3057 && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
3059 enum machine_mode result_mode
3060 = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0];
3061 rtx result = gen_reg_rtx (result_mode);
3062 emit_insn (gen_cmpstrqi (result, x, y, size, GEN_INT (align)));
3063 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
3064 result_mode, 0, 0);
3066 else
3067 #endif
3068 #ifdef HAVE_cmpstrhi
3069 if (HAVE_cmpstrhi
3070 && GET_CODE (size) == CONST_INT
3071 && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
3073 enum machine_mode result_mode
3074 = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0];
3075 rtx result = gen_reg_rtx (result_mode);
3076 emit_insn (gen_cmpstrhi (result, x, y, size, GEN_INT (align)));
3077 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
3078 result_mode, 0, 0);
3080 else
3081 #endif
3082 #ifdef HAVE_cmpstrsi
3083 if (HAVE_cmpstrsi)
3085 enum machine_mode result_mode
3086 = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0];
3087 rtx result = gen_reg_rtx (result_mode);
3088 size = protect_from_queue (size, 0);
3089 emit_insn (gen_cmpstrsi (result, x, y,
3090 convert_to_mode (SImode, size, 1),
3091 GEN_INT (align)));
3092 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
3093 result_mode, 0, 0);
3095 else
3096 #endif
3098 rtx result;
3100 #ifdef TARGET_MEM_FUNCTIONS
3101 emit_library_call (memcmp_libfunc, 0,
3102 TYPE_MODE (integer_type_node), 3,
3103 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
3104 convert_to_mode (TYPE_MODE (sizetype), size,
3105 TREE_UNSIGNED (sizetype)),
3106 TYPE_MODE (sizetype));
3107 #else
3108 emit_library_call (bcmp_libfunc, 0,
3109 TYPE_MODE (integer_type_node), 3,
3110 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
3111 convert_to_mode (TYPE_MODE (integer_type_node),
3112 size,
3113 TREE_UNSIGNED (integer_type_node)),
3114 TYPE_MODE (integer_type_node));
3115 #endif
3117 /* Immediately move the result of the libcall into a pseudo
3118 register so reload doesn't clobber the value if it needs
3119 the return register for a spill reg. */
3120 result = gen_reg_rtx (TYPE_MODE (integer_type_node));
3121 emit_move_insn (result,
3122 hard_libcall_value (TYPE_MODE (integer_type_node)));
3123 emit_cmp_insn (result,
3124 const0_rtx, comparison, NULL_RTX,
3125 TYPE_MODE (integer_type_node), 0, 0);
3127 return;
3130 /* Handle some compares against zero. */
3132 if (y == CONST0_RTX (mode)
3133 && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
3135 int icode = (int) tst_optab->handlers[(int) mode].insn_code;
3137 emit_queue ();
3138 x = protect_from_queue (x, 0);
3139 y = protect_from_queue (y, 0);
3141 /* Now, if insn does accept these operands, put them into pseudos. */
3142 if (! (*insn_operand_predicate[icode][0])
3143 (x, insn_operand_mode[icode][0]))
3144 x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
3146 emit_insn (GEN_FCN (icode) (x));
3147 return;
3150 /* Handle compares for which there is a directly suitable insn. */
3152 if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
3154 int icode = (int) cmp_optab->handlers[(int) mode].insn_code;
3156 emit_queue ();
3157 x = protect_from_queue (x, 0);
3158 y = protect_from_queue (y, 0);
3160 /* Now, if insn doesn't accept these operands, put them into pseudos. */
3161 if (! (*insn_operand_predicate[icode][0])
3162 (x, insn_operand_mode[icode][0]))
3163 x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
3165 if (! (*insn_operand_predicate[icode][1])
3166 (y, insn_operand_mode[icode][1]))
3167 y = copy_to_mode_reg (insn_operand_mode[icode][1], y);
3169 emit_insn (GEN_FCN (icode) (x, y));
3170 return;
3173 /* Try widening if we can find a direct insn that way. */
3175 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
3177 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
3178 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3180 if (cmp_optab->handlers[(int) wider_mode].insn_code
3181 != CODE_FOR_nothing)
3183 x = protect_from_queue (x, 0);
3184 y = protect_from_queue (y, 0);
3185 x = convert_modes (wider_mode, mode, x, unsignedp);
3186 y = convert_modes (wider_mode, mode, y, unsignedp);
3187 emit_cmp_insn (x, y, comparison, NULL_RTX,
3188 wider_mode, unsignedp, align);
3189 return;
3194 /* Handle a lib call just for the mode we are using. */
3196 if (cmp_optab->handlers[(int) mode].libfunc
3197 && class != MODE_FLOAT)
3199 rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
3200 rtx result;
3202 /* If we want unsigned, and this mode has a distinct unsigned
3203 comparison routine, use that. */
3204 if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
3205 libfunc = ucmp_optab->handlers[(int) mode].libfunc;
3207 emit_library_call (libfunc, 1,
3208 word_mode, 2, x, mode, y, mode);
3210 /* Immediately move the result of the libcall into a pseudo
3211 register so reload doesn't clobber the value if it needs
3212 the return register for a spill reg. */
3213 result = gen_reg_rtx (word_mode);
3214 emit_move_insn (result, hard_libcall_value (word_mode));
3216 /* Integer comparison returns a result that must be compared against 1,
3217 so that even if we do an unsigned compare afterward,
3218 there is still a value that can represent the result "less than". */
3219 emit_cmp_insn (result, const1_rtx,
3220 comparison, NULL_RTX, word_mode, unsignedp, 0);
3221 return;
3224 if (class == MODE_FLOAT)
3225 emit_float_lib_cmp (x, y, comparison);
3227 else
3228 abort ();
3231 /* Generate code to compare X with Y so that the condition codes are
3232 set and to jump to LABEL if the condition is true. If X is a
3233 constant and Y is not a constant, then the comparison is swapped to
3234 ensure that the comparison RTL has the canonical form.
3236 UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
3237 need to be widened by emit_cmp_insn. UNSIGNEDP is also used to select
3238 the proper branch condition code.
3240 If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y,
3241 and ALIGN specifies the known shared alignment of X and Y.
3243 MODE is the mode of the inputs (in case they are const_int).
3245 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). It will
3246 be passed unchanged to emit_cmp_insn, then potentially converted into an
3247 unsigned variant based on UNSIGNEDP to select a proper jump instruction. */
3249 void
3250 emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, label)
3251 rtx x, y;
3252 enum rtx_code comparison;
3253 rtx size;
3254 enum machine_mode mode;
3255 int unsignedp;
3256 int align;
3257 rtx label;
3259 rtx op0;
3260 rtx op1;
3262 if (CONSTANT_P (x))
3264 /* Swap operands and condition to ensure canonical RTL. */
3265 op0 = y;
3266 op1 = x;
3267 comparison = swap_condition (comparison);
3269 else
3271 op0 = x;
3272 op1 = y;
3275 #ifdef HAVE_cc0
3276 /* If OP0 is still a constant, then both X and Y must be constants. Force
3277 X into a register to avoid aborting in emit_cmp_insn due to non-canonical
3278 RTL. */
3279 if (CONSTANT_P (op0))
3280 op0 = force_reg (mode, op0);
3281 #endif
3283 emit_cmp_insn (op0, op1, comparison, size, mode, unsignedp, align);
3285 if (unsignedp)
3286 comparison = unsigned_condition (comparison);
3287 emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
3291 /* Nonzero if a compare of mode MODE can be done straightforwardly
3292 (without splitting it into pieces). */
3295 can_compare_p (mode)
3296 enum machine_mode mode;
3300 if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
3301 return 1;
3302 mode = GET_MODE_WIDER_MODE (mode);
3303 } while (mode != VOIDmode);
3305 return 0;
3308 /* Emit a library call comparison between floating point X and Y.
3309 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
3311 void
3312 emit_float_lib_cmp (x, y, comparison)
3313 rtx x, y;
3314 enum rtx_code comparison;
3316 enum machine_mode mode = GET_MODE (x);
3317 rtx libfunc = 0;
3318 rtx result;
3320 if (mode == HFmode)
3321 switch (comparison)
3323 case EQ:
3324 libfunc = eqhf2_libfunc;
3325 break;
3327 case NE:
3328 libfunc = nehf2_libfunc;
3329 break;
3331 case GT:
3332 libfunc = gthf2_libfunc;
3333 break;
3335 case GE:
3336 libfunc = gehf2_libfunc;
3337 break;
3339 case LT:
3340 libfunc = lthf2_libfunc;
3341 break;
3343 case LE:
3344 libfunc = lehf2_libfunc;
3345 break;
3347 default:
3348 break;
3350 else if (mode == SFmode)
3351 switch (comparison)
3353 case EQ:
3354 libfunc = eqsf2_libfunc;
3355 break;
3357 case NE:
3358 libfunc = nesf2_libfunc;
3359 break;
3361 case GT:
3362 libfunc = gtsf2_libfunc;
3363 break;
3365 case GE:
3366 libfunc = gesf2_libfunc;
3367 break;
3369 case LT:
3370 libfunc = ltsf2_libfunc;
3371 break;
3373 case LE:
3374 libfunc = lesf2_libfunc;
3375 break;
3377 default:
3378 break;
3380 else if (mode == DFmode)
3381 switch (comparison)
3383 case EQ:
3384 libfunc = eqdf2_libfunc;
3385 break;
3387 case NE:
3388 libfunc = nedf2_libfunc;
3389 break;
3391 case GT:
3392 libfunc = gtdf2_libfunc;
3393 break;
3395 case GE:
3396 libfunc = gedf2_libfunc;
3397 break;
3399 case LT:
3400 libfunc = ltdf2_libfunc;
3401 break;
3403 case LE:
3404 libfunc = ledf2_libfunc;
3405 break;
3407 default:
3408 break;
3410 else if (mode == XFmode)
3411 switch (comparison)
3413 case EQ:
3414 libfunc = eqxf2_libfunc;
3415 break;
3417 case NE:
3418 libfunc = nexf2_libfunc;
3419 break;
3421 case GT:
3422 libfunc = gtxf2_libfunc;
3423 break;
3425 case GE:
3426 libfunc = gexf2_libfunc;
3427 break;
3429 case LT:
3430 libfunc = ltxf2_libfunc;
3431 break;
3433 case LE:
3434 libfunc = lexf2_libfunc;
3435 break;
3437 default:
3438 break;
3440 else if (mode == TFmode)
3441 switch (comparison)
3443 case EQ:
3444 libfunc = eqtf2_libfunc;
3445 break;
3447 case NE:
3448 libfunc = netf2_libfunc;
3449 break;
3451 case GT:
3452 libfunc = gttf2_libfunc;
3453 break;
3455 case GE:
3456 libfunc = getf2_libfunc;
3457 break;
3459 case LT:
3460 libfunc = lttf2_libfunc;
3461 break;
3463 case LE:
3464 libfunc = letf2_libfunc;
3465 break;
3467 default:
3468 break;
3470 else
3472 enum machine_mode wider_mode;
3474 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
3475 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3477 if ((cmp_optab->handlers[(int) wider_mode].insn_code
3478 != CODE_FOR_nothing)
3479 || (cmp_optab->handlers[(int) wider_mode].libfunc != 0))
3481 x = protect_from_queue (x, 0);
3482 y = protect_from_queue (y, 0);
3483 x = convert_to_mode (wider_mode, x, 0);
3484 y = convert_to_mode (wider_mode, y, 0);
3485 emit_float_lib_cmp (x, y, comparison);
3486 return;
3489 abort ();
3492 if (libfunc == 0)
3493 abort ();
3495 emit_library_call (libfunc, 1,
3496 word_mode, 2, x, mode, y, mode);
3498 /* Immediately move the result of the libcall into a pseudo
3499 register so reload doesn't clobber the value if it needs
3500 the return register for a spill reg. */
3501 result = gen_reg_rtx (word_mode);
3502 emit_move_insn (result, hard_libcall_value (word_mode));
3504 emit_cmp_insn (result, const0_rtx, comparison,
3505 NULL_RTX, word_mode, 0, 0);
3508 /* Generate code to indirectly jump to a location given in the rtx LOC. */
3510 void
3511 emit_indirect_jump (loc)
3512 rtx loc;
3514 if (! ((*insn_operand_predicate[(int)CODE_FOR_indirect_jump][0])
3515 (loc, Pmode)))
3516 loc = copy_to_mode_reg (Pmode, loc);
3518 emit_jump_insn (gen_indirect_jump (loc));
3519 emit_barrier ();
3522 #ifdef HAVE_conditional_move
3524 /* Emit a conditional move instruction if the machine supports one for that
3525 condition and machine mode.
3527 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
3528 the mode to use should they be constants. If it is VOIDmode, they cannot
3529 both be constants.
3531 OP2 should be stored in TARGET if the comparison is true, otherwise OP3
3532 should be stored there. MODE is the mode to use should they be constants.
3533 If it is VOIDmode, they cannot both be constants.
3535 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
3536 is not supported. */
3539 emit_conditional_move (target, code, op0, op1, cmode, op2, op3, mode,
3540 unsignedp)
3541 rtx target;
3542 enum rtx_code code;
3543 rtx op0, op1;
3544 enum machine_mode cmode;
3545 rtx op2, op3;
3546 enum machine_mode mode;
3547 int unsignedp;
3549 rtx tem, subtarget, comparison, insn;
3550 enum insn_code icode;
3552 /* If one operand is constant, make it the second one. Only do this
3553 if the other operand is not constant as well. */
3555 if ((CONSTANT_P (op0) && ! CONSTANT_P (op1))
3556 || (GET_CODE (op0) == CONST_INT && GET_CODE (op1) != CONST_INT))
3558 tem = op0;
3559 op0 = op1;
3560 op1 = tem;
3561 code = swap_condition (code);
3564 if (cmode == VOIDmode)
3565 cmode = GET_MODE (op0);
3567 if (((CONSTANT_P (op2) && ! CONSTANT_P (op3))
3568 || (GET_CODE (op2) == CONST_INT && GET_CODE (op3) != CONST_INT))
3569 && (GET_MODE_CLASS (GET_MODE (op1)) != MODE_FLOAT
3570 || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT || flag_fast_math))
3572 tem = op2;
3573 op2 = op3;
3574 op3 = tem;
3575 code = reverse_condition (code);
3578 if (mode == VOIDmode)
3579 mode = GET_MODE (op2);
3581 icode = movcc_gen_code[mode];
3583 if (icode == CODE_FOR_nothing)
3584 return 0;
3586 if (flag_force_mem)
3588 op2 = force_not_mem (op2);
3589 op3 = force_not_mem (op3);
3592 if (target)
3593 target = protect_from_queue (target, 1);
3594 else
3595 target = gen_reg_rtx (mode);
3597 subtarget = target;
3599 emit_queue ();
3601 op2 = protect_from_queue (op2, 0);
3602 op3 = protect_from_queue (op3, 0);
3604 /* If the insn doesn't accept these operands, put them in pseudos. */
3606 if (! (*insn_operand_predicate[icode][0])
3607 (subtarget, insn_operand_mode[icode][0]))
3608 subtarget = gen_reg_rtx (insn_operand_mode[icode][0]);
3610 if (! (*insn_operand_predicate[icode][2])
3611 (op2, insn_operand_mode[icode][2]))
3612 op2 = copy_to_mode_reg (insn_operand_mode[icode][2], op2);
3614 if (! (*insn_operand_predicate[icode][3])
3615 (op3, insn_operand_mode[icode][3]))
3616 op3 = copy_to_mode_reg (insn_operand_mode[icode][3], op3);
3618 /* Everything should now be in the suitable form, so emit the compare insn
3619 and then the conditional move. */
3621 comparison
3622 = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX, 0);
3624 /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)? */
3625 if (GET_CODE (comparison) != code)
3626 /* This shouldn't happen. */
3627 abort ();
3629 insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
3631 /* If that failed, then give up. */
3632 if (insn == 0)
3633 return 0;
3635 emit_insn (insn);
3637 if (subtarget != target)
3638 convert_move (target, subtarget, 0);
3640 return target;
3643 /* Return non-zero if a conditional move of mode MODE is supported.
3645 This function is for combine so it can tell whether an insn that looks
3646 like a conditional move is actually supported by the hardware. If we
3647 guess wrong we lose a bit on optimization, but that's it. */
3648 /* ??? sparc64 supports conditionally moving integers values based on fp
3649 comparisons, and vice versa. How do we handle them? */
3652 can_conditionally_move_p (mode)
3653 enum machine_mode mode;
3655 if (movcc_gen_code[mode] != CODE_FOR_nothing)
3656 return 1;
3658 return 0;
3661 #endif /* HAVE_conditional_move */
3663 /* These three functions generate an insn body and return it
3664 rather than emitting the insn.
3666 They do not protect from queued increments,
3667 because they may be used 1) in protect_from_queue itself
3668 and 2) in other passes where there is no queue. */
3670 /* Generate and return an insn body to add Y to X. */
3673 gen_add2_insn (x, y)
3674 rtx x, y;
3676 int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code;
3678 if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
3679 || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
3680 || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
3681 abort ();
3683 return (GEN_FCN (icode) (x, x, y));
3687 have_add2_insn (mode)
3688 enum machine_mode mode;
3690 return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
3693 /* Generate and return an insn body to subtract Y from X. */
3696 gen_sub2_insn (x, y)
3697 rtx x, y;
3699 int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code;
3701 if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
3702 || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
3703 || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
3704 abort ();
3706 return (GEN_FCN (icode) (x, x, y));
3710 have_sub2_insn (mode)
3711 enum machine_mode mode;
3713 return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
3716 /* Generate the body of an instruction to copy Y into X.
3717 It may be a SEQUENCE, if one insn isn't enough. */
3720 gen_move_insn (x, y)
3721 rtx x, y;
3723 register enum machine_mode mode = GET_MODE (x);
3724 enum insn_code insn_code;
3725 rtx seq;
3727 if (mode == VOIDmode)
3728 mode = GET_MODE (y);
3730 insn_code = mov_optab->handlers[(int) mode].insn_code;
3732 /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
3733 find a mode to do it in. If we have a movcc, use it. Otherwise,
3734 find the MODE_INT mode of the same width. */
3736 if (GET_MODE_CLASS (mode) == MODE_CC && insn_code == CODE_FOR_nothing)
3738 enum machine_mode tmode = VOIDmode;
3739 rtx x1 = x, y1 = y;
3741 if (mode != CCmode
3742 && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing)
3743 tmode = CCmode;
3744 else
3745 for (tmode = QImode; tmode != VOIDmode;
3746 tmode = GET_MODE_WIDER_MODE (tmode))
3747 if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode))
3748 break;
3750 if (tmode == VOIDmode)
3751 abort ();
3753 /* Get X and Y in TMODE. We can't use gen_lowpart here because it
3754 may call change_address which is not appropriate if we were
3755 called when a reload was in progress. We don't have to worry
3756 about changing the address since the size in bytes is supposed to
3757 be the same. Copy the MEM to change the mode and move any
3758 substitutions from the old MEM to the new one. */
3760 if (reload_in_progress)
3762 x = gen_lowpart_common (tmode, x1);
3763 if (x == 0 && GET_CODE (x1) == MEM)
3765 x = gen_rtx_MEM (tmode, XEXP (x1, 0));
3766 RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1);
3767 MEM_COPY_ATTRIBUTES (x, x1);
3768 copy_replacements (x1, x);
3771 y = gen_lowpart_common (tmode, y1);
3772 if (y == 0 && GET_CODE (y1) == MEM)
3774 y = gen_rtx_MEM (tmode, XEXP (y1, 0));
3775 RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1);
3776 MEM_COPY_ATTRIBUTES (y, y1);
3777 copy_replacements (y1, y);
3780 else
3782 x = gen_lowpart (tmode, x);
3783 y = gen_lowpart (tmode, y);
3786 insn_code = mov_optab->handlers[(int) tmode].insn_code;
3787 return (GEN_FCN (insn_code) (x, y));
3790 start_sequence ();
3791 emit_move_insn_1 (x, y);
3792 seq = gen_sequence ();
3793 end_sequence ();
3794 return seq;
3797 /* Return the insn code used to extend FROM_MODE to TO_MODE.
3798 UNSIGNEDP specifies zero-extension instead of sign-extension. If
3799 no such operation exists, CODE_FOR_nothing will be returned. */
3801 enum insn_code
3802 can_extend_p (to_mode, from_mode, unsignedp)
3803 enum machine_mode to_mode, from_mode;
3804 int unsignedp;
3806 return extendtab[(int) to_mode][(int) from_mode][unsignedp];
3809 /* Generate the body of an insn to extend Y (with mode MFROM)
3810 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
3813 gen_extend_insn (x, y, mto, mfrom, unsignedp)
3814 rtx x, y;
3815 enum machine_mode mto, mfrom;
3816 int unsignedp;
3818 return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp]) (x, y));
3821 /* can_fix_p and can_float_p say whether the target machine
3822 can directly convert a given fixed point type to
3823 a given floating point type, or vice versa.
3824 The returned value is the CODE_FOR_... value to use,
3825 or CODE_FOR_nothing if these modes cannot be directly converted.
3827 *TRUNCP_PTR is set to 1 if it is necessary to output
3828 an explicit FTRUNC insn before the fix insn; otherwise 0. */
3830 static enum insn_code
3831 can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
3832 enum machine_mode fltmode, fixmode;
3833 int unsignedp;
3834 int *truncp_ptr;
3836 *truncp_ptr = 0;
3837 if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp] != CODE_FOR_nothing)
3838 return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp];
3840 if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
3842 *truncp_ptr = 1;
3843 return fixtab[(int) fltmode][(int) fixmode][unsignedp];
3845 return CODE_FOR_nothing;
3848 static enum insn_code
3849 can_float_p (fltmode, fixmode, unsignedp)
3850 enum machine_mode fixmode, fltmode;
3851 int unsignedp;
3853 return floattab[(int) fltmode][(int) fixmode][unsignedp];
3856 /* Generate code to convert FROM to floating point
3857 and store in TO. FROM must be fixed point and not VOIDmode.
3858 UNSIGNEDP nonzero means regard FROM as unsigned.
3859 Normally this is done by correcting the final value
3860 if it is negative. */
3862 void
3863 expand_float (to, from, unsignedp)
3864 rtx to, from;
3865 int unsignedp;
3867 enum insn_code icode;
3868 register rtx target = to;
3869 enum machine_mode fmode, imode;
3871 /* Crash now, because we won't be able to decide which mode to use. */
3872 if (GET_MODE (from) == VOIDmode)
3873 abort ();
3875 /* Look for an insn to do the conversion. Do it in the specified
3876 modes if possible; otherwise convert either input, output or both to
3877 wider mode. If the integer mode is wider than the mode of FROM,
3878 we can do the conversion signed even if the input is unsigned. */
3880 for (imode = GET_MODE (from); imode != VOIDmode;
3881 imode = GET_MODE_WIDER_MODE (imode))
3882 for (fmode = GET_MODE (to); fmode != VOIDmode;
3883 fmode = GET_MODE_WIDER_MODE (fmode))
3885 int doing_unsigned = unsignedp;
3887 icode = can_float_p (fmode, imode, unsignedp);
3888 if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
3889 icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;
3891 if (icode != CODE_FOR_nothing)
3893 to = protect_from_queue (to, 1);
3894 from = protect_from_queue (from, 0);
3896 if (imode != GET_MODE (from))
3897 from = convert_to_mode (imode, from, unsignedp);
3899 if (fmode != GET_MODE (to))
3900 target = gen_reg_rtx (fmode);
3902 emit_unop_insn (icode, target, from,
3903 doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
3905 if (target != to)
3906 convert_move (to, target, 0);
3907 return;
3911 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3913 /* Unsigned integer, and no way to convert directly.
3914 Convert as signed, then conditionally adjust the result. */
3915 if (unsignedp)
3917 rtx label = gen_label_rtx ();
3918 rtx temp;
3919 REAL_VALUE_TYPE offset;
3921 emit_queue ();
3923 to = protect_from_queue (to, 1);
3924 from = protect_from_queue (from, 0);
3926 if (flag_force_mem)
3927 from = force_not_mem (from);
3929 /* Look for a usable floating mode FMODE wider than the source and at
3930 least as wide as the target. Using FMODE will avoid rounding woes
3931 with unsigned values greater than the signed maximum value. */
3933 for (fmode = GET_MODE (to); fmode != VOIDmode;
3934 fmode = GET_MODE_WIDER_MODE (fmode))
3935 if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
3936 && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
3937 break;
3939 if (fmode == VOIDmode)
3941 /* There is no such mode. Pretend the target is wide enough. */
3942 fmode = GET_MODE (to);
3944 /* Avoid double-rounding when TO is narrower than FROM. */
3945 if ((significand_size (fmode) + 1)
3946 < GET_MODE_BITSIZE (GET_MODE (from)))
3948 rtx temp1;
3949 rtx neglabel = gen_label_rtx ();
3951 /* Don't use TARGET if it isn't a register, is a hard register,
3952 or is the wrong mode. */
3953 if (GET_CODE (target) != REG
3954 || REGNO (target) < FIRST_PSEUDO_REGISTER
3955 || GET_MODE (target) != fmode)
3956 target = gen_reg_rtx (fmode);
3958 imode = GET_MODE (from);
3959 do_pending_stack_adjust ();
3961 /* Test whether the sign bit is set. */
3962 emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, imode, 0, 0);
3963 emit_jump_insn (gen_blt (neglabel));
3965 /* The sign bit is not set. Convert as signed. */
3966 expand_float (target, from, 0);
3967 emit_jump_insn (gen_jump (label));
3968 emit_barrier ();
3970 /* The sign bit is set.
3971 Convert to a usable (positive signed) value by shifting right
3972 one bit, while remembering if a nonzero bit was shifted
3973 out; i.e., compute (from & 1) | (from >> 1). */
3975 emit_label (neglabel);
3976 temp = expand_binop (imode, and_optab, from, const1_rtx,
3977 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3978 temp1 = expand_shift (RSHIFT_EXPR, imode, from, integer_one_node,
3979 NULL_RTX, 1);
3980 temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1,
3981 OPTAB_LIB_WIDEN);
3982 expand_float (target, temp, 0);
3984 /* Multiply by 2 to undo the shift above. */
3985 temp = expand_binop (fmode, add_optab, target, target,
3986 target, 0, OPTAB_LIB_WIDEN);
3987 if (temp != target)
3988 emit_move_insn (target, temp);
3990 do_pending_stack_adjust ();
3991 emit_label (label);
3992 goto done;
3996 /* If we are about to do some arithmetic to correct for an
3997 unsigned operand, do it in a pseudo-register. */
3999 if (GET_MODE (to) != fmode
4000 || GET_CODE (to) != REG || REGNO (to) < FIRST_PSEUDO_REGISTER)
4001 target = gen_reg_rtx (fmode);
4003 /* Convert as signed integer to floating. */
4004 expand_float (target, from, 0);
4006 /* If FROM is negative (and therefore TO is negative),
4007 correct its value by 2**bitwidth. */
4009 do_pending_stack_adjust ();
4010 emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
4011 0, 0, label);
4013 /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
4014 Rather than setting up a dconst_dot_5, let's hope SCO
4015 fixes the bug. */
4016 offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from)));
4017 temp = expand_binop (fmode, add_optab, target,
4018 CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
4019 target, 0, OPTAB_LIB_WIDEN);
4020 if (temp != target)
4021 emit_move_insn (target, temp);
4023 do_pending_stack_adjust ();
4024 emit_label (label);
4025 goto done;
4027 #endif
4029 /* No hardware instruction available; call a library routine to convert from
4030 SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */
4032 rtx libfcn;
4033 rtx insns;
4034 rtx value;
4036 to = protect_from_queue (to, 1);
4037 from = protect_from_queue (from, 0);
4039 if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
4040 from = convert_to_mode (SImode, from, unsignedp);
4042 if (flag_force_mem)
4043 from = force_not_mem (from);
4045 if (GET_MODE (to) == SFmode)
4047 if (GET_MODE (from) == SImode)
4048 libfcn = floatsisf_libfunc;
4049 else if (GET_MODE (from) == DImode)
4050 libfcn = floatdisf_libfunc;
4051 else if (GET_MODE (from) == TImode)
4052 libfcn = floattisf_libfunc;
4053 else
4054 abort ();
4056 else if (GET_MODE (to) == DFmode)
4058 if (GET_MODE (from) == SImode)
4059 libfcn = floatsidf_libfunc;
4060 else if (GET_MODE (from) == DImode)
4061 libfcn = floatdidf_libfunc;
4062 else if (GET_MODE (from) == TImode)
4063 libfcn = floattidf_libfunc;
4064 else
4065 abort ();
4067 else if (GET_MODE (to) == XFmode)
4069 if (GET_MODE (from) == SImode)
4070 libfcn = floatsixf_libfunc;
4071 else if (GET_MODE (from) == DImode)
4072 libfcn = floatdixf_libfunc;
4073 else if (GET_MODE (from) == TImode)
4074 libfcn = floattixf_libfunc;
4075 else
4076 abort ();
4078 else if (GET_MODE (to) == TFmode)
4080 if (GET_MODE (from) == SImode)
4081 libfcn = floatsitf_libfunc;
4082 else if (GET_MODE (from) == DImode)
4083 libfcn = floatditf_libfunc;
4084 else if (GET_MODE (from) == TImode)
4085 libfcn = floattitf_libfunc;
4086 else
4087 abort ();
4089 else
4090 abort ();
4092 start_sequence ();
4094 value = emit_library_call_value (libfcn, NULL_RTX, 1,
4095 GET_MODE (to),
4096 1, from, GET_MODE (from));
4097 insns = get_insns ();
4098 end_sequence ();
4100 emit_libcall_block (insns, target, value,
4101 gen_rtx_FLOAT (GET_MODE (to), from));
4104 done:
4106 /* Copy result to requested destination
4107 if we have been computing in a temp location. */
4109 if (target != to)
4111 if (GET_MODE (target) == GET_MODE (to))
4112 emit_move_insn (to, target);
4113 else
4114 convert_move (to, target, 0);
4118 /* expand_fix: generate code to convert FROM to fixed point
4119 and store in TO. FROM must be floating point. */
4121 static rtx
4122 ftruncify (x)
4123 rtx x;
4125 rtx temp = gen_reg_rtx (GET_MODE (x));
4126 return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0);
4129 void
4130 expand_fix (to, from, unsignedp)
4131 register rtx to, from;
4132 int unsignedp;
4134 enum insn_code icode;
4135 register rtx target = to;
4136 enum machine_mode fmode, imode;
4137 int must_trunc = 0;
4138 rtx libfcn = 0;
4140 /* We first try to find a pair of modes, one real and one integer, at
4141 least as wide as FROM and TO, respectively, in which we can open-code
4142 this conversion. If the integer mode is wider than the mode of TO,
4143 we can do the conversion either signed or unsigned. */
4145 for (imode = GET_MODE (to); imode != VOIDmode;
4146 imode = GET_MODE_WIDER_MODE (imode))
4147 for (fmode = GET_MODE (from); fmode != VOIDmode;
4148 fmode = GET_MODE_WIDER_MODE (fmode))
4150 int doing_unsigned = unsignedp;
4152 icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
4153 if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
4154 icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
4156 if (icode != CODE_FOR_nothing)
4158 to = protect_from_queue (to, 1);
4159 from = protect_from_queue (from, 0);
4161 if (fmode != GET_MODE (from))
4162 from = convert_to_mode (fmode, from, 0);
4164 if (must_trunc)
4165 from = ftruncify (from);
4167 if (imode != GET_MODE (to))
4168 target = gen_reg_rtx (imode);
4170 emit_unop_insn (icode, target, from,
4171 doing_unsigned ? UNSIGNED_FIX : FIX);
4172 if (target != to)
4173 convert_move (to, target, unsignedp);
4174 return;
4178 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
4179 /* For an unsigned conversion, there is one more way to do it.
4180 If we have a signed conversion, we generate code that compares
4181 the real value to the largest representable positive number. If if
4182 is smaller, the conversion is done normally. Otherwise, subtract
4183 one plus the highest signed number, convert, and add it back.
4185 We only need to check all real modes, since we know we didn't find
4186 anything with a wider integer mode. */
4188 if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
4189 for (fmode = GET_MODE (from); fmode != VOIDmode;
4190 fmode = GET_MODE_WIDER_MODE (fmode))
4191 /* Make sure we won't lose significant bits doing this. */
4192 if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))
4193 && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
4194 &must_trunc))
4196 int bitsize;
4197 REAL_VALUE_TYPE offset;
4198 rtx limit, lab1, lab2, insn;
4200 bitsize = GET_MODE_BITSIZE (GET_MODE (to));
4201 offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1);
4202 limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
4203 lab1 = gen_label_rtx ();
4204 lab2 = gen_label_rtx ();
4206 emit_queue ();
4207 to = protect_from_queue (to, 1);
4208 from = protect_from_queue (from, 0);
4210 if (flag_force_mem)
4211 from = force_not_mem (from);
4213 if (fmode != GET_MODE (from))
4214 from = convert_to_mode (fmode, from, 0);
4216 /* See if we need to do the subtraction. */
4217 do_pending_stack_adjust ();
4218 emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
4219 0, 0, lab1);
4221 /* If not, do the signed "fix" and branch around fixup code. */
4222 expand_fix (to, from, 0);
4223 emit_jump_insn (gen_jump (lab2));
4224 emit_barrier ();
4226 /* Otherwise, subtract 2**(N-1), convert to signed number,
4227 then add 2**(N-1). Do the addition using XOR since this
4228 will often generate better code. */
4229 emit_label (lab1);
4230 target = expand_binop (GET_MODE (from), sub_optab, from, limit,
4231 NULL_RTX, 0, OPTAB_LIB_WIDEN);
4232 expand_fix (to, target, 0);
4233 target = expand_binop (GET_MODE (to), xor_optab, to,
4234 GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)),
4235 to, 1, OPTAB_LIB_WIDEN);
4237 if (target != to)
4238 emit_move_insn (to, target);
4240 emit_label (lab2);
4242 if (mov_optab->handlers[(int) GET_MODE (to)].insn_code
4243 != CODE_FOR_nothing)
4245 /* Make a place for a REG_NOTE and add it. */
4246 insn = emit_move_insn (to, to);
4247 set_unique_reg_note (insn,
4248 REG_EQUAL,
4249 gen_rtx_fmt_e (UNSIGNED_FIX,
4250 GET_MODE (to),
4251 copy_rtx (from)));
4253 return;
4255 #endif
4257 /* We can't do it with an insn, so use a library call. But first ensure
4258 that the mode of TO is at least as wide as SImode, since those are the
4259 only library calls we know about. */
4261 if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
4263 target = gen_reg_rtx (SImode);
4265 expand_fix (target, from, unsignedp);
4267 else if (GET_MODE (from) == SFmode)
4269 if (GET_MODE (to) == SImode)
4270 libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc;
4271 else if (GET_MODE (to) == DImode)
4272 libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc;
4273 else if (GET_MODE (to) == TImode)
4274 libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc;
4275 else
4276 abort ();
4278 else if (GET_MODE (from) == DFmode)
4280 if (GET_MODE (to) == SImode)
4281 libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc;
4282 else if (GET_MODE (to) == DImode)
4283 libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc;
4284 else if (GET_MODE (to) == TImode)
4285 libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc;
4286 else
4287 abort ();
4289 else if (GET_MODE (from) == XFmode)
4291 if (GET_MODE (to) == SImode)
4292 libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc;
4293 else if (GET_MODE (to) == DImode)
4294 libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc;
4295 else if (GET_MODE (to) == TImode)
4296 libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc;
4297 else
4298 abort ();
4300 else if (GET_MODE (from) == TFmode)
4302 if (GET_MODE (to) == SImode)
4303 libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc;
4304 else if (GET_MODE (to) == DImode)
4305 libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc;
4306 else if (GET_MODE (to) == TImode)
4307 libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc;
4308 else
4309 abort ();
4311 else
4312 abort ();
4314 if (libfcn)
4316 rtx insns;
4317 rtx value;
4319 to = protect_from_queue (to, 1);
4320 from = protect_from_queue (from, 0);
4322 if (flag_force_mem)
4323 from = force_not_mem (from);
4325 start_sequence ();
4327 value = emit_library_call_value (libfcn, NULL_RTX, 1, GET_MODE (to),
4329 1, from, GET_MODE (from));
4330 insns = get_insns ();
4331 end_sequence ();
4333 emit_libcall_block (insns, target, value,
4334 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX,
4335 GET_MODE (to), from));
4338 if (target != to)
4340 if (GET_MODE (to) == GET_MODE (target))
4341 emit_move_insn (to, target);
4342 else
4343 convert_move (to, target, 0);
4347 static optab
4348 init_optab (code)
4349 enum rtx_code code;
4351 int i;
4352 optab op = (optab) xmalloc (sizeof (struct optab));
4353 op->code = code;
4354 for (i = 0; i < NUM_MACHINE_MODES; i++)
4356 op->handlers[i].insn_code = CODE_FOR_nothing;
4357 op->handlers[i].libfunc = 0;
4360 if (code != UNKNOWN)
4361 code_to_optab[(int) code] = op;
4363 return op;
4366 /* Initialize the libfunc fields of an entire group of entries in some
4367 optab. Each entry is set equal to a string consisting of a leading
4368 pair of underscores followed by a generic operation name followed by
4369 a mode name (downshifted to lower case) followed by a single character
4370 representing the number of operands for the given operation (which is
4371 usually one of the characters '2', '3', or '4').
4373 OPTABLE is the table in which libfunc fields are to be initialized.
4374 FIRST_MODE is the first machine mode index in the given optab to
4375 initialize.
4376 LAST_MODE is the last machine mode index in the given optab to
4377 initialize.
4378 OPNAME is the generic (string) name of the operation.
4379 SUFFIX is the character which specifies the number of operands for
4380 the given generic operation.
4383 static void
4384 init_libfuncs (optable, first_mode, last_mode, opname, suffix)
4385 register optab optable;
4386 register int first_mode;
4387 register int last_mode;
4388 register const char *opname;
4389 register int suffix;
4391 register int mode;
4392 register unsigned opname_len = strlen (opname);
4394 for (mode = first_mode; (int) mode <= (int) last_mode;
4395 mode = (enum machine_mode) ((int) mode + 1))
4397 register char *mname = mode_name[(int) mode];
4398 register unsigned mname_len = strlen (mname);
4399 register char *libfunc_name
4400 = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1);
4401 register char *p;
4402 register const char *q;
4404 p = libfunc_name;
4405 *p++ = '_';
4406 *p++ = '_';
4407 for (q = opname; *q; )
4408 *p++ = *q++;
4409 for (q = mname; *q; q++)
4410 *p++ = tolower ((unsigned char)*q);
4411 *p++ = suffix;
4412 *p++ = '\0';
4413 optable->handlers[(int) mode].libfunc
4414 = gen_rtx_SYMBOL_REF (Pmode, libfunc_name);
4418 /* Initialize the libfunc fields of an entire group of entries in some
4419 optab which correspond to all integer mode operations. The parameters
4420 have the same meaning as similarly named ones for the `init_libfuncs'
4421 routine. (See above). */
4423 static void
4424 init_integral_libfuncs (optable, opname, suffix)
4425 register optab optable;
4426 register const char *opname;
4427 register int suffix;
4429 init_libfuncs (optable, SImode, TImode, opname, suffix);
4432 /* Initialize the libfunc fields of an entire group of entries in some
4433 optab which correspond to all real mode operations. The parameters
4434 have the same meaning as similarly named ones for the `init_libfuncs'
4435 routine. (See above). */
4437 static void
4438 init_floating_libfuncs (optable, opname, suffix)
4439 register optab optable;
4440 register const char *opname;
4441 register int suffix;
4443 init_libfuncs (optable, SFmode, TFmode, opname, suffix);
4447 /* Call this once to initialize the contents of the optabs
4448 appropriately for the current target machine. */
4450 void
4451 init_optabs ()
4453 int i;
4454 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
4455 int j;
4456 #endif
4458 enum insn_code *p;
4460 /* Start by initializing all tables to contain CODE_FOR_nothing. */
4462 for (p = fixtab[0][0];
4463 p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]);
4464 p++)
4465 *p = CODE_FOR_nothing;
4467 for (p = fixtrunctab[0][0];
4468 p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]);
4469 p++)
4470 *p = CODE_FOR_nothing;
4472 for (p = floattab[0][0];
4473 p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]);
4474 p++)
4475 *p = CODE_FOR_nothing;
4477 for (p = extendtab[0][0];
4478 p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0];
4479 p++)
4480 *p = CODE_FOR_nothing;
4482 for (i = 0; i < NUM_RTX_CODE; i++)
4483 setcc_gen_code[i] = CODE_FOR_nothing;
4485 #ifdef HAVE_conditional_move
4486 for (i = 0; i < NUM_MACHINE_MODES; i++)
4487 movcc_gen_code[i] = CODE_FOR_nothing;
4488 #endif
4490 add_optab = init_optab (PLUS);
4491 sub_optab = init_optab (MINUS);
4492 smul_optab = init_optab (MULT);
4493 smul_highpart_optab = init_optab (UNKNOWN);
4494 umul_highpart_optab = init_optab (UNKNOWN);
4495 smul_widen_optab = init_optab (UNKNOWN);
4496 umul_widen_optab = init_optab (UNKNOWN);
4497 sdiv_optab = init_optab (DIV);
4498 sdivmod_optab = init_optab (UNKNOWN);
4499 udiv_optab = init_optab (UDIV);
4500 udivmod_optab = init_optab (UNKNOWN);
4501 smod_optab = init_optab (MOD);
4502 umod_optab = init_optab (UMOD);
4503 flodiv_optab = init_optab (DIV);
4504 ftrunc_optab = init_optab (UNKNOWN);
4505 and_optab = init_optab (AND);
4506 ior_optab = init_optab (IOR);
4507 xor_optab = init_optab (XOR);
4508 ashl_optab = init_optab (ASHIFT);
4509 ashr_optab = init_optab (ASHIFTRT);
4510 lshr_optab = init_optab (LSHIFTRT);
4511 rotl_optab = init_optab (ROTATE);
4512 rotr_optab = init_optab (ROTATERT);
4513 smin_optab = init_optab (SMIN);
4514 smax_optab = init_optab (SMAX);
4515 umin_optab = init_optab (UMIN);
4516 umax_optab = init_optab (UMAX);
4517 mov_optab = init_optab (UNKNOWN);
4518 movstrict_optab = init_optab (UNKNOWN);
4519 cmp_optab = init_optab (UNKNOWN);
4520 ucmp_optab = init_optab (UNKNOWN);
4521 tst_optab = init_optab (UNKNOWN);
4522 neg_optab = init_optab (NEG);
4523 abs_optab = init_optab (ABS);
4524 one_cmpl_optab = init_optab (NOT);
4525 ffs_optab = init_optab (FFS);
4526 sqrt_optab = init_optab (SQRT);
4527 sin_optab = init_optab (UNKNOWN);
4528 cos_optab = init_optab (UNKNOWN);
4529 strlen_optab = init_optab (UNKNOWN);
4531 for (i = 0; i < NUM_MACHINE_MODES; i++)
4533 movstr_optab[i] = CODE_FOR_nothing;
4534 clrstr_optab[i] = CODE_FOR_nothing;
4536 #ifdef HAVE_SECONDARY_RELOADS
4537 reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
4538 #endif
4541 /* Fill in the optabs with the insns we support. */
4542 init_all_optabs ();
4544 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
4545 /* This flag says the same insns that convert to a signed fixnum
4546 also convert validly to an unsigned one. */
4547 for (i = 0; i < NUM_MACHINE_MODES; i++)
4548 for (j = 0; j < NUM_MACHINE_MODES; j++)
4549 fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
4550 #endif
4552 #ifdef EXTRA_CC_MODES
4553 init_mov_optab ();
4554 #endif
4556 /* Initialize the optabs with the names of the library functions. */
4557 init_integral_libfuncs (add_optab, "add", '3');
4558 init_floating_libfuncs (add_optab, "add", '3');
4559 init_integral_libfuncs (sub_optab, "sub", '3');
4560 init_floating_libfuncs (sub_optab, "sub", '3');
4561 init_integral_libfuncs (smul_optab, "mul", '3');
4562 init_floating_libfuncs (smul_optab, "mul", '3');
4563 init_integral_libfuncs (sdiv_optab, "div", '3');
4564 init_integral_libfuncs (udiv_optab, "udiv", '3');
4565 init_integral_libfuncs (sdivmod_optab, "divmod", '4');
4566 init_integral_libfuncs (udivmod_optab, "udivmod", '4');
4567 init_integral_libfuncs (smod_optab, "mod", '3');
4568 init_integral_libfuncs (umod_optab, "umod", '3');
4569 init_floating_libfuncs (flodiv_optab, "div", '3');
4570 init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
4571 init_integral_libfuncs (and_optab, "and", '3');
4572 init_integral_libfuncs (ior_optab, "ior", '3');
4573 init_integral_libfuncs (xor_optab, "xor", '3');
4574 init_integral_libfuncs (ashl_optab, "ashl", '3');
4575 init_integral_libfuncs (ashr_optab, "ashr", '3');
4576 init_integral_libfuncs (lshr_optab, "lshr", '3');
4577 init_integral_libfuncs (smin_optab, "min", '3');
4578 init_floating_libfuncs (smin_optab, "min", '3');
4579 init_integral_libfuncs (smax_optab, "max", '3');
4580 init_floating_libfuncs (smax_optab, "max", '3');
4581 init_integral_libfuncs (umin_optab, "umin", '3');
4582 init_integral_libfuncs (umax_optab, "umax", '3');
4583 init_integral_libfuncs (neg_optab, "neg", '2');
4584 init_floating_libfuncs (neg_optab, "neg", '2');
4585 init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
4586 init_integral_libfuncs (ffs_optab, "ffs", '2');
4588 /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
4589 init_integral_libfuncs (cmp_optab, "cmp", '2');
4590 init_integral_libfuncs (ucmp_optab, "ucmp", '2');
4591 init_floating_libfuncs (cmp_optab, "cmp", '2');
4593 #ifdef MULSI3_LIBCALL
4594 smul_optab->handlers[(int) SImode].libfunc
4595 = gen_rtx_SYMBOL_REF (Pmode, MULSI3_LIBCALL);
4596 #endif
4597 #ifdef MULDI3_LIBCALL
4598 smul_optab->handlers[(int) DImode].libfunc
4599 = gen_rtx_SYMBOL_REF (Pmode, MULDI3_LIBCALL);
4600 #endif
4602 #ifdef DIVSI3_LIBCALL
4603 sdiv_optab->handlers[(int) SImode].libfunc
4604 = gen_rtx_SYMBOL_REF (Pmode, DIVSI3_LIBCALL);
4605 #endif
4606 #ifdef DIVDI3_LIBCALL
4607 sdiv_optab->handlers[(int) DImode].libfunc
4608 = gen_rtx_SYMBOL_REF (Pmode, DIVDI3_LIBCALL);
4609 #endif
4611 #ifdef UDIVSI3_LIBCALL
4612 udiv_optab->handlers[(int) SImode].libfunc
4613 = gen_rtx_SYMBOL_REF (Pmode, UDIVSI3_LIBCALL);
4614 #endif
4615 #ifdef UDIVDI3_LIBCALL
4616 udiv_optab->handlers[(int) DImode].libfunc
4617 = gen_rtx_SYMBOL_REF (Pmode, UDIVDI3_LIBCALL);
4618 #endif
4620 #ifdef MODSI3_LIBCALL
4621 smod_optab->handlers[(int) SImode].libfunc
4622 = gen_rtx_SYMBOL_REF (Pmode, MODSI3_LIBCALL);
4623 #endif
4624 #ifdef MODDI3_LIBCALL
4625 smod_optab->handlers[(int) DImode].libfunc
4626 = gen_rtx_SYMBOL_REF (Pmode, MODDI3_LIBCALL);
4627 #endif
4629 #ifdef UMODSI3_LIBCALL
4630 umod_optab->handlers[(int) SImode].libfunc
4631 = gen_rtx_SYMBOL_REF (Pmode, UMODSI3_LIBCALL);
4632 #endif
4633 #ifdef UMODDI3_LIBCALL
4634 umod_optab->handlers[(int) DImode].libfunc
4635 = gen_rtx_SYMBOL_REF (Pmode, UMODDI3_LIBCALL);
4636 #endif
4638 /* Use cabs for DC complex abs, since systems generally have cabs.
4639 Don't define any libcall for SCmode, so that cabs will be used. */
4640 abs_optab->handlers[(int) DCmode].libfunc
4641 = gen_rtx_SYMBOL_REF (Pmode, "cabs");
4643 /* The ffs function operates on `int'. */
4644 #ifndef INT_TYPE_SIZE
4645 #define INT_TYPE_SIZE BITS_PER_WORD
4646 #endif
4647 ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)] .libfunc
4648 = gen_rtx_SYMBOL_REF (Pmode, "ffs");
4650 extendsfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsfdf2");
4651 extendsfxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsfxf2");
4652 extendsftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsftf2");
4653 extenddfxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extenddfxf2");
4654 extenddftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extenddftf2");
4656 truncdfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncdfsf2");
4657 truncxfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncxfsf2");
4658 trunctfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__trunctfsf2");
4659 truncxfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncxfdf2");
4660 trunctfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__trunctfdf2");
4662 memcpy_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memcpy");
4663 bcopy_libfunc = gen_rtx_SYMBOL_REF (Pmode, "bcopy");
4664 memcmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memcmp");
4665 bcmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gcc_bcmp");
4666 memset_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memset");
4667 bzero_libfunc = gen_rtx_SYMBOL_REF (Pmode, "bzero");
4669 throw_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__throw");
4670 rethrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__rethrow");
4671 sjthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjthrow");
4672 sjpopnthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjpopnthrow");
4673 terminate_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__terminate");
4674 eh_rtime_match_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eh_rtime_match");
4675 #ifndef DONT_USE_BUILTIN_SETJMP
4676 setjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__builtin_setjmp");
4677 longjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__builtin_longjmp");
4678 #else
4679 setjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "setjmp");
4680 longjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "longjmp");
4681 #endif
4683 eqhf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqhf2");
4684 nehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nehf2");
4685 gthf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gthf2");
4686 gehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gehf2");
4687 lthf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lthf2");
4688 lehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lehf2");
4690 eqsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqsf2");
4691 nesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nesf2");
4692 gtsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtsf2");
4693 gesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gesf2");
4694 ltsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltsf2");
4695 lesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lesf2");
4697 eqdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqdf2");
4698 nedf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nedf2");
4699 gtdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtdf2");
4700 gedf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gedf2");
4701 ltdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltdf2");
4702 ledf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ledf2");
4704 eqxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqxf2");
4705 nexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nexf2");
4706 gtxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtxf2");
4707 gexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gexf2");
4708 ltxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltxf2");
4709 lexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lexf2");
4711 eqtf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqtf2");
4712 netf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__netf2");
4713 gttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gttf2");
4714 getf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__getf2");
4715 lttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lttf2");
4716 letf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__letf2");
4718 floatsisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsisf");
4719 floatdisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdisf");
4720 floattisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattisf");
4722 floatsidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsidf");
4723 floatdidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdidf");
4724 floattidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattidf");
4726 floatsixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsixf");
4727 floatdixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdixf");
4728 floattixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattixf");
4730 floatsitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsitf");
4731 floatditf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatditf");
4732 floattitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattitf");
4734 fixsfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfsi");
4735 fixsfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfdi");
4736 fixsfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfti");
4738 fixdfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfsi");
4739 fixdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfdi");
4740 fixdfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfti");
4742 fixxfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfsi");
4743 fixxfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfdi");
4744 fixxfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfti");
4746 fixtfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfsi");
4747 fixtfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfdi");
4748 fixtfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfti");
4750 fixunssfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfsi");
4751 fixunssfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfdi");
4752 fixunssfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfti");
4754 fixunsdfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfsi");
4755 fixunsdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfdi");
4756 fixunsdfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfti");
4758 fixunsxfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfsi");
4759 fixunsxfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfdi");
4760 fixunsxfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfti");
4762 fixunstfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfsi");
4763 fixunstfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfdi");
4764 fixunstfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfti");
4766 /* For check-memory-usage. */
4767 chkr_check_addr_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_addr");
4768 chkr_set_right_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_set_right");
4769 chkr_copy_bitmap_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_copy_bitmap");
4770 chkr_check_exec_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_exec");
4771 chkr_check_str_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_str");
4773 /* For function entry/exit instrumentation. */
4774 profile_function_entry_libfunc
4775 = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_enter");
4776 profile_function_exit_libfunc
4777 = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_exit");
4779 #ifdef HAVE_conditional_trap
4780 init_traps ();
4781 #endif
4783 #ifdef INIT_TARGET_OPTABS
4784 /* Allow the target to add more libcalls or rename some, etc. */
4785 INIT_TARGET_OPTABS;
4786 #endif
4789 #ifdef BROKEN_LDEXP
4791 /* SCO 3.2 apparently has a broken ldexp. */
4793 double
4794 ldexp(x,n)
4795 double x;
4796 int n;
4798 if (n > 0)
4799 while (n--)
4800 x *= 2;
4802 return x;
4804 #endif /* BROKEN_LDEXP */
4806 #ifdef HAVE_conditional_trap
4807 /* The insn generating function can not take an rtx_code argument.
4808 TRAP_RTX is used as an rtx argument. Its code is replaced with
4809 the code to be used in the trap insn and all other fields are
4810 ignored.
4812 ??? Will need to change to support garbage collection. */
4813 static rtx trap_rtx;
4815 static void
4816 init_traps ()
4818 if (HAVE_conditional_trap)
4819 trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);
4821 #endif
4823 /* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
4824 CODE. Return 0 on failure. */
4827 gen_cond_trap (code, op1, op2, tcode)
4828 enum rtx_code code ATTRIBUTE_UNUSED;
4829 rtx op1, op2 ATTRIBUTE_UNUSED, tcode ATTRIBUTE_UNUSED;
4831 enum machine_mode mode = GET_MODE (op1);
4833 if (mode == VOIDmode)
4834 return 0;
4836 #ifdef HAVE_conditional_trap
4837 if (HAVE_conditional_trap
4838 && cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
4840 rtx insn;
4841 emit_insn (GEN_FCN (cmp_optab->handlers[(int) mode].insn_code) (op1, op2));
4842 PUT_CODE (trap_rtx, code);
4843 insn = gen_conditional_trap (trap_rtx, tcode);
4844 if (insn)
4845 return insn;
4847 #endif
4849 return 0;