]> gcc.gnu.org Git - gcc.git/blame - gcc/optabs.c
entered into RCS
[gcc.git] / gcc / optabs.c
CommitLineData
77c9c6c2 1/* Expand the basic unary and binary arithmetic operations, for GNU compiler.
34e56753 2 Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.
77c9c6c2
RK
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21#include "config.h"
22#include "rtl.h"
23#include "tree.h"
24#include "flags.h"
25#include "insn-flags.h"
26#include "insn-codes.h"
27#include "expr.h"
28#include "insn-config.h"
29#include "recog.h"
2d9f831e 30#include <ctype.h>
77c9c6c2
RK
31
32/* Each optab contains info on how this target machine
33 can perform a particular operation
34 for all sizes and kinds of operands.
35
36 The operation to be performed is often specified
37 by passing one of these optabs as an argument.
38
39 See expr.h for documentation of these optabs. */
40
41optab add_optab;
42optab sub_optab;
43optab smul_optab;
44optab smul_widen_optab;
45optab umul_widen_optab;
46optab sdiv_optab;
47optab sdivmod_optab;
48optab udiv_optab;
49optab udivmod_optab;
50optab smod_optab;
51optab umod_optab;
52optab flodiv_optab;
53optab ftrunc_optab;
54optab and_optab;
55optab ior_optab;
56optab xor_optab;
57optab ashl_optab;
58optab lshr_optab;
59optab lshl_optab;
60optab ashr_optab;
61optab rotl_optab;
62optab rotr_optab;
63optab smin_optab;
64optab smax_optab;
65optab umin_optab;
66optab umax_optab;
67
68optab mov_optab;
69optab movstrict_optab;
70
71optab neg_optab;
72optab abs_optab;
73optab one_cmpl_optab;
74optab ffs_optab;
d45cf215 75optab sqrt_optab;
77c9c6c2
RK
76
77optab cmp_optab;
78optab ucmp_optab; /* Used only for libcalls for unsigned comparisons. */
79optab tst_optab;
80
19c3fc24
RS
81optab strlen_optab;
82
77c9c6c2
RK
83/* SYMBOL_REF rtx's for the library functions that are called
84 implicitly and not via optabs. */
85
86rtx extendsfdf2_libfunc;
b092b471
JW
87rtx extendsfxf2_libfunc;
88rtx extendsftf2_libfunc;
89rtx extenddfxf2_libfunc;
90rtx extenddftf2_libfunc;
91
77c9c6c2 92rtx truncdfsf2_libfunc;
b092b471
JW
93rtx truncxfsf2_libfunc;
94rtx trunctfsf2_libfunc;
95rtx truncxfdf2_libfunc;
96rtx trunctfdf2_libfunc;
97
77c9c6c2
RK
98rtx memcpy_libfunc;
99rtx bcopy_libfunc;
100rtx memcmp_libfunc;
101rtx bcmp_libfunc;
102rtx memset_libfunc;
103rtx bzero_libfunc;
b092b471 104
77c9c6c2
RK
105rtx eqsf2_libfunc;
106rtx nesf2_libfunc;
107rtx gtsf2_libfunc;
108rtx gesf2_libfunc;
109rtx ltsf2_libfunc;
110rtx lesf2_libfunc;
b092b471 111
77c9c6c2
RK
112rtx eqdf2_libfunc;
113rtx nedf2_libfunc;
114rtx gtdf2_libfunc;
115rtx gedf2_libfunc;
116rtx ltdf2_libfunc;
117rtx ledf2_libfunc;
b092b471
JW
118
119rtx eqxf2_libfunc;
120rtx nexf2_libfunc;
121rtx gtxf2_libfunc;
122rtx gexf2_libfunc;
123rtx ltxf2_libfunc;
124rtx lexf2_libfunc;
125
126rtx eqtf2_libfunc;
127rtx netf2_libfunc;
128rtx gttf2_libfunc;
129rtx getf2_libfunc;
130rtx lttf2_libfunc;
131rtx letf2_libfunc;
132
6bce1b78 133rtx floatsisf_libfunc;
b092b471
JW
134rtx floatdisf_libfunc;
135rtx floattisf_libfunc;
136
6bce1b78 137rtx floatsidf_libfunc;
b092b471
JW
138rtx floatdidf_libfunc;
139rtx floattidf_libfunc;
140
141rtx floatsixf_libfunc;
142rtx floatdixf_libfunc;
143rtx floattixf_libfunc;
144
145rtx floatsitf_libfunc;
146rtx floatditf_libfunc;
147rtx floattitf_libfunc;
148
6bce1b78
RK
149rtx fixsfsi_libfunc;
150rtx fixsfdi_libfunc;
b092b471
JW
151rtx fixsfti_libfunc;
152
6bce1b78
RK
153rtx fixdfsi_libfunc;
154rtx fixdfdi_libfunc;
b092b471
JW
155rtx fixdfti_libfunc;
156
157rtx fixxfsi_libfunc;
158rtx fixxfdi_libfunc;
159rtx fixxfti_libfunc;
160
161rtx fixtfsi_libfunc;
162rtx fixtfdi_libfunc;
163rtx fixtfti_libfunc;
164
6bce1b78
RK
165rtx fixunssfsi_libfunc;
166rtx fixunssfdi_libfunc;
b092b471
JW
167rtx fixunssfti_libfunc;
168
6bce1b78
RK
169rtx fixunsdfsi_libfunc;
170rtx fixunsdfdi_libfunc;
b092b471
JW
171rtx fixunsdfti_libfunc;
172
173rtx fixunsxfsi_libfunc;
174rtx fixunsxfdi_libfunc;
175rtx fixunsxfti_libfunc;
176
177rtx fixunstfsi_libfunc;
178rtx fixunstfdi_libfunc;
179rtx fixunstfti_libfunc;
77c9c6c2
RK
180
181/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
182 gives the gen_function to make a branch to test that condition. */
183
184rtxfun bcc_gen_fctn[NUM_RTX_CODE];
185
186/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
187 gives the insn code to make a store-condition insn
188 to test that condition. */
189
190enum insn_code setcc_gen_code[NUM_RTX_CODE];
191
192static void emit_float_lib_cmp ();
193\f
194/* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
195 the result of operation CODE applied to OP0 (and OP1 if it is a binary
196 operation).
197
198 If the last insn does not set TARGET, don't do anything, but return 1.
199
200 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
201 don't add the REG_EQUAL note but return 0. Our caller can then try
202 again, ensuring that TARGET is not one of the operands. */
203
204static int
205add_equal_note (seq, target, code, op0, op1)
206 rtx seq;
207 rtx target;
208 enum rtx_code code;
209 rtx op0, op1;
210{
211 rtx set;
212 int i;
213 rtx note;
214
215 if ((GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2'
216 && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<')
217 || GET_CODE (seq) != SEQUENCE
218 || (set = single_set (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))) == 0
219 || GET_CODE (target) == ZERO_EXTRACT
220 || (! rtx_equal_p (SET_DEST (set), target)
221 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
222 SUBREG. */
223 && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
224 || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)),
225 target))))
226 return 1;
227
228 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
229 besides the last insn. */
230 if (reg_overlap_mentioned_p (target, op0)
231 || (op1 && reg_overlap_mentioned_p (target, op1)))
232 for (i = XVECLEN (seq, 0) - 2; i >= 0; i--)
233 if (reg_set_p (target, XVECEXP (seq, 0, i)))
234 return 0;
235
236 if (GET_RTX_CLASS (code) == '1')
237 note = gen_rtx (code, GET_MODE (target), op0);
238 else
239 note = gen_rtx (code, GET_MODE (target), op0, op1);
240
241 REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))
242 = gen_rtx (EXPR_LIST, REG_EQUAL, note,
243 REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1)));
244
245 return 1;
246}
247\f
248/* Generate code to perform an operation specified by BINOPTAB
249 on operands OP0 and OP1, with result having machine-mode MODE.
250
251 UNSIGNEDP is for the case where we have to widen the operands
252 to perform the operation. It says to use zero-extension.
253
254 If TARGET is nonzero, the value
255 is generated there, if it is convenient to do so.
256 In all cases an rtx is returned for the locus of the value;
257 this may or may not be TARGET. */
258
259rtx
260expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
261 enum machine_mode mode;
262 optab binoptab;
263 rtx op0, op1;
264 rtx target;
265 int unsignedp;
266 enum optab_methods methods;
267{
268 enum mode_class class;
269 enum machine_mode wider_mode;
77c9c6c2
RK
270 register rtx temp;
271 int commutative_op = 0;
272 int shift_op = (binoptab->code == ASHIFT
273 || binoptab->code == ASHIFTRT
274 || binoptab->code == LSHIFT
275 || binoptab->code == LSHIFTRT
276 || binoptab->code == ROTATE
277 || binoptab->code == ROTATERT);
278 rtx last;
279
280 class = GET_MODE_CLASS (mode);
281
282 op0 = protect_from_queue (op0, 0);
283 op1 = protect_from_queue (op1, 0);
284 if (target)
285 target = protect_from_queue (target, 1);
286
287 if (flag_force_mem)
288 {
289 op0 = force_not_mem (op0);
290 op1 = force_not_mem (op1);
291 }
292
293 /* If we are inside an appropriately-short loop and one operand is an
294 expensive constant, force it into a register. */
aeedc93f
RS
295 if (CONSTANT_P (op0) && preserve_subexpressions_p ()
296 && rtx_cost (op0, binoptab->code) > 2)
77c9c6c2
RK
297 op0 = force_reg (mode, op0);
298
aeedc93f
RS
299 if (CONSTANT_P (op1) && preserve_subexpressions_p ()
300 && rtx_cost (op1, binoptab->code) > 2)
34e56753 301 op1 = force_reg (shift_op ? word_mode : mode, op1);
77c9c6c2
RK
302
303#if 0 /* Turned off because it seems to be a kludgy method. */
304 /* If subtracting integer from pointer, and the pointer has a special mode,
305 then change it to an add. We use the add insn of Pmode for combining
306 integers with pointers, and the sub insn to subtract two pointers. */
307
308 if (binoptab == sub_optab
309 && GET_MODE (op0) == Pmode && GET_MODE (op1) != Pmode)
310 {
311 op1 = negate_rtx (GET_MODE(op1), op1);
312 binoptab = add_optab;
313 }
314#endif /* 0 */
315
316 /* Record where to delete back to if we backtrack. */
317 last = get_last_insn ();
318
319 /* If operation is commutative,
320 try to make the first operand a register.
321 Even better, try to make it the same as the target.
322 Also try to make the last operand a constant. */
323 if (GET_RTX_CLASS (binoptab->code) == 'c'
324 || binoptab == smul_widen_optab
325 || binoptab == umul_widen_optab)
326 {
327 commutative_op = 1;
328
329 if (((target == 0 || GET_CODE (target) == REG)
330 ? ((GET_CODE (op1) == REG
331 && GET_CODE (op0) != REG)
332 || target == op1)
333 : rtx_equal_p (op1, target))
334 || GET_CODE (op0) == CONST_INT)
335 {
336 temp = op1;
337 op1 = op0;
338 op0 = temp;
339 }
340 }
341
342 /* If we can do it with a three-operand insn, do so. */
343
344 if (methods != OPTAB_MUST_WIDEN
345 && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
346 {
347 int icode = (int) binoptab->handlers[(int) mode].insn_code;
348 enum machine_mode mode0 = insn_operand_mode[icode][1];
349 enum machine_mode mode1 = insn_operand_mode[icode][2];
350 rtx pat;
351 rtx xop0 = op0, xop1 = op1;
352
353 if (target)
354 temp = target;
355 else
356 temp = gen_reg_rtx (mode);
357
358 /* If it is a commutative operator and the modes would match
359 if we would swap the operands, we can save the conversions. */
360 if (commutative_op)
361 {
362 if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
363 && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
364 {
365 register rtx tmp;
366
367 tmp = op0; op0 = op1; op1 = tmp;
368 tmp = xop0; xop0 = xop1; xop1 = tmp;
369 }
370 }
371
372 /* In case the insn wants input operands in modes different from
373 the result, convert the operands. */
374
375 if (GET_MODE (op0) != VOIDmode
376 && GET_MODE (op0) != mode0)
377 xop0 = convert_to_mode (mode0, xop0, unsignedp);
378
379 if (GET_MODE (xop1) != VOIDmode
380 && GET_MODE (xop1) != mode1)
381 xop1 = convert_to_mode (mode1, xop1, unsignedp);
382
383 /* Now, if insn's predicates don't allow our operands, put them into
384 pseudo regs. */
385
386 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
387 xop0 = copy_to_mode_reg (mode0, xop0);
388
389 if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
390 xop1 = copy_to_mode_reg (mode1, xop1);
391
392 if (! (*insn_operand_predicate[icode][0]) (temp, mode))
393 temp = gen_reg_rtx (mode);
394
395 pat = GEN_FCN (icode) (temp, xop0, xop1);
396 if (pat)
397 {
398 /* If PAT is a multi-insn sequence, try to add an appropriate
399 REG_EQUAL note to it. If we can't because TEMP conflicts with an
400 operand, call ourselves again, this time without a target. */
401 if (GET_CODE (pat) == SEQUENCE
402 && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
403 {
404 delete_insns_since (last);
b1ec3c92
CH
405 return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
406 unsignedp, methods);
77c9c6c2
RK
407 }
408
409 emit_insn (pat);
410 return temp;
411 }
412 else
413 delete_insns_since (last);
414 }
415
9a856ec7
RK
416 /* Look for a wider mode of the same class for which we think we
417 can open-code the operation. */
418
419 if ((class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
420 && mode != OPTAB_DIRECT && mode != OPTAB_LIB)
421 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
422 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
423 {
424 if (binoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
425 {
426 rtx xop0 = op0, xop1 = op1;
427 int no_extend = 0;
428
429 /* For certain integer operations, we need not actually extend
430 the narrow operands, as long as we will truncate
431 the results to the same narrowness. */
432
433 if ((binoptab == ior_optab || binoptab == and_optab
434 || binoptab == xor_optab
435 || binoptab == add_optab || binoptab == sub_optab
436 || binoptab == smul_optab
437 || binoptab == ashl_optab || binoptab == lshl_optab)
438 && class == MODE_INT)
439 no_extend = 1;
440
441 /* If an operand is a constant integer, we might as well
442 convert it since that is more efficient than using a SUBREG,
443 unlike the case for other operands. */
444
445 if (no_extend && GET_MODE (xop0) != VOIDmode)
446 xop0 = gen_rtx (SUBREG, wider_mode,
447 force_reg (GET_MODE (xop0), xop0), 0);
448 else
449 xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
450
451 if (no_extend && GET_MODE (xop1) != VOIDmode)
452 xop1 = gen_rtx (SUBREG, wider_mode,
453 force_reg (GET_MODE (xop1), xop1), 0);
454 else
455 xop1 = convert_to_mode (wider_mode, xop1, unsignedp);
456
b1ec3c92 457 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
9a856ec7
RK
458 unsignedp, OPTAB_DIRECT);
459 if (temp)
460 {
461 if (class != MODE_INT)
462 {
463 if (target == 0)
464 target = gen_reg_rtx (mode);
465 convert_move (target, temp, 0);
466 return target;
467 }
468 else
469 return gen_lowpart (mode, temp);
470 }
471 else
472 delete_insns_since (last);
473 }
474 }
475
77c9c6c2
RK
476 /* These can be done a word at a time. */
477 if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
478 && class == MODE_INT
479 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
34e56753 480 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
77c9c6c2
RK
481 {
482 int i;
483 rtx insns;
484 rtx equiv_value;
485
486 /* If TARGET is the same as one of the operands, the REG_EQUAL note
487 won't be accurate, so use a new target. */
488 if (target == 0 || target == op0 || target == op1)
489 target = gen_reg_rtx (mode);
490
491 start_sequence ();
492
493 /* Do the actual arithmetic. */
494 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
495 {
496 rtx target_piece = operand_subword (target, i, 1, mode);
34e56753 497 rtx x = expand_binop (word_mode, binoptab,
77c9c6c2
RK
498 operand_subword_force (op0, i, mode),
499 operand_subword_force (op1, i, mode),
500 target_piece, unsignedp, methods);
501 if (target_piece != x)
502 emit_move_insn (target_piece, x);
503 }
504
505 insns = get_insns ();
506 end_sequence ();
507
508 if (binoptab->code != UNKNOWN)
509 equiv_value = gen_rtx (binoptab->code, mode, op0, op1);
510 else
511 equiv_value = 0;
512
513 emit_no_conflict_block (insns, target, op0, op1, equiv_value);
514 return target;
515 }
516
517 /* These can be done a word at a time by propagating carries. */
518 if ((binoptab == add_optab || binoptab == sub_optab)
519 && class == MODE_INT
520 && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
34e56753 521 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
77c9c6c2
RK
522 {
523 int i;
34e56753 524 rtx carry_tmp = gen_reg_rtx (word_mode);
77c9c6c2
RK
525 optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
526 int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
527 rtx carry_in, carry_out;
528
529 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
530 value is one of those, use it. Otherwise, use 1 since it is the
531 one easiest to get. */
532#if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
533 int normalizep = STORE_FLAG_VALUE;
534#else
535 int normalizep = 1;
536#endif
537
538 /* Prepare the operands. */
539 op0 = force_reg (mode, op0);
540 op1 = force_reg (mode, op1);
541
542 if (target == 0 || GET_CODE (target) != REG
543 || target == op0 || target == op1)
544 target = gen_reg_rtx (mode);
545
546 /* Do the actual arithmetic. */
547 for (i = 0; i < nwords; i++)
548 {
549 int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
550 rtx target_piece = operand_subword (target, index, 1, mode);
551 rtx op0_piece = operand_subword_force (op0, index, mode);
552 rtx op1_piece = operand_subword_force (op1, index, mode);
553 rtx x;
554
555 /* Main add/subtract of the input operands. */
34e56753 556 x = expand_binop (word_mode, binoptab,
77c9c6c2
RK
557 op0_piece, op1_piece,
558 target_piece, unsignedp, methods);
559 if (x == 0)
560 break;
561
562 if (i + 1 < nwords)
563 {
564 /* Store carry from main add/subtract. */
34e56753 565 carry_out = gen_reg_rtx (word_mode);
77c9c6c2
RK
566 carry_out = emit_store_flag (carry_out,
567 binoptab == add_optab ? LTU : GTU,
568 x, op0_piece,
34e56753 569 word_mode, 1, normalizep);
77c9c6c2
RK
570 if (!carry_out)
571 break;
572 }
573
574 if (i > 0)
575 {
576 /* Add/subtract previous carry to main result. */
34e56753 577 x = expand_binop (word_mode,
77c9c6c2
RK
578 normalizep == 1 ? binoptab : otheroptab,
579 x, carry_in,
580 target_piece, 1, methods);
581 if (target_piece != x)
582 emit_move_insn (target_piece, x);
583
584 if (i + 1 < nwords)
585 {
586 /* THIS CODE HAS NOT BEEN TESTED. */
587 /* Get out carry from adding/subtracting carry in. */
588 carry_tmp = emit_store_flag (carry_tmp,
589 binoptab == add_optab
590 ? LTU : GTU,
591 x, carry_in,
34e56753 592 word_mode, 1, normalizep);
77c9c6c2 593 /* Logical-ior the two poss. carry together. */
34e56753 594 carry_out = expand_binop (word_mode, ior_optab,
77c9c6c2
RK
595 carry_out, carry_tmp,
596 carry_out, 0, methods);
597 if (!carry_out)
598 break;
599 }
600 }
601
602 carry_in = carry_out;
603 }
604
605 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
606 {
607 rtx temp;
608
609 temp = emit_move_insn (target, target);
610 REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL,
611 gen_rtx (binoptab->code, mode, op0, op1),
612 REG_NOTES (temp));
613 return target;
614 }
615 else
616 delete_insns_since (last);
617 }
618
619 /* If we want to multiply two two-word values and have normal and widening
620 multiplies of single-word values, we can do this with three smaller
621 multiplications. Note that we do not make a REG_NO_CONFLICT block here
622 because we are not operating on one word at a time.
623
624 The multiplication proceeds as follows:
34e56753
RS
625 _______________________
626 [__op0_high_|__op0_low__]
627 _______________________
628 * [__op1_high_|__op1_low__]
629 _______________________________________________
630 _______________________
631 (1) [__op0_low__*__op1_low__]
632 _______________________
633 (2a) [__op0_low__*__op1_high_]
634 _______________________
635 (2b) [__op0_high_*__op1_low__]
636 _______________________
637 (3) [__op0_high_*__op1_high_]
77c9c6c2
RK
638
639
640 This gives a 4-word result. Since we are only interested in the
641 lower 2 words, partial result (3) and the upper words of (2a) and
642 (2b) don't need to be calculated. Hence (2a) and (2b) can be
643 calculated using non-widening multiplication.
644
645 (1), however, needs to be calculated with an unsigned widening
646 multiplication. If this operation is not directly supported we
647 try using a signed widening multiplication and adjust the result.
648 This adjustment works as follows:
649
650 If both operands are positive then no adjustment is needed.
651
652 If the operands have different signs, for example op0_low < 0 and
653 op1_low >= 0, the instruction treats the most significant bit of
654 op0_low as a sign bit instead of a bit with significance
655 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
656 with 2**BITS_PER_WORD - op0_low, and two's complements the
657 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
658 the result.
659
660 Similarly, if both operands are negative, we need to add
661 (op0_low + op1_low) * 2**BITS_PER_WORD.
662
663 We use a trick to adjust quickly. We logically shift op0_low right
664 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
665 op0_high (op1_high) before it is used to calculate 2b (2a). If no
666 logical shift exists, we do an arithmetic right shift and subtract
667 the 0 or -1. */
668
669 if (binoptab == smul_optab
670 && class == MODE_INT
671 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
34e56753
RS
672 && smul_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
673 && add_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
77c9c6c2
RK
674 && ((umul_widen_optab->handlers[(int) mode].insn_code
675 != CODE_FOR_nothing)
676 || (smul_widen_optab->handlers[(int) mode].insn_code
677 != CODE_FOR_nothing)))
678 {
679 int low = (WORDS_BIG_ENDIAN ? 1 : 0);
680 int high = (WORDS_BIG_ENDIAN ? 0 : 1);
681 rtx op0_high = operand_subword_force (op0, high, mode);
682 rtx op0_low = operand_subword_force (op0, low, mode);
683 rtx op1_high = operand_subword_force (op1, high, mode);
684 rtx op1_low = operand_subword_force (op1, low, mode);
685 rtx product = 0;
686 rtx op0_xhigh;
687 rtx op1_xhigh;
688
689 /* If the target is the same as one of the inputs, don't use it. This
690 prevents problems with the REG_EQUAL note. */
691 if (target == op0 || target == op1)
692 target = 0;
693
694 /* Multiply the two lower words to get a double-word product.
695 If unsigned widening multiplication is available, use that;
696 otherwise use the signed form and compensate. */
697
698 if (umul_widen_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
699 {
700 product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
701 target, 1, OPTAB_DIRECT);
702
703 /* If we didn't succeed, delete everything we did so far. */
704 if (product == 0)
705 delete_insns_since (last);
706 else
707 op0_xhigh = op0_high, op1_xhigh = op1_high;
708 }
709
710 if (product == 0
711 && smul_widen_optab->handlers[(int) mode].insn_code
712 != CODE_FOR_nothing)
713 {
b1ec3c92 714 rtx wordm1 = GEN_INT (BITS_PER_WORD - 1);
77c9c6c2
RK
715 product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
716 target, 1, OPTAB_DIRECT);
34e56753 717 op0_xhigh = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
b1ec3c92 718 NULL_RTX, 1, OPTAB_DIRECT);
77c9c6c2 719 if (op0_xhigh)
34e56753
RS
720 op0_xhigh = expand_binop (word_mode, add_optab, op0_high,
721 op0_xhigh, op0_xhigh, 0, OPTAB_DIRECT);
77c9c6c2
RK
722 else
723 {
34e56753 724 op0_xhigh = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
b1ec3c92 725 NULL_RTX, 0, OPTAB_DIRECT);
77c9c6c2 726 if (op0_xhigh)
34e56753 727 op0_xhigh = expand_binop (word_mode, sub_optab, op0_high,
77c9c6c2
RK
728 op0_xhigh, op0_xhigh, 0,
729 OPTAB_DIRECT);
730 }
731
34e56753 732 op1_xhigh = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
b1ec3c92 733 NULL_RTX, 1, OPTAB_DIRECT);
77c9c6c2 734 if (op1_xhigh)
34e56753
RS
735 op1_xhigh = expand_binop (word_mode, add_optab, op1_high,
736 op1_xhigh, op1_xhigh, 0, OPTAB_DIRECT);
77c9c6c2
RK
737 else
738 {
34e56753 739 op1_xhigh = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
b1ec3c92 740 NULL_RTX, 0, OPTAB_DIRECT);
77c9c6c2 741 if (op1_xhigh)
34e56753 742 op1_xhigh = expand_binop (word_mode, sub_optab, op1_high,
77c9c6c2
RK
743 op1_xhigh, op1_xhigh, 0,
744 OPTAB_DIRECT);
745 }
746 }
747
748 /* If we have been able to directly compute the product of the
749 low-order words of the operands and perform any required adjustments
750 of the operands, we proceed by trying two more multiplications
751 and then computing the appropriate sum.
752
753 We have checked above that the required addition is provided.
754 Full-word addition will normally always succeed, especially if
755 it is provided at all, so we don't worry about its failure. The
756 multiplication may well fail, however, so we do handle that. */
757
758 if (product && op0_xhigh && op1_xhigh)
759 {
760 rtx product_piece;
761 rtx product_high = operand_subword (product, high, 1, mode);
b1ec3c92
CH
762 rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh,
763 NULL_RTX, 0, OPTAB_DIRECT);
77c9c6c2
RK
764
765 if (temp)
766 {
34e56753 767 product_piece = expand_binop (word_mode, add_optab, temp,
77c9c6c2
RK
768 product_high, product_high,
769 0, OPTAB_LIB_WIDEN);
770 if (product_piece != product_high)
771 emit_move_insn (product_high, product_piece);
772
b1ec3c92
CH
773 temp = expand_binop (word_mode, binoptab, op1_low, op0_xhigh,
774 NULL_RTX, 0, OPTAB_DIRECT);
77c9c6c2 775
34e56753 776 product_piece = expand_binop (word_mode, add_optab, temp,
77c9c6c2
RK
777 product_high, product_high,
778 0, OPTAB_LIB_WIDEN);
779 if (product_piece != product_high)
780 emit_move_insn (product_high, product_piece);
781
782 temp = emit_move_insn (product, product);
783 REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL,
784 gen_rtx (MULT, mode, op0, op1),
785 REG_NOTES (temp));
786
787 return product;
788 }
789 }
790
791 /* If we get here, we couldn't do it for some reason even though we
792 originally thought we could. Delete anything we've emitted in
793 trying to do it. */
794
795 delete_insns_since (last);
796 }
797
798 /* It can't be open-coded in this mode.
799 Use a library call if one is available and caller says that's ok. */
800
801 if (binoptab->handlers[(int) mode].libfunc
802 && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
803 {
804 rtx insns;
805 rtx funexp = binoptab->handlers[(int) mode].libfunc;
806
807 start_sequence ();
808
809 /* Pass 1 for NO_QUEUE so we don't lose any increments
810 if the libcall is cse'd or moved. */
811 emit_library_call (binoptab->handlers[(int) mode].libfunc,
812 1, mode, 2, op0, mode, op1,
34e56753 813 (shift_op ? word_mode : mode));
77c9c6c2
RK
814
815 insns = get_insns ();
816 end_sequence ();
817
818 target = gen_reg_rtx (mode);
819 emit_libcall_block (insns, target, hard_libcall_value (mode),
820 gen_rtx (binoptab->code, mode, op0, op1));
821
822 return target;
823 }
824
825 delete_insns_since (last);
826
827 /* It can't be done in this mode. Can we do it in a wider mode? */
828
829 if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
830 || methods == OPTAB_MUST_WIDEN))
831 return 0; /* Caller says, don't even try. */
832
833 /* Compute the value of METHODS to pass to recursive calls.
834 Don't allow widening to be tried recursively. */
835
836 methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
837
34e56753
RS
838 /* Look for a wider mode of the same class for which it appears we can do
839 the operation. */
77c9c6c2
RK
840
841 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
842 {
34e56753 843 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
77c9c6c2
RK
844 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
845 {
846 if ((binoptab->handlers[(int) wider_mode].insn_code
847 != CODE_FOR_nothing)
848 || (methods == OPTAB_LIB
849 && binoptab->handlers[(int) wider_mode].libfunc))
850 {
851 rtx xop0 = op0, xop1 = op1;
852 int no_extend = 0;
853
34e56753 854 /* For certain integer operations, we need not actually extend
77c9c6c2
RK
855 the narrow operands, as long as we will truncate
856 the results to the same narrowness. */
857
34e56753
RS
858 if ((binoptab == ior_optab || binoptab == and_optab
859 || binoptab == xor_optab
860 || binoptab == add_optab || binoptab == sub_optab
861 || binoptab == smul_optab
862 || binoptab == ashl_optab || binoptab == lshl_optab)
863 && class == MODE_INT)
77c9c6c2
RK
864 no_extend = 1;
865
34e56753
RS
866 /* If an operand is a constant integer, we might as well
867 convert it since that is more efficient than using a SUBREG,
868 unlike the case for other operands. */
869
870 if (no_extend && GET_MODE (xop0) != VOIDmode)
871 xop0 = gen_rtx (SUBREG, wider_mode,
872 force_reg (GET_MODE (xop0), xop0), 0);
873 else
874 xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
875
876 if (no_extend && GET_MODE (xop1) != VOIDmode)
877 xop1 = gen_rtx (SUBREG, wider_mode,
878 force_reg (GET_MODE (xop1), xop1), 0);
879 else
880 xop1 = convert_to_mode (wider_mode, xop1, unsignedp);
77c9c6c2 881
b1ec3c92 882 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
77c9c6c2
RK
883 unsignedp, methods);
884 if (temp)
885 {
34e56753 886 if (class != MODE_INT)
77c9c6c2
RK
887 {
888 if (target == 0)
889 target = gen_reg_rtx (mode);
890 convert_move (target, temp, 0);
891 return target;
892 }
893 else
894 return gen_lowpart (mode, temp);
895 }
896 else
897 delete_insns_since (last);
898 }
899 }
900 }
901
902 return 0;
903}
904\f
905/* Expand a binary operator which has both signed and unsigned forms.
906 UOPTAB is the optab for unsigned operations, and SOPTAB is for
907 signed operations.
908
909 If we widen unsigned operands, we may use a signed wider operation instead
910 of an unsigned wider operation, since the result would be the same. */
911
912rtx
913sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods)
914 enum machine_mode mode;
915 optab uoptab, soptab;
916 rtx op0, op1, target;
917 int unsignedp;
918 enum optab_methods methods;
919{
920 register rtx temp;
921 optab direct_optab = unsignedp ? uoptab : soptab;
922 struct optab wide_soptab;
923
924 /* Do it without widening, if possible. */
925 temp = expand_binop (mode, direct_optab, op0, op1, target,
926 unsignedp, OPTAB_DIRECT);
927 if (temp || methods == OPTAB_DIRECT)
928 return temp;
929
930 /* Try widening to a signed int. Make a fake signed optab that
931 hides any signed insn for direct use. */
932 wide_soptab = *soptab;
933 wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing;
934 wide_soptab.handlers[(int) mode].libfunc = 0;
935
936 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
937 unsignedp, OPTAB_WIDEN);
938
939 /* For unsigned operands, try widening to an unsigned int. */
940 if (temp == 0 && unsignedp)
941 temp = expand_binop (mode, uoptab, op0, op1, target,
942 unsignedp, OPTAB_WIDEN);
943 if (temp || methods == OPTAB_WIDEN)
944 return temp;
945
946 /* Use the right width lib call if that exists. */
947 temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
948 if (temp || methods == OPTAB_LIB)
949 return temp;
950
951 /* Must widen and use a lib call, use either signed or unsigned. */
952 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
953 unsignedp, methods);
954 if (temp != 0)
955 return temp;
956 if (unsignedp)
957 return expand_binop (mode, uoptab, op0, op1, target,
958 unsignedp, methods);
959 return 0;
960}
961\f
962/* Generate code to perform an operation specified by BINOPTAB
963 on operands OP0 and OP1, with two results to TARG1 and TARG2.
964 We assume that the order of the operands for the instruction
965 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
966 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
967
968 Either TARG0 or TARG1 may be zero, but what that means is that
969 that result is not actually wanted. We will generate it into
970 a dummy pseudo-reg and discard it. They may not both be zero.
971
972 Returns 1 if this operation can be performed; 0 if not. */
973
974int
975expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
976 optab binoptab;
977 rtx op0, op1;
978 rtx targ0, targ1;
979 int unsignedp;
980{
981 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
982 enum mode_class class;
983 enum machine_mode wider_mode;
984 rtx last;
985
986 class = GET_MODE_CLASS (mode);
987
988 op0 = protect_from_queue (op0, 0);
989 op1 = protect_from_queue (op1, 0);
990
991 if (flag_force_mem)
992 {
993 op0 = force_not_mem (op0);
994 op1 = force_not_mem (op1);
995 }
996
997 /* If we are inside an appropriately-short loop and one operand is an
998 expensive constant, force it into a register. */
aeedc93f
RS
999 if (CONSTANT_P (op0) && preserve_subexpressions_p ()
1000 && rtx_cost (op0, binoptab->code) > 2)
77c9c6c2
RK
1001 op0 = force_reg (mode, op0);
1002
aeedc93f
RS
1003 if (CONSTANT_P (op1) && preserve_subexpressions_p ()
1004 && rtx_cost (op1, binoptab->code) > 2)
77c9c6c2
RK
1005 op1 = force_reg (mode, op1);
1006
1007 if (targ0)
1008 targ0 = protect_from_queue (targ0, 1);
1009 else
1010 targ0 = gen_reg_rtx (mode);
1011 if (targ1)
1012 targ1 = protect_from_queue (targ1, 1);
1013 else
1014 targ1 = gen_reg_rtx (mode);
1015
1016 /* Record where to go back to if we fail. */
1017 last = get_last_insn ();
1018
1019 if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1020 {
1021 int icode = (int) binoptab->handlers[(int) mode].insn_code;
1022 enum machine_mode mode0 = insn_operand_mode[icode][1];
1023 enum machine_mode mode1 = insn_operand_mode[icode][2];
1024 rtx pat;
1025 rtx xop0 = op0, xop1 = op1;
1026
1027 /* In case this insn wants input operands in modes different from the
1028 result, convert the operands. */
1029 if (GET_MODE (op0) != VOIDmode && GET_MODE (op0) != mode0)
1030 xop0 = convert_to_mode (mode0, xop0, unsignedp);
1031
1032 if (GET_MODE (op1) != VOIDmode && GET_MODE (op1) != mode1)
1033 xop1 = convert_to_mode (mode1, xop1, unsignedp);
1034
1035 /* Now, if insn doesn't accept these operands, put them into pseudos. */
1036 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
1037 xop0 = copy_to_mode_reg (mode0, xop0);
1038
1039 if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
1040 xop1 = copy_to_mode_reg (mode1, xop1);
1041
1042 /* We could handle this, but we should always be called with a pseudo
1043 for our targets and all insns should take them as outputs. */
1044 if (! (*insn_operand_predicate[icode][0]) (targ0, mode)
1045 || ! (*insn_operand_predicate[icode][3]) (targ1, mode))
1046 abort ();
1047
1048 pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
1049 if (pat)
1050 {
1051 emit_insn (pat);
1052 return 1;
1053 }
1054 else
1055 delete_insns_since (last);
1056 }
1057
1058 /* It can't be done in this mode. Can we do it in a wider mode? */
1059
1060 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1061 {
34e56753 1062 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
77c9c6c2
RK
1063 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1064 {
1065 if (binoptab->handlers[(int) wider_mode].insn_code
1066 != CODE_FOR_nothing)
1067 {
1068 register rtx t0 = gen_reg_rtx (wider_mode);
1069 register rtx t1 = gen_reg_rtx (wider_mode);
1070
1071 if (expand_twoval_binop (binoptab,
1072 convert_to_mode (wider_mode, op0,
1073 unsignedp),
1074 convert_to_mode (wider_mode, op1,
1075 unsignedp),
1076 t0, t1, unsignedp))
1077 {
1078 convert_move (targ0, t0, unsignedp);
1079 convert_move (targ1, t1, unsignedp);
1080 return 1;
1081 }
1082 else
1083 delete_insns_since (last);
1084 }
1085 }
1086 }
1087
1088 return 0;
1089}
1090\f
1091/* Generate code to perform an operation specified by UNOPTAB
1092 on operand OP0, with result having machine-mode MODE.
1093
1094 UNSIGNEDP is for the case where we have to widen the operands
1095 to perform the operation. It says to use zero-extension.
1096
1097 If TARGET is nonzero, the value
1098 is generated there, if it is convenient to do so.
1099 In all cases an rtx is returned for the locus of the value;
1100 this may or may not be TARGET. */
1101
1102rtx
1103expand_unop (mode, unoptab, op0, target, unsignedp)
1104 enum machine_mode mode;
1105 optab unoptab;
1106 rtx op0;
1107 rtx target;
1108 int unsignedp;
1109{
1110 enum mode_class class;
1111 enum machine_mode wider_mode;
77c9c6c2
RK
1112 register rtx temp;
1113 rtx last = get_last_insn ();
1114 rtx pat;
1115
1116 class = GET_MODE_CLASS (mode);
1117
1118 op0 = protect_from_queue (op0, 0);
1119
1120 if (flag_force_mem)
1121 {
1122 op0 = force_not_mem (op0);
1123 }
1124
1125 if (target)
1126 target = protect_from_queue (target, 1);
1127
1128 if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1129 {
1130 int icode = (int) unoptab->handlers[(int) mode].insn_code;
1131 enum machine_mode mode0 = insn_operand_mode[icode][1];
1132 rtx xop0 = op0;
1133
1134 if (target)
1135 temp = target;
1136 else
1137 temp = gen_reg_rtx (mode);
1138
1139 if (GET_MODE (xop0) != VOIDmode
1140 && GET_MODE (xop0) != mode0)
1141 xop0 = convert_to_mode (mode0, xop0, unsignedp);
1142
1143 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
1144
1145 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
1146 xop0 = copy_to_mode_reg (mode0, xop0);
1147
1148 if (! (*insn_operand_predicate[icode][0]) (temp, mode))
1149 temp = gen_reg_rtx (mode);
1150
1151 pat = GEN_FCN (icode) (temp, xop0);
1152 if (pat)
1153 {
1154 if (GET_CODE (pat) == SEQUENCE
b1ec3c92 1155 && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
77c9c6c2
RK
1156 {
1157 delete_insns_since (last);
b1ec3c92 1158 return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
77c9c6c2
RK
1159 }
1160
1161 emit_insn (pat);
1162
1163 return temp;
1164 }
1165 else
1166 delete_insns_since (last);
1167 }
1168
9a856ec7
RK
1169 /* It can't be done in this mode. Can we open-code it in a wider mode? */
1170
1171 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1172 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1173 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1174 {
1175 if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
1176 {
1177 rtx xop0 = op0;
1178
1179 /* For certain operations, we need not actually extend
1180 the narrow operand, as long as we will truncate the
1181 results to the same narrowness. */
1182
1183 if ((unoptab == neg_optab || unoptab == one_cmpl_optab)
1184 && class == MODE_INT)
1185 xop0 = gen_rtx (SUBREG, wider_mode, force_reg (mode, xop0), 0);
1186 else
1187 xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
1188
b1ec3c92
CH
1189 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
1190 unsignedp);
9a856ec7
RK
1191
1192 if (temp)
1193 {
1194 if (class != MODE_INT)
1195 {
1196 if (target == 0)
1197 target = gen_reg_rtx (mode);
1198 convert_move (target, temp, 0);
1199 return target;
1200 }
1201 else
1202 return gen_lowpart (mode, temp);
1203 }
1204 else
1205 delete_insns_since (last);
1206 }
1207 }
1208
77c9c6c2
RK
1209 /* These can be done a word at a time. */
1210 if (unoptab == one_cmpl_optab
1211 && class == MODE_INT
1212 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
34e56753 1213 && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
77c9c6c2
RK
1214 {
1215 int i;
1216 rtx insns;
1217
1218 if (target == 0 || target == op0)
1219 target = gen_reg_rtx (mode);
1220
1221 start_sequence ();
1222
1223 /* Do the actual arithmetic. */
1224 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
1225 {
1226 rtx target_piece = operand_subword (target, i, 1, mode);
34e56753 1227 rtx x = expand_unop (word_mode, unoptab,
77c9c6c2
RK
1228 operand_subword_force (op0, i, mode),
1229 target_piece, unsignedp);
1230 if (target_piece != x)
1231 emit_move_insn (target_piece, x);
1232 }
1233
1234 insns = get_insns ();
1235 end_sequence ();
1236
b1ec3c92 1237 emit_no_conflict_block (insns, target, op0, NULL_RTX,
77c9c6c2
RK
1238 gen_rtx (unoptab->code, mode, op0));
1239 return target;
1240 }
1241
1242 if (unoptab->handlers[(int) mode].libfunc)
1243 {
1244 rtx insns;
1245 rtx funexp = unoptab->handlers[(int) mode].libfunc;
1246
1247 start_sequence ();
1248
1249 /* Pass 1 for NO_QUEUE so we don't lose any increments
1250 if the libcall is cse'd or moved. */
1251 emit_library_call (unoptab->handlers[(int) mode].libfunc,
1252 1, mode, 1, op0, mode);
1253 insns = get_insns ();
1254 end_sequence ();
1255
1256 target = gen_reg_rtx (mode);
1257 emit_libcall_block (insns, target, hard_libcall_value (mode),
1258 gen_rtx (unoptab->code, mode, op0));
1259
1260 return target;
1261 }
1262
1263 /* It can't be done in this mode. Can we do it in a wider mode? */
1264
1265 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1266 {
34e56753 1267 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
77c9c6c2
RK
1268 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1269 {
1270 if ((unoptab->handlers[(int) wider_mode].insn_code
1271 != CODE_FOR_nothing)
1272 || unoptab->handlers[(int) wider_mode].libfunc)
1273 {
34e56753
RS
1274 rtx xop0 = op0;
1275
1276 /* For certain operations, we need not actually extend
1277 the narrow operand, as long as we will truncate the
1278 results to the same narrowness. */
1279
1280 if ((unoptab == neg_optab || unoptab == one_cmpl_optab)
1281 && class == MODE_INT)
1282 xop0 = gen_rtx (SUBREG, wider_mode, force_reg (mode, xop0), 0);
1283 else
1284 xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
77c9c6c2 1285
b1ec3c92
CH
1286 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
1287 unsignedp);
34e56753
RS
1288
1289 if (temp)
77c9c6c2 1290 {
34e56753
RS
1291 if (class != MODE_INT)
1292 {
1293 if (target == 0)
1294 target = gen_reg_rtx (mode);
1295 convert_move (target, temp, 0);
1296 return target;
1297 }
1298 else
1299 return gen_lowpart (mode, temp);
77c9c6c2
RK
1300 }
1301 else
34e56753 1302 delete_insns_since (last);
77c9c6c2
RK
1303 }
1304 }
1305 }
1306
1307 return 0;
1308}
1309\f
1310/* Generate an instruction whose insn-code is INSN_CODE,
1311 with two operands: an output TARGET and an input OP0.
1312 TARGET *must* be nonzero, and the output is always stored there.
1313 CODE is an rtx code such that (CODE OP0) is an rtx that describes
1314 the value that is stored into TARGET. */
1315
1316void
1317emit_unop_insn (icode, target, op0, code)
1318 int icode;
1319 rtx target;
1320 rtx op0;
1321 enum rtx_code code;
1322{
1323 register rtx temp;
1324 enum machine_mode mode0 = insn_operand_mode[icode][1];
1325 rtx pat;
1326
1327 temp = target = protect_from_queue (target, 1);
1328
1329 op0 = protect_from_queue (op0, 0);
1330
1331 if (flag_force_mem)
1332 op0 = force_not_mem (op0);
1333
1334 /* Now, if insn does not accept our operands, put them into pseudos. */
1335
1336 if (! (*insn_operand_predicate[icode][1]) (op0, mode0))
1337 op0 = copy_to_mode_reg (mode0, op0);
1338
1339 if (! (*insn_operand_predicate[icode][0]) (temp, GET_MODE (temp))
1340 || (flag_force_mem && GET_CODE (temp) == MEM))
1341 temp = gen_reg_rtx (GET_MODE (temp));
1342
1343 pat = GEN_FCN (icode) (temp, op0);
1344
1345 if (GET_CODE (pat) == SEQUENCE && code != UNKNOWN)
b1ec3c92 1346 add_equal_note (pat, temp, code, op0, NULL_RTX);
77c9c6c2
RK
1347
1348 emit_insn (pat);
1349
1350 if (temp != target)
1351 emit_move_insn (target, temp);
1352}
1353\f
1354/* Emit code to perform a series of operations on a multi-word quantity, one
1355 word at a time.
1356
d45cf215 1357 Such a block is preceded by a CLOBBER of the output, consists of multiple
77c9c6c2
RK
1358 insns, each setting one word of the output, and followed by a SET copying
1359 the output to itself.
1360
1361 Each of the insns setting words of the output receives a REG_NO_CONFLICT
1362 note indicating that it doesn't conflict with the (also multi-word)
1363 inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
1364 notes.
1365
1366 INSNS is a block of code generated to perform the operation, not including
1367 the CLOBBER and final copy. All insns that compute intermediate values
1368 are first emitted, followed by the block as described above. Only
1369 INSNs are allowed in the block; no library calls or jumps may be
1370 present.
1371
1372 TARGET, OP0, and OP1 are the output and inputs of the operations,
1373 respectively. OP1 may be zero for a unary operation.
1374
1375 EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
1376 on the last insn.
1377
1378 If TARGET is not a register, INSNS is simply emitted with no special
1379 processing.
1380
1381 The final insn emitted is returned. */
1382
1383rtx
1384emit_no_conflict_block (insns, target, op0, op1, equiv)
1385 rtx insns;
1386 rtx target;
1387 rtx op0, op1;
1388 rtx equiv;
1389{
1390 rtx prev, next, first, last, insn;
1391
1392 if (GET_CODE (target) != REG || reload_in_progress)
1393 return emit_insns (insns);
1394
1395 /* First emit all insns that do not store into words of the output and remove
1396 these from the list. */
1397 for (insn = insns; insn; insn = next)
1398 {
1399 rtx set = 0;
1400 int i;
1401
1402 next = NEXT_INSN (insn);
1403
1404 if (GET_CODE (insn) != INSN)
1405 abort ();
1406
1407 if (GET_CODE (PATTERN (insn)) == SET)
1408 set = PATTERN (insn);
1409 else if (GET_CODE (PATTERN (insn)) == PARALLEL)
1410 {
1411 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
1412 if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
1413 {
1414 set = XVECEXP (PATTERN (insn), 0, i);
1415 break;
1416 }
1417 }
1418
1419 if (set == 0)
1420 abort ();
1421
1422 if (! reg_overlap_mentioned_p (target, SET_DEST (set)))
1423 {
1424 if (PREV_INSN (insn))
1425 NEXT_INSN (PREV_INSN (insn)) = next;
1426 else
1427 insns = next;
1428
1429 if (next)
1430 PREV_INSN (next) = PREV_INSN (insn);
1431
1432 add_insn (insn);
1433 }
1434 }
1435
1436 prev = get_last_insn ();
1437
1438 /* Now write the CLOBBER of the output, followed by the setting of each
1439 of the words, followed by the final copy. */
1440 if (target != op0 && target != op1)
1441 emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
1442
1443 for (insn = insns; insn; insn = next)
1444 {
1445 next = NEXT_INSN (insn);
1446 add_insn (insn);
1447
1448 if (op1 && GET_CODE (op1) == REG)
1449 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_NO_CONFLICT, op1,
1450 REG_NOTES (insn));
1451
1452 if (op0 && GET_CODE (op0) == REG)
1453 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_NO_CONFLICT, op0,
1454 REG_NOTES (insn));
1455 }
1456
1457 last = emit_move_insn (target, target);
1458 if (equiv)
1459 REG_NOTES (last) = gen_rtx (EXPR_LIST, REG_EQUAL, equiv, REG_NOTES (last));
1460
1461 if (prev == 0)
1462 first = get_insns ();
1463 else
1464 first = NEXT_INSN (prev);
1465
1466 /* Encapsulate the block so it gets manipulated as a unit. */
1467 REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last,
1468 REG_NOTES (first));
1469 REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last));
1470
1471 return last;
1472}
1473\f
1474/* Emit code to make a call to a constant function or a library call.
1475
1476 INSNS is a list containing all insns emitted in the call.
1477 These insns leave the result in RESULT. Our block is to copy RESULT
1478 to TARGET, which is logically equivalent to EQUIV.
1479
1480 We first emit any insns that set a pseudo on the assumption that these are
1481 loading constants into registers; doing so allows them to be safely cse'ed
1482 between blocks. Then we emit all the other insns in the block, followed by
1483 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
1484 note with an operand of EQUIV.
1485
29ebe69a
RK
1486 Moving assignments to pseudos outside of the block is done to improve
1487 the generated code, but is not required to generate correct code,
1488 hence being unable to move an assignment is not grounds for not making
1489 a libcall block. There are two reasons why it is safe to leave these
1490 insns inside the block: First, we know that these pseudos cannot be
1491 used in generated RTL outside the block since they are created for
1492 temporary purposes within the block. Second, CSE will not record the
1493 values of anything set inside a libcall block, so we know they must
1494 be dead at the end of the block.
1495
77c9c6c2
RK
1496 Except for the first group of insns (the ones setting pseudos), the
1497 block is delimited by REG_RETVAL and REG_LIBCALL notes. */
1498
1499void
1500emit_libcall_block (insns, target, result, equiv)
1501 rtx insns;
1502 rtx target;
1503 rtx result;
1504 rtx equiv;
1505{
1506 rtx prev, next, first, last, insn;
1507
1508 /* First emit all insns that set pseudos. Remove them from the list as
29ebe69a
RK
1509 we go. Avoid insns that set pseudo which were referenced in previous
1510 insns. These can be generated by move_by_pieces, for example,
1511 to update an address. */
77c9c6c2
RK
1512
1513 for (insn = insns; insn; insn = next)
1514 {
1515 rtx set = single_set (insn);
1516
1517 next = NEXT_INSN (insn);
1518
1519 if (set != 0 && GET_CODE (SET_DEST (set)) == REG
29ebe69a 1520 && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
8d9e73cc
RS
1521 && (insn == insns
1522 || (! reg_mentioned_p (SET_DEST (set), PATTERN (insns))
1523 && ! reg_used_between_p (SET_DEST (set), insns, insn))))
77c9c6c2
RK
1524 {
1525 if (PREV_INSN (insn))
1526 NEXT_INSN (PREV_INSN (insn)) = next;
1527 else
1528 insns = next;
1529
1530 if (next)
1531 PREV_INSN (next) = PREV_INSN (insn);
1532
1533 add_insn (insn);
1534 }
1535 }
1536
1537 prev = get_last_insn ();
1538
1539 /* Write the remaining insns followed by the final copy. */
1540
1541 for (insn = insns; insn; insn = next)
1542 {
1543 next = NEXT_INSN (insn);
1544
1545 add_insn (insn);
1546 }
1547
1548 last = emit_move_insn (target, result);
1549 REG_NOTES (last) = gen_rtx (EXPR_LIST, REG_EQUAL, equiv, REG_NOTES (last));
1550
1551 if (prev == 0)
1552 first = get_insns ();
1553 else
1554 first = NEXT_INSN (prev);
1555
1556 /* Encapsulate the block so it gets manipulated as a unit. */
1557 REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last,
1558 REG_NOTES (first));
1559 REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last));
1560}
1561\f
1562/* Generate code to store zero in X. */
1563
1564void
1565emit_clr_insn (x)
1566 rtx x;
1567{
1568 emit_move_insn (x, const0_rtx);
1569}
1570
1571/* Generate code to store 1 in X
1572 assuming it contains zero beforehand. */
1573
1574void
1575emit_0_to_1_insn (x)
1576 rtx x;
1577{
1578 emit_move_insn (x, const1_rtx);
1579}
1580
1581/* Generate code to compare X with Y
1582 so that the condition codes are set.
1583
1584 MODE is the mode of the inputs (in case they are const_int).
1585 UNSIGNEDP nonzero says that X and Y are unsigned;
1586 this matters if they need to be widened.
1587
1588 If they have mode BLKmode, then SIZE specifies the size of both X and Y,
1589 and ALIGN specifies the known shared alignment of X and Y.
1590
1591 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
1592 It is ignored for fixed-point and block comparisons;
1593 it is used only for floating-point comparisons. */
1594
1595void
1596emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
1597 rtx x, y;
1598 enum rtx_code comparison;
1599 rtx size;
2aa8f23f 1600 enum machine_mode mode;
77c9c6c2
RK
1601 int unsignedp;
1602 int align;
1603{
1604 enum mode_class class;
1605 enum machine_mode wider_mode;
1606
1607 class = GET_MODE_CLASS (mode);
1608
1609 /* They could both be VOIDmode if both args are immediate constants,
1610 but we should fold that at an earlier stage.
1611 With no special code here, this will call abort,
1612 reminding the programmer to implement such folding. */
1613
1614 if (mode != BLKmode && flag_force_mem)
1615 {
1616 x = force_not_mem (x);
1617 y = force_not_mem (y);
1618 }
1619
1620 /* If we are inside an appropriately-short loop and one operand is an
1621 expensive constant, force it into a register. */
aeedc93f 1622 if (CONSTANT_P (x) && preserve_subexpressions_p () && rtx_cost (x, COMPARE) > 2)
77c9c6c2
RK
1623 x = force_reg (mode, x);
1624
aeedc93f 1625 if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2)
77c9c6c2
RK
1626 y = force_reg (mode, y);
1627
1628 /* Don't let both operands fail to indicate the mode. */
1629 if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
1630 x = force_reg (mode, x);
1631
1632 /* Handle all BLKmode compares. */
1633
1634 if (mode == BLKmode)
1635 {
1636 emit_queue ();
1637 x = protect_from_queue (x, 0);
1638 y = protect_from_queue (y, 0);
1639
1640 if (size == 0)
1641 abort ();
1642#ifdef HAVE_cmpstrqi
1643 if (HAVE_cmpstrqi
1644 && GET_CODE (size) == CONST_INT
1645 && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
1646 {
1647 enum machine_mode result_mode
1648 = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0];
1649 rtx result = gen_reg_rtx (result_mode);
b1ec3c92
CH
1650 emit_insn (gen_cmpstrqi (result, x, y, size, GEN_INT (align)));
1651 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
1652 result_mode, 0, 0);
77c9c6c2
RK
1653 }
1654 else
1655#endif
1656#ifdef HAVE_cmpstrhi
1657 if (HAVE_cmpstrhi
1658 && GET_CODE (size) == CONST_INT
1659 && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
1660 {
1661 enum machine_mode result_mode
1662 = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0];
1663 rtx result = gen_reg_rtx (result_mode);
b1ec3c92
CH
1664 emit_insn (gen_cmpstrhi (result, x, y, size, GEN_INT (align)));
1665 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
1666 result_mode, 0, 0);
77c9c6c2
RK
1667 }
1668 else
1669#endif
1670#ifdef HAVE_cmpstrsi
1671 if (HAVE_cmpstrsi)
1672 {
1673 enum machine_mode result_mode
1674 = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0];
1675 rtx result = gen_reg_rtx (result_mode);
1676 emit_insn (gen_cmpstrsi (result, x, y,
1677 convert_to_mode (SImode, size, 1),
b1ec3c92
CH
1678 GEN_INT (align)));
1679 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
1680 result_mode, 0, 0);
77c9c6c2
RK
1681 }
1682 else
1683#endif
1684 {
1685#ifdef TARGET_MEM_FUNCTIONS
86f8eff3 1686 emit_library_call (memcmp_libfunc, 1,
77c9c6c2
RK
1687 TYPE_MODE (integer_type_node), 3,
1688 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
1689 size, Pmode);
1690#else
86f8eff3 1691 emit_library_call (bcmp_libfunc, 1,
77c9c6c2
RK
1692 TYPE_MODE (integer_type_node), 3,
1693 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
1694 size, Pmode);
1695#endif
1696 emit_cmp_insn (hard_libcall_value (TYPE_MODE (integer_type_node)),
b1ec3c92 1697 const0_rtx, comparison, NULL_RTX,
77c9c6c2
RK
1698 TYPE_MODE (integer_type_node), 0, 0);
1699 }
1700 return;
1701 }
1702
1703 /* Handle some compares against zero. */
1704
1705 if (y == CONST0_RTX (mode)
1706 && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1707 {
1708 int icode = (int) tst_optab->handlers[(int) mode].insn_code;
1709
1710 emit_queue ();
1711 x = protect_from_queue (x, 0);
1712 y = protect_from_queue (y, 0);
1713
1714 /* Now, if insn does accept these operands, put them into pseudos. */
1715 if (! (*insn_operand_predicate[icode][0])
1716 (x, insn_operand_mode[icode][0]))
1717 x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
1718
1719 emit_insn (GEN_FCN (icode) (x));
1720 return;
1721 }
1722
1723 /* Handle compares for which there is a directly suitable insn. */
1724
1725 if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1726 {
1727 int icode = (int) cmp_optab->handlers[(int) mode].insn_code;
1728
1729 emit_queue ();
1730 x = protect_from_queue (x, 0);
1731 y = protect_from_queue (y, 0);
1732
1733 /* Now, if insn doesn't accept these operands, put them into pseudos. */
1734 if (! (*insn_operand_predicate[icode][0])
1735 (x, insn_operand_mode[icode][0]))
1736 x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
1737
1738 if (! (*insn_operand_predicate[icode][1])
1739 (y, insn_operand_mode[icode][1]))
1740 y = copy_to_mode_reg (insn_operand_mode[icode][1], y);
1741
1742 emit_insn (GEN_FCN (icode) (x, y));
1743 return;
1744 }
1745
1746 /* Try widening if we can find a direct insn that way. */
1747
1748 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1749 {
34e56753 1750 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
77c9c6c2
RK
1751 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1752 {
1753 if (cmp_optab->handlers[(int) wider_mode].insn_code
1754 != CODE_FOR_nothing)
1755 {
1756 x = convert_to_mode (wider_mode, x, unsignedp);
1757 y = convert_to_mode (wider_mode, y, unsignedp);
b1ec3c92 1758 emit_cmp_insn (x, y, comparison, NULL_RTX,
77c9c6c2
RK
1759 wider_mode, unsignedp, align);
1760 return;
1761 }
1762 }
1763 }
1764
1765 /* Handle a lib call just for the mode we are using. */
1766
1767 if (cmp_optab->handlers[(int) mode].libfunc
1768 && class != MODE_FLOAT)
1769 {
1770 rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
1771 /* If we want unsigned, and this mode has a distinct unsigned
1772 comparison routine, use that. */
1773 if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
1774 libfunc = ucmp_optab->handlers[(int) mode].libfunc;
1775
86f8eff3 1776 emit_library_call (libfunc, 1,
77c9c6c2
RK
1777 SImode, 2, x, mode, y, mode);
1778
1779 /* Integer comparison returns a result that must be compared against 1,
1780 so that even if we do an unsigned compare afterward,
1781 there is still a value that can represent the result "less than". */
1782
1783 emit_cmp_insn (hard_libcall_value (SImode), const1_rtx,
b1ec3c92 1784 comparison, NULL_RTX, SImode, unsignedp, 0);
77c9c6c2
RK
1785 return;
1786 }
1787
1788 if (class == MODE_FLOAT)
1789 emit_float_lib_cmp (x, y, comparison);
1790
1791 else
1792 abort ();
1793}
1794
1795/* Nonzero if a compare of mode MODE can be done straightforwardly
1796 (without splitting it into pieces). */
1797
1798int
1799can_compare_p (mode)
1800 enum machine_mode mode;
1801{
1802 do
1803 {
1804 if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
1805 return 1;
1806 mode = GET_MODE_WIDER_MODE (mode);
1807 } while (mode != VOIDmode);
1808
1809 return 0;
1810}
1811\f
1812/* Emit a library call comparison between floating point X and Y.
1813 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
1814
1815static void
1816emit_float_lib_cmp (x, y, comparison)
1817 rtx x, y;
1818 enum rtx_code comparison;
1819{
1820 enum machine_mode mode = GET_MODE (x);
1821 rtx libfunc;
1822
1823 if (mode == SFmode)
1824 switch (comparison)
1825 {
1826 case EQ:
1827 libfunc = eqsf2_libfunc;
1828 break;
1829
1830 case NE:
1831 libfunc = nesf2_libfunc;
1832 break;
1833
1834 case GT:
1835 libfunc = gtsf2_libfunc;
1836 break;
1837
1838 case GE:
1839 libfunc = gesf2_libfunc;
1840 break;
1841
1842 case LT:
1843 libfunc = ltsf2_libfunc;
1844 break;
1845
1846 case LE:
1847 libfunc = lesf2_libfunc;
1848 break;
1849 }
1850 else if (mode == DFmode)
1851 switch (comparison)
1852 {
1853 case EQ:
1854 libfunc = eqdf2_libfunc;
1855 break;
1856
1857 case NE:
1858 libfunc = nedf2_libfunc;
1859 break;
1860
1861 case GT:
1862 libfunc = gtdf2_libfunc;
1863 break;
1864
1865 case GE:
1866 libfunc = gedf2_libfunc;
1867 break;
1868
1869 case LT:
1870 libfunc = ltdf2_libfunc;
1871 break;
1872
1873 case LE:
1874 libfunc = ledf2_libfunc;
1875 break;
1876 }
b092b471
JW
1877 else if (mode == XFmode)
1878 switch (comparison)
1879 {
1880 case EQ:
1881 libfunc = eqxf2_libfunc;
1882 break;
1883
1884 case NE:
1885 libfunc = nexf2_libfunc;
1886 break;
1887
1888 case GT:
1889 libfunc = gtxf2_libfunc;
1890 break;
1891
1892 case GE:
1893 libfunc = gexf2_libfunc;
1894 break;
1895
1896 case LT:
1897 libfunc = ltxf2_libfunc;
1898 break;
1899
1900 case LE:
1901 libfunc = lexf2_libfunc;
1902 break;
1903 }
1904 else if (mode == TFmode)
1905 switch (comparison)
1906 {
1907 case EQ:
1908 libfunc = eqtf2_libfunc;
1909 break;
1910
1911 case NE:
1912 libfunc = netf2_libfunc;
1913 break;
1914
1915 case GT:
1916 libfunc = gttf2_libfunc;
1917 break;
1918
1919 case GE:
1920 libfunc = getf2_libfunc;
1921 break;
1922
1923 case LT:
1924 libfunc = lttf2_libfunc;
1925 break;
1926
1927 case LE:
1928 libfunc = letf2_libfunc;
1929 break;
1930 }
77c9c6c2
RK
1931 else
1932 {
1933 enum machine_mode wider_mode;
1934
34e56753 1935 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
77c9c6c2
RK
1936 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1937 {
1938 if ((cmp_optab->handlers[(int) wider_mode].insn_code
1939 != CODE_FOR_nothing)
1940 || (cmp_optab->handlers[(int) wider_mode].libfunc != 0))
1941 {
1942 x = convert_to_mode (wider_mode, x, 0);
1943 y = convert_to_mode (wider_mode, y, 0);
1944 emit_float_lib_cmp (x, y, comparison);
1945 return;
1946 }
1947 }
1948 abort ();
1949 }
1950
86f8eff3 1951 emit_library_call (libfunc, 1,
77c9c6c2
RK
1952 SImode, 2, x, mode, y, mode);
1953
1954 emit_cmp_insn (hard_libcall_value (SImode), const0_rtx, comparison,
b1ec3c92 1955 NULL_RTX, SImode, 0, 0);
77c9c6c2
RK
1956}
1957\f
1958/* Generate code to indirectly jump to a location given in the rtx LOC. */
1959
1960void
1961emit_indirect_jump (loc)
1962 rtx loc;
1963{
1964 if (! ((*insn_operand_predicate[(int)CODE_FOR_indirect_jump][0])
1965 (loc, VOIDmode)))
1966 loc = copy_to_mode_reg (insn_operand_mode[(int)CODE_FOR_indirect_jump][0],
1967 loc);
1968
1969 emit_jump_insn (gen_indirect_jump (loc));
9649fb4d 1970 emit_barrier ();
77c9c6c2
RK
1971}
1972\f
1973/* These three functions generate an insn body and return it
1974 rather than emitting the insn.
1975
1976 They do not protect from queued increments,
1977 because they may be used 1) in protect_from_queue itself
1978 and 2) in other passes where there is no queue. */
1979
1980/* Generate and return an insn body to add Y to X. */
1981
1982rtx
1983gen_add2_insn (x, y)
1984 rtx x, y;
1985{
1986 int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code;
1987
1988 if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
1989 || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
1990 || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
1991 abort ();
1992
1993 return (GEN_FCN (icode) (x, x, y));
1994}
1995
1996int
1997have_add2_insn (mode)
1998 enum machine_mode mode;
1999{
2000 return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
2001}
2002
2003/* Generate and return an insn body to subtract Y from X. */
2004
2005rtx
2006gen_sub2_insn (x, y)
2007 rtx x, y;
2008{
2009 int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code;
2010
2011 if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
2012 || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
2013 || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
2014 abort ();
2015
2016 return (GEN_FCN (icode) (x, x, y));
2017}
2018
2019int
2020have_sub2_insn (mode)
2021 enum machine_mode mode;
2022{
2023 return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
2024}
2025
2026/* Generate the body of an instruction to copy Y into X. */
2027
2028rtx
2029gen_move_insn (x, y)
2030 rtx x, y;
2031{
2032 register enum machine_mode mode = GET_MODE (x);
2033 enum insn_code insn_code;
2034
2035 if (mode == VOIDmode)
2036 mode = GET_MODE (y);
2037
2038 insn_code = mov_optab->handlers[(int) mode].insn_code;
2039
2040 /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
2041 find a mode to do it in. If we have a movcc, use it. Otherwise,
2042 find the MODE_INT mode of the same width. */
2043
2044 if (insn_code == CODE_FOR_nothing)
2045 {
2046 enum machine_mode tmode = VOIDmode;
2047 rtx x1 = x, y1 = y;
2048
2049 if (GET_MODE_CLASS (mode) == MODE_CC && mode != CCmode
2050 && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing)
2051 tmode = CCmode;
2052 else if (GET_MODE_CLASS (mode) == MODE_CC)
2053 for (tmode = QImode; tmode != VOIDmode;
2054 tmode = GET_MODE_WIDER_MODE (tmode))
2055 if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode))
2056 break;
2057
2058 if (tmode == VOIDmode)
2059 abort ();
2060
2061 /* Get X and Y in TMODE. We can't use gen_lowpart here because it
2062 may call change_address which is not appropriate if we were
2063 called when a reload was in progress. We don't have to worry
2064 about changing the address since the size in bytes is supposed to
2065 be the same. Copy the MEM to change the mode and move any
2066 substitutions from the old MEM to the new one. */
2067
2068 if (reload_in_progress)
2069 {
2070 x = gen_lowpart_common (tmode, x1);
2071 if (x == 0 && GET_CODE (x1) == MEM)
2072 {
2073 x = gen_rtx (MEM, tmode, XEXP (x1, 0));
2074 RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1);
2075 MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (x1);
2076 MEM_VOLATILE_P (x) = MEM_VOLATILE_P (x1);
2077 copy_replacements (x1, x);
2078 }
2079
2080 y = gen_lowpart_common (tmode, y1);
2081 if (y == 0 && GET_CODE (y1) == MEM)
2082 {
2083 y = gen_rtx (MEM, tmode, XEXP (y1, 0));
2084 RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1);
2085 MEM_IN_STRUCT_P (y) = MEM_IN_STRUCT_P (y1);
2086 MEM_VOLATILE_P (y) = MEM_VOLATILE_P (y1);
2087 copy_replacements (y1, y);
2088 }
2089 }
2090 else
2091 {
2092 x = gen_lowpart (tmode, x);
2093 y = gen_lowpart (tmode, y);
2094 }
2095
2096 insn_code = mov_optab->handlers[(int) tmode].insn_code;
2097 }
2098
2099 return (GEN_FCN (insn_code) (x, y));
2100}
2101\f
2102/* Tables of patterns for extending one integer mode to another. */
34e56753 2103static enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2];
77c9c6c2 2104
34e56753
RS
2105/* Return the insn code used to extend FROM_MODE to TO_MODE.
2106 UNSIGNEDP specifies zero-extension instead of sign-extension. If
2107 no such operation exists, CODE_FOR_nothing will be returned. */
77c9c6c2 2108
34e56753 2109enum insn_code
77c9c6c2
RK
2110can_extend_p (to_mode, from_mode, unsignedp)
2111 enum machine_mode to_mode, from_mode;
2112 int unsignedp;
2113{
34e56753 2114 return extendtab[(int) to_mode][(int) from_mode][unsignedp];
77c9c6c2
RK
2115}
2116
2117/* Generate the body of an insn to extend Y (with mode MFROM)
2118 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
2119
2120rtx
2121gen_extend_insn (x, y, mto, mfrom, unsignedp)
2122 rtx x, y;
2123 enum machine_mode mto, mfrom;
2124 int unsignedp;
2125{
34e56753 2126 return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp]) (x, y));
77c9c6c2
RK
2127}
2128
2129static void
2130init_extends ()
2131{
34e56753
RS
2132 enum insn_code *p;
2133
2134 for (p = extendtab[0][0];
2135 p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0];
2136 p++)
2137 *p = CODE_FOR_nothing;
77c9c6c2
RK
2138
2139#ifdef HAVE_extendditi2
2140 if (HAVE_extendditi2)
34e56753 2141 extendtab[(int) TImode][(int) DImode][0] = CODE_FOR_extendditi2;
77c9c6c2
RK
2142#endif
2143#ifdef HAVE_extendsiti2
2144 if (HAVE_extendsiti2)
34e56753 2145 extendtab[(int) TImode][(int) SImode][0] = CODE_FOR_extendsiti2;
77c9c6c2
RK
2146#endif
2147#ifdef HAVE_extendhiti2
2148 if (HAVE_extendhiti2)
34e56753 2149 extendtab[(int) TImode][(int) HImode][0] = CODE_FOR_extendhiti2;
77c9c6c2
RK
2150#endif
2151#ifdef HAVE_extendqiti2
2152 if (HAVE_extendqiti2)
34e56753 2153 extendtab[(int) TImode][(int) QImode][0] = CODE_FOR_extendqiti2;
77c9c6c2
RK
2154#endif
2155#ifdef HAVE_extendsidi2
2156 if (HAVE_extendsidi2)
34e56753 2157 extendtab[(int) DImode][(int) SImode][0] = CODE_FOR_extendsidi2;
77c9c6c2
RK
2158#endif
2159#ifdef HAVE_extendhidi2
2160 if (HAVE_extendhidi2)
34e56753 2161 extendtab[(int) DImode][(int) HImode][0] = CODE_FOR_extendhidi2;
77c9c6c2
RK
2162#endif
2163#ifdef HAVE_extendqidi2
2164 if (HAVE_extendqidi2)
34e56753 2165 extendtab[(int) DImode][(int) QImode][0] = CODE_FOR_extendqidi2;
77c9c6c2
RK
2166#endif
2167#ifdef HAVE_extendhisi2
2168 if (HAVE_extendhisi2)
34e56753 2169 extendtab[(int) SImode][(int) HImode][0] = CODE_FOR_extendhisi2;
77c9c6c2
RK
2170#endif
2171#ifdef HAVE_extendqisi2
2172 if (HAVE_extendqisi2)
34e56753 2173 extendtab[(int) SImode][(int) QImode][0] = CODE_FOR_extendqisi2;
77c9c6c2
RK
2174#endif
2175#ifdef HAVE_extendqihi2
2176 if (HAVE_extendqihi2)
34e56753 2177 extendtab[(int) HImode][(int) QImode][0] = CODE_FOR_extendqihi2;
77c9c6c2
RK
2178#endif
2179
2180#ifdef HAVE_zero_extendditi2
2181 if (HAVE_zero_extendsiti2)
34e56753 2182 extendtab[(int) TImode][(int) DImode][1] = CODE_FOR_zero_extendditi2;
77c9c6c2
RK
2183#endif
2184#ifdef HAVE_zero_extendsiti2
2185 if (HAVE_zero_extendsiti2)
34e56753 2186 extendtab[(int) TImode][(int) SImode][1] = CODE_FOR_zero_extendsiti2;
77c9c6c2
RK
2187#endif
2188#ifdef HAVE_zero_extendhiti2
2189 if (HAVE_zero_extendhiti2)
34e56753 2190 extendtab[(int) TImode][(int) HImode][1] = CODE_FOR_zero_extendhiti2;
77c9c6c2
RK
2191#endif
2192#ifdef HAVE_zero_extendqiti2
2193 if (HAVE_zero_extendqiti2)
34e56753 2194 extendtab[(int) TImode][(int) QImode][1] = CODE_FOR_zero_extendqiti2;
77c9c6c2
RK
2195#endif
2196#ifdef HAVE_zero_extendsidi2
2197 if (HAVE_zero_extendsidi2)
34e56753 2198 extendtab[(int) DImode][(int) SImode][1] = CODE_FOR_zero_extendsidi2;
77c9c6c2
RK
2199#endif
2200#ifdef HAVE_zero_extendhidi2
2201 if (HAVE_zero_extendhidi2)
34e56753 2202 extendtab[(int) DImode][(int) HImode][1] = CODE_FOR_zero_extendhidi2;
77c9c6c2
RK
2203#endif
2204#ifdef HAVE_zero_extendqidi2
2205 if (HAVE_zero_extendqidi2)
34e56753 2206 extendtab[(int) DImode][(int) QImode][1] = CODE_FOR_zero_extendqidi2;
77c9c6c2
RK
2207#endif
2208#ifdef HAVE_zero_extendhisi2
2209 if (HAVE_zero_extendhisi2)
34e56753 2210 extendtab[(int) SImode][(int) HImode][1] = CODE_FOR_zero_extendhisi2;
77c9c6c2
RK
2211#endif
2212#ifdef HAVE_zero_extendqisi2
2213 if (HAVE_zero_extendqisi2)
34e56753 2214 extendtab[(int) SImode][(int) QImode][1] = CODE_FOR_zero_extendqisi2;
77c9c6c2
RK
2215#endif
2216#ifdef HAVE_zero_extendqihi2
2217 if (HAVE_zero_extendqihi2)
34e56753 2218 extendtab[(int) HImode][(int) QImode][1] = CODE_FOR_zero_extendqihi2;
77c9c6c2
RK
2219#endif
2220}
2221\f
2222/* can_fix_p and can_float_p say whether the target machine
2223 can directly convert a given fixed point type to
2224 a given floating point type, or vice versa.
2225 The returned value is the CODE_FOR_... value to use,
2226 or CODE_FOR_nothing if these modes cannot be directly converted. */
2227
2228static enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
2229static enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
2230static enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
2231
2232/* *TRUNCP_PTR is set to 1 if it is necessary to output
2233 an explicit FTRUNC insn before the fix insn; otherwise 0. */
2234
2235static enum insn_code
2236can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
2237 enum machine_mode fltmode, fixmode;
2238 int unsignedp;
2239 int *truncp_ptr;
2240{
2241 *truncp_ptr = 0;
2242 if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp] != CODE_FOR_nothing)
2243 return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp];
2244
2245 if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
2246 {
2247 *truncp_ptr = 1;
2248 return fixtab[(int) fltmode][(int) fixmode][unsignedp];
2249 }
2250 return CODE_FOR_nothing;
2251}
2252
2253static enum insn_code
2254can_float_p (fltmode, fixmode, unsignedp)
2255 enum machine_mode fixmode, fltmode;
2256 int unsignedp;
2257{
2258 return floattab[(int) fltmode][(int) fixmode][unsignedp];
2259}
2260
2261void
2262init_fixtab ()
2263{
2264 enum insn_code *p;
2265 for (p = fixtab[0][0];
2266 p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]);
2267 p++)
2268 *p = CODE_FOR_nothing;
2269 for (p = fixtrunctab[0][0];
2270 p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]);
2271 p++)
2272 *p = CODE_FOR_nothing;
2273
2274#ifdef HAVE_fixsfqi2
2275 if (HAVE_fixsfqi2)
2276 fixtab[(int) SFmode][(int) QImode][0] = CODE_FOR_fixsfqi2;
2277#endif
2278#ifdef HAVE_fixsfhi2
2279 if (HAVE_fixsfhi2)
2280 fixtab[(int) SFmode][(int) HImode][0] = CODE_FOR_fixsfhi2;
2281#endif
2282#ifdef HAVE_fixsfsi2
2283 if (HAVE_fixsfsi2)
2284 fixtab[(int) SFmode][(int) SImode][0] = CODE_FOR_fixsfsi2;
2285#endif
2286#ifdef HAVE_fixsfdi2
2287 if (HAVE_fixsfdi2)
2288 fixtab[(int) SFmode][(int) DImode][0] = CODE_FOR_fixsfdi2;
2289#endif
2290
2291#ifdef HAVE_fixdfqi2
2292 if (HAVE_fixdfqi2)
2293 fixtab[(int) DFmode][(int) QImode][0] = CODE_FOR_fixdfqi2;
2294#endif
2295#ifdef HAVE_fixdfhi2
2296 if (HAVE_fixdfhi2)
2297 fixtab[(int) DFmode][(int) HImode][0] = CODE_FOR_fixdfhi2;
2298#endif
2299#ifdef HAVE_fixdfsi2
2300 if (HAVE_fixdfsi2)
2301 fixtab[(int) DFmode][(int) SImode][0] = CODE_FOR_fixdfsi2;
2302#endif
2303#ifdef HAVE_fixdfdi2
2304 if (HAVE_fixdfdi2)
2305 fixtab[(int) DFmode][(int) DImode][0] = CODE_FOR_fixdfdi2;
2306#endif
2307#ifdef HAVE_fixdfti2
2308 if (HAVE_fixdfti2)
2309 fixtab[(int) DFmode][(int) TImode][0] = CODE_FOR_fixdfti2;
2310#endif
2311
b092b471
JW
2312#ifdef HAVE_fixxfqi2
2313 if (HAVE_fixxfqi2)
2314 fixtab[(int) XFmode][(int) QImode][0] = CODE_FOR_fixxfqi2;
2315#endif
2316#ifdef HAVE_fixxfhi2
2317 if (HAVE_fixxfhi2)
2318 fixtab[(int) XFmode][(int) HImode][0] = CODE_FOR_fixxfhi2;
2319#endif
2320#ifdef HAVE_fixxfsi2
2321 if (HAVE_fixxfsi2)
2322 fixtab[(int) XFmode][(int) SImode][0] = CODE_FOR_fixxfsi2;
2323#endif
2324#ifdef HAVE_fixxfdi2
2325 if (HAVE_fixxfdi2)
2326 fixtab[(int) XFmode][(int) DImode][0] = CODE_FOR_fixxfdi2;
2327#endif
2328#ifdef HAVE_fixxfti2
2329 if (HAVE_fixxfti2)
2330 fixtab[(int) XFmode][(int) TImode][0] = CODE_FOR_fixxfti2;
2331#endif
2332
77c9c6c2
RK
2333#ifdef HAVE_fixtfqi2
2334 if (HAVE_fixtfqi2)
2335 fixtab[(int) TFmode][(int) QImode][0] = CODE_FOR_fixtfqi2;
2336#endif
2337#ifdef HAVE_fixtfhi2
2338 if (HAVE_fixtfhi2)
2339 fixtab[(int) TFmode][(int) HImode][0] = CODE_FOR_fixtfhi2;
2340#endif
2341#ifdef HAVE_fixtfsi2
2342 if (HAVE_fixtfsi2)
2343 fixtab[(int) TFmode][(int) SImode][0] = CODE_FOR_fixtfsi2;
2344#endif
2345#ifdef HAVE_fixtfdi2
2346 if (HAVE_fixtfdi2)
2347 fixtab[(int) TFmode][(int) DImode][0] = CODE_FOR_fixtfdi2;
2348#endif
2349#ifdef HAVE_fixtfti2
2350 if (HAVE_fixtfti2)
2351 fixtab[(int) TFmode][(int) TImode][0] = CODE_FOR_fixtfti2;
2352#endif
2353
2354#ifdef HAVE_fixunssfqi2
2355 if (HAVE_fixunssfqi2)
2356 fixtab[(int) SFmode][(int) QImode][1] = CODE_FOR_fixunssfqi2;
2357#endif
2358#ifdef HAVE_fixunssfhi2
2359 if (HAVE_fixunssfhi2)
2360 fixtab[(int) SFmode][(int) HImode][1] = CODE_FOR_fixunssfhi2;
2361#endif
2362#ifdef HAVE_fixunssfsi2
2363 if (HAVE_fixunssfsi2)
2364 fixtab[(int) SFmode][(int) SImode][1] = CODE_FOR_fixunssfsi2;
2365#endif
2366#ifdef HAVE_fixunssfdi2
2367 if (HAVE_fixunssfdi2)
2368 fixtab[(int) SFmode][(int) DImode][1] = CODE_FOR_fixunssfdi2;
2369#endif
2370
2371#ifdef HAVE_fixunsdfqi2
2372 if (HAVE_fixunsdfqi2)
2373 fixtab[(int) DFmode][(int) QImode][1] = CODE_FOR_fixunsdfqi2;
2374#endif
2375#ifdef HAVE_fixunsdfhi2
2376 if (HAVE_fixunsdfhi2)
2377 fixtab[(int) DFmode][(int) HImode][1] = CODE_FOR_fixunsdfhi2;
2378#endif
2379#ifdef HAVE_fixunsdfsi2
2380 if (HAVE_fixunsdfsi2)
2381 fixtab[(int) DFmode][(int) SImode][1] = CODE_FOR_fixunsdfsi2;
2382#endif
2383#ifdef HAVE_fixunsdfdi2
2384 if (HAVE_fixunsdfdi2)
2385 fixtab[(int) DFmode][(int) DImode][1] = CODE_FOR_fixunsdfdi2;
2386#endif
2387#ifdef HAVE_fixunsdfti2
2388 if (HAVE_fixunsdfti2)
2389 fixtab[(int) DFmode][(int) TImode][1] = CODE_FOR_fixunsdfti2;
2390#endif
2391
b092b471
JW
2392#ifdef HAVE_fixunsxfqi2
2393 if (HAVE_fixunsxfqi2)
2394 fixtab[(int) XFmode][(int) QImode][1] = CODE_FOR_fixunsxfqi2;
2395#endif
2396#ifdef HAVE_fixunsxfhi2
2397 if (HAVE_fixunsxfhi2)
2398 fixtab[(int) XFmode][(int) HImode][1] = CODE_FOR_fixunsxfhi2;
2399#endif
2400#ifdef HAVE_fixunsxfsi2
2401 if (HAVE_fixunsxfsi2)
2402 fixtab[(int) XFmode][(int) SImode][1] = CODE_FOR_fixunsxfsi2;
2403#endif
2404#ifdef HAVE_fixunsxfdi2
2405 if (HAVE_fixunsxfdi2)
2406 fixtab[(int) XFmode][(int) DImode][1] = CODE_FOR_fixunsxfdi2;
2407#endif
2408#ifdef HAVE_fixunsxfti2
2409 if (HAVE_fixunsxfti2)
2410 fixtab[(int) XFmode][(int) TImode][1] = CODE_FOR_fixunsxfti2;
2411#endif
2412
77c9c6c2
RK
2413#ifdef HAVE_fixunstfqi2
2414 if (HAVE_fixunstfqi2)
2415 fixtab[(int) TFmode][(int) QImode][1] = CODE_FOR_fixunstfqi2;
2416#endif
2417#ifdef HAVE_fixunstfhi2
2418 if (HAVE_fixunstfhi2)
2419 fixtab[(int) TFmode][(int) HImode][1] = CODE_FOR_fixunstfhi2;
2420#endif
2421#ifdef HAVE_fixunstfsi2
2422 if (HAVE_fixunstfsi2)
2423 fixtab[(int) TFmode][(int) SImode][1] = CODE_FOR_fixunstfsi2;
2424#endif
2425#ifdef HAVE_fixunstfdi2
2426 if (HAVE_fixunstfdi2)
2427 fixtab[(int) TFmode][(int) DImode][1] = CODE_FOR_fixunstfdi2;
2428#endif
2429#ifdef HAVE_fixunstfti2
2430 if (HAVE_fixunstfti2)
2431 fixtab[(int) TFmode][(int) TImode][1] = CODE_FOR_fixunstfti2;
2432#endif
2433
2434#ifdef HAVE_fix_truncsfqi2
2435 if (HAVE_fix_truncsfqi2)
2436 fixtrunctab[(int) SFmode][(int) QImode][0] = CODE_FOR_fix_truncsfqi2;
2437#endif
2438#ifdef HAVE_fix_truncsfhi2
2439 if (HAVE_fix_truncsfhi2)
2440 fixtrunctab[(int) SFmode][(int) HImode][0] = CODE_FOR_fix_truncsfhi2;
2441#endif
2442#ifdef HAVE_fix_truncsfsi2
2443 if (HAVE_fix_truncsfsi2)
2444 fixtrunctab[(int) SFmode][(int) SImode][0] = CODE_FOR_fix_truncsfsi2;
2445#endif
2446#ifdef HAVE_fix_truncsfdi2
2447 if (HAVE_fix_truncsfdi2)
2448 fixtrunctab[(int) SFmode][(int) DImode][0] = CODE_FOR_fix_truncsfdi2;
2449#endif
2450
2451#ifdef HAVE_fix_truncdfqi2
2452 if (HAVE_fix_truncdfsi2)
2453 fixtrunctab[(int) DFmode][(int) QImode][0] = CODE_FOR_fix_truncdfqi2;
2454#endif
2455#ifdef HAVE_fix_truncdfhi2
2456 if (HAVE_fix_truncdfhi2)
2457 fixtrunctab[(int) DFmode][(int) HImode][0] = CODE_FOR_fix_truncdfhi2;
2458#endif
2459#ifdef HAVE_fix_truncdfsi2
2460 if (HAVE_fix_truncdfsi2)
2461 fixtrunctab[(int) DFmode][(int) SImode][0] = CODE_FOR_fix_truncdfsi2;
2462#endif
2463#ifdef HAVE_fix_truncdfdi2
2464 if (HAVE_fix_truncdfdi2)
2465 fixtrunctab[(int) DFmode][(int) DImode][0] = CODE_FOR_fix_truncdfdi2;
2466#endif
2467#ifdef HAVE_fix_truncdfti2
2468 if (HAVE_fix_truncdfti2)
2469 fixtrunctab[(int) DFmode][(int) TImode][0] = CODE_FOR_fix_truncdfti2;
2470#endif
2471
b092b471
JW
2472#ifdef HAVE_fix_truncxfqi2
2473 if (HAVE_fix_truncxfqi2)
2474 fixtrunctab[(int) XFmode][(int) QImode][0] = CODE_FOR_fix_truncxfqi2;
2475#endif
2476#ifdef HAVE_fix_truncxfhi2
2477 if (HAVE_fix_truncxfhi2)
2478 fixtrunctab[(int) XFmode][(int) HImode][0] = CODE_FOR_fix_truncxfhi2;
2479#endif
2480#ifdef HAVE_fix_truncxfsi2
2481 if (HAVE_fix_truncxfsi2)
2482 fixtrunctab[(int) XFmode][(int) SImode][0] = CODE_FOR_fix_truncxfsi2;
2483#endif
2484#ifdef HAVE_fix_truncxfdi2
2485 if (HAVE_fix_truncxfdi2)
2486 fixtrunctab[(int) XFmode][(int) DImode][0] = CODE_FOR_fix_truncxfdi2;
2487#endif
2488#ifdef HAVE_fix_truncxfti2
2489 if (HAVE_fix_truncxfti2)
2490 fixtrunctab[(int) XFmode][(int) TImode][0] = CODE_FOR_fix_truncxfti2;
2491#endif
2492
77c9c6c2
RK
2493#ifdef HAVE_fix_trunctfqi2
2494 if (HAVE_fix_trunctfqi2)
2495 fixtrunctab[(int) TFmode][(int) QImode][0] = CODE_FOR_fix_trunctfqi2;
2496#endif
2497#ifdef HAVE_fix_trunctfhi2
2498 if (HAVE_fix_trunctfhi2)
2499 fixtrunctab[(int) TFmode][(int) HImode][0] = CODE_FOR_fix_trunctfhi2;
2500#endif
2501#ifdef HAVE_fix_trunctfsi2
2502 if (HAVE_fix_trunctfsi2)
2503 fixtrunctab[(int) TFmode][(int) SImode][0] = CODE_FOR_fix_trunctfsi2;
2504#endif
2505#ifdef HAVE_fix_trunctfdi2
2506 if (HAVE_fix_trunctfdi2)
2507 fixtrunctab[(int) TFmode][(int) DImode][0] = CODE_FOR_fix_trunctfdi2;
2508#endif
2509#ifdef HAVE_fix_trunctfti2
2510 if (HAVE_fix_trunctfti2)
2511 fixtrunctab[(int) TFmode][(int) TImode][0] = CODE_FOR_fix_trunctfti2;
2512#endif
2513
2514#ifdef HAVE_fixuns_truncsfqi2
2515 if (HAVE_fixuns_truncsfqi2)
2516 fixtrunctab[(int) SFmode][(int) QImode][1] = CODE_FOR_fixuns_truncsfqi2;
2517#endif
2518#ifdef HAVE_fixuns_truncsfhi2
2519 if (HAVE_fixuns_truncsfhi2)
2520 fixtrunctab[(int) SFmode][(int) HImode][1] = CODE_FOR_fixuns_truncsfhi2;
2521#endif
2522#ifdef HAVE_fixuns_truncsfsi2
2523 if (HAVE_fixuns_truncsfsi2)
2524 fixtrunctab[(int) SFmode][(int) SImode][1] = CODE_FOR_fixuns_truncsfsi2;
2525#endif
2526#ifdef HAVE_fixuns_truncsfdi2
2527 if (HAVE_fixuns_truncsfdi2)
2528 fixtrunctab[(int) SFmode][(int) DImode][1] = CODE_FOR_fixuns_truncsfdi2;
2529#endif
2530
2531#ifdef HAVE_fixuns_truncdfqi2
2532 if (HAVE_fixuns_truncdfqi2)
2533 fixtrunctab[(int) DFmode][(int) QImode][1] = CODE_FOR_fixuns_truncdfqi2;
2534#endif
2535#ifdef HAVE_fixuns_truncdfhi2
2536 if (HAVE_fixuns_truncdfhi2)
2537 fixtrunctab[(int) DFmode][(int) HImode][1] = CODE_FOR_fixuns_truncdfhi2;
2538#endif
2539#ifdef HAVE_fixuns_truncdfsi2
2540 if (HAVE_fixuns_truncdfsi2)
2541 fixtrunctab[(int) DFmode][(int) SImode][1] = CODE_FOR_fixuns_truncdfsi2;
2542#endif
2543#ifdef HAVE_fixuns_truncdfdi2
2544 if (HAVE_fixuns_truncdfdi2)
2545 fixtrunctab[(int) DFmode][(int) DImode][1] = CODE_FOR_fixuns_truncdfdi2;
2546#endif
2547#ifdef HAVE_fixuns_truncdfti2
2548 if (HAVE_fixuns_truncdfti2)
2549 fixtrunctab[(int) DFmode][(int) TImode][1] = CODE_FOR_fixuns_truncdfti2;
2550#endif
2551
b092b471
JW
2552#ifdef HAVE_fixuns_truncxfqi2
2553 if (HAVE_fixuns_truncxfqi2)
2554 fixtrunctab[(int) XFmode][(int) QImode][1] = CODE_FOR_fixuns_truncxfqi2;
2555#endif
2556#ifdef HAVE_fixuns_truncxfhi2
2557 if (HAVE_fixuns_truncxfhi2)
2558 fixtrunctab[(int) XFmode][(int) HImode][1] = CODE_FOR_fixuns_truncxfhi2;
2559#endif
2560#ifdef HAVE_fixuns_truncxfsi2
2561 if (HAVE_fixuns_truncxfsi2)
2562 fixtrunctab[(int) XFmode][(int) SImode][1] = CODE_FOR_fixuns_truncxfsi2;
2563#endif
2564#ifdef HAVE_fixuns_truncxfdi2
2565 if (HAVE_fixuns_truncxfdi2)
2566 fixtrunctab[(int) XFmode][(int) DImode][1] = CODE_FOR_fixuns_truncxfdi2;
2567#endif
2568#ifdef HAVE_fixuns_truncxfti2
2569 if (HAVE_fixuns_truncxfti2)
2570 fixtrunctab[(int) XFmode][(int) TImode][1] = CODE_FOR_fixuns_truncxfti2;
2571#endif
2572
77c9c6c2
RK
2573#ifdef HAVE_fixuns_trunctfqi2
2574 if (HAVE_fixuns_trunctfqi2)
2575 fixtrunctab[(int) TFmode][(int) QImode][1] = CODE_FOR_fixuns_trunctfqi2;
2576#endif
2577#ifdef HAVE_fixuns_trunctfhi2
2578 if (HAVE_fixuns_trunctfhi2)
2579 fixtrunctab[(int) TFmode][(int) HImode][1] = CODE_FOR_fixuns_trunctfhi2;
2580#endif
2581#ifdef HAVE_fixuns_trunctfsi2
2582 if (HAVE_fixuns_trunctfsi2)
2583 fixtrunctab[(int) TFmode][(int) SImode][1] = CODE_FOR_fixuns_trunctfsi2;
2584#endif
2585#ifdef HAVE_fixuns_trunctfdi2
2586 if (HAVE_fixuns_trunctfdi2)
2587 fixtrunctab[(int) TFmode][(int) DImode][1] = CODE_FOR_fixuns_trunctfdi2;
2588#endif
2589#ifdef HAVE_fixuns_trunctfti2
2590 if (HAVE_fixuns_trunctfti2)
2591 fixtrunctab[(int) TFmode][(int) TImode][1] = CODE_FOR_fixuns_trunctfti2;
2592#endif
2593
2594#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
2595 /* This flag says the same insns that convert to a signed fixnum
2596 also convert validly to an unsigned one. */
2597 {
2598 int i;
2599 int j;
2600 for (i = 0; i < NUM_MACHINE_MODES; i++)
2601 for (j = 0; j < NUM_MACHINE_MODES; j++)
2602 fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
2603 }
2604#endif
2605}
2606
2607void
2608init_floattab ()
2609{
2610 enum insn_code *p;
2611 for (p = floattab[0][0];
2612 p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]);
2613 p++)
2614 *p = CODE_FOR_nothing;
2615
2616#ifdef HAVE_floatqisf2
2617 if (HAVE_floatqisf2)
2618 floattab[(int) SFmode][(int) QImode][0] = CODE_FOR_floatqisf2;
2619#endif
2620#ifdef HAVE_floathisf2
2621 if (HAVE_floathisf2)
2622 floattab[(int) SFmode][(int) HImode][0] = CODE_FOR_floathisf2;
2623#endif
2624#ifdef HAVE_floatsisf2
2625 if (HAVE_floatsisf2)
2626 floattab[(int) SFmode][(int) SImode][0] = CODE_FOR_floatsisf2;
2627#endif
2628#ifdef HAVE_floatdisf2
2629 if (HAVE_floatdisf2)
2630 floattab[(int) SFmode][(int) DImode][0] = CODE_FOR_floatdisf2;
2631#endif
2632#ifdef HAVE_floattisf2
2633 if (HAVE_floattisf2)
2634 floattab[(int) SFmode][(int) TImode][0] = CODE_FOR_floattisf2;
2635#endif
2636
2637#ifdef HAVE_floatqidf2
2638 if (HAVE_floatqidf2)
2639 floattab[(int) DFmode][(int) QImode][0] = CODE_FOR_floatqidf2;
2640#endif
2641#ifdef HAVE_floathidf2
2642 if (HAVE_floathidf2)
2643 floattab[(int) DFmode][(int) HImode][0] = CODE_FOR_floathidf2;
2644#endif
2645#ifdef HAVE_floatsidf2
2646 if (HAVE_floatsidf2)
2647 floattab[(int) DFmode][(int) SImode][0] = CODE_FOR_floatsidf2;
2648#endif
2649#ifdef HAVE_floatdidf2
2650 if (HAVE_floatdidf2)
2651 floattab[(int) DFmode][(int) DImode][0] = CODE_FOR_floatdidf2;
2652#endif
2653#ifdef HAVE_floattidf2
2654 if (HAVE_floattidf2)
2655 floattab[(int) DFmode][(int) TImode][0] = CODE_FOR_floattidf2;
2656#endif
2657
b092b471
JW
2658#ifdef HAVE_floatqixf2
2659 if (HAVE_floatqixf2)
2660 floattab[(int) XFmode][(int) QImode][0] = CODE_FOR_floatqixf2;
2661#endif
2662#ifdef HAVE_floathixf2
2663 if (HAVE_floathixf2)
2664 floattab[(int) XFmode][(int) HImode][0] = CODE_FOR_floathixf2;
2665#endif
2666#ifdef HAVE_floatsixf2
2667 if (HAVE_floatsixf2)
2668 floattab[(int) XFmode][(int) SImode][0] = CODE_FOR_floatsixf2;
2669#endif
2670#ifdef HAVE_floatdixf2
2671 if (HAVE_floatdixf2)
2672 floattab[(int) XFmode][(int) DImode][0] = CODE_FOR_floatdixf2;
2673#endif
2674#ifdef HAVE_floattixf2
2675 if (HAVE_floattixf2)
2676 floattab[(int) XFmode][(int) TImode][0] = CODE_FOR_floattixf2;
2677#endif
2678
77c9c6c2
RK
2679#ifdef HAVE_floatqitf2
2680 if (HAVE_floatqitf2)
2681 floattab[(int) TFmode][(int) QImode][0] = CODE_FOR_floatqitf2;
2682#endif
2683#ifdef HAVE_floathitf2
2684 if (HAVE_floathitf2)
2685 floattab[(int) TFmode][(int) HImode][0] = CODE_FOR_floathitf2;
2686#endif
2687#ifdef HAVE_floatsitf2
2688 if (HAVE_floatsitf2)
2689 floattab[(int) TFmode][(int) SImode][0] = CODE_FOR_floatsitf2;
2690#endif
2691#ifdef HAVE_floatditf2
2692 if (HAVE_floatditf2)
2693 floattab[(int) TFmode][(int) DImode][0] = CODE_FOR_floatditf2;
2694#endif
2695#ifdef HAVE_floattitf2
2696 if (HAVE_floattitf2)
2697 floattab[(int) TFmode][(int) TImode][0] = CODE_FOR_floattitf2;
2698#endif
2699
2700#ifdef HAVE_floatunsqisf2
2701 if (HAVE_floatunsqisf2)
2702 floattab[(int) SFmode][(int) QImode][1] = CODE_FOR_floatunsqisf2;
2703#endif
2704#ifdef HAVE_floatunshisf2
2705 if (HAVE_floatunshisf2)
2706 floattab[(int) SFmode][(int) HImode][1] = CODE_FOR_floatunshisf2;
2707#endif
2708#ifdef HAVE_floatunssisf2
2709 if (HAVE_floatunssisf2)
2710 floattab[(int) SFmode][(int) SImode][1] = CODE_FOR_floatunssisf2;
2711#endif
2712#ifdef HAVE_floatunsdisf2
2713 if (HAVE_floatunsdisf2)
2714 floattab[(int) SFmode][(int) DImode][1] = CODE_FOR_floatunsdisf2;
2715#endif
2716#ifdef HAVE_floatunstisf2
2717 if (HAVE_floatunstisf2)
2718 floattab[(int) SFmode][(int) TImode][1] = CODE_FOR_floatunstisf2;
2719#endif
2720
2721#ifdef HAVE_floatunsqidf2
2722 if (HAVE_floatunsqidf2)
2723 floattab[(int) DFmode][(int) QImode][1] = CODE_FOR_floatunsqidf2;
2724#endif
2725#ifdef HAVE_floatunshidf2
2726 if (HAVE_floatunshidf2)
2727 floattab[(int) DFmode][(int) HImode][1] = CODE_FOR_floatunshidf2;
2728#endif
2729#ifdef HAVE_floatunssidf2
2730 if (HAVE_floatunssidf2)
2731 floattab[(int) DFmode][(int) SImode][1] = CODE_FOR_floatunssidf2;
2732#endif
2733#ifdef HAVE_floatunsdidf2
2734 if (HAVE_floatunsdidf2)
2735 floattab[(int) DFmode][(int) DImode][1] = CODE_FOR_floatunsdidf2;
2736#endif
2737#ifdef HAVE_floatunstidf2
2738 if (HAVE_floatunstidf2)
2739 floattab[(int) DFmode][(int) TImode][1] = CODE_FOR_floatunstidf2;
2740#endif
2741
b092b471
JW
2742#ifdef HAVE_floatunsqixf2
2743 if (HAVE_floatunsqixf2)
2744 floattab[(int) XFmode][(int) QImode][1] = CODE_FOR_floatunsqixf2;
2745#endif
2746#ifdef HAVE_floatunshixf2
2747 if (HAVE_floatunshixf2)
2748 floattab[(int) XFmode][(int) HImode][1] = CODE_FOR_floatunshixf2;
2749#endif
2750#ifdef HAVE_floatunssixf2
2751 if (HAVE_floatunssixf2)
2752 floattab[(int) XFmode][(int) SImode][1] = CODE_FOR_floatunssixf2;
2753#endif
2754#ifdef HAVE_floatunsdixf2
2755 if (HAVE_floatunsdixf2)
2756 floattab[(int) XFmode][(int) DImode][1] = CODE_FOR_floatunsdixf2;
2757#endif
2758#ifdef HAVE_floatunstixf2
2759 if (HAVE_floatunstixf2)
2760 floattab[(int) XFmode][(int) TImode][1] = CODE_FOR_floatunstixf2;
2761#endif
2762
77c9c6c2
RK
2763#ifdef HAVE_floatunsqitf2
2764 if (HAVE_floatunsqitf2)
2765 floattab[(int) TFmode][(int) QImode][1] = CODE_FOR_floatunsqitf2;
2766#endif
2767#ifdef HAVE_floatunshitf2
2768 if (HAVE_floatunshitf2)
2769 floattab[(int) TFmode][(int) HImode][1] = CODE_FOR_floatunshitf2;
2770#endif
2771#ifdef HAVE_floatunssitf2
2772 if (HAVE_floatunssitf2)
2773 floattab[(int) TFmode][(int) SImode][1] = CODE_FOR_floatunssitf2;
2774#endif
2775#ifdef HAVE_floatunsditf2
2776 if (HAVE_floatunsditf2)
2777 floattab[(int) TFmode][(int) DImode][1] = CODE_FOR_floatunsditf2;
2778#endif
2779#ifdef HAVE_floatunstitf2
2780 if (HAVE_floatunstitf2)
2781 floattab[(int) TFmode][(int) TImode][1] = CODE_FOR_floatunstitf2;
2782#endif
2783}
2784\f
2785/* Generate code to convert FROM to floating point
34e56753 2786 and store in TO. FROM must be fixed point and not VOIDmode.
77c9c6c2
RK
2787 UNSIGNEDP nonzero means regard FROM as unsigned.
2788 Normally this is done by correcting the final value
2789 if it is negative. */
2790
2791void
2792expand_float (to, from, unsignedp)
2793 rtx to, from;
2794 int unsignedp;
2795{
2796 enum insn_code icode;
2797 register rtx target = to;
2798 enum machine_mode fmode, imode;
2799
34e56753
RS
2800 /* Crash now, because we won't be able to decide which mode to use. */
2801 if (GET_MODE (from) == VOIDmode)
2802 abort ();
2803
77c9c6c2
RK
2804 /* Look for an insn to do the conversion. Do it in the specified
2805 modes if possible; otherwise convert either input, output or both to
2806 wider mode. If the integer mode is wider than the mode of FROM,
2807 we can do the conversion signed even if the input is unsigned. */
2808
2809 for (imode = GET_MODE (from); imode != VOIDmode;
2810 imode = GET_MODE_WIDER_MODE (imode))
2811 for (fmode = GET_MODE (to); fmode != VOIDmode;
2812 fmode = GET_MODE_WIDER_MODE (fmode))
2813 {
2814 int doing_unsigned = unsignedp;
2815
2816 icode = can_float_p (fmode, imode, unsignedp);
2817 if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
2818 icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;
2819
2820 if (icode != CODE_FOR_nothing)
2821 {
2822 to = protect_from_queue (to, 1);
2823
2824 if (imode != GET_MODE (from))
2825 from = convert_to_mode (imode, from, unsignedp);
2826 else
2827 from = protect_from_queue (from, 0);
2828
2829 if (fmode != GET_MODE (to))
2830 target = gen_reg_rtx (fmode);
2831
2832 emit_unop_insn (icode, target, from,
2833 doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
2834
2835 if (target != to)
2836 convert_move (to, target, 0);
2837 return;
2838 }
2839 }
2840
2841#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
2842
2843 /* Unsigned integer, and no way to convert directly.
2844 Convert as signed, then conditionally adjust the result. */
2845 if (unsignedp)
2846 {
2847 rtx label = gen_label_rtx ();
2848 rtx temp;
2849 REAL_VALUE_TYPE offset;
2850
2851 emit_queue ();
2852
2853 to = protect_from_queue (to, 1);
2854 from = protect_from_queue (from, 0);
2855
2856 if (flag_force_mem)
2857 from = force_not_mem (from);
2858
2859 /* If we are about to do some arithmetic to correct for an
2860 unsigned operand, do it in a pseudo-register. */
2861
2862 if (GET_CODE (to) != REG || REGNO (to) <= LAST_VIRTUAL_REGISTER)
2863 target = gen_reg_rtx (GET_MODE (to));
2864
2865 /* Convert as signed integer to floating. */
2866 expand_float (target, from, 0);
2867
2868 /* If FROM is negative (and therefore TO is negative),
2869 correct its value by 2**bitwidth. */
2870
2871 do_pending_stack_adjust ();
b1ec3c92 2872 emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, GET_MODE (from), 0, 0);
77c9c6c2
RK
2873 emit_jump_insn (gen_bge (label));
2874 /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
2875 Rather than setting up a dconst_dot_5, let's hope SCO
2876 fixes the bug. */
2877 offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from)));
2878 temp = expand_binop (GET_MODE (to), add_optab, target,
2879 immed_real_const_1 (offset, GET_MODE (to)),
2880 target, 0, OPTAB_LIB_WIDEN);
2881 if (temp != target)
2882 emit_move_insn (target, temp);
2883 do_pending_stack_adjust ();
2884 emit_label (label);
2885 }
2886 else
2887#endif
2888
b092b471
JW
2889 /* No hardware instruction available; call a library rotine to convert from
2890 SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */
77c9c6c2 2891 {
6bce1b78 2892 rtx libfcn;
77c9c6c2
RK
2893 rtx insns;
2894
2895 to = protect_from_queue (to, 1);
2896
2897 if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
2898 from = convert_to_mode (SImode, from, unsignedp);
2899 else
2900 from = protect_from_queue (from, 0);
2901
2902 if (flag_force_mem)
2903 from = force_not_mem (from);
2904
2905 if (GET_MODE (to) == SFmode)
2906 {
2907 if (GET_MODE (from) == SImode)
6bce1b78 2908 libfcn = floatsisf_libfunc;
77c9c6c2 2909 else if (GET_MODE (from) == DImode)
6bce1b78 2910 libfcn = floatdisf_libfunc;
b092b471
JW
2911 else if (GET_MODE (from) == TImode)
2912 libfcn = floattisf_libfunc;
77c9c6c2
RK
2913 else
2914 abort ();
2915 }
2916 else if (GET_MODE (to) == DFmode)
2917 {
2918 if (GET_MODE (from) == SImode)
6bce1b78 2919 libfcn = floatsidf_libfunc;
77c9c6c2 2920 else if (GET_MODE (from) == DImode)
6bce1b78 2921 libfcn = floatdidf_libfunc;
b092b471
JW
2922 else if (GET_MODE (from) == TImode)
2923 libfcn = floattidf_libfunc;
2924 else
2925 abort ();
2926 }
2927 else if (GET_MODE (to) == XFmode)
2928 {
2929 if (GET_MODE (from) == SImode)
2930 libfcn = floatsixf_libfunc;
2931 else if (GET_MODE (from) == DImode)
2932 libfcn = floatdixf_libfunc;
2933 else if (GET_MODE (from) == TImode)
2934 libfcn = floattixf_libfunc;
2935 else
2936 abort ();
2937 }
2938 else if (GET_MODE (to) == TFmode)
2939 {
2940 if (GET_MODE (from) == SImode)
2941 libfcn = floatsitf_libfunc;
2942 else if (GET_MODE (from) == DImode)
2943 libfcn = floatditf_libfunc;
2944 else if (GET_MODE (from) == TImode)
2945 libfcn = floattitf_libfunc;
77c9c6c2
RK
2946 else
2947 abort ();
2948 }
2949 else
2950 abort ();
2951
2952 start_sequence ();
2953
86f8eff3 2954 emit_library_call (libfcn, 1, GET_MODE (to), 1, from, GET_MODE (from));
77c9c6c2
RK
2955 insns = get_insns ();
2956 end_sequence ();
2957
2958 emit_libcall_block (insns, target, hard_libcall_value (GET_MODE (to)),
2959 gen_rtx (FLOAT, GET_MODE (to), from));
2960 }
2961
2962 /* Copy result to requested destination
2963 if we have been computing in a temp location. */
2964
2965 if (target != to)
2966 {
2967 if (GET_MODE (target) == GET_MODE (to))
2968 emit_move_insn (to, target);
2969 else
2970 convert_move (to, target, 0);
2971 }
2972}
2973\f
2974/* expand_fix: generate code to convert FROM to fixed point
2975 and store in TO. FROM must be floating point. */
2976
2977static rtx
2978ftruncify (x)
2979 rtx x;
2980{
2981 rtx temp = gen_reg_rtx (GET_MODE (x));
2982 return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0);
2983}
2984
2985void
2986expand_fix (to, from, unsignedp)
2987 register rtx to, from;
2988 int unsignedp;
2989{
2990 enum insn_code icode;
2991 register rtx target = to;
2992 enum machine_mode fmode, imode;
2993 int must_trunc = 0;
6bce1b78 2994 rtx libfcn = 0;
77c9c6c2
RK
2995
2996 /* We first try to find a pair of modes, one real and one integer, at
2997 least as wide as FROM and TO, respectively, in which we can open-code
2998 this conversion. If the integer mode is wider than the mode of TO,
2999 we can do the conversion either signed or unsigned. */
3000
3001 for (imode = GET_MODE (to); imode != VOIDmode;
3002 imode = GET_MODE_WIDER_MODE (imode))
3003 for (fmode = GET_MODE (from); fmode != VOIDmode;
3004 fmode = GET_MODE_WIDER_MODE (fmode))
3005 {
3006 int doing_unsigned = unsignedp;
3007
3008 icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
3009 if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
3010 icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
3011
3012 if (icode != CODE_FOR_nothing)
3013 {
3014 to = protect_from_queue (to, 1);
3015
3016 if (fmode != GET_MODE (from))
3017 from = convert_to_mode (fmode, from, 0);
3018 else
3019 from = protect_from_queue (from, 0);
3020
3021 if (must_trunc)
3022 from = ftruncify (from);
3023
3024 if (imode != GET_MODE (to))
3025 target = gen_reg_rtx (imode);
3026
3027 emit_unop_insn (icode, target, from,
3028 doing_unsigned ? UNSIGNED_FIX : FIX);
3029 if (target != to)
3030 convert_move (to, target, unsignedp);
3031 return;
3032 }
3033 }
3034
3035#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3036 /* For an unsigned conversion, there is one more way to do it.
3037 If we have a signed conversion, we generate code that compares
3038 the real value to the largest representable positive number. If if
3039 is smaller, the conversion is done normally. Otherwise, subtract
3040 one plus the highest signed number, convert, and add it back.
3041
3042 We only need to check all real modes, since we know we didn't find
6dc42e49 3043 anything with a wider integer mode. */
77c9c6c2 3044
b1ec3c92 3045 if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
77c9c6c2
RK
3046 for (fmode = GET_MODE (from); fmode != VOIDmode;
3047 fmode = GET_MODE_WIDER_MODE (fmode))
3048 /* Make sure we won't lose significant bits doing this. */
3049 if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))
3050 && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
3051 &must_trunc))
3052 {
3053 int bitsize = GET_MODE_BITSIZE (GET_MODE (to));
3054 REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1);
3055 rtx limit = immed_real_const_1 (offset, fmode);
3056 rtx lab1 = gen_label_rtx ();
3057 rtx lab2 = gen_label_rtx ();
3058 rtx insn;
3059
3060 emit_queue ();
3061 to = protect_from_queue (to, 1);
3062 from = protect_from_queue (from, 0);
3063
3064 if (flag_force_mem)
3065 from = force_not_mem (from);
3066
3067 if (fmode != GET_MODE (from))
3068 from = convert_to_mode (fmode, from, 0);
3069
3070 /* See if we need to do the subtraction. */
3071 do_pending_stack_adjust ();
b1ec3c92 3072 emit_cmp_insn (from, limit, GE, NULL_RTX, GET_MODE (from), 0, 0);
77c9c6c2
RK
3073 emit_jump_insn (gen_bge (lab1));
3074
3075 /* If not, do the signed "fix" and branch around fixup code. */
3076 expand_fix (to, from, 0);
3077 emit_jump_insn (gen_jump (lab2));
3078 emit_barrier ();
3079
3080 /* Otherwise, subtract 2**(N-1), convert to signed number,
3081 then add 2**(N-1). Do the addition using XOR since this
3082 will often generate better code. */
3083 emit_label (lab1);
3084 target = expand_binop (GET_MODE (from), sub_optab, from, limit,
b1ec3c92 3085 NULL_RTX, 0, OPTAB_LIB_WIDEN);
77c9c6c2
RK
3086 expand_fix (to, target, 0);
3087 target = expand_binop (GET_MODE (to), xor_optab, to,
b1ec3c92 3088 GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)),
77c9c6c2
RK
3089 to, 1, OPTAB_LIB_WIDEN);
3090
3091 if (target != to)
3092 emit_move_insn (to, target);
3093
3094 emit_label (lab2);
3095
3096 /* Make a place for a REG_NOTE and add it. */
3097 insn = emit_move_insn (to, to);
3098 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
3099 gen_rtx (UNSIGNED_FIX, GET_MODE (to),
3100 from), REG_NOTES (insn));
3101
3102 return;
3103 }
3104#endif
3105
3106 /* We can't do it with an insn, so use a library call. But first ensure
3107 that the mode of TO is at least as wide as SImode, since those are the
3108 only library calls we know about. */
3109
3110 if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
3111 {
3112 target = gen_reg_rtx (SImode);
3113
3114 expand_fix (target, from, unsignedp);
3115 }
3116 else if (GET_MODE (from) == SFmode)
3117 {
3118 if (GET_MODE (to) == SImode)
6bce1b78 3119 libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc;
77c9c6c2 3120 else if (GET_MODE (to) == DImode)
6bce1b78 3121 libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc;
b092b471
JW
3122 else if (GET_MODE (to) == TImode)
3123 libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc;
77c9c6c2
RK
3124 else
3125 abort ();
3126 }
3127 else if (GET_MODE (from) == DFmode)
3128 {
3129 if (GET_MODE (to) == SImode)
6bce1b78 3130 libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc;
77c9c6c2 3131 else if (GET_MODE (to) == DImode)
6bce1b78 3132 libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc;
b092b471
JW
3133 else if (GET_MODE (to) == TImode)
3134 libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc;
3135 else
3136 abort ();
3137 }
3138 else if (GET_MODE (from) == XFmode)
3139 {
3140 if (GET_MODE (to) == SImode)
3141 libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc;
3142 else if (GET_MODE (to) == DImode)
3143 libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc;
3144 else if (GET_MODE (to) == TImode)
3145 libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc;
3146 else
3147 abort ();
3148 }
3149 else if (GET_MODE (from) == TFmode)
3150 {
3151 if (GET_MODE (to) == SImode)
3152 libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc;
3153 else if (GET_MODE (to) == DImode)
3154 libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc;
3155 else if (GET_MODE (to) == TImode)
3156 libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc;
77c9c6c2
RK
3157 else
3158 abort ();
3159 }
3160 else
3161 abort ();
3162
6bce1b78 3163 if (libfcn)
77c9c6c2
RK
3164 {
3165 rtx insns;
3166
3167 to = protect_from_queue (to, 1);
3168 from = protect_from_queue (from, 0);
3169
3170 if (flag_force_mem)
3171 from = force_not_mem (from);
3172
3173 start_sequence ();
3174
86f8eff3 3175 emit_library_call (libfcn, 1, GET_MODE (to), 1, from, GET_MODE (from));
77c9c6c2
RK
3176 insns = get_insns ();
3177 end_sequence ();
3178
3179 emit_libcall_block (insns, target, hard_libcall_value (GET_MODE (to)),
3180 gen_rtx (unsignedp ? FIX : UNSIGNED_FIX,
3181 GET_MODE (to), from));
3182 }
3183
3184 if (GET_MODE (to) == GET_MODE (target))
3185 emit_move_insn (to, target);
3186 else
3187 convert_move (to, target, 0);
3188}
3189\f
3190static optab
3191init_optab (code)
3192 enum rtx_code code;
3193{
3194 int i;
3195 optab op = (optab) xmalloc (sizeof (struct optab));
3196 op->code = code;
3197 for (i = 0; i < NUM_MACHINE_MODES; i++)
3198 {
3199 op->handlers[i].insn_code = CODE_FOR_nothing;
3200 op->handlers[i].libfunc = 0;
3201 }
3202 return op;
3203}
3204
b092b471
JW
3205/* Initialize the libfunc fields of an entire group of entries in some
3206 optab. Each entry is set equal to a string consisting of a leading
3207 pair of underscores followed by a generic operation name followed by
3208 a mode name (downshifted to lower case) followed by a single character
3209 representing the number of operands for the given operation (which is
3210 usually one of the characters '2', '3', or '4').
3211
3212 OPTABLE is the table in which libfunc fields are to be initialized.
3213 FIRST_MODE is the first machine mode index in the given optab to
3214 initialize.
3215 LAST_MODE is the last machine mode index in the given optab to
3216 initialize.
3217 OPNAME is the generic (string) name of the operation.
3218 SUFFIX is the character which specifies the number of operands for
3219 the given generic operation.
3220*/
3221
3222static void
3223init_libfuncs (optable, first_mode, last_mode, opname, suffix)
3224 register optab optable;
3225 register char *opname;
3226 register enum machine_mode first_mode;
3227 register enum machine_mode last_mode;
3228 register char suffix;
3229{
3230 register enum machine_mode mode;
3231 register unsigned opname_len = strlen (opname);
3232
3233 for (mode = first_mode; mode <= last_mode; mode++)
3234 {
3235 register char *mname = mode_name[(int) mode];
3236 register unsigned mname_len = strlen (mname);
3237 register char *libfunc_name
3238 = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1);
3239 register char *p;
3240 register char *q;
3241
3242 p = libfunc_name;
3243 *p++ = '_';
3244 *p++ = '_';
3245 for (q = opname; *q; )
3246 *p++ = *q++;
3247 for (q = mname; *q; q++)
3248 *p++ = tolower (*q);
3249 *p++ = suffix;
3250 *p++ = '\0';
3251 optable->handlers[(int) mode].libfunc
3252 = gen_rtx (SYMBOL_REF, Pmode, libfunc_name);
3253 }
3254}
3255
3256/* Initialize the libfunc fields of an entire group of entries in some
3257 optab which correspond to all integer mode operations. The parameters
3258 have the same meaning as similarly named ones for the `init_libfuncs'
3259 routine. (See above). */
3260
3261static void
3262init_integral_libfuncs (optable, opname, suffix)
3263 register optab optable;
3264 register char *opname;
3265 register char suffix;
3266{
3267 init_libfuncs (optable, SImode, TImode, opname, suffix);
3268}
3269
3270/* Initialize the libfunc fields of an entire group of entries in some
3271 optab which correspond to all real mode operations. The parameters
3272 have the same meaning as similarly named ones for the `init_libfuncs'
3273 routine. (See above). */
3274
3275static void
3276init_floating_libfuncs (optable, opname, suffix)
3277 register optab optable;
3278 register char *opname;
3279 register char suffix;
3280{
3281 init_libfuncs (optable, SFmode, TFmode, opname, suffix);
3282}
3283
77c9c6c2
RK
3284/* Call this once to initialize the contents of the optabs
3285 appropriately for the current target machine. */
3286
3287void
3288init_optabs ()
3289{
3290 int i;
3291
3292 init_fixtab ();
3293 init_floattab ();
3294 init_extends ();
3295
3296 add_optab = init_optab (PLUS);
3297 sub_optab = init_optab (MINUS);
3298 smul_optab = init_optab (MULT);
3299 smul_widen_optab = init_optab (UNKNOWN);
3300 umul_widen_optab = init_optab (UNKNOWN);
3301 sdiv_optab = init_optab (DIV);
3302 sdivmod_optab = init_optab (UNKNOWN);
3303 udiv_optab = init_optab (UDIV);
3304 udivmod_optab = init_optab (UNKNOWN);
3305 smod_optab = init_optab (MOD);
3306 umod_optab = init_optab (UMOD);
3307 flodiv_optab = init_optab (DIV);
3308 ftrunc_optab = init_optab (UNKNOWN);
3309 and_optab = init_optab (AND);
3310 ior_optab = init_optab (IOR);
3311 xor_optab = init_optab (XOR);
3312 ashl_optab = init_optab (ASHIFT);
3313 ashr_optab = init_optab (ASHIFTRT);
3314 lshl_optab = init_optab (LSHIFT);
3315 lshr_optab = init_optab (LSHIFTRT);
3316 rotl_optab = init_optab (ROTATE);
3317 rotr_optab = init_optab (ROTATERT);
3318 smin_optab = init_optab (SMIN);
3319 smax_optab = init_optab (SMAX);
3320 umin_optab = init_optab (UMIN);
3321 umax_optab = init_optab (UMAX);
3322 mov_optab = init_optab (UNKNOWN);
3323 movstrict_optab = init_optab (UNKNOWN);
3324 cmp_optab = init_optab (UNKNOWN);
3325 ucmp_optab = init_optab (UNKNOWN);
3326 tst_optab = init_optab (UNKNOWN);
3327 neg_optab = init_optab (NEG);
3328 abs_optab = init_optab (ABS);
3329 one_cmpl_optab = init_optab (NOT);
3330 ffs_optab = init_optab (FFS);
d45cf215 3331 sqrt_optab = init_optab (SQRT);
19c3fc24 3332 strlen_optab = init_optab (UNKNOWN);
77c9c6c2
RK
3333
3334#ifdef HAVE_addqi3
3335 if (HAVE_addqi3)
3336 add_optab->handlers[(int) QImode].insn_code = CODE_FOR_addqi3;
3337#endif
3338#ifdef HAVE_addhi3
3339 if (HAVE_addhi3)
3340 add_optab->handlers[(int) HImode].insn_code = CODE_FOR_addhi3;
3341#endif
3342#ifdef HAVE_addpsi3
3343 if (HAVE_addpsi3)
3344 add_optab->handlers[(int) PSImode].insn_code = CODE_FOR_addpsi3;
3345#endif
3346#ifdef HAVE_addsi3
3347 if (HAVE_addsi3)
3348 add_optab->handlers[(int) SImode].insn_code = CODE_FOR_addsi3;
3349#endif
3350#ifdef HAVE_adddi3
3351 if (HAVE_adddi3)
3352 add_optab->handlers[(int) DImode].insn_code = CODE_FOR_adddi3;
3353#endif
3354#ifdef HAVE_addti3
3355 if (HAVE_addti3)
3356 add_optab->handlers[(int) TImode].insn_code = CODE_FOR_addti3;
3357#endif
3358#ifdef HAVE_addsf3
3359 if (HAVE_addsf3)
3360 add_optab->handlers[(int) SFmode].insn_code = CODE_FOR_addsf3;
3361#endif
3362#ifdef HAVE_adddf3
3363 if (HAVE_adddf3)
3364 add_optab->handlers[(int) DFmode].insn_code = CODE_FOR_adddf3;
3365#endif
b092b471
JW
3366#ifdef HAVE_addxf3
3367 if (HAVE_addxf3)
3368 add_optab->handlers[(int) XFmode].insn_code = CODE_FOR_addxf3;
3369#endif
77c9c6c2
RK
3370#ifdef HAVE_addtf3
3371 if (HAVE_addtf3)
3372 add_optab->handlers[(int) TFmode].insn_code = CODE_FOR_addtf3;
3373#endif
b092b471
JW
3374 init_integral_libfuncs (add_optab, "add", '3');
3375 init_floating_libfuncs (add_optab, "add", '3');
77c9c6c2
RK
3376
3377#ifdef HAVE_subqi3
3378 if (HAVE_subqi3)
3379 sub_optab->handlers[(int) QImode].insn_code = CODE_FOR_subqi3;
3380#endif
3381#ifdef HAVE_subhi3
3382 if (HAVE_subhi3)
3383 sub_optab->handlers[(int) HImode].insn_code = CODE_FOR_subhi3;
3384#endif
3385#ifdef HAVE_subpsi3
3386 if (HAVE_subpsi3)
3387 sub_optab->handlers[(int) PSImode].insn_code = CODE_FOR_subpsi3;
3388#endif
3389#ifdef HAVE_subsi3
3390 if (HAVE_subsi3)
3391 sub_optab->handlers[(int) SImode].insn_code = CODE_FOR_subsi3;
3392#endif
3393#ifdef HAVE_subdi3
3394 if (HAVE_subdi3)
3395 sub_optab->handlers[(int) DImode].insn_code = CODE_FOR_subdi3;
3396#endif
3397#ifdef HAVE_subti3
3398 if (HAVE_subti3)
ded40dfe 3399 sub_optab->handlers[(int) TImode].insn_code = CODE_FOR_subti3;
77c9c6c2
RK
3400#endif
3401#ifdef HAVE_subsf3
3402 if (HAVE_subsf3)
3403 sub_optab->handlers[(int) SFmode].insn_code = CODE_FOR_subsf3;
3404#endif
3405#ifdef HAVE_subdf3
3406 if (HAVE_subdf3)
3407 sub_optab->handlers[(int) DFmode].insn_code = CODE_FOR_subdf3;
3408#endif
b092b471
JW
3409#ifdef HAVE_subxf3
3410 if (HAVE_subxf3)
3411 sub_optab->handlers[(int) XFmode].insn_code = CODE_FOR_subxf3;
3412#endif
77c9c6c2
RK
3413#ifdef HAVE_subtf3
3414 if (HAVE_subtf3)
3415 sub_optab->handlers[(int) TFmode].insn_code = CODE_FOR_subtf3;
3416#endif
b092b471
JW
3417 init_integral_libfuncs (sub_optab, "sub", '3');
3418 init_floating_libfuncs (sub_optab, "sub", '3');
77c9c6c2
RK
3419
3420#ifdef HAVE_mulqi3
3421 if (HAVE_mulqi3)
3422 smul_optab->handlers[(int) QImode].insn_code = CODE_FOR_mulqi3;
3423#endif
3424#ifdef HAVE_mulhi3
3425 if (HAVE_mulhi3)
3426 smul_optab->handlers[(int) HImode].insn_code = CODE_FOR_mulhi3;
3427#endif
3428#ifdef HAVE_mulpsi3
3429 if (HAVE_mulpsi3)
3430 smul_optab->handlers[(int) PSImode].insn_code = CODE_FOR_mulpsi3;
3431#endif
3432#ifdef HAVE_mulsi3
3433 if (HAVE_mulsi3)
3434 smul_optab->handlers[(int) SImode].insn_code = CODE_FOR_mulsi3;
3435#endif
3436#ifdef HAVE_muldi3
3437 if (HAVE_muldi3)
3438 smul_optab->handlers[(int) DImode].insn_code = CODE_FOR_muldi3;
3439#endif
3440#ifdef HAVE_multi3
3441 if (HAVE_multi3)
3442 smul_optab->handlers[(int) TImode].insn_code = CODE_FOR_multi3;
3443#endif
3444#ifdef HAVE_mulsf3
3445 if (HAVE_mulsf3)
3446 smul_optab->handlers[(int) SFmode].insn_code = CODE_FOR_mulsf3;
3447#endif
3448#ifdef HAVE_muldf3
3449 if (HAVE_muldf3)
3450 smul_optab->handlers[(int) DFmode].insn_code = CODE_FOR_muldf3;
3451#endif
b092b471
JW
3452#ifdef HAVE_mulxf3
3453 if (HAVE_mulxf3)
3454 smul_optab->handlers[(int) XFmode].insn_code = CODE_FOR_mulxf3;
3455#endif
77c9c6c2
RK
3456#ifdef HAVE_multf3
3457 if (HAVE_multf3)
3458 smul_optab->handlers[(int) TFmode].insn_code = CODE_FOR_multf3;
3459#endif
b092b471
JW
3460 init_integral_libfuncs (smul_optab, "mul", '3');
3461 init_floating_libfuncs (smul_optab, "mul", '3');
77c9c6c2
RK
3462
3463#ifdef MULSI3_LIBCALL
3464 smul_optab->handlers[(int) SImode].libfunc
3465 = gen_rtx (SYMBOL_REF, Pmode, MULSI3_LIBCALL);
77c9c6c2
RK
3466#endif
3467#ifdef MULDI3_LIBCALL
3468 smul_optab->handlers[(int) DImode].libfunc
3469 = gen_rtx (SYMBOL_REF, Pmode, MULDI3_LIBCALL);
77c9c6c2 3470#endif
b092b471
JW
3471#ifdef MULTI3_LIBCALL
3472 smul_optab->handlers[(int) TImode].libfunc
3473 = gen_rtx (SYMBOL_REF, Pmode, MULTI3_LIBCALL);
3474#endif
77c9c6c2
RK
3475
3476#ifdef HAVE_mulqihi3
3477 if (HAVE_mulqihi3)
3478 smul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_mulqihi3;
3479#endif
3480#ifdef HAVE_mulhisi3
3481 if (HAVE_mulhisi3)
3482 smul_widen_optab->handlers[(int) SImode].insn_code = CODE_FOR_mulhisi3;
3483#endif
3484#ifdef HAVE_mulsidi3
3485 if (HAVE_mulsidi3)
3486 smul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_mulsidi3;
3487#endif
3488#ifdef HAVE_mulditi3
3489 if (HAVE_mulditi3)
3490 smul_widen_optab->handlers[(int) TImode].insn_code = CODE_FOR_mulditi3;
3491#endif
3492
3493#ifdef HAVE_umulqihi3
3494 if (HAVE_umulqihi3)
3495 umul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_umulqihi3;
3496#endif
3497#ifdef HAVE_umulhisi3
3498 if (HAVE_umulhisi3)
3499 umul_widen_optab->handlers[(int) SImode].insn_code = CODE_FOR_umulhisi3;
3500#endif
3501#ifdef HAVE_umulsidi3
3502 if (HAVE_umulsidi3)
3503 umul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_umulsidi3;
3504#endif
3505#ifdef HAVE_umulditi3
3506 if (HAVE_umulditi3)
3507 umul_widen_optab->handlers[(int) TImode].insn_code = CODE_FOR_umulditi3;
3508#endif
3509
3510#ifdef HAVE_divqi3
3511 if (HAVE_divqi3)
3512 sdiv_optab->handlers[(int) QImode].insn_code = CODE_FOR_divqi3;
3513#endif
3514#ifdef HAVE_divhi3
3515 if (HAVE_divhi3)
3516 sdiv_optab->handlers[(int) HImode].insn_code = CODE_FOR_divhi3;
3517#endif
3518#ifdef HAVE_divpsi3
3519 if (HAVE_divpsi3)
3520 sdiv_optab->handlers[(int) PSImode].insn_code = CODE_FOR_divpsi3;
3521#endif
3522#ifdef HAVE_divsi3
3523 if (HAVE_divsi3)
3524 sdiv_optab->handlers[(int) SImode].insn_code = CODE_FOR_divsi3;
3525#endif
3526#ifdef HAVE_divdi3
3527 if (HAVE_divdi3)
3528 sdiv_optab->handlers[(int) DImode].insn_code = CODE_FOR_divdi3;
3529#endif
3530#ifdef HAVE_divti3
3531 if (HAVE_divti3)
3532 sdiv_optab->handlers[(int) TImode].insn_code = CODE_FOR_divti3;
3533#endif
b092b471 3534 init_integral_libfuncs (sdiv_optab, "div", '3');
77c9c6c2
RK
3535
3536#ifdef DIVSI3_LIBCALL
3537 sdiv_optab->handlers[(int) SImode].libfunc
3538 = gen_rtx (SYMBOL_REF, Pmode, DIVSI3_LIBCALL);
77c9c6c2
RK
3539#endif
3540#ifdef DIVDI3_LIBCALL
3541 sdiv_optab->handlers[(int) DImode].libfunc
3542 = gen_rtx (SYMBOL_REF, Pmode, DIVDI3_LIBCALL);
b092b471
JW
3543#endif
3544#ifdef DIVTI3_LIBCALL
3545 sdiv_optab->handlers[(int) TImode].libfunc
3546 = gen_rtx (SYMBOL_REF, Pmode, DIVTI3_LIBCALL);
77c9c6c2
RK
3547#endif
3548
3549#ifdef HAVE_udivqi3
3550 if (HAVE_udivqi3)
3551 udiv_optab->handlers[(int) QImode].insn_code = CODE_FOR_udivqi3;
3552#endif
3553#ifdef HAVE_udivhi3
3554 if (HAVE_udivhi3)
3555 udiv_optab->handlers[(int) HImode].insn_code = CODE_FOR_udivhi3;
3556#endif
3557#ifdef HAVE_udivpsi3
3558 if (HAVE_udivpsi3)
3559 udiv_optab->handlers[(int) PSImode].insn_code = CODE_FOR_udivpsi3;
3560#endif
3561#ifdef HAVE_udivsi3
3562 if (HAVE_udivsi3)
3563 udiv_optab->handlers[(int) SImode].insn_code = CODE_FOR_udivsi3;
3564#endif
3565#ifdef HAVE_udivdi3
3566 if (HAVE_udivdi3)
3567 udiv_optab->handlers[(int) DImode].insn_code = CODE_FOR_udivdi3;
3568#endif
3569#ifdef HAVE_udivti3
3570 if (HAVE_udivti3)
3571 udiv_optab->handlers[(int) TImode].insn_code = CODE_FOR_udivti3;
3572#endif
b092b471 3573 init_integral_libfuncs (udiv_optab, "udiv", '3');
77c9c6c2
RK
3574
3575#ifdef UDIVSI3_LIBCALL
3576 udiv_optab->handlers[(int) SImode].libfunc
3577 = gen_rtx (SYMBOL_REF, Pmode, UDIVSI3_LIBCALL);
77c9c6c2
RK
3578#endif
3579#ifdef UDIVDI3_LIBCALL
3580 udiv_optab->handlers[(int) DImode].libfunc
3581 = gen_rtx (SYMBOL_REF, Pmode, UDIVDI3_LIBCALL);
b092b471
JW
3582#endif
3583#ifdef UDIVTI3_LIBCALL
3584 udiv_optab->handlers[(int) TImode].libfunc
3585 = gen_rtx (SYMBOL_REF, Pmode, UDIVTI3_LIBCALL);
77c9c6c2
RK
3586#endif
3587
3588#ifdef HAVE_divmodqi4
3589 if (HAVE_divmodqi4)
3590 sdivmod_optab->handlers[(int) QImode].insn_code = CODE_FOR_divmodqi4;
3591#endif
3592#ifdef HAVE_divmodhi4
3593 if (HAVE_divmodhi4)
3594 sdivmod_optab->handlers[(int) HImode].insn_code = CODE_FOR_divmodhi4;
3595#endif
3596#ifdef HAVE_divmodsi4
3597 if (HAVE_divmodsi4)
3598 sdivmod_optab->handlers[(int) SImode].insn_code = CODE_FOR_divmodsi4;
3599#endif
3600#ifdef HAVE_divmoddi4
3601 if (HAVE_divmoddi4)
3602 sdivmod_optab->handlers[(int) DImode].insn_code = CODE_FOR_divmoddi4;
3603#endif
3604#ifdef HAVE_divmodti4
3605 if (HAVE_divmodti4)
3606 sdivmod_optab->handlers[(int) TImode].insn_code = CODE_FOR_divmodti4;
3607#endif
b092b471 3608 init_integral_libfuncs (sdivmod_optab, "divmod", '4');
77c9c6c2
RK
3609
3610#ifdef HAVE_udivmodqi4
3611 if (HAVE_udivmodqi4)
3612 udivmod_optab->handlers[(int) QImode].insn_code = CODE_FOR_udivmodqi4;
3613#endif
3614#ifdef HAVE_udivmodhi4
3615 if (HAVE_udivmodhi4)
3616 udivmod_optab->handlers[(int) HImode].insn_code = CODE_FOR_udivmodhi4;
3617#endif
3618#ifdef HAVE_udivmodsi4
3619 if (HAVE_udivmodsi4)
3620 udivmod_optab->handlers[(int) SImode].insn_code = CODE_FOR_udivmodsi4;
3621#endif
3622#ifdef HAVE_udivmoddi4
3623 if (HAVE_udivmoddi4)
3624 udivmod_optab->handlers[(int) DImode].insn_code = CODE_FOR_udivmoddi4;
3625#endif
3626#ifdef HAVE_udivmodti4
3627 if (HAVE_udivmodti4)
3628 udivmod_optab->handlers[(int) TImode].insn_code = CODE_FOR_udivmodti4;
3629#endif
b092b471 3630 init_integral_libfuncs (udivmod_optab, "udivmod", '4');
77c9c6c2
RK
3631
3632#ifdef HAVE_modqi3
3633 if (HAVE_modqi3)
3634 smod_optab->handlers[(int) QImode].insn_code = CODE_FOR_modqi3;
3635#endif
3636#ifdef HAVE_modhi3
3637 if (HAVE_modhi3)
3638 smod_optab->handlers[(int) HImode].insn_code = CODE_FOR_modhi3;
3639#endif
3640#ifdef HAVE_modpsi3
3641 if (HAVE_modpsi3)
3642 smod_optab->handlers[(int) PSImode].insn_code = CODE_FOR_modpsi3;
3643#endif
3644#ifdef HAVE_modsi3
3645 if (HAVE_modsi3)
3646 smod_optab->handlers[(int) SImode].insn_code = CODE_FOR_modsi3;
3647#endif
3648#ifdef HAVE_moddi3
3649 if (HAVE_moddi3)
3650 smod_optab->handlers[(int) DImode].insn_code = CODE_FOR_moddi3;
3651#endif
3652#ifdef HAVE_modti3
3653 if (HAVE_modti3)
3654 smod_optab->handlers[(int) TImode].insn_code = CODE_FOR_modti3;
3655#endif
b092b471 3656 init_integral_libfuncs (smod_optab, "mod", '3');
77c9c6c2
RK
3657
3658#ifdef MODSI3_LIBCALL
3659 smod_optab->handlers[(int) SImode].libfunc
3660 = gen_rtx (SYMBOL_REF, Pmode, MODSI3_LIBCALL);
77c9c6c2
RK
3661#endif
3662#ifdef MODDI3_LIBCALL
3663 smod_optab->handlers[(int) DImode].libfunc
3664 = gen_rtx (SYMBOL_REF, Pmode, MODDI3_LIBCALL);
b092b471
JW
3665#endif
3666#ifdef MODTI3_LIBCALL
3667 smod_optab->handlers[(int) TImode].libfunc
3668 = gen_rtx (SYMBOL_REF, Pmode, MODTI3_LIBCALL);
77c9c6c2
RK
3669#endif
3670
3671#ifdef HAVE_umodqi3
3672 if (HAVE_umodqi3)
3673 umod_optab->handlers[(int) QImode].insn_code = CODE_FOR_umodqi3;
3674#endif
3675#ifdef HAVE_umodhi3
3676 if (HAVE_umodhi3)
3677 umod_optab->handlers[(int) HImode].insn_code = CODE_FOR_umodhi3;
3678#endif
3679#ifdef HAVE_umodpsi3
3680 if (HAVE_umodpsi3)
3681 umod_optab->handlers[(int) PSImode].insn_code = CODE_FOR_umodpsi3;
3682#endif
3683#ifdef HAVE_umodsi3
3684 if (HAVE_umodsi3)
3685 umod_optab->handlers[(int) SImode].insn_code = CODE_FOR_umodsi3;
3686#endif
3687#ifdef HAVE_umoddi3
3688 if (HAVE_umoddi3)
3689 umod_optab->handlers[(int) DImode].insn_code = CODE_FOR_umoddi3;
3690#endif
3691#ifdef HAVE_umodti3
3692 if (HAVE_umodti3)
3693 umod_optab->handlers[(int) TImode].insn_code = CODE_FOR_umodti3;
3694#endif
b092b471 3695 init_integral_libfuncs (umod_optab, "umod", '3');
77c9c6c2
RK
3696
3697#ifdef UMODSI3_LIBCALL
3698 umod_optab->handlers[(int) SImode].libfunc
3699 = gen_rtx (SYMBOL_REF, Pmode, UMODSI3_LIBCALL);
77c9c6c2
RK
3700#endif
3701#ifdef UMODDI3_LIBCALL
3702 umod_optab->handlers[(int) DImode].libfunc
3703 = gen_rtx (SYMBOL_REF, Pmode, UMODDI3_LIBCALL);
b092b471
JW
3704#endif
3705#ifdef UMODTI3_LIBCALL
3706 umod_optab->handlers[(int) TImode].libfunc
3707 = gen_rtx (SYMBOL_REF, Pmode, UMODTI3_LIBCALL);
77c9c6c2
RK
3708#endif
3709
3710#ifdef HAVE_divsf3
3711 if (HAVE_divsf3)
3712 flodiv_optab->handlers[(int) SFmode].insn_code = CODE_FOR_divsf3;
3713#endif
3714#ifdef HAVE_divdf3
3715 if (HAVE_divdf3)
3716 flodiv_optab->handlers[(int) DFmode].insn_code = CODE_FOR_divdf3;
3717#endif
b092b471
JW
3718#ifdef HAVE_divxf3
3719 if (HAVE_divxf3)
3720 flodiv_optab->handlers[(int) XFmode].insn_code = CODE_FOR_divxf3;
3721#endif
77c9c6c2
RK
3722#ifdef HAVE_divtf3
3723 if (HAVE_divtf3)
3724 flodiv_optab->handlers[(int) TFmode].insn_code = CODE_FOR_divtf3;
3725#endif
b092b471 3726 init_floating_libfuncs (flodiv_optab, "div", '3');
77c9c6c2
RK
3727
3728#ifdef HAVE_ftruncsf2
3729 if (HAVE_ftruncsf2)
3730 ftrunc_optab->handlers[(int) SFmode].insn_code = CODE_FOR_ftruncsf2;
3731#endif
3732#ifdef HAVE_ftruncdf2
3733 if (HAVE_ftruncdf2)
3734 ftrunc_optab->handlers[(int) DFmode].insn_code = CODE_FOR_ftruncdf2;
3735#endif
b092b471
JW
3736#ifdef HAVE_ftruncxf2
3737 if (HAVE_ftruncxf2)
3738 ftrunc_optab->handlers[(int) XFmode].insn_code = CODE_FOR_ftruncxf2;
3739#endif
77c9c6c2
RK
3740#ifdef HAVE_ftrunctf2
3741 if (HAVE_ftrunctf2)
3742 ftrunc_optab->handlers[(int) TFmode].insn_code = CODE_FOR_ftrunctf2;
3743#endif
b092b471 3744 init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
77c9c6c2
RK
3745
3746#ifdef HAVE_andqi3
3747 if (HAVE_andqi3)
3748 and_optab->handlers[(int) QImode].insn_code = CODE_FOR_andqi3;
3749#endif
3750#ifdef HAVE_andhi3
3751 if (HAVE_andhi3)
3752 and_optab->handlers[(int) HImode].insn_code = CODE_FOR_andhi3;
3753#endif
3754#ifdef HAVE_andpsi3
3755 if (HAVE_andpsi3)
3756 and_optab->handlers[(int) PSImode].insn_code = CODE_FOR_andpsi3;
3757#endif
3758#ifdef HAVE_andsi3
3759 if (HAVE_andsi3)
3760 and_optab->handlers[(int) SImode].insn_code = CODE_FOR_andsi3;
3761#endif
3762#ifdef HAVE_anddi3
3763 if (HAVE_anddi3)
3764 and_optab->handlers[(int) DImode].insn_code = CODE_FOR_anddi3;
3765#endif
3766#ifdef HAVE_andti3
3767 if (HAVE_andti3)
3768 and_optab->handlers[(int) TImode].insn_code = CODE_FOR_andti3;
3769#endif
b092b471 3770 init_integral_libfuncs (and_optab, "and", '3');
77c9c6c2
RK
3771
3772#ifdef HAVE_iorqi3
3773 if (HAVE_iorqi3)
3774 ior_optab->handlers[(int) QImode].insn_code = CODE_FOR_iorqi3;
3775#endif
3776#ifdef HAVE_iorhi3
3777 if (HAVE_iorhi3)
3778 ior_optab->handlers[(int) HImode].insn_code = CODE_FOR_iorhi3;
3779#endif
3780#ifdef HAVE_iorpsi3
3781 if (HAVE_iorpsi3)
3782 ior_optab->handlers[(int) PSImode].insn_code = CODE_FOR_iorpsi3;
3783#endif
3784#ifdef HAVE_iorsi3
3785 if (HAVE_iorsi3)
3786 ior_optab->handlers[(int) SImode].insn_code = CODE_FOR_iorsi3;
3787#endif
3788#ifdef HAVE_iordi3
3789 if (HAVE_iordi3)
3790 ior_optab->handlers[(int) DImode].insn_code = CODE_FOR_iordi3;
3791#endif
3792#ifdef HAVE_iorti3
3793 if (HAVE_iorti3)
3794 ior_optab->handlers[(int) TImode].insn_code = CODE_FOR_iorti3;
3795#endif
b092b471 3796 init_integral_libfuncs (ior_optab, "ior", '3');
77c9c6c2
RK
3797
3798#ifdef HAVE_xorqi3
3799 if (HAVE_xorqi3)
3800 xor_optab->handlers[(int) QImode].insn_code = CODE_FOR_xorqi3;
3801#endif
3802#ifdef HAVE_xorhi3
3803 if (HAVE_xorhi3)
3804 xor_optab->handlers[(int) HImode].insn_code = CODE_FOR_xorhi3;
3805#endif
3806#ifdef HAVE_xorpsi3
3807 if (HAVE_xorpsi3)
3808 xor_optab->handlers[(int) PSImode].insn_code = CODE_FOR_xorpsi3;
3809#endif
3810#ifdef HAVE_xorsi3
3811 if (HAVE_xorsi3)
3812 xor_optab->handlers[(int) SImode].insn_code = CODE_FOR_xorsi3;
3813#endif
3814#ifdef HAVE_xordi3
3815 if (HAVE_xordi3)
3816 xor_optab->handlers[(int) DImode].insn_code = CODE_FOR_xordi3;
3817#endif
3818#ifdef HAVE_xorti3
3819 if (HAVE_xorti3)
3820 xor_optab->handlers[(int) TImode].insn_code = CODE_FOR_xorti3;
3821#endif
b092b471 3822 init_integral_libfuncs (xor_optab, "xor", '3');
77c9c6c2
RK
3823
3824#ifdef HAVE_ashlqi3
3825 if (HAVE_ashlqi3)
3826 ashl_optab->handlers[(int) QImode].insn_code = CODE_FOR_ashlqi3;
3827#endif
3828#ifdef HAVE_ashlhi3
3829 if (HAVE_ashlhi3)
3830 ashl_optab->handlers[(int) HImode].insn_code = CODE_FOR_ashlhi3;
3831#endif
3832#ifdef HAVE_ashlpsi3
3833 if (HAVE_ashlpsi3)
3834 ashl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_ashlpsi3;
3835#endif
3836#ifdef HAVE_ashlsi3
3837 if (HAVE_ashlsi3)
3838 ashl_optab->handlers[(int) SImode].insn_code = CODE_FOR_ashlsi3;
3839#endif
3840#ifdef HAVE_ashldi3
3841 if (HAVE_ashldi3)
3842 ashl_optab->handlers[(int) DImode].insn_code = CODE_FOR_ashldi3;
3843#endif
3844#ifdef HAVE_ashlti3
3845 if (HAVE_ashlti3)
3846 ashl_optab->handlers[(int) TImode].insn_code = CODE_FOR_ashlti3;
3847#endif
b092b471 3848 init_integral_libfuncs (ashl_optab, "ashl", '3');
77c9c6c2
RK
3849
3850#ifdef HAVE_ashrqi3
3851 if (HAVE_ashrqi3)
3852 ashr_optab->handlers[(int) QImode].insn_code = CODE_FOR_ashrqi3;
3853#endif
3854#ifdef HAVE_ashrhi3
3855 if (HAVE_ashrhi3)
3856 ashr_optab->handlers[(int) HImode].insn_code = CODE_FOR_ashrhi3;
3857#endif
3858#ifdef HAVE_ashrpsi3
3859 if (HAVE_ashrpsi3)
3860 ashr_optab->handlers[(int) PSImode].insn_code = CODE_FOR_ashrpsi3;
3861#endif
3862#ifdef HAVE_ashrsi3
3863 if (HAVE_ashrsi3)
3864 ashr_optab->handlers[(int) SImode].insn_code = CODE_FOR_ashrsi3;
3865#endif
3866#ifdef HAVE_ashrdi3
3867 if (HAVE_ashrdi3)
3868 ashr_optab->handlers[(int) DImode].insn_code = CODE_FOR_ashrdi3;
3869#endif
3870#ifdef HAVE_ashrti3
3871 if (HAVE_ashrti3)
3872 ashr_optab->handlers[(int) TImode].insn_code = CODE_FOR_ashrti3;
3873#endif
b092b471 3874 init_integral_libfuncs (ashr_optab, "ashr", '3');
77c9c6c2
RK
3875
3876#ifdef HAVE_lshlqi3
3877 if (HAVE_lshlqi3)
3878 lshl_optab->handlers[(int) QImode].insn_code = CODE_FOR_lshlqi3;
3879#endif
3880#ifdef HAVE_lshlhi3
3881 if (HAVE_lshlhi3)
3882 lshl_optab->handlers[(int) HImode].insn_code = CODE_FOR_lshlhi3;
3883#endif
3884#ifdef HAVE_lshlpsi3
3885 if (HAVE_lshlpsi3)
3886 lshl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_lshlpsi3;
3887#endif
3888#ifdef HAVE_lshlsi3
3889 if (HAVE_lshlsi3)
3890 lshl_optab->handlers[(int) SImode].insn_code = CODE_FOR_lshlsi3;
3891#endif
3892#ifdef HAVE_lshldi3
3893 if (HAVE_lshldi3)
3894 lshl_optab->handlers[(int) DImode].insn_code = CODE_FOR_lshldi3;
3895#endif
3896#ifdef HAVE_lshlti3
3897 if (HAVE_lshlti3)
3898 lshl_optab->handlers[(int) TImode].insn_code = CODE_FOR_lshlti3;
3899#endif
b092b471 3900 init_integral_libfuncs (lshl_optab, "lshl", '3');
77c9c6c2
RK
3901
3902#ifdef HAVE_lshrqi3
3903 if (HAVE_lshrqi3)
3904 lshr_optab->handlers[(int) QImode].insn_code = CODE_FOR_lshrqi3;
3905#endif
3906#ifdef HAVE_lshrhi3
3907 if (HAVE_lshrhi3)
3908 lshr_optab->handlers[(int) HImode].insn_code = CODE_FOR_lshrhi3;
3909#endif
3910#ifdef HAVE_lshrpsi3
3911 if (HAVE_lshrpsi3)
3912 lshr_optab->handlers[(int) PSImode].insn_code = CODE_FOR_lshrpsi3;
3913#endif
3914#ifdef HAVE_lshrsi3
3915 if (HAVE_lshrsi3)
3916 lshr_optab->handlers[(int) SImode].insn_code = CODE_FOR_lshrsi3;
3917#endif
3918#ifdef HAVE_lshrdi3
3919 if (HAVE_lshrdi3)
3920 lshr_optab->handlers[(int) DImode].insn_code = CODE_FOR_lshrdi3;
3921#endif
3922#ifdef HAVE_lshrti3
3923 if (HAVE_lshrti3)
3924 lshr_optab->handlers[(int) TImode].insn_code = CODE_FOR_lshrti3;
3925#endif
b092b471 3926 init_integral_libfuncs (lshr_optab, "lshr", '3');
77c9c6c2
RK
3927
3928#ifdef HAVE_rotlqi3
3929 if (HAVE_rotlqi3)
3930 rotl_optab->handlers[(int) QImode].insn_code = CODE_FOR_rotlqi3;
3931#endif
3932#ifdef HAVE_rotlhi3
3933 if (HAVE_rotlhi3)
3934 rotl_optab->handlers[(int) HImode].insn_code = CODE_FOR_rotlhi3;
3935#endif
3936#ifdef HAVE_rotlpsi3
3937 if (HAVE_rotlpsi3)
3938 rotl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_rotlpsi3;
3939#endif
3940#ifdef HAVE_rotlsi3
3941 if (HAVE_rotlsi3)
3942 rotl_optab->handlers[(int) SImode].insn_code = CODE_FOR_rotlsi3;
3943#endif
3944#ifdef HAVE_rotldi3
3945 if (HAVE_rotldi3)
3946 rotl_optab->handlers[(int) DImode].insn_code = CODE_FOR_rotldi3;
3947#endif
3948#ifdef HAVE_rotlti3
3949 if (HAVE_rotlti3)
3950 rotl_optab->handlers[(int) TImode].insn_code = CODE_FOR_rotlti3;
3951#endif
b092b471 3952 init_integral_libfuncs (rotl_optab, "rotl", '3');
77c9c6c2
RK
3953
3954#ifdef HAVE_rotrqi3
3955 if (HAVE_rotrqi3)
3956 rotr_optab->handlers[(int) QImode].insn_code = CODE_FOR_rotrqi3;
3957#endif
3958#ifdef HAVE_rotrhi3
3959 if (HAVE_rotrhi3)
3960 rotr_optab->handlers[(int) HImode].insn_code = CODE_FOR_rotrhi3;
3961#endif
3962#ifdef HAVE_rotrpsi3
3963 if (HAVE_rotrpsi3)
3964 rotr_optab->handlers[(int) PSImode].insn_code = CODE_FOR_rotrpsi3;
3965#endif
3966#ifdef HAVE_rotrsi3
3967 if (HAVE_rotrsi3)
3968 rotr_optab->handlers[(int) SImode].insn_code = CODE_FOR_rotrsi3;
3969#endif
3970#ifdef HAVE_rotrdi3
3971 if (HAVE_rotrdi3)
3972 rotr_optab->handlers[(int) DImode].insn_code = CODE_FOR_rotrdi3;
3973#endif
3974#ifdef HAVE_rotrti3
3975 if (HAVE_rotrti3)
3976 rotr_optab->handlers[(int) TImode].insn_code = CODE_FOR_rotrti3;
3977#endif
b092b471 3978 init_integral_libfuncs (rotr_optab, "rotr", '3');
77c9c6c2
RK
3979
3980#ifdef HAVE_sminqi3
3981 if (HAVE_sminqi3)
3982 smin_optab->handlers[(int) QImode].insn_code = CODE_FOR_sminqi3;
3983#endif
3984#ifdef HAVE_sminhi3
3985 if (HAVE_sminhi3)
3986 smin_optab->handlers[(int) HImode].insn_code = CODE_FOR_sminhi3;
3987#endif
3988#ifdef HAVE_sminsi3
3989 if (HAVE_sminsi3)
3990 smin_optab->handlers[(int) SImode].insn_code = CODE_FOR_sminsi3;
3991#endif
3992#ifdef HAVE_smindi3
3993 if (HAVE_smindi3)
3994 smin_optab->handlers[(int) DImode].insn_code = CODE_FOR_smindi3;
3995#endif
3996#ifdef HAVE_sminti3
3997 if (HAVE_sminti3)
3998 smin_optab->handlers[(int) TImode].insn_code = CODE_FOR_sminti3;
3999#endif
b092b471
JW
4000#ifdef HAVE_minsf3
4001 if (HAVE_minsf3)
4002 smin_optab->handlers[(int) SFmode].insn_code = CODE_FOR_minsf3;
4003#endif
4004#ifdef HAVE_mindf3
4005 if (HAVE_mindf3)
4006 smin_optab->handlers[(int) DFmode].insn_code = CODE_FOR_mindf3;
77c9c6c2 4007#endif
b092b471
JW
4008#ifdef HAVE_minxf3
4009 if (HAVE_minxf3)
4010 smin_optab->handlers[(int) XFmode].insn_code = CODE_FOR_minxf3;
77c9c6c2 4011#endif
b092b471
JW
4012#ifdef HAVE_mintf3
4013 if (HAVE_mintf3)
4014 smin_optab->handlers[(int) TFmode].insn_code = CODE_FOR_mintf3;
77c9c6c2 4015#endif
b092b471
JW
4016 init_integral_libfuncs (smin_optab, "min", '3');
4017 init_floating_libfuncs (smin_optab, "min", '3');
77c9c6c2
RK
4018
4019#ifdef HAVE_smaxqi3
4020 if (HAVE_smaxqi3)
4021 smax_optab->handlers[(int) QImode].insn_code = CODE_FOR_smaxqi3;
4022#endif
4023#ifdef HAVE_smaxhi3
4024 if (HAVE_smaxhi3)
4025 smax_optab->handlers[(int) HImode].insn_code = CODE_FOR_smaxhi3;
4026#endif
4027#ifdef HAVE_smaxsi3
4028 if (HAVE_smaxsi3)
4029 smax_optab->handlers[(int) SImode].insn_code = CODE_FOR_smaxsi3;
4030#endif
4031#ifdef HAVE_smaxdi3
4032 if (HAVE_smaxdi3)
4033 smax_optab->handlers[(int) DImode].insn_code = CODE_FOR_smaxdi3;
4034#endif
4035#ifdef HAVE_smaxti3
4036 if (HAVE_smaxti3)
4037 smax_optab->handlers[(int) TImode].insn_code = CODE_FOR_smaxti3;
4038#endif
b092b471
JW
4039#ifdef HAVE_maxsf3
4040 if (HAVE_maxsf3)
4041 smax_optab->handlers[(int) SFmode].insn_code = CODE_FOR_maxsf3;
77c9c6c2 4042#endif
b092b471
JW
4043#ifdef HAVE_maxdf3
4044 if (HAVE_maxdf3)
4045 smax_optab->handlers[(int) DFmode].insn_code = CODE_FOR_maxdf3;
77c9c6c2 4046#endif
b092b471
JW
4047#ifdef HAVE_maxxf3
4048 if (HAVE_maxxf3)
4049 smax_optab->handlers[(int) XFmode].insn_code = CODE_FOR_maxxf3;
77c9c6c2 4050#endif
b092b471
JW
4051#ifdef HAVE_maxtf3
4052 if (HAVE_maxtf3)
4053 smax_optab->handlers[(int) TFmode].insn_code = CODE_FOR_maxtf3;
4054#endif
4055 init_integral_libfuncs (smax_optab, "max", '3');
4056 init_floating_libfuncs (smax_optab, "max", '3');
77c9c6c2
RK
4057
4058#ifdef HAVE_uminqi3
4059 if (HAVE_uminqi3)
4060 umin_optab->handlers[(int) QImode].insn_code = CODE_FOR_uminqi3;
4061#endif
4062#ifdef HAVE_uminhi3
4063 if (HAVE_uminhi3)
4064 umin_optab->handlers[(int) HImode].insn_code = CODE_FOR_uminhi3;
4065#endif
4066#ifdef HAVE_uminsi3
4067 if (HAVE_uminsi3)
4068 umin_optab->handlers[(int) SImode].insn_code = CODE_FOR_uminsi3;
4069#endif
4070#ifdef HAVE_umindi3
4071 if (HAVE_umindi3)
4072 umin_optab->handlers[(int) DImode].insn_code = CODE_FOR_umindi3;
4073#endif
4074#ifdef HAVE_uminti3
4075 if (HAVE_uminti3)
4076 umin_optab->handlers[(int) TImode].insn_code = CODE_FOR_uminti3;
4077#endif
b092b471 4078 init_integral_libfuncs (umin_optab, "umin", '3');
77c9c6c2
RK
4079
4080#ifdef HAVE_umaxqi3
4081 if (HAVE_umaxqi3)
4082 umax_optab->handlers[(int) QImode].insn_code = CODE_FOR_umaxqi3;
4083#endif
4084#ifdef HAVE_umaxhi3
4085 if (HAVE_umaxhi3)
4086 umax_optab->handlers[(int) HImode].insn_code = CODE_FOR_umaxhi3;
4087#endif
4088#ifdef HAVE_umaxsi3
4089 if (HAVE_umaxsi3)
4090 umax_optab->handlers[(int) SImode].insn_code = CODE_FOR_umaxsi3;
4091#endif
4092#ifdef HAVE_umaxdi3
4093 if (HAVE_umaxdi3)
4094 umax_optab->handlers[(int) DImode].insn_code = CODE_FOR_umaxdi3;
4095#endif
4096#ifdef HAVE_umaxti3
4097 if (HAVE_umaxti3)
4098 umax_optab->handlers[(int) TImode].insn_code = CODE_FOR_umaxti3;
4099#endif
b092b471 4100 init_integral_libfuncs (umax_optab, "umax", '3');
77c9c6c2
RK
4101
4102#ifdef HAVE_negqi2
4103 if (HAVE_negqi2)
4104 neg_optab->handlers[(int) QImode].insn_code = CODE_FOR_negqi2;
4105#endif
4106#ifdef HAVE_neghi2
4107 if (HAVE_neghi2)
4108 neg_optab->handlers[(int) HImode].insn_code = CODE_FOR_neghi2;
4109#endif
4110#ifdef HAVE_negpsi2
4111 if (HAVE_negpsi2)
4112 neg_optab->handlers[(int) PSImode].insn_code = CODE_FOR_negpsi2;
4113#endif
4114#ifdef HAVE_negsi2
4115 if (HAVE_negsi2)
4116 neg_optab->handlers[(int) SImode].insn_code = CODE_FOR_negsi2;
4117#endif
4118#ifdef HAVE_negdi2
4119 if (HAVE_negdi2)
4120 neg_optab->handlers[(int) DImode].insn_code = CODE_FOR_negdi2;
4121#endif
4122#ifdef HAVE_negti2
4123 if (HAVE_negti2)
4124 neg_optab->handlers[(int) TImode].insn_code = CODE_FOR_negti2;
4125#endif
4126#ifdef HAVE_negsf2
4127 if (HAVE_negsf2)
4128 neg_optab->handlers[(int) SFmode].insn_code = CODE_FOR_negsf2;
4129#endif
4130#ifdef HAVE_negdf2
4131 if (HAVE_negdf2)
4132 neg_optab->handlers[(int) DFmode].insn_code = CODE_FOR_negdf2;
4133#endif
b092b471
JW
4134#ifdef HAVE_negxf2
4135 if (HAVE_negxf2)
4136 neg_optab->handlers[(int) XFmode].insn_code = CODE_FOR_negxf2;
4137#endif
77c9c6c2
RK
4138#ifdef HAVE_negtf2
4139 if (HAVE_negtf2)
4140 neg_optab->handlers[(int) TFmode].insn_code = CODE_FOR_negtf2;
4141#endif
b092b471
JW
4142 init_integral_libfuncs (neg_optab, "neg", '2');
4143 init_floating_libfuncs (neg_optab, "neg", '2');
77c9c6c2
RK
4144
4145#ifdef HAVE_absqi2
4146 if (HAVE_absqi2)
4147 abs_optab->handlers[(int) QImode].insn_code = CODE_FOR_absqi2;
4148#endif
4149#ifdef HAVE_abshi2
4150 if (HAVE_abshi2)
4151 abs_optab->handlers[(int) HImode].insn_code = CODE_FOR_abshi2;
4152#endif
4153#ifdef HAVE_abspsi2
4154 if (HAVE_abspsi2)
4155 abs_optab->handlers[(int) PSImode].insn_code = CODE_FOR_abspsi2;
4156#endif
4157#ifdef HAVE_abssi2
4158 if (HAVE_abssi2)
4159 abs_optab->handlers[(int) SImode].insn_code = CODE_FOR_abssi2;
4160#endif
4161#ifdef HAVE_absdi2
4162 if (HAVE_absdi2)
4163 abs_optab->handlers[(int) DImode].insn_code = CODE_FOR_absdi2;
4164#endif
4165#ifdef HAVE_absti2
4166 if (HAVE_absti2)
4167 abs_optab->handlers[(int) TImode].insn_code = CODE_FOR_absti2;
4168#endif
4169#ifdef HAVE_abssf2
4170 if (HAVE_abssf2)
4171 abs_optab->handlers[(int) SFmode].insn_code = CODE_FOR_abssf2;
4172#endif
4173#ifdef HAVE_absdf2
4174 if (HAVE_absdf2)
4175 abs_optab->handlers[(int) DFmode].insn_code = CODE_FOR_absdf2;
4176#endif
b092b471
JW
4177#ifdef HAVE_absxf2
4178 if (HAVE_absxf2)
4179 abs_optab->handlers[(int) XFmode].insn_code = CODE_FOR_absxf2;
4180#endif
77c9c6c2
RK
4181#ifdef HAVE_abstf2
4182 if (HAVE_abstf2)
4183 abs_optab->handlers[(int) TFmode].insn_code = CODE_FOR_abstf2;
4184#endif
4185 /* No library calls here! If there is no abs instruction,
4186 expand_expr will generate a conditional negation. */
4187
d45cf215
RS
4188#ifdef HAVE_sqrtqi2
4189 if (HAVE_sqrtqi2)
4190 sqrt_optab->handlers[(int) QImode].insn_code = CODE_FOR_sqrtqi2;
4191#endif
4192#ifdef HAVE_sqrthi2
4193 if (HAVE_sqrthi2)
4194 sqrt_optab->handlers[(int) HImode].insn_code = CODE_FOR_sqrthi2;
4195#endif
4196#ifdef HAVE_sqrtpsi2
4197 if (HAVE_sqrtpsi2)
4198 sqrt_optab->handlers[(int) PSImode].insn_code = CODE_FOR_sqrtpsi2;
4199#endif
4200#ifdef HAVE_sqrtsi2
4201 if (HAVE_sqrtsi2)
4202 sqrt_optab->handlers[(int) SImode].insn_code = CODE_FOR_sqrtsi2;
4203#endif
4204#ifdef HAVE_sqrtdi2
4205 if (HAVE_sqrtdi2)
4206 sqrt_optab->handlers[(int) DImode].insn_code = CODE_FOR_sqrtdi2;
4207#endif
4208#ifdef HAVE_sqrtti2
4209 if (HAVE_sqrtti2)
4210 sqrt_optab->handlers[(int) TImode].insn_code = CODE_FOR_sqrtti2;
4211#endif
4212#ifdef HAVE_sqrtsf2
4213 if (HAVE_sqrtsf2)
4214 sqrt_optab->handlers[(int) SFmode].insn_code = CODE_FOR_sqrtsf2;
4215#endif
4216#ifdef HAVE_sqrtdf2
4217 if (HAVE_sqrtdf2)
4218 sqrt_optab->handlers[(int) DFmode].insn_code = CODE_FOR_sqrtdf2;
4219#endif
4220#ifdef HAVE_sqrttf2
4221 if (HAVE_sqrttf2)
4222 sqrt_optab->handlers[(int) TFmode].insn_code = CODE_FOR_sqrttf2;
4223#endif
4224 /* No library calls here! If there is no sqrt instruction expand_builtin
4225 should force the library call. */
4226
19c3fc24
RS
4227#ifdef HAVE_strlenqi
4228 if (HAVE_strlenqi)
4229 strlen_optab->handlers[(int) QImode].insn_code = CODE_FOR_strlenqi;
4230#endif
4231#ifdef HAVE_strlenhi
4232 if (HAVE_strlenhi)
4233 strlen_optab->handlers[(int) HImode].insn_code = CODE_FOR_strlenhi;
4234#endif
4235#ifdef HAVE_strlenpsi
4236 if (HAVE_strlenpsi)
4237 strlen_optab->handlers[(int) PSImode].insn_code = CODE_FOR_strlenpsi;
4238#endif
4239#ifdef HAVE_strlensi
4240 if (HAVE_strlensi)
4241 strlen_optab->handlers[(int) SImode].insn_code = CODE_FOR_strlensi;
4242#endif
4243#ifdef HAVE_strlendi
4244 if (HAVE_strlendi)
4245 strlen_optab->handlers[(int) DImode].insn_code = CODE_FOR_strlendi;
4246#endif
4247#ifdef HAVE_strlenti
4248 if (HAVE_strlenti)
4249 strlen_optab->handlers[(int) TImode].insn_code = CODE_FOR_strlenti;
4250#endif
4251 /* No library calls here! If there is no strlen instruction expand_builtin
4252 should force the library call. */
4253
77c9c6c2
RK
4254#ifdef HAVE_one_cmplqi2
4255 if (HAVE_one_cmplqi2)
4256 one_cmpl_optab->handlers[(int) QImode].insn_code = CODE_FOR_one_cmplqi2;
4257#endif
4258#ifdef HAVE_one_cmplhi2
4259 if (HAVE_one_cmplhi2)
4260 one_cmpl_optab->handlers[(int) HImode].insn_code = CODE_FOR_one_cmplhi2;
4261#endif
4262#ifdef HAVE_one_cmplpsi2
4263 if (HAVE_one_cmplpsi2)
4264 one_cmpl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_one_cmplpsi2;
4265#endif
4266#ifdef HAVE_one_cmplsi2
4267 if (HAVE_one_cmplsi2)
4268 one_cmpl_optab->handlers[(int) SImode].insn_code = CODE_FOR_one_cmplsi2;
4269#endif
4270#ifdef HAVE_one_cmpldi2
4271 if (HAVE_one_cmpldi2)
4272 one_cmpl_optab->handlers[(int) DImode].insn_code = CODE_FOR_one_cmpldi2;
4273#endif
4274#ifdef HAVE_one_cmplti2
4275 if (HAVE_one_cmplti2)
4276 one_cmpl_optab->handlers[(int) TImode].insn_code = CODE_FOR_one_cmplti2;
4277#endif
b092b471 4278 init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
77c9c6c2
RK
4279
4280#ifdef HAVE_ffsqi2
4281 if (HAVE_ffsqi2)
4282 ffs_optab->handlers[(int) QImode].insn_code = CODE_FOR_ffsqi2;
4283#endif
4284#ifdef HAVE_ffshi2
4285 if (HAVE_ffshi2)
4286 ffs_optab->handlers[(int) HImode].insn_code = CODE_FOR_ffshi2;
4287#endif
4288#ifdef HAVE_ffspsi2
4289 if (HAVE_ffspsi2)
4290 ffs_optab->handlers[(int) PSImode].insn_code = CODE_FOR_ffspsi2;
4291#endif
4292#ifdef HAVE_ffssi2
4293 if (HAVE_ffssi2)
4294 ffs_optab->handlers[(int) SImode].insn_code = CODE_FOR_ffssi2;
4295#endif
4296#ifdef HAVE_ffsdi2
4297 if (HAVE_ffsdi2)
4298 ffs_optab->handlers[(int) DImode].insn_code = CODE_FOR_ffsdi2;
4299#endif
4300#ifdef HAVE_ffsti2
4301 if (HAVE_ffsti2)
4302 ffs_optab->handlers[(int) TImode].insn_code = CODE_FOR_ffsti2;
4303#endif
b092b471 4304 init_integral_libfuncs (ffs_optab, "ffs", '2');
77c9c6c2
RK
4305
4306#ifdef HAVE_movqi
4307 if (HAVE_movqi)
4308 mov_optab->handlers[(int) QImode].insn_code = CODE_FOR_movqi;
4309#endif
4310#ifdef HAVE_movhi
4311 if (HAVE_movhi)
4312 mov_optab->handlers[(int) HImode].insn_code = CODE_FOR_movhi;
4313#endif
4314#ifdef HAVE_movpsi
4315 if (HAVE_movpsi)
4316 mov_optab->handlers[(int) PSImode].insn_code = CODE_FOR_movpsi;
4317#endif
4318#ifdef HAVE_movsi
4319 if (HAVE_movsi)
4320 mov_optab->handlers[(int) SImode].insn_code = CODE_FOR_movsi;
4321#endif
4322#ifdef HAVE_movdi
4323 if (HAVE_movdi)
4324 mov_optab->handlers[(int) DImode].insn_code = CODE_FOR_movdi;
4325#endif
4326#ifdef HAVE_movti
4327 if (HAVE_movti)
4328 mov_optab->handlers[(int) TImode].insn_code = CODE_FOR_movti;
4329#endif
4330#ifdef HAVE_movsf
4331 if (HAVE_movsf)
4332 mov_optab->handlers[(int) SFmode].insn_code = CODE_FOR_movsf;
4333#endif
4334#ifdef HAVE_movdf
4335 if (HAVE_movdf)
4336 mov_optab->handlers[(int) DFmode].insn_code = CODE_FOR_movdf;
4337#endif
b092b471
JW
4338#ifdef HAVE_movxf
4339 if (HAVE_movxf)
4340 mov_optab->handlers[(int) XFmode].insn_code = CODE_FOR_movxf;
4341#endif
77c9c6c2
RK
4342#ifdef HAVE_movtf
4343 if (HAVE_movtf)
4344 mov_optab->handlers[(int) TFmode].insn_code = CODE_FOR_movtf;
4345#endif
4346#ifdef HAVE_movcc
4347 if (HAVE_movcc)
4348 mov_optab->handlers[(int) CCmode].insn_code = CODE_FOR_movcc;
4349#endif
4350
4351#ifdef EXTRA_CC_MODES
4352 init_mov_optab ();
4353#endif
4354
4355#ifdef HAVE_movstrictqi
4356 if (HAVE_movstrictqi)
4357 movstrict_optab->handlers[(int) QImode].insn_code = CODE_FOR_movstrictqi;
4358#endif
4359#ifdef HAVE_movstricthi
4360 if (HAVE_movstricthi)
4361 movstrict_optab->handlers[(int) HImode].insn_code = CODE_FOR_movstricthi;
4362#endif
4363#ifdef HAVE_movstrictpsi
4364 if (HAVE_movstrictpsi)
4365 movstrict_optab->handlers[(int) PSImode].insn_code = CODE_FOR_movstrictpsi;
4366#endif
4367#ifdef HAVE_movstrictsi
4368 if (HAVE_movstrictsi)
4369 movstrict_optab->handlers[(int) SImode].insn_code = CODE_FOR_movstrictsi;
4370#endif
4371#ifdef HAVE_movstrictdi
4372 if (HAVE_movstrictdi)
4373 movstrict_optab->handlers[(int) DImode].insn_code = CODE_FOR_movstrictdi;
4374#endif
4375#ifdef HAVE_movstrictti
4376 if (HAVE_movstrictti)
4377 movstrict_optab->handlers[(int) TImode].insn_code = CODE_FOR_movstrictti;
4378#endif
4379
4380#ifdef HAVE_cmpqi
4381 if (HAVE_cmpqi)
4382 cmp_optab->handlers[(int) QImode].insn_code = CODE_FOR_cmpqi;
4383#endif
4384#ifdef HAVE_cmphi
4385 if (HAVE_cmphi)
4386 cmp_optab->handlers[(int) HImode].insn_code = CODE_FOR_cmphi;
4387#endif
4388#ifdef HAVE_cmppsi
4389 if (HAVE_cmppsi)
4390 cmp_optab->handlers[(int) PSImode].insn_code = CODE_FOR_cmppsi;
4391#endif
4392#ifdef HAVE_cmpsi
4393 if (HAVE_cmpsi)
4394 cmp_optab->handlers[(int) SImode].insn_code = CODE_FOR_cmpsi;
4395#endif
4396#ifdef HAVE_cmpdi
4397 if (HAVE_cmpdi)
4398 cmp_optab->handlers[(int) DImode].insn_code = CODE_FOR_cmpdi;
4399#endif
4400#ifdef HAVE_cmpti
4401 if (HAVE_cmpti)
4402 cmp_optab->handlers[(int) TImode].insn_code = CODE_FOR_cmpti;
4403#endif
4404#ifdef HAVE_cmpsf
4405 if (HAVE_cmpsf)
4406 cmp_optab->handlers[(int) SFmode].insn_code = CODE_FOR_cmpsf;
4407#endif
4408#ifdef HAVE_cmpdf
4409 if (HAVE_cmpdf)
4410 cmp_optab->handlers[(int) DFmode].insn_code = CODE_FOR_cmpdf;
4411#endif
b092b471
JW
4412#ifdef HAVE_cmpxf
4413 if (HAVE_cmpxf)
4414 cmp_optab->handlers[(int) XFmode].insn_code = CODE_FOR_cmpxf;
4415#endif
77c9c6c2
RK
4416#ifdef HAVE_cmptf
4417 if (HAVE_cmptf)
4418 cmp_optab->handlers[(int) TFmode].insn_code = CODE_FOR_cmptf;
4419#endif
b092b471
JW
4420 /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
4421 init_integral_libfuncs (cmp_optab, "cmp", '2');
4422 init_integral_libfuncs (ucmp_optab, "ucmp", '2');
4423 init_floating_libfuncs (cmp_optab, "cmp", '2');
4424
77c9c6c2
RK
4425#ifdef HAVE_tstqi
4426 if (HAVE_tstqi)
4427 tst_optab->handlers[(int) QImode].insn_code = CODE_FOR_tstqi;
4428#endif
4429#ifdef HAVE_tsthi
4430 if (HAVE_tsthi)
4431 tst_optab->handlers[(int) HImode].insn_code = CODE_FOR_tsthi;
4432#endif
4433#ifdef HAVE_tstpsi
4434 if (HAVE_tstpsi)
4435 tst_optab->handlers[(int) PSImode].insn_code = CODE_FOR_tstpsi;
4436#endif
4437#ifdef HAVE_tstsi
4438 if (HAVE_tstsi)
4439 tst_optab->handlers[(int) SImode].insn_code = CODE_FOR_tstsi;
4440#endif
4441#ifdef HAVE_tstdi
4442 if (HAVE_tstdi)
4443 tst_optab->handlers[(int) DImode].insn_code = CODE_FOR_tstdi;
4444#endif
4445#ifdef HAVE_tstti
4446 if (HAVE_tstti)
4447 tst_optab->handlers[(int) TImode].insn_code = CODE_FOR_tstti;
4448#endif
4449#ifdef HAVE_tstsf
4450 if (HAVE_tstsf)
4451 tst_optab->handlers[(int) SFmode].insn_code = CODE_FOR_tstsf;
4452#endif
4453#ifdef HAVE_tstdf
4454 if (HAVE_tstdf)
4455 tst_optab->handlers[(int) DFmode].insn_code = CODE_FOR_tstdf;
4456#endif
b092b471
JW
4457#ifdef HAVE_tstxf
4458 if (HAVE_tstxf)
4459 tst_optab->handlers[(int) XFmode].insn_code = CODE_FOR_tstxf;
4460#endif
77c9c6c2
RK
4461#ifdef HAVE_tsttf
4462 if (HAVE_tsttf)
4463 tst_optab->handlers[(int) TFmode].insn_code = CODE_FOR_tsttf;
4464#endif
77c9c6c2
RK
4465
4466#ifdef HAVE_beq
4467 if (HAVE_beq)
4468 bcc_gen_fctn[(int) EQ] = gen_beq;
4469#endif
4470#ifdef HAVE_bne
4471 if (HAVE_bne)
4472 bcc_gen_fctn[(int) NE] = gen_bne;
4473#endif
4474#ifdef HAVE_bgt
4475 if (HAVE_bgt)
4476 bcc_gen_fctn[(int) GT] = gen_bgt;
4477#endif
4478#ifdef HAVE_bge
4479 if (HAVE_bge)
4480 bcc_gen_fctn[(int) GE] = gen_bge;
4481#endif
4482#ifdef HAVE_bgtu
4483 if (HAVE_bgtu)
4484 bcc_gen_fctn[(int) GTU] = gen_bgtu;
4485#endif
4486#ifdef HAVE_bgeu
4487 if (HAVE_bgeu)
4488 bcc_gen_fctn[(int) GEU] = gen_bgeu;
4489#endif
4490#ifdef HAVE_blt
4491 if (HAVE_blt)
4492 bcc_gen_fctn[(int) LT] = gen_blt;
4493#endif
4494#ifdef HAVE_ble
4495 if (HAVE_ble)
4496 bcc_gen_fctn[(int) LE] = gen_ble;
4497#endif
4498#ifdef HAVE_bltu
4499 if (HAVE_bltu)
4500 bcc_gen_fctn[(int) LTU] = gen_bltu;
4501#endif
4502#ifdef HAVE_bleu
4503 if (HAVE_bleu)
4504 bcc_gen_fctn[(int) LEU] = gen_bleu;
4505#endif
4506
4507 for (i = 0; i < NUM_RTX_CODE; i++)
4508 setcc_gen_code[i] = CODE_FOR_nothing;
4509
4510#ifdef HAVE_seq
4511 if (HAVE_seq)
4512 setcc_gen_code[(int) EQ] = CODE_FOR_seq;
4513#endif
4514#ifdef HAVE_sne
4515 if (HAVE_sne)
4516 setcc_gen_code[(int) NE] = CODE_FOR_sne;
4517#endif
4518#ifdef HAVE_sgt
4519 if (HAVE_sgt)
4520 setcc_gen_code[(int) GT] = CODE_FOR_sgt;
4521#endif
4522#ifdef HAVE_sge
4523 if (HAVE_sge)
4524 setcc_gen_code[(int) GE] = CODE_FOR_sge;
4525#endif
4526#ifdef HAVE_sgtu
4527 if (HAVE_sgtu)
4528 setcc_gen_code[(int) GTU] = CODE_FOR_sgtu;
4529#endif
4530#ifdef HAVE_sgeu
4531 if (HAVE_sgeu)
4532 setcc_gen_code[(int) GEU] = CODE_FOR_sgeu;
4533#endif
4534#ifdef HAVE_slt
4535 if (HAVE_slt)
4536 setcc_gen_code[(int) LT] = CODE_FOR_slt;
4537#endif
4538#ifdef HAVE_sle
4539 if (HAVE_sle)
4540 setcc_gen_code[(int) LE] = CODE_FOR_sle;
4541#endif
4542#ifdef HAVE_sltu
4543 if (HAVE_sltu)
4544 setcc_gen_code[(int) LTU] = CODE_FOR_sltu;
4545#endif
4546#ifdef HAVE_sleu
4547 if (HAVE_sleu)
4548 setcc_gen_code[(int) LEU] = CODE_FOR_sleu;
4549#endif
4550
4551 extendsfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfdf2");
b092b471
JW
4552 extendsfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfxf2");
4553 extendsftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsftf2");
4554 extenddfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddfxf2");
4555 extenddftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddftf2");
4556
77c9c6c2 4557 truncdfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncdfsf2");
b092b471
JW
4558 truncxfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfsf2");
4559 trunctfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfsf2");
4560 truncxfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfdf2");
4561 trunctfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfdf2");
4562
77c9c6c2
RK
4563 memcpy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcpy");
4564 bcopy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bcopy");
4565 memcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcmp");
4566 bcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bcmp");
4567 memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset");
4568 bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero");
b092b471 4569
77c9c6c2
RK
4570 eqsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqsf2");
4571 nesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nesf2");
4572 gtsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtsf2");
4573 gesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gesf2");
4574 ltsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltsf2");
4575 lesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lesf2");
b092b471 4576
77c9c6c2
RK
4577 eqdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqdf2");
4578 nedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nedf2");
4579 gtdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtdf2");
4580 gedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gedf2");
4581 ltdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltdf2");
4582 ledf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ledf2");
b092b471
JW
4583
4584 eqxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqxf2");
4585 nexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nexf2");
4586 gtxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtxf2");
4587 gexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gexf2");
4588 ltxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltxf2");
4589 lexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lexf2");
4590
4591 eqtf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqtf2");
4592 netf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__netf2");
4593 gttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gttf2");
4594 getf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__getf2");
4595 lttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lttf2");
4596 letf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__letf2");
4597
6bce1b78 4598 floatsisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsisf");
b092b471
JW
4599 floatdisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdisf");
4600 floattisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattisf");
4601
6bce1b78 4602 floatsidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsidf");
b092b471
JW
4603 floatdidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdidf");
4604 floattidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattidf");
4605
4606 floatsixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsixf");
4607 floatdixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdixf");
4608 floattixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattixf");
4609
4610 floatsitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsitf");
4611 floatditf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatditf");
4612 floattitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattitf");
4613
6bce1b78
RK
4614 fixsfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfsi");
4615 fixsfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfdi");
b092b471
JW
4616 fixsfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfti");
4617
6bce1b78
RK
4618 fixdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfsi");
4619 fixdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfdi");
b092b471
JW
4620 fixdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfti");
4621
4622 fixxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfsi");
4623 fixxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfdi");
4624 fixxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfti");
4625
4626 fixtfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfsi");
4627 fixtfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfdi");
4628 fixtfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfti");
4629
6bce1b78
RK
4630 fixunssfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfsi");
4631 fixunssfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfdi");
b092b471
JW
4632 fixunssfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfti");
4633
6bce1b78
RK
4634 fixunsdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfsi");
4635 fixunsdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfdi");
b092b471
JW
4636 fixunsdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfti");
4637
4638 fixunsxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfsi");
4639 fixunsxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfdi");
4640 fixunsxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfti");
4641
4642 fixunstfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfsi");
4643 fixunstfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfdi");
4644 fixunstfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfti");
77c9c6c2 4645}
7e1966ca
JVA
4646\f
4647#ifdef BROKEN_LDEXP
4648
4649/* SCO 3.2 apparently has a broken ldexp. */
4650
4651double
4652ldexp(x,n)
4653 double x;
4654 int n;
4655{
4656 if (n > 0)
4657 while (n--)
4658 x *= 2;
4659
4660 return x;
4661}
4662#endif /* BROKEN_LDEXP */
This page took 0.530634 seconds and 5 git commands to generate.