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