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