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