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