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