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