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