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