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