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