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