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