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