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