]> gcc.gnu.org Git - gcc.git/blob - gcc/optabs.c
Warning fixes:
[gcc.git] / gcc / optabs.c
1 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2 Copyright (C) 1987, 88, 92-97, 1998 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
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.
10
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.
15
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. */
20
21
22 #include "config.h"
23 #include "system.h"
24 #include "rtl.h"
25 #include "tree.h"
26 #include "flags.h"
27 #include "insn-flags.h"
28 #include "insn-codes.h"
29 #include "expr.h"
30 #include "insn-config.h"
31 #include "recog.h"
32 #include "reload.h"
33
34 /* Each optab contains info on how this target machine
35 can perform a particular operation
36 for all sizes and kinds of operands.
37
38 The operation to be performed is often specified
39 by passing one of these optabs as an argument.
40
41 See expr.h for documentation of these optabs. */
42
43 optab add_optab;
44 optab sub_optab;
45 optab smul_optab;
46 optab smul_highpart_optab;
47 optab umul_highpart_optab;
48 optab smul_widen_optab;
49 optab umul_widen_optab;
50 optab sdiv_optab;
51 optab sdivmod_optab;
52 optab udiv_optab;
53 optab udivmod_optab;
54 optab smod_optab;
55 optab umod_optab;
56 optab flodiv_optab;
57 optab ftrunc_optab;
58 optab and_optab;
59 optab ior_optab;
60 optab xor_optab;
61 optab ashl_optab;
62 optab lshr_optab;
63 optab ashr_optab;
64 optab rotl_optab;
65 optab rotr_optab;
66 optab smin_optab;
67 optab smax_optab;
68 optab umin_optab;
69 optab umax_optab;
70
71 optab mov_optab;
72 optab movstrict_optab;
73
74 optab neg_optab;
75 optab abs_optab;
76 optab one_cmpl_optab;
77 optab ffs_optab;
78 optab sqrt_optab;
79 optab sin_optab;
80 optab cos_optab;
81
82 optab cmp_optab;
83 optab ucmp_optab; /* Used only for libcalls for unsigned comparisons. */
84 optab tst_optab;
85
86 optab strlen_optab;
87
88 /* Tables of patterns for extending one integer mode to another. */
89 enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2];
90
91 /* Tables of patterns for converting between fixed and floating point. */
92 enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
93 enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
94 enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
95
96 /* Contains the optab used for each rtx code. */
97 optab code_to_optab[NUM_RTX_CODE + 1];
98
99 /* SYMBOL_REF rtx's for the library functions that are called
100 implicitly and not via optabs. */
101
102 rtx extendsfdf2_libfunc;
103 rtx extendsfxf2_libfunc;
104 rtx extendsftf2_libfunc;
105 rtx extenddfxf2_libfunc;
106 rtx extenddftf2_libfunc;
107
108 rtx truncdfsf2_libfunc;
109 rtx truncxfsf2_libfunc;
110 rtx trunctfsf2_libfunc;
111 rtx truncxfdf2_libfunc;
112 rtx trunctfdf2_libfunc;
113
114 rtx memcpy_libfunc;
115 rtx bcopy_libfunc;
116 rtx memcmp_libfunc;
117 rtx bcmp_libfunc;
118 rtx memset_libfunc;
119 rtx bzero_libfunc;
120
121 rtx throw_libfunc;
122 rtx sjthrow_libfunc;
123 rtx sjpopnthrow_libfunc;
124 rtx terminate_libfunc;
125 rtx setjmp_libfunc;
126 rtx longjmp_libfunc;
127 rtx eh_rtime_match_libfunc;
128
129 rtx eqhf2_libfunc;
130 rtx nehf2_libfunc;
131 rtx gthf2_libfunc;
132 rtx gehf2_libfunc;
133 rtx lthf2_libfunc;
134 rtx lehf2_libfunc;
135
136 rtx eqsf2_libfunc;
137 rtx nesf2_libfunc;
138 rtx gtsf2_libfunc;
139 rtx gesf2_libfunc;
140 rtx ltsf2_libfunc;
141 rtx lesf2_libfunc;
142
143 rtx eqdf2_libfunc;
144 rtx nedf2_libfunc;
145 rtx gtdf2_libfunc;
146 rtx gedf2_libfunc;
147 rtx ltdf2_libfunc;
148 rtx ledf2_libfunc;
149
150 rtx eqxf2_libfunc;
151 rtx nexf2_libfunc;
152 rtx gtxf2_libfunc;
153 rtx gexf2_libfunc;
154 rtx ltxf2_libfunc;
155 rtx lexf2_libfunc;
156
157 rtx eqtf2_libfunc;
158 rtx netf2_libfunc;
159 rtx gttf2_libfunc;
160 rtx getf2_libfunc;
161 rtx lttf2_libfunc;
162 rtx letf2_libfunc;
163
164 rtx floatsisf_libfunc;
165 rtx floatdisf_libfunc;
166 rtx floattisf_libfunc;
167
168 rtx floatsidf_libfunc;
169 rtx floatdidf_libfunc;
170 rtx floattidf_libfunc;
171
172 rtx floatsixf_libfunc;
173 rtx floatdixf_libfunc;
174 rtx floattixf_libfunc;
175
176 rtx floatsitf_libfunc;
177 rtx floatditf_libfunc;
178 rtx floattitf_libfunc;
179
180 rtx fixsfsi_libfunc;
181 rtx fixsfdi_libfunc;
182 rtx fixsfti_libfunc;
183
184 rtx fixdfsi_libfunc;
185 rtx fixdfdi_libfunc;
186 rtx fixdfti_libfunc;
187
188 rtx fixxfsi_libfunc;
189 rtx fixxfdi_libfunc;
190 rtx fixxfti_libfunc;
191
192 rtx fixtfsi_libfunc;
193 rtx fixtfdi_libfunc;
194 rtx fixtfti_libfunc;
195
196 rtx fixunssfsi_libfunc;
197 rtx fixunssfdi_libfunc;
198 rtx fixunssfti_libfunc;
199
200 rtx fixunsdfsi_libfunc;
201 rtx fixunsdfdi_libfunc;
202 rtx fixunsdfti_libfunc;
203
204 rtx fixunsxfsi_libfunc;
205 rtx fixunsxfdi_libfunc;
206 rtx fixunsxfti_libfunc;
207
208 rtx fixunstfsi_libfunc;
209 rtx fixunstfdi_libfunc;
210 rtx fixunstfti_libfunc;
211
212 rtx chkr_check_addr_libfunc;
213 rtx chkr_set_right_libfunc;
214 rtx chkr_copy_bitmap_libfunc;
215 rtx chkr_check_exec_libfunc;
216 rtx chkr_check_str_libfunc;
217
218 rtx profile_function_entry_libfunc;
219 rtx profile_function_exit_libfunc;
220
221 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
222 gives the gen_function to make a branch to test that condition. */
223
224 rtxfun bcc_gen_fctn[NUM_RTX_CODE];
225
226 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
227 gives the insn code to make a store-condition insn
228 to test that condition. */
229
230 enum insn_code setcc_gen_code[NUM_RTX_CODE];
231
232 #ifdef HAVE_conditional_move
233 /* Indexed by the machine mode, gives the insn code to make a conditional
234 move insn. This is not indexed by the rtx-code like bcc_gen_fctn and
235 setcc_gen_code to cut down on the number of named patterns. Consider a day
236 when a lot more rtx codes are conditional (eg: for the ARM). */
237
238 enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
239 #endif
240
241 static int add_equal_note PROTO((rtx, rtx, enum rtx_code, rtx, rtx));
242 static rtx widen_operand PROTO((rtx, enum machine_mode,
243 enum machine_mode, int, int));
244 static enum insn_code can_fix_p PROTO((enum machine_mode, enum machine_mode,
245 int, int *));
246 static enum insn_code can_float_p PROTO((enum machine_mode, enum machine_mode,
247 int));
248 static rtx ftruncify PROTO((rtx));
249 static optab init_optab PROTO((enum rtx_code));
250 static void init_libfuncs PROTO((optab, int, int, char *, int));
251 static void init_integral_libfuncs PROTO((optab, char *, int));
252 static void init_floating_libfuncs PROTO((optab, char *, int));
253 #ifdef HAVE_conditional_trap
254 static void init_traps PROTO((void));
255 #endif
256 \f
257 /* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
258 the result of operation CODE applied to OP0 (and OP1 if it is a binary
259 operation).
260
261 If the last insn does not set TARGET, don't do anything, but return 1.
262
263 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
264 don't add the REG_EQUAL note but return 0. Our caller can then try
265 again, ensuring that TARGET is not one of the operands. */
266
267 static int
268 add_equal_note (seq, target, code, op0, op1)
269 rtx seq;
270 rtx target;
271 enum rtx_code code;
272 rtx op0, op1;
273 {
274 rtx set;
275 int i;
276 rtx note;
277
278 if ((GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2'
279 && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<')
280 || GET_CODE (seq) != SEQUENCE
281 || (set = single_set (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))) == 0
282 || GET_CODE (target) == ZERO_EXTRACT
283 || (! rtx_equal_p (SET_DEST (set), target)
284 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
285 SUBREG. */
286 && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
287 || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)),
288 target))))
289 return 1;
290
291 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
292 besides the last insn. */
293 if (reg_overlap_mentioned_p (target, op0)
294 || (op1 && reg_overlap_mentioned_p (target, op1)))
295 for (i = XVECLEN (seq, 0) - 2; i >= 0; i--)
296 if (reg_set_p (target, XVECEXP (seq, 0, i)))
297 return 0;
298
299 if (GET_RTX_CLASS (code) == '1')
300 note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0));
301 else
302 note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
303
304 REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))
305 = gen_rtx_EXPR_LIST (REG_EQUAL, note,
306 REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1)));
307
308 return 1;
309 }
310 \f
311 /* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP
312 says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need
313 not actually do a sign-extend or zero-extend, but can leave the
314 higher-order bits of the result rtx undefined, for example, in the case
315 of logical operations, but not right shifts. */
316
317 static rtx
318 widen_operand (op, mode, oldmode, unsignedp, no_extend)
319 rtx op;
320 enum machine_mode mode, oldmode;
321 int unsignedp;
322 int no_extend;
323 {
324 rtx result;
325
326 /* If we must extend do so. If OP is either a constant or a SUBREG
327 for a promoted object, also extend since it will be more efficient to
328 do so. */
329 if (! no_extend
330 || GET_MODE (op) == VOIDmode
331 || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op)))
332 return convert_modes (mode, oldmode, op, unsignedp);
333
334 /* If MODE is no wider than a single word, we return a paradoxical
335 SUBREG. */
336 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
337 return gen_rtx_SUBREG (mode, force_reg (GET_MODE (op), op), 0);
338
339 /* Otherwise, get an object of MODE, clobber it, and set the low-order
340 part to OP. */
341
342 result = gen_reg_rtx (mode);
343 emit_insn (gen_rtx_CLOBBER (VOIDmode, result));
344 emit_move_insn (gen_lowpart (GET_MODE (op), result), op);
345 return result;
346 }
347 \f
348 /* Generate code to perform an operation specified by BINOPTAB
349 on operands OP0 and OP1, with result having machine-mode MODE.
350
351 UNSIGNEDP is for the case where we have to widen the operands
352 to perform the operation. It says to use zero-extension.
353
354 If TARGET is nonzero, the value
355 is generated there, if it is convenient to do so.
356 In all cases an rtx is returned for the locus of the value;
357 this may or may not be TARGET. */
358
359 rtx
360 expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
361 enum machine_mode mode;
362 optab binoptab;
363 rtx op0, op1;
364 rtx target;
365 int unsignedp;
366 enum optab_methods methods;
367 {
368 enum optab_methods next_methods
369 = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN
370 ? OPTAB_WIDEN : methods);
371 enum mode_class class;
372 enum machine_mode wider_mode;
373 register rtx temp;
374 int commutative_op = 0;
375 int shift_op = (binoptab->code == ASHIFT
376 || binoptab->code == ASHIFTRT
377 || binoptab->code == LSHIFTRT
378 || binoptab->code == ROTATE
379 || binoptab->code == ROTATERT);
380 rtx entry_last = get_last_insn ();
381 rtx last;
382
383 class = GET_MODE_CLASS (mode);
384
385 op0 = protect_from_queue (op0, 0);
386 op1 = protect_from_queue (op1, 0);
387 if (target)
388 target = protect_from_queue (target, 1);
389
390 if (flag_force_mem)
391 {
392 op0 = force_not_mem (op0);
393 op1 = force_not_mem (op1);
394 }
395
396 /* If subtracting an integer constant, convert this into an addition of
397 the negated constant. */
398
399 if (binoptab == sub_optab && GET_CODE (op1) == CONST_INT)
400 {
401 op1 = negate_rtx (mode, op1);
402 binoptab = add_optab;
403 }
404
405 /* If we are inside an appropriately-short loop and one operand is an
406 expensive constant, force it into a register. */
407 if (CONSTANT_P (op0) && preserve_subexpressions_p ()
408 && rtx_cost (op0, binoptab->code) > 2)
409 op0 = force_reg (mode, op0);
410
411 if (CONSTANT_P (op1) && preserve_subexpressions_p ()
412 && ! shift_op && rtx_cost (op1, binoptab->code) > 2)
413 op1 = force_reg (mode, op1);
414
415 /* Record where to delete back to if we backtrack. */
416 last = get_last_insn ();
417
418 /* If operation is commutative,
419 try to make the first operand a register.
420 Even better, try to make it the same as the target.
421 Also try to make the last operand a constant. */
422 if (GET_RTX_CLASS (binoptab->code) == 'c'
423 || binoptab == smul_widen_optab
424 || binoptab == umul_widen_optab
425 || binoptab == smul_highpart_optab
426 || binoptab == umul_highpart_optab)
427 {
428 commutative_op = 1;
429
430 if (((target == 0 || GET_CODE (target) == REG)
431 ? ((GET_CODE (op1) == REG
432 && GET_CODE (op0) != REG)
433 || target == op1)
434 : rtx_equal_p (op1, target))
435 || GET_CODE (op0) == CONST_INT)
436 {
437 temp = op1;
438 op1 = op0;
439 op0 = temp;
440 }
441 }
442
443 /* If we can do it with a three-operand insn, do so. */
444
445 if (methods != OPTAB_MUST_WIDEN
446 && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
447 {
448 int icode = (int) binoptab->handlers[(int) mode].insn_code;
449 enum machine_mode mode0 = insn_operand_mode[icode][1];
450 enum machine_mode mode1 = insn_operand_mode[icode][2];
451 rtx pat;
452 rtx xop0 = op0, xop1 = op1;
453
454 if (target)
455 temp = target;
456 else
457 temp = gen_reg_rtx (mode);
458
459 /* If it is a commutative operator and the modes would match
460 if we would swap the operands, we can save the conversions. */
461 if (commutative_op)
462 {
463 if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
464 && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
465 {
466 register rtx tmp;
467
468 tmp = op0; op0 = op1; op1 = tmp;
469 tmp = xop0; xop0 = xop1; xop1 = tmp;
470 }
471 }
472
473 /* In case the insn wants input operands in modes different from
474 the result, convert the operands. */
475
476 if (GET_MODE (op0) != VOIDmode
477 && GET_MODE (op0) != mode0
478 && mode0 != VOIDmode)
479 xop0 = convert_to_mode (mode0, xop0, unsignedp);
480
481 if (GET_MODE (xop1) != VOIDmode
482 && GET_MODE (xop1) != mode1
483 && mode1 != VOIDmode)
484 xop1 = convert_to_mode (mode1, xop1, unsignedp);
485
486 /* Now, if insn's predicates don't allow our operands, put them into
487 pseudo regs. */
488
489 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0)
490 && mode0 != VOIDmode)
491 xop0 = copy_to_mode_reg (mode0, xop0);
492
493 if (! (*insn_operand_predicate[icode][2]) (xop1, mode1)
494 && mode1 != VOIDmode)
495 xop1 = copy_to_mode_reg (mode1, xop1);
496
497 if (! (*insn_operand_predicate[icode][0]) (temp, mode))
498 temp = gen_reg_rtx (mode);
499
500 pat = GEN_FCN (icode) (temp, xop0, xop1);
501 if (pat)
502 {
503 /* If PAT is a multi-insn sequence, try to add an appropriate
504 REG_EQUAL note to it. If we can't because TEMP conflicts with an
505 operand, call ourselves again, this time without a target. */
506 if (GET_CODE (pat) == SEQUENCE
507 && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
508 {
509 delete_insns_since (last);
510 return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
511 unsignedp, methods);
512 }
513
514 emit_insn (pat);
515 return temp;
516 }
517 else
518 delete_insns_since (last);
519 }
520
521 /* If this is a multiply, see if we can do a widening operation that
522 takes operands of this mode and makes a wider mode. */
523
524 if (binoptab == smul_optab && GET_MODE_WIDER_MODE (mode) != VOIDmode
525 && (((unsignedp ? umul_widen_optab : smul_widen_optab)
526 ->handlers[(int) GET_MODE_WIDER_MODE (mode)].insn_code)
527 != CODE_FOR_nothing))
528 {
529 temp = expand_binop (GET_MODE_WIDER_MODE (mode),
530 unsignedp ? umul_widen_optab : smul_widen_optab,
531 op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT);
532
533 if (temp != 0)
534 {
535 if (GET_MODE_CLASS (mode) == MODE_INT)
536 return gen_lowpart (mode, temp);
537 else
538 return convert_to_mode (mode, temp, unsignedp);
539 }
540 }
541
542 /* Look for a wider mode of the same class for which we think we
543 can open-code the operation. Check for a widening multiply at the
544 wider mode as well. */
545
546 if ((class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
547 && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
548 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
549 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
550 {
551 if (binoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing
552 || (binoptab == smul_optab
553 && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
554 && (((unsignedp ? umul_widen_optab : smul_widen_optab)
555 ->handlers[(int) GET_MODE_WIDER_MODE (wider_mode)].insn_code)
556 != CODE_FOR_nothing)))
557 {
558 rtx xop0 = op0, xop1 = op1;
559 int no_extend = 0;
560
561 /* For certain integer operations, we need not actually extend
562 the narrow operands, as long as we will truncate
563 the results to the same narrowness. */
564
565 if ((binoptab == ior_optab || binoptab == and_optab
566 || binoptab == xor_optab
567 || binoptab == add_optab || binoptab == sub_optab
568 || binoptab == smul_optab || binoptab == ashl_optab)
569 && class == MODE_INT)
570 no_extend = 1;
571
572 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend);
573
574 /* The second operand of a shift must always be extended. */
575 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
576 no_extend && binoptab != ashl_optab);
577
578 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
579 unsignedp, OPTAB_DIRECT);
580 if (temp)
581 {
582 if (class != MODE_INT)
583 {
584 if (target == 0)
585 target = gen_reg_rtx (mode);
586 convert_move (target, temp, 0);
587 return target;
588 }
589 else
590 return gen_lowpart (mode, temp);
591 }
592 else
593 delete_insns_since (last);
594 }
595 }
596
597 /* These can be done a word at a time. */
598 if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
599 && class == MODE_INT
600 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
601 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
602 {
603 int i;
604 rtx insns;
605 rtx equiv_value;
606
607 /* If TARGET is the same as one of the operands, the REG_EQUAL note
608 won't be accurate, so use a new target. */
609 if (target == 0 || target == op0 || target == op1)
610 target = gen_reg_rtx (mode);
611
612 start_sequence ();
613
614 /* Do the actual arithmetic. */
615 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
616 {
617 rtx target_piece = operand_subword (target, i, 1, mode);
618 rtx x = expand_binop (word_mode, binoptab,
619 operand_subword_force (op0, i, mode),
620 operand_subword_force (op1, i, mode),
621 target_piece, unsignedp, next_methods);
622
623 if (x == 0)
624 break;
625
626 if (target_piece != x)
627 emit_move_insn (target_piece, x);
628 }
629
630 insns = get_insns ();
631 end_sequence ();
632
633 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
634 {
635 if (binoptab->code != UNKNOWN)
636 equiv_value
637 = gen_rtx_fmt_ee (binoptab->code, mode,
638 copy_rtx (op0), copy_rtx (op1));
639 else
640 equiv_value = 0;
641
642 emit_no_conflict_block (insns, target, op0, op1, equiv_value);
643 return target;
644 }
645 }
646
647 /* Synthesize double word shifts from single word shifts. */
648 if ((binoptab == lshr_optab || binoptab == ashl_optab
649 || binoptab == ashr_optab)
650 && class == MODE_INT
651 && GET_CODE (op1) == CONST_INT
652 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
653 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
654 && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
655 && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
656 {
657 rtx insns, inter, equiv_value;
658 rtx into_target, outof_target;
659 rtx into_input, outof_input;
660 int shift_count, left_shift, outof_word;
661
662 /* If TARGET is the same as one of the operands, the REG_EQUAL note
663 won't be accurate, so use a new target. */
664 if (target == 0 || target == op0 || target == op1)
665 target = gen_reg_rtx (mode);
666
667 start_sequence ();
668
669 shift_count = INTVAL (op1);
670
671 /* OUTOF_* is the word we are shifting bits away from, and
672 INTO_* is the word that we are shifting bits towards, thus
673 they differ depending on the direction of the shift and
674 WORDS_BIG_ENDIAN. */
675
676 left_shift = binoptab == ashl_optab;
677 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
678
679 outof_target = operand_subword (target, outof_word, 1, mode);
680 into_target = operand_subword (target, 1 - outof_word, 1, mode);
681
682 outof_input = operand_subword_force (op0, outof_word, mode);
683 into_input = operand_subword_force (op0, 1 - outof_word, mode);
684
685 if (shift_count >= BITS_PER_WORD)
686 {
687 inter = expand_binop (word_mode, binoptab,
688 outof_input,
689 GEN_INT (shift_count - BITS_PER_WORD),
690 into_target, unsignedp, next_methods);
691
692 if (inter != 0 && inter != into_target)
693 emit_move_insn (into_target, inter);
694
695 /* For a signed right shift, we must fill the word we are shifting
696 out of with copies of the sign bit. Otherwise it is zeroed. */
697 if (inter != 0 && binoptab != ashr_optab)
698 inter = CONST0_RTX (word_mode);
699 else if (inter != 0)
700 inter = expand_binop (word_mode, binoptab,
701 outof_input,
702 GEN_INT (BITS_PER_WORD - 1),
703 outof_target, unsignedp, next_methods);
704
705 if (inter != 0 && inter != outof_target)
706 emit_move_insn (outof_target, inter);
707 }
708 else
709 {
710 rtx carries;
711 optab reverse_unsigned_shift, unsigned_shift;
712
713 /* For a shift of less then BITS_PER_WORD, to compute the carry,
714 we must do a logical shift in the opposite direction of the
715 desired shift. */
716
717 reverse_unsigned_shift = (left_shift ? lshr_optab : ashl_optab);
718
719 /* For a shift of less than BITS_PER_WORD, to compute the word
720 shifted towards, we need to unsigned shift the orig value of
721 that word. */
722
723 unsigned_shift = (left_shift ? ashl_optab : lshr_optab);
724
725 carries = expand_binop (word_mode, reverse_unsigned_shift,
726 outof_input,
727 GEN_INT (BITS_PER_WORD - shift_count),
728 0, unsignedp, next_methods);
729
730 if (carries == 0)
731 inter = 0;
732 else
733 inter = expand_binop (word_mode, unsigned_shift, into_input,
734 op1, 0, unsignedp, next_methods);
735
736 if (inter != 0)
737 inter = expand_binop (word_mode, ior_optab, carries, inter,
738 into_target, unsignedp, next_methods);
739
740 if (inter != 0 && inter != into_target)
741 emit_move_insn (into_target, inter);
742
743 if (inter != 0)
744 inter = expand_binop (word_mode, binoptab, outof_input,
745 op1, outof_target, unsignedp, next_methods);
746
747 if (inter != 0 && inter != outof_target)
748 emit_move_insn (outof_target, inter);
749 }
750
751 insns = get_insns ();
752 end_sequence ();
753
754 if (inter != 0)
755 {
756 if (binoptab->code != UNKNOWN)
757 equiv_value = gen_rtx_fmt_ee (binoptab->code, mode, op0, op1);
758 else
759 equiv_value = 0;
760
761 emit_no_conflict_block (insns, target, op0, op1, equiv_value);
762 return target;
763 }
764 }
765
766 /* Synthesize double word rotates from single word shifts. */
767 if ((binoptab == rotl_optab || binoptab == rotr_optab)
768 && class == MODE_INT
769 && GET_CODE (op1) == CONST_INT
770 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
771 && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
772 && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
773 {
774 rtx insns, equiv_value;
775 rtx into_target, outof_target;
776 rtx into_input, outof_input;
777 rtx inter;
778 int shift_count, left_shift, outof_word;
779
780 /* If TARGET is the same as one of the operands, the REG_EQUAL note
781 won't be accurate, so use a new target. */
782 if (target == 0 || target == op0 || target == op1)
783 target = gen_reg_rtx (mode);
784
785 start_sequence ();
786
787 shift_count = INTVAL (op1);
788
789 /* OUTOF_* is the word we are shifting bits away from, and
790 INTO_* is the word that we are shifting bits towards, thus
791 they differ depending on the direction of the shift and
792 WORDS_BIG_ENDIAN. */
793
794 left_shift = (binoptab == rotl_optab);
795 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
796
797 outof_target = operand_subword (target, outof_word, 1, mode);
798 into_target = operand_subword (target, 1 - outof_word, 1, mode);
799
800 outof_input = operand_subword_force (op0, outof_word, mode);
801 into_input = operand_subword_force (op0, 1 - outof_word, mode);
802
803 if (shift_count == BITS_PER_WORD)
804 {
805 /* This is just a word swap. */
806 emit_move_insn (outof_target, into_input);
807 emit_move_insn (into_target, outof_input);
808 inter = const0_rtx;
809 }
810 else
811 {
812 rtx into_temp1, into_temp2, outof_temp1, outof_temp2;
813 rtx first_shift_count, second_shift_count;
814 optab reverse_unsigned_shift, unsigned_shift;
815
816 reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
817 ? lshr_optab : ashl_optab);
818
819 unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
820 ? ashl_optab : lshr_optab);
821
822 if (shift_count > BITS_PER_WORD)
823 {
824 first_shift_count = GEN_INT (shift_count - BITS_PER_WORD);
825 second_shift_count = GEN_INT (2*BITS_PER_WORD - shift_count);
826 }
827 else
828 {
829 first_shift_count = GEN_INT (BITS_PER_WORD - shift_count);
830 second_shift_count = GEN_INT (shift_count);
831 }
832
833 into_temp1 = expand_binop (word_mode, unsigned_shift,
834 outof_input, first_shift_count,
835 NULL_RTX, unsignedp, next_methods);
836 into_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
837 into_input, second_shift_count,
838 into_target, unsignedp, next_methods);
839
840 if (into_temp1 != 0 && into_temp2 != 0)
841 inter = expand_binop (word_mode, ior_optab, into_temp1, into_temp2,
842 into_target, unsignedp, next_methods);
843 else
844 inter = 0;
845
846 if (inter != 0 && inter != into_target)
847 emit_move_insn (into_target, inter);
848
849 outof_temp1 = expand_binop (word_mode, unsigned_shift,
850 into_input, first_shift_count,
851 NULL_RTX, unsignedp, next_methods);
852 outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
853 outof_input, second_shift_count,
854 outof_target, unsignedp, next_methods);
855
856 if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0)
857 inter = expand_binop (word_mode, ior_optab,
858 outof_temp1, outof_temp2,
859 outof_target, unsignedp, next_methods);
860
861 if (inter != 0 && inter != outof_target)
862 emit_move_insn (outof_target, inter);
863 }
864
865 insns = get_insns ();
866 end_sequence ();
867
868 if (inter != 0)
869 {
870 if (binoptab->code != UNKNOWN)
871 equiv_value = gen_rtx_fmt_ee (binoptab->code, mode, op0, op1);
872 else
873 equiv_value = 0;
874
875 /* We can't make this a no conflict block if this is a word swap,
876 because the word swap case fails if the input and output values
877 are in the same register. */
878 if (shift_count != BITS_PER_WORD)
879 emit_no_conflict_block (insns, target, op0, op1, equiv_value);
880 else
881 emit_insns (insns);
882
883
884 return target;
885 }
886 }
887
888 /* These can be done a word at a time by propagating carries. */
889 if ((binoptab == add_optab || binoptab == sub_optab)
890 && class == MODE_INT
891 && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
892 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
893 {
894 int i;
895 rtx carry_tmp = gen_reg_rtx (word_mode);
896 optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
897 int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
898 rtx carry_in, carry_out;
899 rtx xop0, xop1;
900
901 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
902 value is one of those, use it. Otherwise, use 1 since it is the
903 one easiest to get. */
904 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
905 int normalizep = STORE_FLAG_VALUE;
906 #else
907 int normalizep = 1;
908 #endif
909
910 /* Prepare the operands. */
911 xop0 = force_reg (mode, op0);
912 xop1 = force_reg (mode, op1);
913
914 if (target == 0 || GET_CODE (target) != REG
915 || target == xop0 || target == xop1)
916 target = gen_reg_rtx (mode);
917
918 /* Indicate for flow that the entire target reg is being set. */
919 if (GET_CODE (target) == REG)
920 emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
921
922 /* Do the actual arithmetic. */
923 for (i = 0; i < nwords; i++)
924 {
925 int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
926 rtx target_piece = operand_subword (target, index, 1, mode);
927 rtx op0_piece = operand_subword_force (xop0, index, mode);
928 rtx op1_piece = operand_subword_force (xop1, index, mode);
929 rtx x;
930
931 /* Main add/subtract of the input operands. */
932 x = expand_binop (word_mode, binoptab,
933 op0_piece, op1_piece,
934 target_piece, unsignedp, next_methods);
935 if (x == 0)
936 break;
937
938 if (i + 1 < nwords)
939 {
940 /* Store carry from main add/subtract. */
941 carry_out = gen_reg_rtx (word_mode);
942 carry_out = emit_store_flag_force (carry_out,
943 (binoptab == add_optab
944 ? LTU : GTU),
945 x, op0_piece,
946 word_mode, 1, normalizep);
947 }
948
949 if (i > 0)
950 {
951 /* Add/subtract previous carry to main result. */
952 x = expand_binop (word_mode,
953 normalizep == 1 ? binoptab : otheroptab,
954 x, carry_in,
955 target_piece, 1, next_methods);
956 if (x == 0)
957 break;
958 else if (target_piece != x)
959 emit_move_insn (target_piece, x);
960
961 if (i + 1 < nwords)
962 {
963 /* THIS CODE HAS NOT BEEN TESTED. */
964 /* Get out carry from adding/subtracting carry in. */
965 carry_tmp = emit_store_flag_force (carry_tmp,
966 binoptab == add_optab
967 ? LTU : GTU,
968 x, carry_in,
969 word_mode, 1, normalizep);
970
971 /* Logical-ior the two poss. carry together. */
972 carry_out = expand_binop (word_mode, ior_optab,
973 carry_out, carry_tmp,
974 carry_out, 0, next_methods);
975 if (carry_out == 0)
976 break;
977 }
978 }
979
980 carry_in = carry_out;
981 }
982
983 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
984 {
985 if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
986 {
987 rtx temp = emit_move_insn (target, target);
988
989 REG_NOTES (temp)
990 = gen_rtx_EXPR_LIST (REG_EQUAL,
991 gen_rtx_fmt_ee (binoptab->code, mode,
992 copy_rtx (xop0),
993 copy_rtx (xop1)),
994 REG_NOTES (temp));
995 }
996 return target;
997 }
998 else
999 delete_insns_since (last);
1000 }
1001
1002 /* If we want to multiply two two-word values and have normal and widening
1003 multiplies of single-word values, we can do this with three smaller
1004 multiplications. Note that we do not make a REG_NO_CONFLICT block here
1005 because we are not operating on one word at a time.
1006
1007 The multiplication proceeds as follows:
1008 _______________________
1009 [__op0_high_|__op0_low__]
1010 _______________________
1011 * [__op1_high_|__op1_low__]
1012 _______________________________________________
1013 _______________________
1014 (1) [__op0_low__*__op1_low__]
1015 _______________________
1016 (2a) [__op0_low__*__op1_high_]
1017 _______________________
1018 (2b) [__op0_high_*__op1_low__]
1019 _______________________
1020 (3) [__op0_high_*__op1_high_]
1021
1022
1023 This gives a 4-word result. Since we are only interested in the
1024 lower 2 words, partial result (3) and the upper words of (2a) and
1025 (2b) don't need to be calculated. Hence (2a) and (2b) can be
1026 calculated using non-widening multiplication.
1027
1028 (1), however, needs to be calculated with an unsigned widening
1029 multiplication. If this operation is not directly supported we
1030 try using a signed widening multiplication and adjust the result.
1031 This adjustment works as follows:
1032
1033 If both operands are positive then no adjustment is needed.
1034
1035 If the operands have different signs, for example op0_low < 0 and
1036 op1_low >= 0, the instruction treats the most significant bit of
1037 op0_low as a sign bit instead of a bit with significance
1038 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
1039 with 2**BITS_PER_WORD - op0_low, and two's complements the
1040 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
1041 the result.
1042
1043 Similarly, if both operands are negative, we need to add
1044 (op0_low + op1_low) * 2**BITS_PER_WORD.
1045
1046 We use a trick to adjust quickly. We logically shift op0_low right
1047 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
1048 op0_high (op1_high) before it is used to calculate 2b (2a). If no
1049 logical shift exists, we do an arithmetic right shift and subtract
1050 the 0 or -1. */
1051
1052 if (binoptab == smul_optab
1053 && class == MODE_INT
1054 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1055 && smul_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
1056 && add_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
1057 && ((umul_widen_optab->handlers[(int) mode].insn_code
1058 != CODE_FOR_nothing)
1059 || (smul_widen_optab->handlers[(int) mode].insn_code
1060 != CODE_FOR_nothing)))
1061 {
1062 int low = (WORDS_BIG_ENDIAN ? 1 : 0);
1063 int high = (WORDS_BIG_ENDIAN ? 0 : 1);
1064 rtx op0_high = operand_subword_force (op0, high, mode);
1065 rtx op0_low = operand_subword_force (op0, low, mode);
1066 rtx op1_high = operand_subword_force (op1, high, mode);
1067 rtx op1_low = operand_subword_force (op1, low, mode);
1068 rtx product = 0;
1069 rtx op0_xhigh;
1070 rtx op1_xhigh;
1071
1072 /* If the target is the same as one of the inputs, don't use it. This
1073 prevents problems with the REG_EQUAL note. */
1074 if (target == op0 || target == op1
1075 || (target != 0 && GET_CODE (target) != REG))
1076 target = 0;
1077
1078 /* Multiply the two lower words to get a double-word product.
1079 If unsigned widening multiplication is available, use that;
1080 otherwise use the signed form and compensate. */
1081
1082 if (umul_widen_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1083 {
1084 product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
1085 target, 1, OPTAB_DIRECT);
1086
1087 /* If we didn't succeed, delete everything we did so far. */
1088 if (product == 0)
1089 delete_insns_since (last);
1090 else
1091 op0_xhigh = op0_high, op1_xhigh = op1_high;
1092 }
1093
1094 if (product == 0
1095 && smul_widen_optab->handlers[(int) mode].insn_code
1096 != CODE_FOR_nothing)
1097 {
1098 rtx wordm1 = GEN_INT (BITS_PER_WORD - 1);
1099 product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
1100 target, 1, OPTAB_DIRECT);
1101 op0_xhigh = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
1102 NULL_RTX, 1, next_methods);
1103 if (op0_xhigh)
1104 op0_xhigh = expand_binop (word_mode, add_optab, op0_high,
1105 op0_xhigh, op0_xhigh, 0, next_methods);
1106 else
1107 {
1108 op0_xhigh = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
1109 NULL_RTX, 0, next_methods);
1110 if (op0_xhigh)
1111 op0_xhigh = expand_binop (word_mode, sub_optab, op0_high,
1112 op0_xhigh, op0_xhigh, 0,
1113 next_methods);
1114 }
1115
1116 op1_xhigh = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
1117 NULL_RTX, 1, next_methods);
1118 if (op1_xhigh)
1119 op1_xhigh = expand_binop (word_mode, add_optab, op1_high,
1120 op1_xhigh, op1_xhigh, 0, next_methods);
1121 else
1122 {
1123 op1_xhigh = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
1124 NULL_RTX, 0, next_methods);
1125 if (op1_xhigh)
1126 op1_xhigh = expand_binop (word_mode, sub_optab, op1_high,
1127 op1_xhigh, op1_xhigh, 0,
1128 next_methods);
1129 }
1130 }
1131
1132 /* If we have been able to directly compute the product of the
1133 low-order words of the operands and perform any required adjustments
1134 of the operands, we proceed by trying two more multiplications
1135 and then computing the appropriate sum.
1136
1137 We have checked above that the required addition is provided.
1138 Full-word addition will normally always succeed, especially if
1139 it is provided at all, so we don't worry about its failure. The
1140 multiplication may well fail, however, so we do handle that. */
1141
1142 if (product && op0_xhigh && op1_xhigh)
1143 {
1144 rtx product_high = operand_subword (product, high, 1, mode);
1145 rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh,
1146 NULL_RTX, 0, OPTAB_DIRECT);
1147
1148 if (temp != 0)
1149 temp = expand_binop (word_mode, add_optab, temp, product_high,
1150 product_high, 0, next_methods);
1151
1152 if (temp != 0 && temp != product_high)
1153 emit_move_insn (product_high, temp);
1154
1155 if (temp != 0)
1156 temp = expand_binop (word_mode, binoptab, op1_low, op0_xhigh,
1157 NULL_RTX, 0, OPTAB_DIRECT);
1158
1159 if (temp != 0)
1160 temp = expand_binop (word_mode, add_optab, temp,
1161 product_high, product_high,
1162 0, next_methods);
1163
1164 if (temp != 0 && temp != product_high)
1165 emit_move_insn (product_high, temp);
1166
1167 if (temp != 0)
1168 {
1169 if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1170 {
1171 temp = emit_move_insn (product, product);
1172 REG_NOTES (temp)
1173 = gen_rtx_EXPR_LIST (REG_EQUAL,
1174 gen_rtx_fmt_ee (MULT, mode,
1175 copy_rtx (op0),
1176 copy_rtx (op1)),
1177 REG_NOTES (temp));
1178 }
1179 return product;
1180 }
1181 }
1182
1183 /* If we get here, we couldn't do it for some reason even though we
1184 originally thought we could. Delete anything we've emitted in
1185 trying to do it. */
1186
1187 delete_insns_since (last);
1188 }
1189
1190 /* We need to open-code the complex type operations: '+, -, * and /' */
1191
1192 /* At this point we allow operations between two similar complex
1193 numbers, and also if one of the operands is not a complex number
1194 but rather of MODE_FLOAT or MODE_INT. However, the caller
1195 must make sure that the MODE of the non-complex operand matches
1196 the SUBMODE of the complex operand. */
1197
1198 if (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
1199 {
1200 rtx real0 = 0, imag0 = 0;
1201 rtx real1 = 0, imag1 = 0;
1202 rtx realr, imagr, res;
1203 rtx seq;
1204 rtx equiv_value;
1205 int ok = 0;
1206
1207 /* Find the correct mode for the real and imaginary parts */
1208 enum machine_mode submode
1209 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
1210 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
1211 0);
1212
1213 if (submode == BLKmode)
1214 abort ();
1215
1216 if (! target)
1217 target = gen_reg_rtx (mode);
1218
1219 start_sequence ();
1220
1221 realr = gen_realpart (submode, target);
1222 imagr = gen_imagpart (submode, target);
1223
1224 if (GET_MODE (op0) == mode)
1225 {
1226 real0 = gen_realpart (submode, op0);
1227 imag0 = gen_imagpart (submode, op0);
1228 }
1229 else
1230 real0 = op0;
1231
1232 if (GET_MODE (op1) == mode)
1233 {
1234 real1 = gen_realpart (submode, op1);
1235 imag1 = gen_imagpart (submode, op1);
1236 }
1237 else
1238 real1 = op1;
1239
1240 if (real0 == 0 || real1 == 0 || ! (imag0 != 0|| imag1 != 0))
1241 abort ();
1242
1243 switch (binoptab->code)
1244 {
1245 case PLUS:
1246 /* (a+ib) + (c+id) = (a+c) + i(b+d) */
1247 case MINUS:
1248 /* (a+ib) - (c+id) = (a-c) + i(b-d) */
1249 res = expand_binop (submode, binoptab, real0, real1,
1250 realr, unsignedp, methods);
1251
1252 if (res == 0)
1253 break;
1254 else if (res != realr)
1255 emit_move_insn (realr, res);
1256
1257 if (imag0 && imag1)
1258 res = expand_binop (submode, binoptab, imag0, imag1,
1259 imagr, unsignedp, methods);
1260 else if (imag0)
1261 res = imag0;
1262 else if (binoptab->code == MINUS)
1263 res = expand_unop (submode, neg_optab, imag1, imagr, unsignedp);
1264 else
1265 res = imag1;
1266
1267 if (res == 0)
1268 break;
1269 else if (res != imagr)
1270 emit_move_insn (imagr, res);
1271
1272 ok = 1;
1273 break;
1274
1275 case MULT:
1276 /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */
1277
1278 if (imag0 && imag1)
1279 {
1280 rtx temp1, temp2;
1281
1282 /* Don't fetch these from memory more than once. */
1283 real0 = force_reg (submode, real0);
1284 real1 = force_reg (submode, real1);
1285 imag0 = force_reg (submode, imag0);
1286 imag1 = force_reg (submode, imag1);
1287
1288 temp1 = expand_binop (submode, binoptab, real0, real1, NULL_RTX,
1289 unsignedp, methods);
1290
1291 temp2 = expand_binop (submode, binoptab, imag0, imag1, NULL_RTX,
1292 unsignedp, methods);
1293
1294 if (temp1 == 0 || temp2 == 0)
1295 break;
1296
1297 res = expand_binop (submode, sub_optab, temp1, temp2,
1298 realr, unsignedp, methods);
1299
1300 if (res == 0)
1301 break;
1302 else if (res != realr)
1303 emit_move_insn (realr, res);
1304
1305 temp1 = expand_binop (submode, binoptab, real0, imag1,
1306 NULL_RTX, unsignedp, methods);
1307
1308 temp2 = expand_binop (submode, binoptab, real1, imag0,
1309 NULL_RTX, unsignedp, methods);
1310
1311 if (temp1 == 0 || temp2 == 0)
1312 break;
1313
1314 res = expand_binop (submode, add_optab, temp1, temp2,
1315 imagr, unsignedp, methods);
1316
1317 if (res == 0)
1318 break;
1319 else if (res != imagr)
1320 emit_move_insn (imagr, res);
1321
1322 ok = 1;
1323 }
1324 else
1325 {
1326 /* Don't fetch these from memory more than once. */
1327 real0 = force_reg (submode, real0);
1328 real1 = force_reg (submode, real1);
1329
1330 res = expand_binop (submode, binoptab, real0, real1,
1331 realr, unsignedp, methods);
1332 if (res == 0)
1333 break;
1334 else if (res != realr)
1335 emit_move_insn (realr, res);
1336
1337 if (imag0 != 0)
1338 res = expand_binop (submode, binoptab,
1339 real1, imag0, imagr, unsignedp, methods);
1340 else
1341 res = expand_binop (submode, binoptab,
1342 real0, imag1, imagr, unsignedp, methods);
1343
1344 if (res == 0)
1345 break;
1346 else if (res != imagr)
1347 emit_move_insn (imagr, res);
1348
1349 ok = 1;
1350 }
1351 break;
1352
1353 case DIV:
1354 /* (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) */
1355
1356 if (imag1 == 0)
1357 {
1358 /* (a+ib) / (c+i0) = (a/c) + i(b/c) */
1359
1360 /* Don't fetch these from memory more than once. */
1361 real1 = force_reg (submode, real1);
1362
1363 /* Simply divide the real and imaginary parts by `c' */
1364 if (class == MODE_COMPLEX_FLOAT)
1365 res = expand_binop (submode, binoptab, real0, real1,
1366 realr, unsignedp, methods);
1367 else
1368 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
1369 real0, real1, realr, unsignedp);
1370
1371 if (res == 0)
1372 break;
1373 else if (res != realr)
1374 emit_move_insn (realr, res);
1375
1376 if (class == MODE_COMPLEX_FLOAT)
1377 res = expand_binop (submode, binoptab, imag0, real1,
1378 imagr, unsignedp, methods);
1379 else
1380 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
1381 imag0, real1, imagr, unsignedp);
1382
1383 if (res == 0)
1384 break;
1385 else if (res != imagr)
1386 emit_move_insn (imagr, res);
1387
1388 ok = 1;
1389 }
1390 else
1391 {
1392 /* Divisor is of complex type:
1393 X/(a+ib) */
1394 rtx divisor;
1395 rtx real_t, imag_t;
1396 rtx temp1, temp2;
1397
1398 /* Don't fetch these from memory more than once. */
1399 real0 = force_reg (submode, real0);
1400 real1 = force_reg (submode, real1);
1401
1402 if (imag0 != 0)
1403 imag0 = force_reg (submode, imag0);
1404
1405 imag1 = force_reg (submode, imag1);
1406
1407 /* Divisor: c*c + d*d */
1408 temp1 = expand_binop (submode, smul_optab, real1, real1,
1409 NULL_RTX, unsignedp, methods);
1410
1411 temp2 = expand_binop (submode, smul_optab, imag1, imag1,
1412 NULL_RTX, unsignedp, methods);
1413
1414 if (temp1 == 0 || temp2 == 0)
1415 break;
1416
1417 divisor = expand_binop (submode, add_optab, temp1, temp2,
1418 NULL_RTX, unsignedp, methods);
1419 if (divisor == 0)
1420 break;
1421
1422 if (imag0 == 0)
1423 {
1424 /* ((a)(c-id))/divisor */
1425 /* (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)) */
1426
1427 /* Calculate the dividend */
1428 real_t = expand_binop (submode, smul_optab, real0, real1,
1429 NULL_RTX, unsignedp, methods);
1430
1431 imag_t = expand_binop (submode, smul_optab, real0, imag1,
1432 NULL_RTX, unsignedp, methods);
1433
1434 if (real_t == 0 || imag_t == 0)
1435 break;
1436
1437 imag_t = expand_unop (submode, neg_optab, imag_t,
1438 NULL_RTX, unsignedp);
1439 }
1440 else
1441 {
1442 /* ((a+ib)(c-id))/divider */
1443 /* Calculate the dividend */
1444 temp1 = expand_binop (submode, smul_optab, real0, real1,
1445 NULL_RTX, unsignedp, methods);
1446
1447 temp2 = expand_binop (submode, smul_optab, imag0, imag1,
1448 NULL_RTX, unsignedp, methods);
1449
1450 if (temp1 == 0 || temp2 == 0)
1451 break;
1452
1453 real_t = expand_binop (submode, add_optab, temp1, temp2,
1454 NULL_RTX, unsignedp, methods);
1455
1456 temp1 = expand_binop (submode, smul_optab, imag0, real1,
1457 NULL_RTX, unsignedp, methods);
1458
1459 temp2 = expand_binop (submode, smul_optab, real0, imag1,
1460 NULL_RTX, unsignedp, methods);
1461
1462 if (temp1 == 0 || temp2 == 0)
1463 break;
1464
1465 imag_t = expand_binop (submode, sub_optab, temp1, temp2,
1466 NULL_RTX, unsignedp, methods);
1467
1468 if (real_t == 0 || imag_t == 0)
1469 break;
1470 }
1471
1472 if (class == MODE_COMPLEX_FLOAT)
1473 res = expand_binop (submode, binoptab, real_t, divisor,
1474 realr, unsignedp, methods);
1475 else
1476 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
1477 real_t, divisor, realr, unsignedp);
1478
1479 if (res == 0)
1480 break;
1481 else if (res != realr)
1482 emit_move_insn (realr, res);
1483
1484 if (class == MODE_COMPLEX_FLOAT)
1485 res = expand_binop (submode, binoptab, imag_t, divisor,
1486 imagr, unsignedp, methods);
1487 else
1488 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
1489 imag_t, divisor, imagr, unsignedp);
1490
1491 if (res == 0)
1492 break;
1493 else if (res != imagr)
1494 emit_move_insn (imagr, res);
1495
1496 ok = 1;
1497 }
1498 break;
1499
1500 default:
1501 abort ();
1502 }
1503
1504 seq = get_insns ();
1505 end_sequence ();
1506
1507 if (ok)
1508 {
1509 if (binoptab->code != UNKNOWN)
1510 equiv_value
1511 = gen_rtx_fmt_ee (binoptab->code, mode,
1512 copy_rtx (op0), copy_rtx (op1));
1513 else
1514 equiv_value = 0;
1515
1516 emit_no_conflict_block (seq, target, op0, op1, equiv_value);
1517
1518 return target;
1519 }
1520 }
1521
1522 /* It can't be open-coded in this mode.
1523 Use a library call if one is available and caller says that's ok. */
1524
1525 if (binoptab->handlers[(int) mode].libfunc
1526 && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
1527 {
1528 rtx insns;
1529 rtx op1x = op1;
1530 enum machine_mode op1_mode = mode;
1531 rtx value;
1532
1533 start_sequence ();
1534
1535 if (shift_op)
1536 {
1537 op1_mode = word_mode;
1538 /* Specify unsigned here,
1539 since negative shift counts are meaningless. */
1540 op1x = convert_to_mode (word_mode, op1, 1);
1541 }
1542
1543 if (GET_MODE (op0) != VOIDmode
1544 && GET_MODE (op0) != mode)
1545 op0 = convert_to_mode (mode, op0, unsignedp);
1546
1547 /* Pass 1 for NO_QUEUE so we don't lose any increments
1548 if the libcall is cse'd or moved. */
1549 value = emit_library_call_value (binoptab->handlers[(int) mode].libfunc,
1550 NULL_RTX, 1, mode, 2,
1551 op0, mode, op1x, op1_mode);
1552
1553 insns = get_insns ();
1554 end_sequence ();
1555
1556 target = gen_reg_rtx (mode);
1557 emit_libcall_block (insns, target, value,
1558 gen_rtx_fmt_ee (binoptab->code, mode, op0, op1));
1559
1560 return target;
1561 }
1562
1563 delete_insns_since (last);
1564
1565 /* It can't be done in this mode. Can we do it in a wider mode? */
1566
1567 if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
1568 || methods == OPTAB_MUST_WIDEN))
1569 {
1570 /* Caller says, don't even try. */
1571 delete_insns_since (entry_last);
1572 return 0;
1573 }
1574
1575 /* Compute the value of METHODS to pass to recursive calls.
1576 Don't allow widening to be tried recursively. */
1577
1578 methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
1579
1580 /* Look for a wider mode of the same class for which it appears we can do
1581 the operation. */
1582
1583 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1584 {
1585 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1586 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1587 {
1588 if ((binoptab->handlers[(int) wider_mode].insn_code
1589 != CODE_FOR_nothing)
1590 || (methods == OPTAB_LIB
1591 && binoptab->handlers[(int) wider_mode].libfunc))
1592 {
1593 rtx xop0 = op0, xop1 = op1;
1594 int no_extend = 0;
1595
1596 /* For certain integer operations, we need not actually extend
1597 the narrow operands, as long as we will truncate
1598 the results to the same narrowness. */
1599
1600 if ((binoptab == ior_optab || binoptab == and_optab
1601 || binoptab == xor_optab
1602 || binoptab == add_optab || binoptab == sub_optab
1603 || binoptab == smul_optab || binoptab == ashl_optab)
1604 && class == MODE_INT)
1605 no_extend = 1;
1606
1607 xop0 = widen_operand (xop0, wider_mode, mode,
1608 unsignedp, no_extend);
1609
1610 /* The second operand of a shift must always be extended. */
1611 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
1612 no_extend && binoptab != ashl_optab);
1613
1614 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
1615 unsignedp, methods);
1616 if (temp)
1617 {
1618 if (class != MODE_INT)
1619 {
1620 if (target == 0)
1621 target = gen_reg_rtx (mode);
1622 convert_move (target, temp, 0);
1623 return target;
1624 }
1625 else
1626 return gen_lowpart (mode, temp);
1627 }
1628 else
1629 delete_insns_since (last);
1630 }
1631 }
1632 }
1633
1634 delete_insns_since (entry_last);
1635 return 0;
1636 }
1637 \f
1638 /* Expand a binary operator which has both signed and unsigned forms.
1639 UOPTAB is the optab for unsigned operations, and SOPTAB is for
1640 signed operations.
1641
1642 If we widen unsigned operands, we may use a signed wider operation instead
1643 of an unsigned wider operation, since the result would be the same. */
1644
1645 rtx
1646 sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods)
1647 enum machine_mode mode;
1648 optab uoptab, soptab;
1649 rtx op0, op1, target;
1650 int unsignedp;
1651 enum optab_methods methods;
1652 {
1653 register rtx temp;
1654 optab direct_optab = unsignedp ? uoptab : soptab;
1655 struct optab wide_soptab;
1656
1657 /* Do it without widening, if possible. */
1658 temp = expand_binop (mode, direct_optab, op0, op1, target,
1659 unsignedp, OPTAB_DIRECT);
1660 if (temp || methods == OPTAB_DIRECT)
1661 return temp;
1662
1663 /* Try widening to a signed int. Make a fake signed optab that
1664 hides any signed insn for direct use. */
1665 wide_soptab = *soptab;
1666 wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing;
1667 wide_soptab.handlers[(int) mode].libfunc = 0;
1668
1669 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
1670 unsignedp, OPTAB_WIDEN);
1671
1672 /* For unsigned operands, try widening to an unsigned int. */
1673 if (temp == 0 && unsignedp)
1674 temp = expand_binop (mode, uoptab, op0, op1, target,
1675 unsignedp, OPTAB_WIDEN);
1676 if (temp || methods == OPTAB_WIDEN)
1677 return temp;
1678
1679 /* Use the right width lib call if that exists. */
1680 temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
1681 if (temp || methods == OPTAB_LIB)
1682 return temp;
1683
1684 /* Must widen and use a lib call, use either signed or unsigned. */
1685 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
1686 unsignedp, methods);
1687 if (temp != 0)
1688 return temp;
1689 if (unsignedp)
1690 return expand_binop (mode, uoptab, op0, op1, target,
1691 unsignedp, methods);
1692 return 0;
1693 }
1694 \f
1695 /* Generate code to perform an operation specified by BINOPTAB
1696 on operands OP0 and OP1, with two results to TARG1 and TARG2.
1697 We assume that the order of the operands for the instruction
1698 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
1699 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
1700
1701 Either TARG0 or TARG1 may be zero, but what that means is that
1702 the result is not actually wanted. We will generate it into
1703 a dummy pseudo-reg and discard it. They may not both be zero.
1704
1705 Returns 1 if this operation can be performed; 0 if not. */
1706
1707 int
1708 expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
1709 optab binoptab;
1710 rtx op0, op1;
1711 rtx targ0, targ1;
1712 int unsignedp;
1713 {
1714 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
1715 enum mode_class class;
1716 enum machine_mode wider_mode;
1717 rtx entry_last = get_last_insn ();
1718 rtx last;
1719
1720 class = GET_MODE_CLASS (mode);
1721
1722 op0 = protect_from_queue (op0, 0);
1723 op1 = protect_from_queue (op1, 0);
1724
1725 if (flag_force_mem)
1726 {
1727 op0 = force_not_mem (op0);
1728 op1 = force_not_mem (op1);
1729 }
1730
1731 /* If we are inside an appropriately-short loop and one operand is an
1732 expensive constant, force it into a register. */
1733 if (CONSTANT_P (op0) && preserve_subexpressions_p ()
1734 && rtx_cost (op0, binoptab->code) > 2)
1735 op0 = force_reg (mode, op0);
1736
1737 if (CONSTANT_P (op1) && preserve_subexpressions_p ()
1738 && rtx_cost (op1, binoptab->code) > 2)
1739 op1 = force_reg (mode, op1);
1740
1741 if (targ0)
1742 targ0 = protect_from_queue (targ0, 1);
1743 else
1744 targ0 = gen_reg_rtx (mode);
1745 if (targ1)
1746 targ1 = protect_from_queue (targ1, 1);
1747 else
1748 targ1 = gen_reg_rtx (mode);
1749
1750 /* Record where to go back to if we fail. */
1751 last = get_last_insn ();
1752
1753 if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1754 {
1755 int icode = (int) binoptab->handlers[(int) mode].insn_code;
1756 enum machine_mode mode0 = insn_operand_mode[icode][1];
1757 enum machine_mode mode1 = insn_operand_mode[icode][2];
1758 rtx pat;
1759 rtx xop0 = op0, xop1 = op1;
1760
1761 /* In case this insn wants input operands in modes different from the
1762 result, convert the operands. */
1763 if (GET_MODE (op0) != VOIDmode && GET_MODE (op0) != mode0)
1764 xop0 = convert_to_mode (mode0, xop0, unsignedp);
1765
1766 if (GET_MODE (op1) != VOIDmode && GET_MODE (op1) != mode1)
1767 xop1 = convert_to_mode (mode1, xop1, unsignedp);
1768
1769 /* Now, if insn doesn't accept these operands, put them into pseudos. */
1770 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
1771 xop0 = copy_to_mode_reg (mode0, xop0);
1772
1773 if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
1774 xop1 = copy_to_mode_reg (mode1, xop1);
1775
1776 /* We could handle this, but we should always be called with a pseudo
1777 for our targets and all insns should take them as outputs. */
1778 if (! (*insn_operand_predicate[icode][0]) (targ0, mode)
1779 || ! (*insn_operand_predicate[icode][3]) (targ1, mode))
1780 abort ();
1781
1782 pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
1783 if (pat)
1784 {
1785 emit_insn (pat);
1786 return 1;
1787 }
1788 else
1789 delete_insns_since (last);
1790 }
1791
1792 /* It can't be done in this mode. Can we do it in a wider mode? */
1793
1794 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1795 {
1796 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1797 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1798 {
1799 if (binoptab->handlers[(int) wider_mode].insn_code
1800 != CODE_FOR_nothing)
1801 {
1802 register rtx t0 = gen_reg_rtx (wider_mode);
1803 register rtx t1 = gen_reg_rtx (wider_mode);
1804
1805 if (expand_twoval_binop (binoptab,
1806 convert_modes (wider_mode, mode, op0,
1807 unsignedp),
1808 convert_modes (wider_mode, mode, op1,
1809 unsignedp),
1810 t0, t1, unsignedp))
1811 {
1812 convert_move (targ0, t0, unsignedp);
1813 convert_move (targ1, t1, unsignedp);
1814 return 1;
1815 }
1816 else
1817 delete_insns_since (last);
1818 }
1819 }
1820 }
1821
1822 delete_insns_since (entry_last);
1823 return 0;
1824 }
1825 \f
1826 /* Generate code to perform an operation specified by UNOPTAB
1827 on operand OP0, with result having machine-mode MODE.
1828
1829 UNSIGNEDP is for the case where we have to widen the operands
1830 to perform the operation. It says to use zero-extension.
1831
1832 If TARGET is nonzero, the value
1833 is generated there, if it is convenient to do so.
1834 In all cases an rtx is returned for the locus of the value;
1835 this may or may not be TARGET. */
1836
1837 rtx
1838 expand_unop (mode, unoptab, op0, target, unsignedp)
1839 enum machine_mode mode;
1840 optab unoptab;
1841 rtx op0;
1842 rtx target;
1843 int unsignedp;
1844 {
1845 enum mode_class class;
1846 enum machine_mode wider_mode;
1847 register rtx temp;
1848 rtx last = get_last_insn ();
1849 rtx pat;
1850
1851 class = GET_MODE_CLASS (mode);
1852
1853 op0 = protect_from_queue (op0, 0);
1854
1855 if (flag_force_mem)
1856 {
1857 op0 = force_not_mem (op0);
1858 }
1859
1860 if (target)
1861 target = protect_from_queue (target, 1);
1862
1863 if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1864 {
1865 int icode = (int) unoptab->handlers[(int) mode].insn_code;
1866 enum machine_mode mode0 = insn_operand_mode[icode][1];
1867 rtx xop0 = op0;
1868
1869 if (target)
1870 temp = target;
1871 else
1872 temp = gen_reg_rtx (mode);
1873
1874 if (GET_MODE (xop0) != VOIDmode
1875 && GET_MODE (xop0) != mode0)
1876 xop0 = convert_to_mode (mode0, xop0, unsignedp);
1877
1878 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
1879
1880 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
1881 xop0 = copy_to_mode_reg (mode0, xop0);
1882
1883 if (! (*insn_operand_predicate[icode][0]) (temp, mode))
1884 temp = gen_reg_rtx (mode);
1885
1886 pat = GEN_FCN (icode) (temp, xop0);
1887 if (pat)
1888 {
1889 if (GET_CODE (pat) == SEQUENCE
1890 && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
1891 {
1892 delete_insns_since (last);
1893 return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
1894 }
1895
1896 emit_insn (pat);
1897
1898 return temp;
1899 }
1900 else
1901 delete_insns_since (last);
1902 }
1903
1904 /* It can't be done in this mode. Can we open-code it in a wider mode? */
1905
1906 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1907 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1908 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1909 {
1910 if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
1911 {
1912 rtx xop0 = op0;
1913
1914 /* For certain operations, we need not actually extend
1915 the narrow operand, as long as we will truncate the
1916 results to the same narrowness. */
1917
1918 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
1919 (unoptab == neg_optab
1920 || unoptab == one_cmpl_optab)
1921 && class == MODE_INT);
1922
1923 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
1924 unsignedp);
1925
1926 if (temp)
1927 {
1928 if (class != MODE_INT)
1929 {
1930 if (target == 0)
1931 target = gen_reg_rtx (mode);
1932 convert_move (target, temp, 0);
1933 return target;
1934 }
1935 else
1936 return gen_lowpart (mode, temp);
1937 }
1938 else
1939 delete_insns_since (last);
1940 }
1941 }
1942
1943 /* These can be done a word at a time. */
1944 if (unoptab == one_cmpl_optab
1945 && class == MODE_INT
1946 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
1947 && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
1948 {
1949 int i;
1950 rtx insns;
1951
1952 if (target == 0 || target == op0)
1953 target = gen_reg_rtx (mode);
1954
1955 start_sequence ();
1956
1957 /* Do the actual arithmetic. */
1958 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
1959 {
1960 rtx target_piece = operand_subword (target, i, 1, mode);
1961 rtx x = expand_unop (word_mode, unoptab,
1962 operand_subword_force (op0, i, mode),
1963 target_piece, unsignedp);
1964 if (target_piece != x)
1965 emit_move_insn (target_piece, x);
1966 }
1967
1968 insns = get_insns ();
1969 end_sequence ();
1970
1971 emit_no_conflict_block (insns, target, op0, NULL_RTX,
1972 gen_rtx_fmt_e (unoptab->code, mode,
1973 copy_rtx (op0)));
1974 return target;
1975 }
1976
1977 /* Open-code the complex negation operation. */
1978 else if (unoptab == neg_optab
1979 && (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT))
1980 {
1981 rtx target_piece;
1982 rtx x;
1983 rtx seq;
1984
1985 /* Find the correct mode for the real and imaginary parts */
1986 enum machine_mode submode
1987 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
1988 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
1989 0);
1990
1991 if (submode == BLKmode)
1992 abort ();
1993
1994 if (target == 0)
1995 target = gen_reg_rtx (mode);
1996
1997 start_sequence ();
1998
1999 target_piece = gen_imagpart (submode, target);
2000 x = expand_unop (submode, unoptab,
2001 gen_imagpart (submode, op0),
2002 target_piece, unsignedp);
2003 if (target_piece != x)
2004 emit_move_insn (target_piece, x);
2005
2006 target_piece = gen_realpart (submode, target);
2007 x = expand_unop (submode, unoptab,
2008 gen_realpart (submode, op0),
2009 target_piece, unsignedp);
2010 if (target_piece != x)
2011 emit_move_insn (target_piece, x);
2012
2013 seq = get_insns ();
2014 end_sequence ();
2015
2016 emit_no_conflict_block (seq, target, op0, 0,
2017 gen_rtx_fmt_e (unoptab->code, mode,
2018 copy_rtx (op0)));
2019 return target;
2020 }
2021
2022 /* Now try a library call in this mode. */
2023 if (unoptab->handlers[(int) mode].libfunc)
2024 {
2025 rtx insns;
2026 rtx value;
2027
2028 start_sequence ();
2029
2030 /* Pass 1 for NO_QUEUE so we don't lose any increments
2031 if the libcall is cse'd or moved. */
2032 value = emit_library_call_value (unoptab->handlers[(int) mode].libfunc,
2033 NULL_RTX, 1, mode, 1, op0, mode);
2034 insns = get_insns ();
2035 end_sequence ();
2036
2037 target = gen_reg_rtx (mode);
2038 emit_libcall_block (insns, target, value,
2039 gen_rtx_fmt_e (unoptab->code, mode, op0));
2040
2041 return target;
2042 }
2043
2044 /* It can't be done in this mode. Can we do it in a wider mode? */
2045
2046 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
2047 {
2048 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2049 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2050 {
2051 if ((unoptab->handlers[(int) wider_mode].insn_code
2052 != CODE_FOR_nothing)
2053 || unoptab->handlers[(int) wider_mode].libfunc)
2054 {
2055 rtx xop0 = op0;
2056
2057 /* For certain operations, we need not actually extend
2058 the narrow operand, as long as we will truncate the
2059 results to the same narrowness. */
2060
2061 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
2062 (unoptab == neg_optab
2063 || unoptab == one_cmpl_optab)
2064 && class == MODE_INT);
2065
2066 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
2067 unsignedp);
2068
2069 if (temp)
2070 {
2071 if (class != MODE_INT)
2072 {
2073 if (target == 0)
2074 target = gen_reg_rtx (mode);
2075 convert_move (target, temp, 0);
2076 return target;
2077 }
2078 else
2079 return gen_lowpart (mode, temp);
2080 }
2081 else
2082 delete_insns_since (last);
2083 }
2084 }
2085 }
2086
2087 /* If there is no negate operation, try doing a subtract from zero.
2088 The US Software GOFAST library needs this. */
2089 if (unoptab == neg_optab)
2090 {
2091 rtx temp;
2092 temp = expand_binop (mode, sub_optab, CONST0_RTX (mode), op0,
2093 target, unsignedp, OPTAB_LIB_WIDEN);
2094 if (temp)
2095 return temp;
2096 }
2097
2098 return 0;
2099 }
2100 \f
2101 /* Emit code to compute the absolute value of OP0, with result to
2102 TARGET if convenient. (TARGET may be 0.) The return value says
2103 where the result actually is to be found.
2104
2105 MODE is the mode of the operand; the mode of the result is
2106 different but can be deduced from MODE.
2107
2108 UNSIGNEDP is relevant if extension is needed. */
2109
2110 rtx
2111 expand_abs (mode, op0, target, unsignedp, safe)
2112 enum machine_mode mode;
2113 rtx op0;
2114 rtx target;
2115 int unsignedp;
2116 int safe;
2117 {
2118 rtx temp, op1;
2119
2120 /* First try to do it with a special abs instruction. */
2121 temp = expand_unop (mode, abs_optab, op0, target, 0);
2122 if (temp != 0)
2123 return temp;
2124
2125 /* If this machine has expensive jumps, we can do integer absolute
2126 value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
2127 where W is the width of MODE. */
2128
2129 if (GET_MODE_CLASS (mode) == MODE_INT && BRANCH_COST >= 2)
2130 {
2131 rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
2132 size_int (GET_MODE_BITSIZE (mode) - 1),
2133 NULL_RTX, 0);
2134
2135 temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
2136 OPTAB_LIB_WIDEN);
2137 if (temp != 0)
2138 temp = expand_binop (mode, sub_optab, temp, extended, target, 0,
2139 OPTAB_LIB_WIDEN);
2140
2141 if (temp != 0)
2142 return temp;
2143 }
2144
2145 /* If that does not win, use conditional jump and negate. */
2146
2147 /* It is safe to use the target if it is the same
2148 as the source if this is also a pseudo register */
2149 if (op0 == target && GET_CODE (op0) == REG
2150 && REGNO (op0) >= FIRST_PSEUDO_REGISTER)
2151 safe = 1;
2152
2153 op1 = gen_label_rtx ();
2154 if (target == 0 || ! safe
2155 || GET_MODE (target) != mode
2156 || (GET_CODE (target) == MEM && MEM_VOLATILE_P (target))
2157 || (GET_CODE (target) == REG
2158 && REGNO (target) < FIRST_PSEUDO_REGISTER))
2159 target = gen_reg_rtx (mode);
2160
2161 emit_move_insn (target, op0);
2162 NO_DEFER_POP;
2163
2164 /* If this mode is an integer too wide to compare properly,
2165 compare word by word. Rely on CSE to optimize constant cases. */
2166 if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode))
2167 do_jump_by_parts_greater_rtx (mode, 0, target, const0_rtx,
2168 NULL_RTX, op1);
2169 else
2170 {
2171 temp = compare_from_rtx (target, CONST0_RTX (mode), GE, 0, mode,
2172 NULL_RTX, 0);
2173 if (temp == const1_rtx)
2174 return target;
2175 else if (temp != const0_rtx)
2176 {
2177 if (bcc_gen_fctn[(int) GET_CODE (temp)] != 0)
2178 emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (temp)]) (op1));
2179 else
2180 abort ();
2181 }
2182 }
2183
2184 op0 = expand_unop (mode, neg_optab, target, target, 0);
2185 if (op0 != target)
2186 emit_move_insn (target, op0);
2187 emit_label (op1);
2188 OK_DEFER_POP;
2189 return target;
2190 }
2191 \f
2192 /* Emit code to compute the absolute value of OP0, with result to
2193 TARGET if convenient. (TARGET may be 0.) The return value says
2194 where the result actually is to be found.
2195
2196 MODE is the mode of the operand; the mode of the result is
2197 different but can be deduced from MODE.
2198
2199 UNSIGNEDP is relevant for complex integer modes. */
2200
2201 rtx
2202 expand_complex_abs (mode, op0, target, unsignedp)
2203 enum machine_mode mode;
2204 rtx op0;
2205 rtx target;
2206 int unsignedp;
2207 {
2208 enum mode_class class = GET_MODE_CLASS (mode);
2209 enum machine_mode wider_mode;
2210 register rtx temp;
2211 rtx entry_last = get_last_insn ();
2212 rtx last;
2213 rtx pat;
2214
2215 /* Find the correct mode for the real and imaginary parts. */
2216 enum machine_mode submode
2217 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
2218 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
2219 0);
2220
2221 if (submode == BLKmode)
2222 abort ();
2223
2224 op0 = protect_from_queue (op0, 0);
2225
2226 if (flag_force_mem)
2227 {
2228 op0 = force_not_mem (op0);
2229 }
2230
2231 last = get_last_insn ();
2232
2233 if (target)
2234 target = protect_from_queue (target, 1);
2235
2236 if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2237 {
2238 int icode = (int) abs_optab->handlers[(int) mode].insn_code;
2239 enum machine_mode mode0 = insn_operand_mode[icode][1];
2240 rtx xop0 = op0;
2241
2242 if (target)
2243 temp = target;
2244 else
2245 temp = gen_reg_rtx (submode);
2246
2247 if (GET_MODE (xop0) != VOIDmode
2248 && GET_MODE (xop0) != mode0)
2249 xop0 = convert_to_mode (mode0, xop0, unsignedp);
2250
2251 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
2252
2253 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
2254 xop0 = copy_to_mode_reg (mode0, xop0);
2255
2256 if (! (*insn_operand_predicate[icode][0]) (temp, submode))
2257 temp = gen_reg_rtx (submode);
2258
2259 pat = GEN_FCN (icode) (temp, xop0);
2260 if (pat)
2261 {
2262 if (GET_CODE (pat) == SEQUENCE
2263 && ! add_equal_note (pat, temp, abs_optab->code, xop0, NULL_RTX))
2264 {
2265 delete_insns_since (last);
2266 return expand_unop (mode, abs_optab, op0, NULL_RTX, unsignedp);
2267 }
2268
2269 emit_insn (pat);
2270
2271 return temp;
2272 }
2273 else
2274 delete_insns_since (last);
2275 }
2276
2277 /* It can't be done in this mode. Can we open-code it in a wider mode? */
2278
2279 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2280 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2281 {
2282 if (abs_optab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
2283 {
2284 rtx xop0 = op0;
2285
2286 xop0 = convert_modes (wider_mode, mode, xop0, unsignedp);
2287 temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
2288
2289 if (temp)
2290 {
2291 if (class != MODE_COMPLEX_INT)
2292 {
2293 if (target == 0)
2294 target = gen_reg_rtx (submode);
2295 convert_move (target, temp, 0);
2296 return target;
2297 }
2298 else
2299 return gen_lowpart (submode, temp);
2300 }
2301 else
2302 delete_insns_since (last);
2303 }
2304 }
2305
2306 /* Open-code the complex absolute-value operation
2307 if we can open-code sqrt. Otherwise it's not worth while. */
2308 if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing)
2309 {
2310 rtx real, imag, total;
2311
2312 real = gen_realpart (submode, op0);
2313 imag = gen_imagpart (submode, op0);
2314
2315 /* Square both parts. */
2316 real = expand_mult (submode, real, real, NULL_RTX, 0);
2317 imag = expand_mult (submode, imag, imag, NULL_RTX, 0);
2318
2319 /* Sum the parts. */
2320 total = expand_binop (submode, add_optab, real, imag, NULL_RTX,
2321 0, OPTAB_LIB_WIDEN);
2322
2323 /* Get sqrt in TARGET. Set TARGET to where the result is. */
2324 target = expand_unop (submode, sqrt_optab, total, target, 0);
2325 if (target == 0)
2326 delete_insns_since (last);
2327 else
2328 return target;
2329 }
2330
2331 /* Now try a library call in this mode. */
2332 if (abs_optab->handlers[(int) mode].libfunc)
2333 {
2334 rtx insns;
2335 rtx value;
2336
2337 start_sequence ();
2338
2339 /* Pass 1 for NO_QUEUE so we don't lose any increments
2340 if the libcall is cse'd or moved. */
2341 value = emit_library_call_value (abs_optab->handlers[(int) mode].libfunc,
2342 NULL_RTX, 1, submode, 1, op0, mode);
2343 insns = get_insns ();
2344 end_sequence ();
2345
2346 target = gen_reg_rtx (submode);
2347 emit_libcall_block (insns, target, value,
2348 gen_rtx_fmt_e (abs_optab->code, mode, op0));
2349
2350 return target;
2351 }
2352
2353 /* It can't be done in this mode. Can we do it in a wider mode? */
2354
2355 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2356 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2357 {
2358 if ((abs_optab->handlers[(int) wider_mode].insn_code
2359 != CODE_FOR_nothing)
2360 || abs_optab->handlers[(int) wider_mode].libfunc)
2361 {
2362 rtx xop0 = op0;
2363
2364 xop0 = convert_modes (wider_mode, mode, xop0, unsignedp);
2365
2366 temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
2367
2368 if (temp)
2369 {
2370 if (class != MODE_COMPLEX_INT)
2371 {
2372 if (target == 0)
2373 target = gen_reg_rtx (submode);
2374 convert_move (target, temp, 0);
2375 return target;
2376 }
2377 else
2378 return gen_lowpart (submode, temp);
2379 }
2380 else
2381 delete_insns_since (last);
2382 }
2383 }
2384
2385 delete_insns_since (entry_last);
2386 return 0;
2387 }
2388 \f
2389 /* Generate an instruction whose insn-code is INSN_CODE,
2390 with two operands: an output TARGET and an input OP0.
2391 TARGET *must* be nonzero, and the output is always stored there.
2392 CODE is an rtx code such that (CODE OP0) is an rtx that describes
2393 the value that is stored into TARGET. */
2394
2395 void
2396 emit_unop_insn (icode, target, op0, code)
2397 int icode;
2398 rtx target;
2399 rtx op0;
2400 enum rtx_code code;
2401 {
2402 register rtx temp;
2403 enum machine_mode mode0 = insn_operand_mode[icode][1];
2404 rtx pat;
2405
2406 temp = target = protect_from_queue (target, 1);
2407
2408 op0 = protect_from_queue (op0, 0);
2409
2410 /* Sign and zero extension from memory is often done specially on
2411 RISC machines, so forcing into a register here can pessimize
2412 code. */
2413 if (flag_force_mem && code != SIGN_EXTEND && code != ZERO_EXTEND)
2414 op0 = force_not_mem (op0);
2415
2416 /* Now, if insn does not accept our operands, put them into pseudos. */
2417
2418 if (! (*insn_operand_predicate[icode][1]) (op0, mode0))
2419 op0 = copy_to_mode_reg (mode0, op0);
2420
2421 if (! (*insn_operand_predicate[icode][0]) (temp, GET_MODE (temp))
2422 || (flag_force_mem && GET_CODE (temp) == MEM))
2423 temp = gen_reg_rtx (GET_MODE (temp));
2424
2425 pat = GEN_FCN (icode) (temp, op0);
2426
2427 if (GET_CODE (pat) == SEQUENCE && code != UNKNOWN)
2428 add_equal_note (pat, temp, code, op0, NULL_RTX);
2429
2430 emit_insn (pat);
2431
2432 if (temp != target)
2433 emit_move_insn (target, temp);
2434 }
2435 \f
2436 /* Emit code to perform a series of operations on a multi-word quantity, one
2437 word at a time.
2438
2439 Such a block is preceded by a CLOBBER of the output, consists of multiple
2440 insns, each setting one word of the output, and followed by a SET copying
2441 the output to itself.
2442
2443 Each of the insns setting words of the output receives a REG_NO_CONFLICT
2444 note indicating that it doesn't conflict with the (also multi-word)
2445 inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
2446 notes.
2447
2448 INSNS is a block of code generated to perform the operation, not including
2449 the CLOBBER and final copy. All insns that compute intermediate values
2450 are first emitted, followed by the block as described above.
2451
2452 TARGET, OP0, and OP1 are the output and inputs of the operations,
2453 respectively. OP1 may be zero for a unary operation.
2454
2455 EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
2456 on the last insn.
2457
2458 If TARGET is not a register, INSNS is simply emitted with no special
2459 processing. Likewise if anything in INSNS is not an INSN or if
2460 there is a libcall block inside INSNS.
2461
2462 The final insn emitted is returned. */
2463
2464 rtx
2465 emit_no_conflict_block (insns, target, op0, op1, equiv)
2466 rtx insns;
2467 rtx target;
2468 rtx op0, op1;
2469 rtx equiv;
2470 {
2471 rtx prev, next, first, last, insn;
2472
2473 if (GET_CODE (target) != REG || reload_in_progress)
2474 return emit_insns (insns);
2475 else
2476 for (insn = insns; insn; insn = NEXT_INSN (insn))
2477 if (GET_CODE (insn) != INSN
2478 || find_reg_note (insn, REG_LIBCALL, NULL_RTX))
2479 return emit_insns (insns);
2480
2481 /* First emit all insns that do not store into words of the output and remove
2482 these from the list. */
2483 for (insn = insns; insn; insn = next)
2484 {
2485 rtx set = 0;
2486 int i;
2487
2488 next = NEXT_INSN (insn);
2489
2490 if (GET_CODE (PATTERN (insn)) == SET)
2491 set = PATTERN (insn);
2492 else if (GET_CODE (PATTERN (insn)) == PARALLEL)
2493 {
2494 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
2495 if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
2496 {
2497 set = XVECEXP (PATTERN (insn), 0, i);
2498 break;
2499 }
2500 }
2501
2502 if (set == 0)
2503 abort ();
2504
2505 if (! reg_overlap_mentioned_p (target, SET_DEST (set)))
2506 {
2507 if (PREV_INSN (insn))
2508 NEXT_INSN (PREV_INSN (insn)) = next;
2509 else
2510 insns = next;
2511
2512 if (next)
2513 PREV_INSN (next) = PREV_INSN (insn);
2514
2515 add_insn (insn);
2516 }
2517 }
2518
2519 prev = get_last_insn ();
2520
2521 /* Now write the CLOBBER of the output, followed by the setting of each
2522 of the words, followed by the final copy. */
2523 if (target != op0 && target != op1)
2524 emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
2525
2526 for (insn = insns; insn; insn = next)
2527 {
2528 next = NEXT_INSN (insn);
2529 add_insn (insn);
2530
2531 if (op1 && GET_CODE (op1) == REG)
2532 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op1,
2533 REG_NOTES (insn));
2534
2535 if (op0 && GET_CODE (op0) == REG)
2536 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op0,
2537 REG_NOTES (insn));
2538 }
2539
2540 if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
2541 != CODE_FOR_nothing)
2542 {
2543 last = emit_move_insn (target, target);
2544 if (equiv)
2545 REG_NOTES (last)
2546 = gen_rtx_EXPR_LIST (REG_EQUAL, equiv, REG_NOTES (last));
2547 }
2548 else
2549 last = get_last_insn ();
2550
2551 if (prev == 0)
2552 first = get_insns ();
2553 else
2554 first = NEXT_INSN (prev);
2555
2556 /* Encapsulate the block so it gets manipulated as a unit. */
2557 REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
2558 REG_NOTES (first));
2559 REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2560
2561 return last;
2562 }
2563 \f
2564 /* Emit code to make a call to a constant function or a library call.
2565
2566 INSNS is a list containing all insns emitted in the call.
2567 These insns leave the result in RESULT. Our block is to copy RESULT
2568 to TARGET, which is logically equivalent to EQUIV.
2569
2570 We first emit any insns that set a pseudo on the assumption that these are
2571 loading constants into registers; doing so allows them to be safely cse'ed
2572 between blocks. Then we emit all the other insns in the block, followed by
2573 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
2574 note with an operand of EQUIV.
2575
2576 Moving assignments to pseudos outside of the block is done to improve
2577 the generated code, but is not required to generate correct code,
2578 hence being unable to move an assignment is not grounds for not making
2579 a libcall block. There are two reasons why it is safe to leave these
2580 insns inside the block: First, we know that these pseudos cannot be
2581 used in generated RTL outside the block since they are created for
2582 temporary purposes within the block. Second, CSE will not record the
2583 values of anything set inside a libcall block, so we know they must
2584 be dead at the end of the block.
2585
2586 Except for the first group of insns (the ones setting pseudos), the
2587 block is delimited by REG_RETVAL and REG_LIBCALL notes. */
2588
2589 void
2590 emit_libcall_block (insns, target, result, equiv)
2591 rtx insns;
2592 rtx target;
2593 rtx result;
2594 rtx equiv;
2595 {
2596 rtx prev, next, first, last, insn;
2597
2598 /* First emit all insns that set pseudos. Remove them from the list as
2599 we go. Avoid insns that set pseudos which were referenced in previous
2600 insns. These can be generated by move_by_pieces, for example,
2601 to update an address. Similarly, avoid insns that reference things
2602 set in previous insns. */
2603
2604 for (insn = insns; insn; insn = next)
2605 {
2606 rtx set = single_set (insn);
2607
2608 next = NEXT_INSN (insn);
2609
2610 if (set != 0 && GET_CODE (SET_DEST (set)) == REG
2611 && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
2612 && (insn == insns
2613 || (! reg_mentioned_p (SET_DEST (set), PATTERN (insns))
2614 && ! reg_used_between_p (SET_DEST (set), insns, insn)
2615 && ! modified_in_p (SET_SRC (set), insns)
2616 && ! modified_between_p (SET_SRC (set), insns, insn))))
2617 {
2618 if (PREV_INSN (insn))
2619 NEXT_INSN (PREV_INSN (insn)) = next;
2620 else
2621 insns = next;
2622
2623 if (next)
2624 PREV_INSN (next) = PREV_INSN (insn);
2625
2626 add_insn (insn);
2627 }
2628 }
2629
2630 prev = get_last_insn ();
2631
2632 /* Write the remaining insns followed by the final copy. */
2633
2634 for (insn = insns; insn; insn = next)
2635 {
2636 next = NEXT_INSN (insn);
2637
2638 add_insn (insn);
2639 }
2640
2641 last = emit_move_insn (target, result);
2642 if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
2643 != CODE_FOR_nothing)
2644 REG_NOTES (last) = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (equiv),
2645 REG_NOTES (last));
2646
2647 if (prev == 0)
2648 first = get_insns ();
2649 else
2650 first = NEXT_INSN (prev);
2651
2652 /* Encapsulate the block so it gets manipulated as a unit. */
2653 REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
2654 REG_NOTES (first));
2655 REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2656 }
2657 \f
2658 /* Generate code to store zero in X. */
2659
2660 void
2661 emit_clr_insn (x)
2662 rtx x;
2663 {
2664 emit_move_insn (x, const0_rtx);
2665 }
2666
2667 /* Generate code to store 1 in X
2668 assuming it contains zero beforehand. */
2669
2670 void
2671 emit_0_to_1_insn (x)
2672 rtx x;
2673 {
2674 emit_move_insn (x, const1_rtx);
2675 }
2676
2677 /* Generate code to compare X with Y
2678 so that the condition codes are set.
2679
2680 MODE is the mode of the inputs (in case they are const_int).
2681 UNSIGNEDP nonzero says that X and Y are unsigned;
2682 this matters if they need to be widened.
2683
2684 If they have mode BLKmode, then SIZE specifies the size of both X and Y,
2685 and ALIGN specifies the known shared alignment of X and Y.
2686
2687 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
2688 It is ignored for fixed-point and block comparisons;
2689 it is used only for floating-point comparisons. */
2690
2691 void
2692 emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
2693 rtx x, y;
2694 enum rtx_code comparison;
2695 rtx size;
2696 enum machine_mode mode;
2697 int unsignedp;
2698 int align;
2699 {
2700 enum mode_class class;
2701 enum machine_mode wider_mode;
2702
2703 class = GET_MODE_CLASS (mode);
2704
2705 /* They could both be VOIDmode if both args are immediate constants,
2706 but we should fold that at an earlier stage.
2707 With no special code here, this will call abort,
2708 reminding the programmer to implement such folding. */
2709
2710 if (mode != BLKmode && flag_force_mem)
2711 {
2712 x = force_not_mem (x);
2713 y = force_not_mem (y);
2714 }
2715
2716 /* If we are inside an appropriately-short loop and one operand is an
2717 expensive constant, force it into a register. */
2718 if (CONSTANT_P (x) && preserve_subexpressions_p () && rtx_cost (x, COMPARE) > 2)
2719 x = force_reg (mode, x);
2720
2721 if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2)
2722 y = force_reg (mode, y);
2723
2724 /* Don't let both operands fail to indicate the mode. */
2725 if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
2726 x = force_reg (mode, x);
2727
2728 /* Handle all BLKmode compares. */
2729
2730 if (mode == BLKmode)
2731 {
2732 emit_queue ();
2733 x = protect_from_queue (x, 0);
2734 y = protect_from_queue (y, 0);
2735
2736 if (size == 0)
2737 abort ();
2738 #ifdef HAVE_cmpstrqi
2739 if (HAVE_cmpstrqi
2740 && GET_CODE (size) == CONST_INT
2741 && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
2742 {
2743 enum machine_mode result_mode
2744 = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0];
2745 rtx result = gen_reg_rtx (result_mode);
2746 emit_insn (gen_cmpstrqi (result, x, y, size, GEN_INT (align)));
2747 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
2748 result_mode, 0, 0);
2749 }
2750 else
2751 #endif
2752 #ifdef HAVE_cmpstrhi
2753 if (HAVE_cmpstrhi
2754 && GET_CODE (size) == CONST_INT
2755 && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
2756 {
2757 enum machine_mode result_mode
2758 = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0];
2759 rtx result = gen_reg_rtx (result_mode);
2760 emit_insn (gen_cmpstrhi (result, x, y, size, GEN_INT (align)));
2761 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
2762 result_mode, 0, 0);
2763 }
2764 else
2765 #endif
2766 #ifdef HAVE_cmpstrsi
2767 if (HAVE_cmpstrsi)
2768 {
2769 enum machine_mode result_mode
2770 = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0];
2771 rtx result = gen_reg_rtx (result_mode);
2772 size = protect_from_queue (size, 0);
2773 emit_insn (gen_cmpstrsi (result, x, y,
2774 convert_to_mode (SImode, size, 1),
2775 GEN_INT (align)));
2776 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
2777 result_mode, 0, 0);
2778 }
2779 else
2780 #endif
2781 {
2782 rtx result;
2783
2784 #ifdef TARGET_MEM_FUNCTIONS
2785 emit_library_call (memcmp_libfunc, 0,
2786 TYPE_MODE (integer_type_node), 3,
2787 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
2788 convert_to_mode (TYPE_MODE (sizetype), size,
2789 TREE_UNSIGNED (sizetype)),
2790 TYPE_MODE (sizetype));
2791 #else
2792 emit_library_call (bcmp_libfunc, 0,
2793 TYPE_MODE (integer_type_node), 3,
2794 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
2795 convert_to_mode (TYPE_MODE (integer_type_node),
2796 size,
2797 TREE_UNSIGNED (integer_type_node)),
2798 TYPE_MODE (integer_type_node));
2799 #endif
2800
2801 /* Immediately move the result of the libcall into a pseudo
2802 register so reload doesn't clobber the value if it needs
2803 the return register for a spill reg. */
2804 result = gen_reg_rtx (TYPE_MODE (integer_type_node));
2805 emit_move_insn (result,
2806 hard_libcall_value (TYPE_MODE (integer_type_node)));
2807 emit_cmp_insn (result,
2808 const0_rtx, comparison, NULL_RTX,
2809 TYPE_MODE (integer_type_node), 0, 0);
2810 }
2811 return;
2812 }
2813
2814 /* Handle some compares against zero. */
2815
2816 if (y == CONST0_RTX (mode)
2817 && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2818 {
2819 int icode = (int) tst_optab->handlers[(int) mode].insn_code;
2820
2821 emit_queue ();
2822 x = protect_from_queue (x, 0);
2823 y = protect_from_queue (y, 0);
2824
2825 /* Now, if insn does accept these operands, put them into pseudos. */
2826 if (! (*insn_operand_predicate[icode][0])
2827 (x, insn_operand_mode[icode][0]))
2828 x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
2829
2830 emit_insn (GEN_FCN (icode) (x));
2831 return;
2832 }
2833
2834 /* Handle compares for which there is a directly suitable insn. */
2835
2836 if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2837 {
2838 int icode = (int) cmp_optab->handlers[(int) mode].insn_code;
2839
2840 emit_queue ();
2841 x = protect_from_queue (x, 0);
2842 y = protect_from_queue (y, 0);
2843
2844 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2845 if (! (*insn_operand_predicate[icode][0])
2846 (x, insn_operand_mode[icode][0]))
2847 x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
2848
2849 if (! (*insn_operand_predicate[icode][1])
2850 (y, insn_operand_mode[icode][1]))
2851 y = copy_to_mode_reg (insn_operand_mode[icode][1], y);
2852
2853 emit_insn (GEN_FCN (icode) (x, y));
2854 return;
2855 }
2856
2857 /* Try widening if we can find a direct insn that way. */
2858
2859 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
2860 {
2861 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2862 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2863 {
2864 if (cmp_optab->handlers[(int) wider_mode].insn_code
2865 != CODE_FOR_nothing)
2866 {
2867 x = protect_from_queue (x, 0);
2868 y = protect_from_queue (y, 0);
2869 x = convert_modes (wider_mode, mode, x, unsignedp);
2870 y = convert_modes (wider_mode, mode, y, unsignedp);
2871 emit_cmp_insn (x, y, comparison, NULL_RTX,
2872 wider_mode, unsignedp, align);
2873 return;
2874 }
2875 }
2876 }
2877
2878 /* Handle a lib call just for the mode we are using. */
2879
2880 if (cmp_optab->handlers[(int) mode].libfunc
2881 && class != MODE_FLOAT)
2882 {
2883 rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
2884 rtx result;
2885
2886 /* If we want unsigned, and this mode has a distinct unsigned
2887 comparison routine, use that. */
2888 if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
2889 libfunc = ucmp_optab->handlers[(int) mode].libfunc;
2890
2891 emit_library_call (libfunc, 1,
2892 word_mode, 2, x, mode, y, mode);
2893
2894 /* Immediately move the result of the libcall into a pseudo
2895 register so reload doesn't clobber the value if it needs
2896 the return register for a spill reg. */
2897 result = gen_reg_rtx (word_mode);
2898 emit_move_insn (result, hard_libcall_value (word_mode));
2899
2900 /* Integer comparison returns a result that must be compared against 1,
2901 so that even if we do an unsigned compare afterward,
2902 there is still a value that can represent the result "less than". */
2903 emit_cmp_insn (result, const1_rtx,
2904 comparison, NULL_RTX, word_mode, unsignedp, 0);
2905 return;
2906 }
2907
2908 if (class == MODE_FLOAT)
2909 emit_float_lib_cmp (x, y, comparison);
2910
2911 else
2912 abort ();
2913 }
2914
2915 /* Nonzero if a compare of mode MODE can be done straightforwardly
2916 (without splitting it into pieces). */
2917
2918 int
2919 can_compare_p (mode)
2920 enum machine_mode mode;
2921 {
2922 do
2923 {
2924 if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
2925 return 1;
2926 mode = GET_MODE_WIDER_MODE (mode);
2927 } while (mode != VOIDmode);
2928
2929 return 0;
2930 }
2931 \f
2932 /* Emit a library call comparison between floating point X and Y.
2933 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
2934
2935 void
2936 emit_float_lib_cmp (x, y, comparison)
2937 rtx x, y;
2938 enum rtx_code comparison;
2939 {
2940 enum machine_mode mode = GET_MODE (x);
2941 rtx libfunc = 0;
2942 rtx result;
2943
2944 if (mode == HFmode)
2945 switch (comparison)
2946 {
2947 case EQ:
2948 libfunc = eqhf2_libfunc;
2949 break;
2950
2951 case NE:
2952 libfunc = nehf2_libfunc;
2953 break;
2954
2955 case GT:
2956 libfunc = gthf2_libfunc;
2957 break;
2958
2959 case GE:
2960 libfunc = gehf2_libfunc;
2961 break;
2962
2963 case LT:
2964 libfunc = lthf2_libfunc;
2965 break;
2966
2967 case LE:
2968 libfunc = lehf2_libfunc;
2969 break;
2970
2971 default:
2972 break;
2973 }
2974 else if (mode == SFmode)
2975 switch (comparison)
2976 {
2977 case EQ:
2978 libfunc = eqsf2_libfunc;
2979 break;
2980
2981 case NE:
2982 libfunc = nesf2_libfunc;
2983 break;
2984
2985 case GT:
2986 libfunc = gtsf2_libfunc;
2987 break;
2988
2989 case GE:
2990 libfunc = gesf2_libfunc;
2991 break;
2992
2993 case LT:
2994 libfunc = ltsf2_libfunc;
2995 break;
2996
2997 case LE:
2998 libfunc = lesf2_libfunc;
2999 break;
3000
3001 default:
3002 break;
3003 }
3004 else if (mode == DFmode)
3005 switch (comparison)
3006 {
3007 case EQ:
3008 libfunc = eqdf2_libfunc;
3009 break;
3010
3011 case NE:
3012 libfunc = nedf2_libfunc;
3013 break;
3014
3015 case GT:
3016 libfunc = gtdf2_libfunc;
3017 break;
3018
3019 case GE:
3020 libfunc = gedf2_libfunc;
3021 break;
3022
3023 case LT:
3024 libfunc = ltdf2_libfunc;
3025 break;
3026
3027 case LE:
3028 libfunc = ledf2_libfunc;
3029 break;
3030
3031 default:
3032 break;
3033 }
3034 else if (mode == XFmode)
3035 switch (comparison)
3036 {
3037 case EQ:
3038 libfunc = eqxf2_libfunc;
3039 break;
3040
3041 case NE:
3042 libfunc = nexf2_libfunc;
3043 break;
3044
3045 case GT:
3046 libfunc = gtxf2_libfunc;
3047 break;
3048
3049 case GE:
3050 libfunc = gexf2_libfunc;
3051 break;
3052
3053 case LT:
3054 libfunc = ltxf2_libfunc;
3055 break;
3056
3057 case LE:
3058 libfunc = lexf2_libfunc;
3059 break;
3060
3061 default:
3062 break;
3063 }
3064 else if (mode == TFmode)
3065 switch (comparison)
3066 {
3067 case EQ:
3068 libfunc = eqtf2_libfunc;
3069 break;
3070
3071 case NE:
3072 libfunc = netf2_libfunc;
3073 break;
3074
3075 case GT:
3076 libfunc = gttf2_libfunc;
3077 break;
3078
3079 case GE:
3080 libfunc = getf2_libfunc;
3081 break;
3082
3083 case LT:
3084 libfunc = lttf2_libfunc;
3085 break;
3086
3087 case LE:
3088 libfunc = letf2_libfunc;
3089 break;
3090
3091 default:
3092 break;
3093 }
3094 else
3095 {
3096 enum machine_mode wider_mode;
3097
3098 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
3099 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3100 {
3101 if ((cmp_optab->handlers[(int) wider_mode].insn_code
3102 != CODE_FOR_nothing)
3103 || (cmp_optab->handlers[(int) wider_mode].libfunc != 0))
3104 {
3105 x = protect_from_queue (x, 0);
3106 y = protect_from_queue (y, 0);
3107 x = convert_to_mode (wider_mode, x, 0);
3108 y = convert_to_mode (wider_mode, y, 0);
3109 emit_float_lib_cmp (x, y, comparison);
3110 return;
3111 }
3112 }
3113 abort ();
3114 }
3115
3116 if (libfunc == 0)
3117 abort ();
3118
3119 emit_library_call (libfunc, 1,
3120 word_mode, 2, x, mode, y, mode);
3121
3122 /* Immediately move the result of the libcall into a pseudo
3123 register so reload doesn't clobber the value if it needs
3124 the return register for a spill reg. */
3125 result = gen_reg_rtx (word_mode);
3126 emit_move_insn (result, hard_libcall_value (word_mode));
3127
3128 emit_cmp_insn (result, const0_rtx, comparison,
3129 NULL_RTX, word_mode, 0, 0);
3130 }
3131 \f
3132 /* Generate code to indirectly jump to a location given in the rtx LOC. */
3133
3134 void
3135 emit_indirect_jump (loc)
3136 rtx loc;
3137 {
3138 if (! ((*insn_operand_predicate[(int)CODE_FOR_indirect_jump][0])
3139 (loc, Pmode)))
3140 loc = copy_to_mode_reg (Pmode, loc);
3141
3142 emit_jump_insn (gen_indirect_jump (loc));
3143 emit_barrier ();
3144 }
3145 \f
3146 #ifdef HAVE_conditional_move
3147
3148 /* Emit a conditional move instruction if the machine supports one for that
3149 condition and machine mode.
3150
3151 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
3152 the mode to use should they be constants. If it is VOIDmode, they cannot
3153 both be constants.
3154
3155 OP2 should be stored in TARGET if the comparison is true, otherwise OP3
3156 should be stored there. MODE is the mode to use should they be constants.
3157 If it is VOIDmode, they cannot both be constants.
3158
3159 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
3160 is not supported. */
3161
3162 rtx
3163 emit_conditional_move (target, code, op0, op1, cmode, op2, op3, mode,
3164 unsignedp)
3165 rtx target;
3166 enum rtx_code code;
3167 rtx op0, op1;
3168 enum machine_mode cmode;
3169 rtx op2, op3;
3170 enum machine_mode mode;
3171 int unsignedp;
3172 {
3173 rtx tem, subtarget, comparison, insn;
3174 enum insn_code icode;
3175
3176 /* If one operand is constant, make it the second one. Only do this
3177 if the other operand is not constant as well. */
3178
3179 if ((CONSTANT_P (op0) && ! CONSTANT_P (op1))
3180 || (GET_CODE (op0) == CONST_INT && GET_CODE (op1) != CONST_INT))
3181 {
3182 tem = op0;
3183 op0 = op1;
3184 op1 = tem;
3185 code = swap_condition (code);
3186 }
3187
3188 if (cmode == VOIDmode)
3189 cmode = GET_MODE (op0);
3190
3191 if (((CONSTANT_P (op2) && ! CONSTANT_P (op3))
3192 || (GET_CODE (op2) == CONST_INT && GET_CODE (op3) != CONST_INT))
3193 && (GET_MODE_CLASS (GET_MODE (op1)) != MODE_FLOAT
3194 || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT || flag_fast_math))
3195 {
3196 tem = op2;
3197 op2 = op3;
3198 op3 = tem;
3199 code = reverse_condition (code);
3200 }
3201
3202 if (mode == VOIDmode)
3203 mode = GET_MODE (op2);
3204
3205 icode = movcc_gen_code[mode];
3206
3207 if (icode == CODE_FOR_nothing)
3208 return 0;
3209
3210 if (flag_force_mem)
3211 {
3212 op2 = force_not_mem (op2);
3213 op3 = force_not_mem (op3);
3214 }
3215
3216 if (target)
3217 target = protect_from_queue (target, 1);
3218 else
3219 target = gen_reg_rtx (mode);
3220
3221 subtarget = target;
3222
3223 emit_queue ();
3224
3225 op2 = protect_from_queue (op2, 0);
3226 op3 = protect_from_queue (op3, 0);
3227
3228 /* If the insn doesn't accept these operands, put them in pseudos. */
3229
3230 if (! (*insn_operand_predicate[icode][0])
3231 (subtarget, insn_operand_mode[icode][0]))
3232 subtarget = gen_reg_rtx (insn_operand_mode[icode][0]);
3233
3234 if (! (*insn_operand_predicate[icode][2])
3235 (op2, insn_operand_mode[icode][2]))
3236 op2 = copy_to_mode_reg (insn_operand_mode[icode][2], op2);
3237
3238 if (! (*insn_operand_predicate[icode][3])
3239 (op3, insn_operand_mode[icode][3]))
3240 op3 = copy_to_mode_reg (insn_operand_mode[icode][3], op3);
3241
3242 /* Everything should now be in the suitable form, so emit the compare insn
3243 and then the conditional move. */
3244
3245 comparison
3246 = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX, 0);
3247
3248 /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)? */
3249 if (GET_CODE (comparison) != code)
3250 /* This shouldn't happen. */
3251 abort ();
3252
3253 insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
3254
3255 /* If that failed, then give up. */
3256 if (insn == 0)
3257 return 0;
3258
3259 emit_insn (insn);
3260
3261 if (subtarget != target)
3262 convert_move (target, subtarget, 0);
3263
3264 return target;
3265 }
3266
3267 /* Return non-zero if a conditional move of mode MODE is supported.
3268
3269 This function is for combine so it can tell whether an insn that looks
3270 like a conditional move is actually supported by the hardware. If we
3271 guess wrong we lose a bit on optimization, but that's it. */
3272 /* ??? sparc64 supports conditionally moving integers values based on fp
3273 comparisons, and vice versa. How do we handle them? */
3274
3275 int
3276 can_conditionally_move_p (mode)
3277 enum machine_mode mode;
3278 {
3279 if (movcc_gen_code[mode] != CODE_FOR_nothing)
3280 return 1;
3281
3282 return 0;
3283 }
3284
3285 #endif /* HAVE_conditional_move */
3286 \f
3287 /* These three functions generate an insn body and return it
3288 rather than emitting the insn.
3289
3290 They do not protect from queued increments,
3291 because they may be used 1) in protect_from_queue itself
3292 and 2) in other passes where there is no queue. */
3293
3294 /* Generate and return an insn body to add Y to X. */
3295
3296 rtx
3297 gen_add2_insn (x, y)
3298 rtx x, y;
3299 {
3300 int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code;
3301
3302 if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
3303 || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
3304 || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
3305 abort ();
3306
3307 return (GEN_FCN (icode) (x, x, y));
3308 }
3309
3310 int
3311 have_add2_insn (mode)
3312 enum machine_mode mode;
3313 {
3314 return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
3315 }
3316
3317 /* Generate and return an insn body to subtract Y from X. */
3318
3319 rtx
3320 gen_sub2_insn (x, y)
3321 rtx x, y;
3322 {
3323 int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code;
3324
3325 if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
3326 || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
3327 || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
3328 abort ();
3329
3330 return (GEN_FCN (icode) (x, x, y));
3331 }
3332
3333 int
3334 have_sub2_insn (mode)
3335 enum machine_mode mode;
3336 {
3337 return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
3338 }
3339
3340 /* Generate the body of an instruction to copy Y into X.
3341 It may be a SEQUENCE, if one insn isn't enough. */
3342
3343 rtx
3344 gen_move_insn (x, y)
3345 rtx x, y;
3346 {
3347 register enum machine_mode mode = GET_MODE (x);
3348 enum insn_code insn_code;
3349 rtx seq;
3350
3351 if (mode == VOIDmode)
3352 mode = GET_MODE (y);
3353
3354 insn_code = mov_optab->handlers[(int) mode].insn_code;
3355
3356 /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
3357 find a mode to do it in. If we have a movcc, use it. Otherwise,
3358 find the MODE_INT mode of the same width. */
3359
3360 if (GET_MODE_CLASS (mode) == MODE_CC && insn_code == CODE_FOR_nothing)
3361 {
3362 enum machine_mode tmode = VOIDmode;
3363 rtx x1 = x, y1 = y;
3364
3365 if (mode != CCmode
3366 && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing)
3367 tmode = CCmode;
3368 else
3369 for (tmode = QImode; tmode != VOIDmode;
3370 tmode = GET_MODE_WIDER_MODE (tmode))
3371 if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode))
3372 break;
3373
3374 if (tmode == VOIDmode)
3375 abort ();
3376
3377 /* Get X and Y in TMODE. We can't use gen_lowpart here because it
3378 may call change_address which is not appropriate if we were
3379 called when a reload was in progress. We don't have to worry
3380 about changing the address since the size in bytes is supposed to
3381 be the same. Copy the MEM to change the mode and move any
3382 substitutions from the old MEM to the new one. */
3383
3384 if (reload_in_progress)
3385 {
3386 x = gen_lowpart_common (tmode, x1);
3387 if (x == 0 && GET_CODE (x1) == MEM)
3388 {
3389 x = gen_rtx_MEM (tmode, XEXP (x1, 0));
3390 RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1);
3391 MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (x1);
3392 MEM_VOLATILE_P (x) = MEM_VOLATILE_P (x1);
3393 copy_replacements (x1, x);
3394 }
3395
3396 y = gen_lowpart_common (tmode, y1);
3397 if (y == 0 && GET_CODE (y1) == MEM)
3398 {
3399 y = gen_rtx_MEM (tmode, XEXP (y1, 0));
3400 RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1);
3401 MEM_IN_STRUCT_P (y) = MEM_IN_STRUCT_P (y1);
3402 MEM_VOLATILE_P (y) = MEM_VOLATILE_P (y1);
3403 copy_replacements (y1, y);
3404 }
3405 }
3406 else
3407 {
3408 x = gen_lowpart (tmode, x);
3409 y = gen_lowpart (tmode, y);
3410 }
3411
3412 insn_code = mov_optab->handlers[(int) tmode].insn_code;
3413 return (GEN_FCN (insn_code) (x, y));
3414 }
3415
3416 start_sequence ();
3417 emit_move_insn_1 (x, y);
3418 seq = gen_sequence ();
3419 end_sequence ();
3420 return seq;
3421 }
3422 \f
3423 /* Return the insn code used to extend FROM_MODE to TO_MODE.
3424 UNSIGNEDP specifies zero-extension instead of sign-extension. If
3425 no such operation exists, CODE_FOR_nothing will be returned. */
3426
3427 enum insn_code
3428 can_extend_p (to_mode, from_mode, unsignedp)
3429 enum machine_mode to_mode, from_mode;
3430 int unsignedp;
3431 {
3432 return extendtab[(int) to_mode][(int) from_mode][unsignedp];
3433 }
3434
3435 /* Generate the body of an insn to extend Y (with mode MFROM)
3436 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
3437
3438 rtx
3439 gen_extend_insn (x, y, mto, mfrom, unsignedp)
3440 rtx x, y;
3441 enum machine_mode mto, mfrom;
3442 int unsignedp;
3443 {
3444 return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp]) (x, y));
3445 }
3446 \f
3447 /* can_fix_p and can_float_p say whether the target machine
3448 can directly convert a given fixed point type to
3449 a given floating point type, or vice versa.
3450 The returned value is the CODE_FOR_... value to use,
3451 or CODE_FOR_nothing if these modes cannot be directly converted.
3452
3453 *TRUNCP_PTR is set to 1 if it is necessary to output
3454 an explicit FTRUNC insn before the fix insn; otherwise 0. */
3455
3456 static enum insn_code
3457 can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
3458 enum machine_mode fltmode, fixmode;
3459 int unsignedp;
3460 int *truncp_ptr;
3461 {
3462 *truncp_ptr = 0;
3463 if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp] != CODE_FOR_nothing)
3464 return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp];
3465
3466 if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
3467 {
3468 *truncp_ptr = 1;
3469 return fixtab[(int) fltmode][(int) fixmode][unsignedp];
3470 }
3471 return CODE_FOR_nothing;
3472 }
3473
3474 static enum insn_code
3475 can_float_p (fltmode, fixmode, unsignedp)
3476 enum machine_mode fixmode, fltmode;
3477 int unsignedp;
3478 {
3479 return floattab[(int) fltmode][(int) fixmode][unsignedp];
3480 }
3481 \f
3482 /* Generate code to convert FROM to floating point
3483 and store in TO. FROM must be fixed point and not VOIDmode.
3484 UNSIGNEDP nonzero means regard FROM as unsigned.
3485 Normally this is done by correcting the final value
3486 if it is negative. */
3487
3488 void
3489 expand_float (to, from, unsignedp)
3490 rtx to, from;
3491 int unsignedp;
3492 {
3493 enum insn_code icode;
3494 register rtx target = to;
3495 enum machine_mode fmode, imode;
3496
3497 /* Crash now, because we won't be able to decide which mode to use. */
3498 if (GET_MODE (from) == VOIDmode)
3499 abort ();
3500
3501 /* Look for an insn to do the conversion. Do it in the specified
3502 modes if possible; otherwise convert either input, output or both to
3503 wider mode. If the integer mode is wider than the mode of FROM,
3504 we can do the conversion signed even if the input is unsigned. */
3505
3506 for (imode = GET_MODE (from); imode != VOIDmode;
3507 imode = GET_MODE_WIDER_MODE (imode))
3508 for (fmode = GET_MODE (to); fmode != VOIDmode;
3509 fmode = GET_MODE_WIDER_MODE (fmode))
3510 {
3511 int doing_unsigned = unsignedp;
3512
3513 icode = can_float_p (fmode, imode, unsignedp);
3514 if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
3515 icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;
3516
3517 if (icode != CODE_FOR_nothing)
3518 {
3519 to = protect_from_queue (to, 1);
3520 from = protect_from_queue (from, 0);
3521
3522 if (imode != GET_MODE (from))
3523 from = convert_to_mode (imode, from, unsignedp);
3524
3525 if (fmode != GET_MODE (to))
3526 target = gen_reg_rtx (fmode);
3527
3528 emit_unop_insn (icode, target, from,
3529 doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
3530
3531 if (target != to)
3532 convert_move (to, target, 0);
3533 return;
3534 }
3535 }
3536
3537 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3538
3539 /* Unsigned integer, and no way to convert directly.
3540 Convert as signed, then conditionally adjust the result. */
3541 if (unsignedp)
3542 {
3543 rtx label = gen_label_rtx ();
3544 rtx temp;
3545 REAL_VALUE_TYPE offset;
3546
3547 emit_queue ();
3548
3549 to = protect_from_queue (to, 1);
3550 from = protect_from_queue (from, 0);
3551
3552 if (flag_force_mem)
3553 from = force_not_mem (from);
3554
3555 /* Look for a usable floating mode FMODE wider than the source and at
3556 least as wide as the target. Using FMODE will avoid rounding woes
3557 with unsigned values greater than the signed maximum value. */
3558
3559 for (fmode = GET_MODE (to); fmode != VOIDmode;
3560 fmode = GET_MODE_WIDER_MODE (fmode))
3561 if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
3562 && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
3563 break;
3564
3565 if (fmode == VOIDmode)
3566 {
3567 /* There is no such mode. Pretend the target is wide enough. */
3568 fmode = GET_MODE (to);
3569
3570 /* Avoid double-rounding when TO is narrower than FROM. */
3571 if ((significand_size (fmode) + 1)
3572 < GET_MODE_BITSIZE (GET_MODE (from)))
3573 {
3574 rtx temp1;
3575 rtx neglabel = gen_label_rtx ();
3576
3577 /* Don't use TARGET if it isn't a register, is a hard register,
3578 or is the wrong mode. */
3579 if (GET_CODE (target) != REG
3580 || REGNO (target) < FIRST_PSEUDO_REGISTER
3581 || GET_MODE (target) != fmode)
3582 target = gen_reg_rtx (fmode);
3583
3584 imode = GET_MODE (from);
3585 do_pending_stack_adjust ();
3586
3587 /* Test whether the sign bit is set. */
3588 emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, imode, 0, 0);
3589 emit_jump_insn (gen_blt (neglabel));
3590
3591 /* The sign bit is not set. Convert as signed. */
3592 expand_float (target, from, 0);
3593 emit_jump_insn (gen_jump (label));
3594 emit_barrier ();
3595
3596 /* The sign bit is set.
3597 Convert to a usable (positive signed) value by shifting right
3598 one bit, while remembering if a nonzero bit was shifted
3599 out; i.e., compute (from & 1) | (from >> 1). */
3600
3601 emit_label (neglabel);
3602 temp = expand_binop (imode, and_optab, from, const1_rtx,
3603 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3604 temp1 = expand_shift (RSHIFT_EXPR, imode, from, integer_one_node,
3605 NULL_RTX, 1);
3606 temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1,
3607 OPTAB_LIB_WIDEN);
3608 expand_float (target, temp, 0);
3609
3610 /* Multiply by 2 to undo the shift above. */
3611 temp = expand_binop (fmode, add_optab, target, target,
3612 target, 0, OPTAB_LIB_WIDEN);
3613 if (temp != target)
3614 emit_move_insn (target, temp);
3615
3616 do_pending_stack_adjust ();
3617 emit_label (label);
3618 goto done;
3619 }
3620 }
3621
3622 /* If we are about to do some arithmetic to correct for an
3623 unsigned operand, do it in a pseudo-register. */
3624
3625 if (GET_MODE (to) != fmode
3626 || GET_CODE (to) != REG || REGNO (to) < FIRST_PSEUDO_REGISTER)
3627 target = gen_reg_rtx (fmode);
3628
3629 /* Convert as signed integer to floating. */
3630 expand_float (target, from, 0);
3631
3632 /* If FROM is negative (and therefore TO is negative),
3633 correct its value by 2**bitwidth. */
3634
3635 do_pending_stack_adjust ();
3636 emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, GET_MODE (from), 0, 0);
3637 emit_jump_insn (gen_bge (label));
3638
3639 /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
3640 Rather than setting up a dconst_dot_5, let's hope SCO
3641 fixes the bug. */
3642 offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from)));
3643 temp = expand_binop (fmode, add_optab, target,
3644 CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
3645 target, 0, OPTAB_LIB_WIDEN);
3646 if (temp != target)
3647 emit_move_insn (target, temp);
3648
3649 do_pending_stack_adjust ();
3650 emit_label (label);
3651 goto done;
3652 }
3653 #endif
3654
3655 /* No hardware instruction available; call a library routine to convert from
3656 SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */
3657 {
3658 rtx libfcn;
3659 rtx insns;
3660 rtx value;
3661
3662 to = protect_from_queue (to, 1);
3663 from = protect_from_queue (from, 0);
3664
3665 if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
3666 from = convert_to_mode (SImode, from, unsignedp);
3667
3668 if (flag_force_mem)
3669 from = force_not_mem (from);
3670
3671 if (GET_MODE (to) == SFmode)
3672 {
3673 if (GET_MODE (from) == SImode)
3674 libfcn = floatsisf_libfunc;
3675 else if (GET_MODE (from) == DImode)
3676 libfcn = floatdisf_libfunc;
3677 else if (GET_MODE (from) == TImode)
3678 libfcn = floattisf_libfunc;
3679 else
3680 abort ();
3681 }
3682 else if (GET_MODE (to) == DFmode)
3683 {
3684 if (GET_MODE (from) == SImode)
3685 libfcn = floatsidf_libfunc;
3686 else if (GET_MODE (from) == DImode)
3687 libfcn = floatdidf_libfunc;
3688 else if (GET_MODE (from) == TImode)
3689 libfcn = floattidf_libfunc;
3690 else
3691 abort ();
3692 }
3693 else if (GET_MODE (to) == XFmode)
3694 {
3695 if (GET_MODE (from) == SImode)
3696 libfcn = floatsixf_libfunc;
3697 else if (GET_MODE (from) == DImode)
3698 libfcn = floatdixf_libfunc;
3699 else if (GET_MODE (from) == TImode)
3700 libfcn = floattixf_libfunc;
3701 else
3702 abort ();
3703 }
3704 else if (GET_MODE (to) == TFmode)
3705 {
3706 if (GET_MODE (from) == SImode)
3707 libfcn = floatsitf_libfunc;
3708 else if (GET_MODE (from) == DImode)
3709 libfcn = floatditf_libfunc;
3710 else if (GET_MODE (from) == TImode)
3711 libfcn = floattitf_libfunc;
3712 else
3713 abort ();
3714 }
3715 else
3716 abort ();
3717
3718 start_sequence ();
3719
3720 value = emit_library_call_value (libfcn, NULL_RTX, 1,
3721 GET_MODE (to),
3722 1, from, GET_MODE (from));
3723 insns = get_insns ();
3724 end_sequence ();
3725
3726 emit_libcall_block (insns, target, value,
3727 gen_rtx_FLOAT (GET_MODE (to), from));
3728 }
3729
3730 done:
3731
3732 /* Copy result to requested destination
3733 if we have been computing in a temp location. */
3734
3735 if (target != to)
3736 {
3737 if (GET_MODE (target) == GET_MODE (to))
3738 emit_move_insn (to, target);
3739 else
3740 convert_move (to, target, 0);
3741 }
3742 }
3743 \f
3744 /* expand_fix: generate code to convert FROM to fixed point
3745 and store in TO. FROM must be floating point. */
3746
3747 static rtx
3748 ftruncify (x)
3749 rtx x;
3750 {
3751 rtx temp = gen_reg_rtx (GET_MODE (x));
3752 return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0);
3753 }
3754
3755 void
3756 expand_fix (to, from, unsignedp)
3757 register rtx to, from;
3758 int unsignedp;
3759 {
3760 enum insn_code icode;
3761 register rtx target = to;
3762 enum machine_mode fmode, imode;
3763 int must_trunc = 0;
3764 rtx libfcn = 0;
3765
3766 /* We first try to find a pair of modes, one real and one integer, at
3767 least as wide as FROM and TO, respectively, in which we can open-code
3768 this conversion. If the integer mode is wider than the mode of TO,
3769 we can do the conversion either signed or unsigned. */
3770
3771 for (imode = GET_MODE (to); imode != VOIDmode;
3772 imode = GET_MODE_WIDER_MODE (imode))
3773 for (fmode = GET_MODE (from); fmode != VOIDmode;
3774 fmode = GET_MODE_WIDER_MODE (fmode))
3775 {
3776 int doing_unsigned = unsignedp;
3777
3778 icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
3779 if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
3780 icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
3781
3782 if (icode != CODE_FOR_nothing)
3783 {
3784 to = protect_from_queue (to, 1);
3785 from = protect_from_queue (from, 0);
3786
3787 if (fmode != GET_MODE (from))
3788 from = convert_to_mode (fmode, from, 0);
3789
3790 if (must_trunc)
3791 from = ftruncify (from);
3792
3793 if (imode != GET_MODE (to))
3794 target = gen_reg_rtx (imode);
3795
3796 emit_unop_insn (icode, target, from,
3797 doing_unsigned ? UNSIGNED_FIX : FIX);
3798 if (target != to)
3799 convert_move (to, target, unsignedp);
3800 return;
3801 }
3802 }
3803
3804 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3805 /* For an unsigned conversion, there is one more way to do it.
3806 If we have a signed conversion, we generate code that compares
3807 the real value to the largest representable positive number. If if
3808 is smaller, the conversion is done normally. Otherwise, subtract
3809 one plus the highest signed number, convert, and add it back.
3810
3811 We only need to check all real modes, since we know we didn't find
3812 anything with a wider integer mode. */
3813
3814 if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
3815 for (fmode = GET_MODE (from); fmode != VOIDmode;
3816 fmode = GET_MODE_WIDER_MODE (fmode))
3817 /* Make sure we won't lose significant bits doing this. */
3818 if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))
3819 && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
3820 &must_trunc))
3821 {
3822 int bitsize;
3823 REAL_VALUE_TYPE offset;
3824 rtx limit, lab1, lab2, insn;
3825
3826 bitsize = GET_MODE_BITSIZE (GET_MODE (to));
3827 offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1);
3828 limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
3829 lab1 = gen_label_rtx ();
3830 lab2 = gen_label_rtx ();
3831
3832 emit_queue ();
3833 to = protect_from_queue (to, 1);
3834 from = protect_from_queue (from, 0);
3835
3836 if (flag_force_mem)
3837 from = force_not_mem (from);
3838
3839 if (fmode != GET_MODE (from))
3840 from = convert_to_mode (fmode, from, 0);
3841
3842 /* See if we need to do the subtraction. */
3843 do_pending_stack_adjust ();
3844 emit_cmp_insn (from, limit, GE, NULL_RTX, GET_MODE (from), 0, 0);
3845 emit_jump_insn (gen_bge (lab1));
3846
3847 /* If not, do the signed "fix" and branch around fixup code. */
3848 expand_fix (to, from, 0);
3849 emit_jump_insn (gen_jump (lab2));
3850 emit_barrier ();
3851
3852 /* Otherwise, subtract 2**(N-1), convert to signed number,
3853 then add 2**(N-1). Do the addition using XOR since this
3854 will often generate better code. */
3855 emit_label (lab1);
3856 target = expand_binop (GET_MODE (from), sub_optab, from, limit,
3857 NULL_RTX, 0, OPTAB_LIB_WIDEN);
3858 expand_fix (to, target, 0);
3859 target = expand_binop (GET_MODE (to), xor_optab, to,
3860 GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)),
3861 to, 1, OPTAB_LIB_WIDEN);
3862
3863 if (target != to)
3864 emit_move_insn (to, target);
3865
3866 emit_label (lab2);
3867
3868 if (mov_optab->handlers[(int) GET_MODE (to)].insn_code
3869 != CODE_FOR_nothing)
3870 {
3871 /* Make a place for a REG_NOTE and add it. */
3872 insn = emit_move_insn (to, to);
3873 REG_NOTES (insn)
3874 = gen_rtx_EXPR_LIST (REG_EQUAL,
3875 gen_rtx_fmt_e (UNSIGNED_FIX,
3876 GET_MODE (to),
3877 copy_rtx (from)),
3878 REG_NOTES (insn));
3879 }
3880 return;
3881 }
3882 #endif
3883
3884 /* We can't do it with an insn, so use a library call. But first ensure
3885 that the mode of TO is at least as wide as SImode, since those are the
3886 only library calls we know about. */
3887
3888 if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
3889 {
3890 target = gen_reg_rtx (SImode);
3891
3892 expand_fix (target, from, unsignedp);
3893 }
3894 else if (GET_MODE (from) == SFmode)
3895 {
3896 if (GET_MODE (to) == SImode)
3897 libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc;
3898 else if (GET_MODE (to) == DImode)
3899 libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc;
3900 else if (GET_MODE (to) == TImode)
3901 libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc;
3902 else
3903 abort ();
3904 }
3905 else if (GET_MODE (from) == DFmode)
3906 {
3907 if (GET_MODE (to) == SImode)
3908 libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc;
3909 else if (GET_MODE (to) == DImode)
3910 libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc;
3911 else if (GET_MODE (to) == TImode)
3912 libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc;
3913 else
3914 abort ();
3915 }
3916 else if (GET_MODE (from) == XFmode)
3917 {
3918 if (GET_MODE (to) == SImode)
3919 libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc;
3920 else if (GET_MODE (to) == DImode)
3921 libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc;
3922 else if (GET_MODE (to) == TImode)
3923 libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc;
3924 else
3925 abort ();
3926 }
3927 else if (GET_MODE (from) == TFmode)
3928 {
3929 if (GET_MODE (to) == SImode)
3930 libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc;
3931 else if (GET_MODE (to) == DImode)
3932 libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc;
3933 else if (GET_MODE (to) == TImode)
3934 libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc;
3935 else
3936 abort ();
3937 }
3938 else
3939 abort ();
3940
3941 if (libfcn)
3942 {
3943 rtx insns;
3944 rtx value;
3945
3946 to = protect_from_queue (to, 1);
3947 from = protect_from_queue (from, 0);
3948
3949 if (flag_force_mem)
3950 from = force_not_mem (from);
3951
3952 start_sequence ();
3953
3954 value = emit_library_call_value (libfcn, NULL_RTX, 1, GET_MODE (to),
3955
3956 1, from, GET_MODE (from));
3957 insns = get_insns ();
3958 end_sequence ();
3959
3960 emit_libcall_block (insns, target, value,
3961 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX,
3962 GET_MODE (to), from));
3963 }
3964
3965 if (target != to)
3966 {
3967 if (GET_MODE (to) == GET_MODE (target))
3968 emit_move_insn (to, target);
3969 else
3970 convert_move (to, target, 0);
3971 }
3972 }
3973 \f
3974 static optab
3975 init_optab (code)
3976 enum rtx_code code;
3977 {
3978 int i;
3979 optab op = (optab) xmalloc (sizeof (struct optab));
3980 op->code = code;
3981 for (i = 0; i < NUM_MACHINE_MODES; i++)
3982 {
3983 op->handlers[i].insn_code = CODE_FOR_nothing;
3984 op->handlers[i].libfunc = 0;
3985 }
3986
3987 if (code != UNKNOWN)
3988 code_to_optab[(int) code] = op;
3989
3990 return op;
3991 }
3992
3993 /* Initialize the libfunc fields of an entire group of entries in some
3994 optab. Each entry is set equal to a string consisting of a leading
3995 pair of underscores followed by a generic operation name followed by
3996 a mode name (downshifted to lower case) followed by a single character
3997 representing the number of operands for the given operation (which is
3998 usually one of the characters '2', '3', or '4').
3999
4000 OPTABLE is the table in which libfunc fields are to be initialized.
4001 FIRST_MODE is the first machine mode index in the given optab to
4002 initialize.
4003 LAST_MODE is the last machine mode index in the given optab to
4004 initialize.
4005 OPNAME is the generic (string) name of the operation.
4006 SUFFIX is the character which specifies the number of operands for
4007 the given generic operation.
4008 */
4009
4010 static void
4011 init_libfuncs (optable, first_mode, last_mode, opname, suffix)
4012 register optab optable;
4013 register int first_mode;
4014 register int last_mode;
4015 register char *opname;
4016 register int suffix;
4017 {
4018 register int mode;
4019 register unsigned opname_len = strlen (opname);
4020
4021 for (mode = first_mode; (int) mode <= (int) last_mode;
4022 mode = (enum machine_mode) ((int) mode + 1))
4023 {
4024 register char *mname = mode_name[(int) mode];
4025 register unsigned mname_len = strlen (mname);
4026 register char *libfunc_name
4027 = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1);
4028 register char *p;
4029 register char *q;
4030
4031 p = libfunc_name;
4032 *p++ = '_';
4033 *p++ = '_';
4034 for (q = opname; *q; )
4035 *p++ = *q++;
4036 for (q = mname; *q; q++)
4037 *p++ = tolower (*q);
4038 *p++ = suffix;
4039 *p++ = '\0';
4040 optable->handlers[(int) mode].libfunc
4041 = gen_rtx_SYMBOL_REF (Pmode, libfunc_name);
4042 }
4043 }
4044
4045 /* Initialize the libfunc fields of an entire group of entries in some
4046 optab which correspond to all integer mode operations. The parameters
4047 have the same meaning as similarly named ones for the `init_libfuncs'
4048 routine. (See above). */
4049
4050 static void
4051 init_integral_libfuncs (optable, opname, suffix)
4052 register optab optable;
4053 register char *opname;
4054 register int suffix;
4055 {
4056 init_libfuncs (optable, SImode, TImode, opname, suffix);
4057 }
4058
4059 /* Initialize the libfunc fields of an entire group of entries in some
4060 optab which correspond to all real mode operations. The parameters
4061 have the same meaning as similarly named ones for the `init_libfuncs'
4062 routine. (See above). */
4063
4064 static void
4065 init_floating_libfuncs (optable, opname, suffix)
4066 register optab optable;
4067 register char *opname;
4068 register int suffix;
4069 {
4070 init_libfuncs (optable, SFmode, TFmode, opname, suffix);
4071 }
4072
4073
4074 /* Call this once to initialize the contents of the optabs
4075 appropriately for the current target machine. */
4076
4077 void
4078 init_optabs ()
4079 {
4080 int i;
4081 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
4082 int j;
4083 #endif
4084
4085 enum insn_code *p;
4086
4087 /* Start by initializing all tables to contain CODE_FOR_nothing. */
4088
4089 for (p = fixtab[0][0];
4090 p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]);
4091 p++)
4092 *p = CODE_FOR_nothing;
4093
4094 for (p = fixtrunctab[0][0];
4095 p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]);
4096 p++)
4097 *p = CODE_FOR_nothing;
4098
4099 for (p = floattab[0][0];
4100 p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]);
4101 p++)
4102 *p = CODE_FOR_nothing;
4103
4104 for (p = extendtab[0][0];
4105 p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0];
4106 p++)
4107 *p = CODE_FOR_nothing;
4108
4109 for (i = 0; i < NUM_RTX_CODE; i++)
4110 setcc_gen_code[i] = CODE_FOR_nothing;
4111
4112 #ifdef HAVE_conditional_move
4113 for (i = 0; i < NUM_MACHINE_MODES; i++)
4114 movcc_gen_code[i] = CODE_FOR_nothing;
4115 #endif
4116
4117 add_optab = init_optab (PLUS);
4118 sub_optab = init_optab (MINUS);
4119 smul_optab = init_optab (MULT);
4120 smul_highpart_optab = init_optab (UNKNOWN);
4121 umul_highpart_optab = init_optab (UNKNOWN);
4122 smul_widen_optab = init_optab (UNKNOWN);
4123 umul_widen_optab = init_optab (UNKNOWN);
4124 sdiv_optab = init_optab (DIV);
4125 sdivmod_optab = init_optab (UNKNOWN);
4126 udiv_optab = init_optab (UDIV);
4127 udivmod_optab = init_optab (UNKNOWN);
4128 smod_optab = init_optab (MOD);
4129 umod_optab = init_optab (UMOD);
4130 flodiv_optab = init_optab (DIV);
4131 ftrunc_optab = init_optab (UNKNOWN);
4132 and_optab = init_optab (AND);
4133 ior_optab = init_optab (IOR);
4134 xor_optab = init_optab (XOR);
4135 ashl_optab = init_optab (ASHIFT);
4136 ashr_optab = init_optab (ASHIFTRT);
4137 lshr_optab = init_optab (LSHIFTRT);
4138 rotl_optab = init_optab (ROTATE);
4139 rotr_optab = init_optab (ROTATERT);
4140 smin_optab = init_optab (SMIN);
4141 smax_optab = init_optab (SMAX);
4142 umin_optab = init_optab (UMIN);
4143 umax_optab = init_optab (UMAX);
4144 mov_optab = init_optab (UNKNOWN);
4145 movstrict_optab = init_optab (UNKNOWN);
4146 cmp_optab = init_optab (UNKNOWN);
4147 ucmp_optab = init_optab (UNKNOWN);
4148 tst_optab = init_optab (UNKNOWN);
4149 neg_optab = init_optab (NEG);
4150 abs_optab = init_optab (ABS);
4151 one_cmpl_optab = init_optab (NOT);
4152 ffs_optab = init_optab (FFS);
4153 sqrt_optab = init_optab (SQRT);
4154 sin_optab = init_optab (UNKNOWN);
4155 cos_optab = init_optab (UNKNOWN);
4156 strlen_optab = init_optab (UNKNOWN);
4157
4158 for (i = 0; i < NUM_MACHINE_MODES; i++)
4159 {
4160 movstr_optab[i] = CODE_FOR_nothing;
4161 clrstr_optab[i] = CODE_FOR_nothing;
4162
4163 #ifdef HAVE_SECONDARY_RELOADS
4164 reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
4165 #endif
4166 }
4167
4168 /* Fill in the optabs with the insns we support. */
4169 init_all_optabs ();
4170
4171 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
4172 /* This flag says the same insns that convert to a signed fixnum
4173 also convert validly to an unsigned one. */
4174 for (i = 0; i < NUM_MACHINE_MODES; i++)
4175 for (j = 0; j < NUM_MACHINE_MODES; j++)
4176 fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
4177 #endif
4178
4179 #ifdef EXTRA_CC_MODES
4180 init_mov_optab ();
4181 #endif
4182
4183 /* Initialize the optabs with the names of the library functions. */
4184 init_integral_libfuncs (add_optab, "add", '3');
4185 init_floating_libfuncs (add_optab, "add", '3');
4186 init_integral_libfuncs (sub_optab, "sub", '3');
4187 init_floating_libfuncs (sub_optab, "sub", '3');
4188 init_integral_libfuncs (smul_optab, "mul", '3');
4189 init_floating_libfuncs (smul_optab, "mul", '3');
4190 init_integral_libfuncs (sdiv_optab, "div", '3');
4191 init_integral_libfuncs (udiv_optab, "udiv", '3');
4192 init_integral_libfuncs (sdivmod_optab, "divmod", '4');
4193 init_integral_libfuncs (udivmod_optab, "udivmod", '4');
4194 init_integral_libfuncs (smod_optab, "mod", '3');
4195 init_integral_libfuncs (umod_optab, "umod", '3');
4196 init_floating_libfuncs (flodiv_optab, "div", '3');
4197 init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
4198 init_integral_libfuncs (and_optab, "and", '3');
4199 init_integral_libfuncs (ior_optab, "ior", '3');
4200 init_integral_libfuncs (xor_optab, "xor", '3');
4201 init_integral_libfuncs (ashl_optab, "ashl", '3');
4202 init_integral_libfuncs (ashr_optab, "ashr", '3');
4203 init_integral_libfuncs (lshr_optab, "lshr", '3');
4204 init_integral_libfuncs (smin_optab, "min", '3');
4205 init_floating_libfuncs (smin_optab, "min", '3');
4206 init_integral_libfuncs (smax_optab, "max", '3');
4207 init_floating_libfuncs (smax_optab, "max", '3');
4208 init_integral_libfuncs (umin_optab, "umin", '3');
4209 init_integral_libfuncs (umax_optab, "umax", '3');
4210 init_integral_libfuncs (neg_optab, "neg", '2');
4211 init_floating_libfuncs (neg_optab, "neg", '2');
4212 init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
4213 init_integral_libfuncs (ffs_optab, "ffs", '2');
4214
4215 /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
4216 init_integral_libfuncs (cmp_optab, "cmp", '2');
4217 init_integral_libfuncs (ucmp_optab, "ucmp", '2');
4218 init_floating_libfuncs (cmp_optab, "cmp", '2');
4219
4220 #ifdef MULSI3_LIBCALL
4221 smul_optab->handlers[(int) SImode].libfunc
4222 = gen_rtx_SYMBOL_REF (Pmode, MULSI3_LIBCALL);
4223 #endif
4224 #ifdef MULDI3_LIBCALL
4225 smul_optab->handlers[(int) DImode].libfunc
4226 = gen_rtx_SYMBOL_REF (Pmode, MULDI3_LIBCALL);
4227 #endif
4228
4229 #ifdef DIVSI3_LIBCALL
4230 sdiv_optab->handlers[(int) SImode].libfunc
4231 = gen_rtx_SYMBOL_REF (Pmode, DIVSI3_LIBCALL);
4232 #endif
4233 #ifdef DIVDI3_LIBCALL
4234 sdiv_optab->handlers[(int) DImode].libfunc
4235 = gen_rtx_SYMBOL_REF (Pmode, DIVDI3_LIBCALL);
4236 #endif
4237
4238 #ifdef UDIVSI3_LIBCALL
4239 udiv_optab->handlers[(int) SImode].libfunc
4240 = gen_rtx_SYMBOL_REF (Pmode, UDIVSI3_LIBCALL);
4241 #endif
4242 #ifdef UDIVDI3_LIBCALL
4243 udiv_optab->handlers[(int) DImode].libfunc
4244 = gen_rtx_SYMBOL_REF (Pmode, UDIVDI3_LIBCALL);
4245 #endif
4246
4247 #ifdef MODSI3_LIBCALL
4248 smod_optab->handlers[(int) SImode].libfunc
4249 = gen_rtx_SYMBOL_REF (Pmode, MODSI3_LIBCALL);
4250 #endif
4251 #ifdef MODDI3_LIBCALL
4252 smod_optab->handlers[(int) DImode].libfunc
4253 = gen_rtx_SYMBOL_REF (Pmode, MODDI3_LIBCALL);
4254 #endif
4255
4256 #ifdef UMODSI3_LIBCALL
4257 umod_optab->handlers[(int) SImode].libfunc
4258 = gen_rtx_SYMBOL_REF (Pmode, UMODSI3_LIBCALL);
4259 #endif
4260 #ifdef UMODDI3_LIBCALL
4261 umod_optab->handlers[(int) DImode].libfunc
4262 = gen_rtx_SYMBOL_REF (Pmode, UMODDI3_LIBCALL);
4263 #endif
4264
4265 /* Use cabs for DC complex abs, since systems generally have cabs.
4266 Don't define any libcall for SCmode, so that cabs will be used. */
4267 abs_optab->handlers[(int) DCmode].libfunc
4268 = gen_rtx_SYMBOL_REF (Pmode, "cabs");
4269
4270 /* The ffs function operates on `int'. */
4271 #ifndef INT_TYPE_SIZE
4272 #define INT_TYPE_SIZE BITS_PER_WORD
4273 #endif
4274 ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)] .libfunc
4275 = gen_rtx_SYMBOL_REF (Pmode, "ffs");
4276
4277 extendsfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsfdf2");
4278 extendsfxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsfxf2");
4279 extendsftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsftf2");
4280 extenddfxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extenddfxf2");
4281 extenddftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extenddftf2");
4282
4283 truncdfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncdfsf2");
4284 truncxfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncxfsf2");
4285 trunctfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__trunctfsf2");
4286 truncxfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncxfdf2");
4287 trunctfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__trunctfdf2");
4288
4289 memcpy_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memcpy");
4290 bcopy_libfunc = gen_rtx_SYMBOL_REF (Pmode, "bcopy");
4291 memcmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memcmp");
4292 bcmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gcc_bcmp");
4293 memset_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memset");
4294 bzero_libfunc = gen_rtx_SYMBOL_REF (Pmode, "bzero");
4295
4296 throw_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__throw");
4297 sjthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjthrow");
4298 sjpopnthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjpopnthrow");
4299 terminate_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__terminate");
4300 eh_rtime_match_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eh_rtime_match");
4301 #ifndef DONT_USE_BUILTIN_SETJMP
4302 setjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__builtin_setjmp");
4303 longjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__builtin_longjmp");
4304 #else
4305 setjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "setjmp");
4306 longjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "longjmp");
4307 #endif
4308
4309 eqhf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqhf2");
4310 nehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nehf2");
4311 gthf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gthf2");
4312 gehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gehf2");
4313 lthf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lthf2");
4314 lehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lehf2");
4315
4316 eqsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqsf2");
4317 nesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nesf2");
4318 gtsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtsf2");
4319 gesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gesf2");
4320 ltsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltsf2");
4321 lesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lesf2");
4322
4323 eqdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqdf2");
4324 nedf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nedf2");
4325 gtdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtdf2");
4326 gedf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gedf2");
4327 ltdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltdf2");
4328 ledf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ledf2");
4329
4330 eqxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqxf2");
4331 nexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nexf2");
4332 gtxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtxf2");
4333 gexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gexf2");
4334 ltxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltxf2");
4335 lexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lexf2");
4336
4337 eqtf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqtf2");
4338 netf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__netf2");
4339 gttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gttf2");
4340 getf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__getf2");
4341 lttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lttf2");
4342 letf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__letf2");
4343
4344 floatsisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsisf");
4345 floatdisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdisf");
4346 floattisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattisf");
4347
4348 floatsidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsidf");
4349 floatdidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdidf");
4350 floattidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattidf");
4351
4352 floatsixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsixf");
4353 floatdixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdixf");
4354 floattixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattixf");
4355
4356 floatsitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsitf");
4357 floatditf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatditf");
4358 floattitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattitf");
4359
4360 fixsfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfsi");
4361 fixsfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfdi");
4362 fixsfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfti");
4363
4364 fixdfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfsi");
4365 fixdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfdi");
4366 fixdfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfti");
4367
4368 fixxfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfsi");
4369 fixxfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfdi");
4370 fixxfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfti");
4371
4372 fixtfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfsi");
4373 fixtfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfdi");
4374 fixtfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfti");
4375
4376 fixunssfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfsi");
4377 fixunssfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfdi");
4378 fixunssfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfti");
4379
4380 fixunsdfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfsi");
4381 fixunsdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfdi");
4382 fixunsdfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfti");
4383
4384 fixunsxfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfsi");
4385 fixunsxfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfdi");
4386 fixunsxfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfti");
4387
4388 fixunstfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfsi");
4389 fixunstfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfdi");
4390 fixunstfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfti");
4391
4392 /* For check-memory-usage. */
4393 chkr_check_addr_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_addr");
4394 chkr_set_right_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_set_right");
4395 chkr_copy_bitmap_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_copy_bitmap");
4396 chkr_check_exec_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_exec");
4397 chkr_check_str_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_str");
4398
4399 /* For function entry/exit instrumentation. */
4400 profile_function_entry_libfunc
4401 = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_enter");
4402 profile_function_exit_libfunc
4403 = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_exit");
4404
4405 #ifdef HAVE_conditional_trap
4406 init_traps ();
4407 #endif
4408
4409 #ifdef INIT_TARGET_OPTABS
4410 /* Allow the target to add more libcalls or rename some, etc. */
4411 INIT_TARGET_OPTABS;
4412 #endif
4413 }
4414 \f
4415 #ifdef BROKEN_LDEXP
4416
4417 /* SCO 3.2 apparently has a broken ldexp. */
4418
4419 double
4420 ldexp(x,n)
4421 double x;
4422 int n;
4423 {
4424 if (n > 0)
4425 while (n--)
4426 x *= 2;
4427
4428 return x;
4429 }
4430 #endif /* BROKEN_LDEXP */
4431 \f
4432 #ifdef HAVE_conditional_trap
4433 /* The insn generating function can not take an rtx_code argument.
4434 TRAP_RTX is used as an rtx argument. Its code is replaced with
4435 the code to be used in the trap insn and all other fields are
4436 ignored.
4437
4438 ??? Will need to change to support garbage collection. */
4439 static rtx trap_rtx;
4440
4441 static void
4442 init_traps ()
4443 {
4444 if (HAVE_conditional_trap)
4445 trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);
4446 }
4447 #endif
4448
4449 /* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
4450 CODE. Return 0 on failure. */
4451
4452 rtx
4453 gen_cond_trap (code, op1, op2, tcode)
4454 enum rtx_code code ATTRIBUTE_UNUSED;
4455 rtx op1, op2 ATTRIBUTE_UNUSED, tcode ATTRIBUTE_UNUSED;
4456 {
4457 enum machine_mode mode = GET_MODE (op1);
4458
4459 if (mode == VOIDmode)
4460 return 0;
4461
4462 #ifdef HAVE_conditional_trap
4463 if (HAVE_conditional_trap
4464 && cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
4465 {
4466 rtx insn;
4467 emit_insn (GEN_FCN (cmp_optab->handlers[(int) mode].insn_code) (op1, op2));
4468 PUT_CODE (trap_rtx, code);
4469 insn = gen_conditional_trap (trap_rtx, tcode);
4470 if (insn)
4471 return insn;
4472 }
4473 #endif
4474
4475 return 0;
4476 }
This page took 0.251362 seconds and 6 git commands to generate.