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