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