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