1 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2 Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
25 #include "insn-flags.h"
26 #include "insn-codes.h"
28 #include "insn-config.h"
31 /* Each optab contains info on how this target machine
32 can perform a particular operation
33 for all sizes and kinds of operands.
35 The operation to be performed is often specified
36 by passing one of these optabs as an argument.
38 See expr.h for documentation of these optabs. */
43 optab smul_widen_optab
;
44 optab umul_widen_optab
;
68 optab movstrict_optab
;
77 optab ucmp_optab
; /* Used only for libcalls for unsigned comparisons. */
82 /* SYMBOL_REF rtx's for the library functions that are called
83 implicitly and not via optabs. */
85 rtx extendsfdf2_libfunc
;
86 rtx truncdfsf2_libfunc
;
105 rtx floatdisf_libfunc
;
106 rtx floatsisf_libfunc
;
107 rtx floatdidf_libfunc
;
108 rtx floatsidf_libfunc
;
113 rtx fixunssfsi_libfunc
;
114 rtx fixunssfdi_libfunc
;
115 rtx fixunsdfsi_libfunc
;
116 rtx fixunsdfdi_libfunc
;
118 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
119 gives the gen_function to make a branch to test that condition. */
121 rtxfun bcc_gen_fctn
[NUM_RTX_CODE
];
123 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
124 gives the insn code to make a store-condition insn
125 to test that condition. */
127 enum insn_code setcc_gen_code
[NUM_RTX_CODE
];
129 static void emit_float_lib_cmp ();
131 /* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
132 the result of operation CODE applied to OP0 (and OP1 if it is a binary
135 If the last insn does not set TARGET, don't do anything, but return 1.
137 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
138 don't add the REG_EQUAL note but return 0. Our caller can then try
139 again, ensuring that TARGET is not one of the operands. */
142 add_equal_note (seq
, target
, code
, op0
, op1
)
152 if ((GET_RTX_CLASS (code
) != '1' && GET_RTX_CLASS (code
) != '2'
153 && GET_RTX_CLASS (code
) != 'c' && GET_RTX_CLASS (code
) != '<')
154 || GET_CODE (seq
) != SEQUENCE
155 || (set
= single_set (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1))) == 0
156 || GET_CODE (target
) == ZERO_EXTRACT
157 || (! rtx_equal_p (SET_DEST (set
), target
)
158 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
160 && (GET_CODE (SET_DEST (set
)) != STRICT_LOW_PART
161 || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set
), 0)),
165 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
166 besides the last insn. */
167 if (reg_overlap_mentioned_p (target
, op0
)
168 || (op1
&& reg_overlap_mentioned_p (target
, op1
)))
169 for (i
= XVECLEN (seq
, 0) - 2; i
>= 0; i
--)
170 if (reg_set_p (target
, XVECEXP (seq
, 0, i
)))
173 if (GET_RTX_CLASS (code
) == '1')
174 note
= gen_rtx (code
, GET_MODE (target
), op0
);
176 note
= gen_rtx (code
, GET_MODE (target
), op0
, op1
);
178 REG_NOTES (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1))
179 = gen_rtx (EXPR_LIST
, REG_EQUAL
, note
,
180 REG_NOTES (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1)));
185 /* Generate code to perform an operation specified by BINOPTAB
186 on operands OP0 and OP1, with result having machine-mode MODE.
188 UNSIGNEDP is for the case where we have to widen the operands
189 to perform the operation. It says to use zero-extension.
191 If TARGET is nonzero, the value
192 is generated there, if it is convenient to do so.
193 In all cases an rtx is returned for the locus of the value;
194 this may or may not be TARGET. */
197 expand_binop (mode
, binoptab
, op0
, op1
, target
, unsignedp
, methods
)
198 enum machine_mode mode
;
203 enum optab_methods methods
;
205 enum mode_class
class;
206 enum machine_mode wider_mode
;
208 int commutative_op
= 0;
209 int shift_op
= (binoptab
->code
== ASHIFT
210 || binoptab
->code
== ASHIFTRT
211 || binoptab
->code
== LSHIFT
212 || binoptab
->code
== LSHIFTRT
213 || binoptab
->code
== ROTATE
214 || binoptab
->code
== ROTATERT
);
217 class = GET_MODE_CLASS (mode
);
219 op0
= protect_from_queue (op0
, 0);
220 op1
= protect_from_queue (op1
, 0);
222 target
= protect_from_queue (target
, 1);
226 op0
= force_not_mem (op0
);
227 op1
= force_not_mem (op1
);
230 /* If we are inside an appropriately-short loop and one operand is an
231 expensive constant, force it into a register. */
232 if (CONSTANT_P (op0
) && preserve_subexpressions_p ()
233 && rtx_cost (op0
, binoptab
->code
) > 2)
234 op0
= force_reg (mode
, op0
);
236 if (CONSTANT_P (op1
) && preserve_subexpressions_p ()
237 && rtx_cost (op1
, binoptab
->code
) > 2)
238 op1
= force_reg (shift_op
? word_mode
: mode
, op1
);
240 #if 0 /* Turned off because it seems to be a kludgy method. */
241 /* If subtracting integer from pointer, and the pointer has a special mode,
242 then change it to an add. We use the add insn of Pmode for combining
243 integers with pointers, and the sub insn to subtract two pointers. */
245 if (binoptab
== sub_optab
246 && GET_MODE (op0
) == Pmode
&& GET_MODE (op1
) != Pmode
)
248 op1
= negate_rtx (GET_MODE(op1
), op1
);
249 binoptab
= add_optab
;
253 /* Record where to delete back to if we backtrack. */
254 last
= get_last_insn ();
256 /* If operation is commutative,
257 try to make the first operand a register.
258 Even better, try to make it the same as the target.
259 Also try to make the last operand a constant. */
260 if (GET_RTX_CLASS (binoptab
->code
) == 'c'
261 || binoptab
== smul_widen_optab
262 || binoptab
== umul_widen_optab
)
266 if (((target
== 0 || GET_CODE (target
) == REG
)
267 ? ((GET_CODE (op1
) == REG
268 && GET_CODE (op0
) != REG
)
270 : rtx_equal_p (op1
, target
))
271 || GET_CODE (op0
) == CONST_INT
)
279 /* If we can do it with a three-operand insn, do so. */
281 if (methods
!= OPTAB_MUST_WIDEN
282 && binoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
284 int icode
= (int) binoptab
->handlers
[(int) mode
].insn_code
;
285 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
286 enum machine_mode mode1
= insn_operand_mode
[icode
][2];
288 rtx xop0
= op0
, xop1
= op1
;
293 temp
= gen_reg_rtx (mode
);
295 /* If it is a commutative operator and the modes would match
296 if we would swap the operands, we can save the conversions. */
299 if (GET_MODE (op0
) != mode0
&& GET_MODE (op1
) != mode1
300 && GET_MODE (op0
) == mode1
&& GET_MODE (op1
) == mode0
)
304 tmp
= op0
; op0
= op1
; op1
= tmp
;
305 tmp
= xop0
; xop0
= xop1
; xop1
= tmp
;
309 /* In case the insn wants input operands in modes different from
310 the result, convert the operands. */
312 if (GET_MODE (op0
) != VOIDmode
313 && GET_MODE (op0
) != mode0
)
314 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
316 if (GET_MODE (xop1
) != VOIDmode
317 && GET_MODE (xop1
) != mode1
)
318 xop1
= convert_to_mode (mode1
, xop1
, unsignedp
);
320 /* Now, if insn's predicates don't allow our operands, put them into
323 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
324 xop0
= copy_to_mode_reg (mode0
, xop0
);
326 if (! (*insn_operand_predicate
[icode
][2]) (xop1
, mode1
))
327 xop1
= copy_to_mode_reg (mode1
, xop1
);
329 if (! (*insn_operand_predicate
[icode
][0]) (temp
, mode
))
330 temp
= gen_reg_rtx (mode
);
332 pat
= GEN_FCN (icode
) (temp
, xop0
, xop1
);
335 /* If PAT is a multi-insn sequence, try to add an appropriate
336 REG_EQUAL note to it. If we can't because TEMP conflicts with an
337 operand, call ourselves again, this time without a target. */
338 if (GET_CODE (pat
) == SEQUENCE
339 && ! add_equal_note (pat
, temp
, binoptab
->code
, xop0
, xop1
))
341 delete_insns_since (last
);
342 return expand_binop (mode
, binoptab
, op0
, op1
, 0, unsignedp
,
350 delete_insns_since (last
);
353 /* These can be done a word at a time. */
354 if ((binoptab
== and_optab
|| binoptab
== ior_optab
|| binoptab
== xor_optab
)
356 && GET_MODE_SIZE (mode
) > UNITS_PER_WORD
357 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
363 /* If TARGET is the same as one of the operands, the REG_EQUAL note
364 won't be accurate, so use a new target. */
365 if (target
== 0 || target
== op0
|| target
== op1
)
366 target
= gen_reg_rtx (mode
);
370 /* Do the actual arithmetic. */
371 for (i
= 0; i
< GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
; i
++)
373 rtx target_piece
= operand_subword (target
, i
, 1, mode
);
374 rtx x
= expand_binop (word_mode
, binoptab
,
375 operand_subword_force (op0
, i
, mode
),
376 operand_subword_force (op1
, i
, mode
),
377 target_piece
, unsignedp
, methods
);
378 if (target_piece
!= x
)
379 emit_move_insn (target_piece
, x
);
382 insns
= get_insns ();
385 if (binoptab
->code
!= UNKNOWN
)
386 equiv_value
= gen_rtx (binoptab
->code
, mode
, op0
, op1
);
390 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv_value
);
394 /* These can be done a word at a time by propagating carries. */
395 if ((binoptab
== add_optab
|| binoptab
== sub_optab
)
397 && GET_MODE_SIZE (mode
) >= 2 * UNITS_PER_WORD
398 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
401 rtx carry_tmp
= gen_reg_rtx (word_mode
);
402 optab otheroptab
= binoptab
== add_optab
? sub_optab
: add_optab
;
403 int nwords
= GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
;
404 rtx carry_in
, carry_out
;
406 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
407 value is one of those, use it. Otherwise, use 1 since it is the
408 one easiest to get. */
409 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
410 int normalizep
= STORE_FLAG_VALUE
;
415 /* Prepare the operands. */
416 op0
= force_reg (mode
, op0
);
417 op1
= force_reg (mode
, op1
);
419 if (target
== 0 || GET_CODE (target
) != REG
420 || target
== op0
|| target
== op1
)
421 target
= gen_reg_rtx (mode
);
423 /* Do the actual arithmetic. */
424 for (i
= 0; i
< nwords
; i
++)
426 int index
= (WORDS_BIG_ENDIAN
? nwords
- i
- 1 : i
);
427 rtx target_piece
= operand_subword (target
, index
, 1, mode
);
428 rtx op0_piece
= operand_subword_force (op0
, index
, mode
);
429 rtx op1_piece
= operand_subword_force (op1
, index
, mode
);
432 /* Main add/subtract of the input operands. */
433 x
= expand_binop (word_mode
, binoptab
,
434 op0_piece
, op1_piece
,
435 target_piece
, unsignedp
, methods
);
441 /* Store carry from main add/subtract. */
442 carry_out
= gen_reg_rtx (word_mode
);
443 carry_out
= emit_store_flag (carry_out
,
444 binoptab
== add_optab
? LTU
: GTU
,
446 word_mode
, 1, normalizep
);
453 /* Add/subtract previous carry to main result. */
454 x
= expand_binop (word_mode
,
455 normalizep
== 1 ? binoptab
: otheroptab
,
457 target_piece
, 1, methods
);
458 if (target_piece
!= x
)
459 emit_move_insn (target_piece
, x
);
463 /* THIS CODE HAS NOT BEEN TESTED. */
464 /* Get out carry from adding/subtracting carry in. */
465 carry_tmp
= emit_store_flag (carry_tmp
,
466 binoptab
== add_optab
469 word_mode
, 1, normalizep
);
470 /* Logical-ior the two poss. carry together. */
471 carry_out
= expand_binop (word_mode
, ior_optab
,
472 carry_out
, carry_tmp
,
473 carry_out
, 0, methods
);
479 carry_in
= carry_out
;
482 if (i
== GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
)
486 temp
= emit_move_insn (target
, target
);
487 REG_NOTES (temp
) = gen_rtx (EXPR_LIST
, REG_EQUAL
,
488 gen_rtx (binoptab
->code
, mode
, op0
, op1
),
493 delete_insns_since (last
);
496 /* If we want to multiply two two-word values and have normal and widening
497 multiplies of single-word values, we can do this with three smaller
498 multiplications. Note that we do not make a REG_NO_CONFLICT block here
499 because we are not operating on one word at a time.
501 The multiplication proceeds as follows:
502 _______________________
503 [__op0_high_|__op0_low__]
504 _______________________
505 * [__op1_high_|__op1_low__]
506 _______________________________________________
507 _______________________
508 (1) [__op0_low__*__op1_low__]
509 _______________________
510 (2a) [__op0_low__*__op1_high_]
511 _______________________
512 (2b) [__op0_high_*__op1_low__]
513 _______________________
514 (3) [__op0_high_*__op1_high_]
517 This gives a 4-word result. Since we are only interested in the
518 lower 2 words, partial result (3) and the upper words of (2a) and
519 (2b) don't need to be calculated. Hence (2a) and (2b) can be
520 calculated using non-widening multiplication.
522 (1), however, needs to be calculated with an unsigned widening
523 multiplication. If this operation is not directly supported we
524 try using a signed widening multiplication and adjust the result.
525 This adjustment works as follows:
527 If both operands are positive then no adjustment is needed.
529 If the operands have different signs, for example op0_low < 0 and
530 op1_low >= 0, the instruction treats the most significant bit of
531 op0_low as a sign bit instead of a bit with significance
532 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
533 with 2**BITS_PER_WORD - op0_low, and two's complements the
534 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
537 Similarly, if both operands are negative, we need to add
538 (op0_low + op1_low) * 2**BITS_PER_WORD.
540 We use a trick to adjust quickly. We logically shift op0_low right
541 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
542 op0_high (op1_high) before it is used to calculate 2b (2a). If no
543 logical shift exists, we do an arithmetic right shift and subtract
546 if (binoptab
== smul_optab
548 && GET_MODE_SIZE (mode
) == 2 * UNITS_PER_WORD
549 && smul_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
550 && add_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
551 && ((umul_widen_optab
->handlers
[(int) mode
].insn_code
553 || (smul_widen_optab
->handlers
[(int) mode
].insn_code
554 != CODE_FOR_nothing
)))
556 int low
= (WORDS_BIG_ENDIAN
? 1 : 0);
557 int high
= (WORDS_BIG_ENDIAN
? 0 : 1);
558 rtx op0_high
= operand_subword_force (op0
, high
, mode
);
559 rtx op0_low
= operand_subword_force (op0
, low
, mode
);
560 rtx op1_high
= operand_subword_force (op1
, high
, mode
);
561 rtx op1_low
= operand_subword_force (op1
, low
, mode
);
566 /* If the target is the same as one of the inputs, don't use it. This
567 prevents problems with the REG_EQUAL note. */
568 if (target
== op0
|| target
== op1
)
571 /* Multiply the two lower words to get a double-word product.
572 If unsigned widening multiplication is available, use that;
573 otherwise use the signed form and compensate. */
575 if (umul_widen_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
577 product
= expand_binop (mode
, umul_widen_optab
, op0_low
, op1_low
,
578 target
, 1, OPTAB_DIRECT
);
580 /* If we didn't succeed, delete everything we did so far. */
582 delete_insns_since (last
);
584 op0_xhigh
= op0_high
, op1_xhigh
= op1_high
;
588 && smul_widen_optab
->handlers
[(int) mode
].insn_code
591 rtx wordm1
= gen_rtx (CONST_INT
, VOIDmode
, BITS_PER_WORD
- 1);
592 product
= expand_binop (mode
, smul_widen_optab
, op0_low
, op1_low
,
593 target
, 1, OPTAB_DIRECT
);
594 op0_xhigh
= expand_binop (word_mode
, lshr_optab
, op0_low
, wordm1
,
597 op0_xhigh
= expand_binop (word_mode
, add_optab
, op0_high
,
598 op0_xhigh
, op0_xhigh
, 0, OPTAB_DIRECT
);
601 op0_xhigh
= expand_binop (word_mode
, ashr_optab
, op0_low
, wordm1
,
604 op0_xhigh
= expand_binop (word_mode
, sub_optab
, op0_high
,
605 op0_xhigh
, op0_xhigh
, 0,
609 op1_xhigh
= expand_binop (word_mode
, lshr_optab
, op1_low
, wordm1
,
612 op1_xhigh
= expand_binop (word_mode
, add_optab
, op1_high
,
613 op1_xhigh
, op1_xhigh
, 0, OPTAB_DIRECT
);
616 op1_xhigh
= expand_binop (word_mode
, ashr_optab
, op1_low
, wordm1
,
619 op1_xhigh
= expand_binop (word_mode
, sub_optab
, op1_high
,
620 op1_xhigh
, op1_xhigh
, 0,
625 /* If we have been able to directly compute the product of the
626 low-order words of the operands and perform any required adjustments
627 of the operands, we proceed by trying two more multiplications
628 and then computing the appropriate sum.
630 We have checked above that the required addition is provided.
631 Full-word addition will normally always succeed, especially if
632 it is provided at all, so we don't worry about its failure. The
633 multiplication may well fail, however, so we do handle that. */
635 if (product
&& op0_xhigh
&& op1_xhigh
)
638 rtx product_high
= operand_subword (product
, high
, 1, mode
);
639 rtx temp
= expand_binop (word_mode
, binoptab
, op0_low
, op1_xhigh
, 0,
644 product_piece
= expand_binop (word_mode
, add_optab
, temp
,
645 product_high
, product_high
,
647 if (product_piece
!= product_high
)
648 emit_move_insn (product_high
, product_piece
);
650 temp
= expand_binop (word_mode
, binoptab
, op1_low
, op0_xhigh
, 0,
653 product_piece
= expand_binop (word_mode
, add_optab
, temp
,
654 product_high
, product_high
,
656 if (product_piece
!= product_high
)
657 emit_move_insn (product_high
, product_piece
);
659 temp
= emit_move_insn (product
, product
);
660 REG_NOTES (temp
) = gen_rtx (EXPR_LIST
, REG_EQUAL
,
661 gen_rtx (MULT
, mode
, op0
, op1
),
668 /* If we get here, we couldn't do it for some reason even though we
669 originally thought we could. Delete anything we've emitted in
672 delete_insns_since (last
);
675 /* It can't be open-coded in this mode.
676 Use a library call if one is available and caller says that's ok. */
678 if (binoptab
->handlers
[(int) mode
].libfunc
679 && (methods
== OPTAB_LIB
|| methods
== OPTAB_LIB_WIDEN
))
682 rtx funexp
= binoptab
->handlers
[(int) mode
].libfunc
;
686 /* Pass 1 for NO_QUEUE so we don't lose any increments
687 if the libcall is cse'd or moved. */
688 emit_library_call (binoptab
->handlers
[(int) mode
].libfunc
,
689 1, mode
, 2, op0
, mode
, op1
,
690 (shift_op
? word_mode
: mode
));
692 insns
= get_insns ();
695 target
= gen_reg_rtx (mode
);
696 emit_libcall_block (insns
, target
, hard_libcall_value (mode
),
697 gen_rtx (binoptab
->code
, mode
, op0
, op1
));
702 delete_insns_since (last
);
704 /* It can't be done in this mode. Can we do it in a wider mode? */
706 if (! (methods
== OPTAB_WIDEN
|| methods
== OPTAB_LIB_WIDEN
707 || methods
== OPTAB_MUST_WIDEN
))
708 return 0; /* Caller says, don't even try. */
710 /* Compute the value of METHODS to pass to recursive calls.
711 Don't allow widening to be tried recursively. */
713 methods
= (methods
== OPTAB_LIB_WIDEN
? OPTAB_LIB
: OPTAB_DIRECT
);
715 /* Look for a wider mode of the same class for which it appears we can do
718 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
720 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
721 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
723 if ((binoptab
->handlers
[(int) wider_mode
].insn_code
725 || (methods
== OPTAB_LIB
726 && binoptab
->handlers
[(int) wider_mode
].libfunc
))
728 rtx xop0
= op0
, xop1
= op1
;
731 /* For certain integer operations, we need not actually extend
732 the narrow operands, as long as we will truncate
733 the results to the same narrowness. */
735 if ((binoptab
== ior_optab
|| binoptab
== and_optab
736 || binoptab
== xor_optab
737 || binoptab
== add_optab
|| binoptab
== sub_optab
738 || binoptab
== smul_optab
739 || binoptab
== ashl_optab
|| binoptab
== lshl_optab
)
740 && class == MODE_INT
)
743 /* If an operand is a constant integer, we might as well
744 convert it since that is more efficient than using a SUBREG,
745 unlike the case for other operands. */
747 if (no_extend
&& GET_MODE (xop0
) != VOIDmode
)
748 xop0
= gen_rtx (SUBREG
, wider_mode
,
749 force_reg (GET_MODE (xop0
), xop0
), 0);
751 xop0
= convert_to_mode (wider_mode
, xop0
, unsignedp
);
753 if (no_extend
&& GET_MODE (xop1
) != VOIDmode
)
754 xop1
= gen_rtx (SUBREG
, wider_mode
,
755 force_reg (GET_MODE (xop1
), xop1
), 0);
757 xop1
= convert_to_mode (wider_mode
, xop1
, unsignedp
);
759 temp
= expand_binop (wider_mode
, binoptab
, xop0
, xop1
, 0,
763 if (class != MODE_INT
)
766 target
= gen_reg_rtx (mode
);
767 convert_move (target
, temp
, 0);
771 return gen_lowpart (mode
, temp
);
774 delete_insns_since (last
);
782 /* Expand a binary operator which has both signed and unsigned forms.
783 UOPTAB is the optab for unsigned operations, and SOPTAB is for
786 If we widen unsigned operands, we may use a signed wider operation instead
787 of an unsigned wider operation, since the result would be the same. */
790 sign_expand_binop (mode
, uoptab
, soptab
, op0
, op1
, target
, unsignedp
, methods
)
791 enum machine_mode mode
;
792 optab uoptab
, soptab
;
793 rtx op0
, op1
, target
;
795 enum optab_methods methods
;
798 optab direct_optab
= unsignedp
? uoptab
: soptab
;
799 struct optab wide_soptab
;
801 /* Do it without widening, if possible. */
802 temp
= expand_binop (mode
, direct_optab
, op0
, op1
, target
,
803 unsignedp
, OPTAB_DIRECT
);
804 if (temp
|| methods
== OPTAB_DIRECT
)
807 /* Try widening to a signed int. Make a fake signed optab that
808 hides any signed insn for direct use. */
809 wide_soptab
= *soptab
;
810 wide_soptab
.handlers
[(int) mode
].insn_code
= CODE_FOR_nothing
;
811 wide_soptab
.handlers
[(int) mode
].libfunc
= 0;
813 temp
= expand_binop (mode
, &wide_soptab
, op0
, op1
, target
,
814 unsignedp
, OPTAB_WIDEN
);
816 /* For unsigned operands, try widening to an unsigned int. */
817 if (temp
== 0 && unsignedp
)
818 temp
= expand_binop (mode
, uoptab
, op0
, op1
, target
,
819 unsignedp
, OPTAB_WIDEN
);
820 if (temp
|| methods
== OPTAB_WIDEN
)
823 /* Use the right width lib call if that exists. */
824 temp
= expand_binop (mode
, direct_optab
, op0
, op1
, target
, unsignedp
, OPTAB_LIB
);
825 if (temp
|| methods
== OPTAB_LIB
)
828 /* Must widen and use a lib call, use either signed or unsigned. */
829 temp
= expand_binop (mode
, &wide_soptab
, op0
, op1
, target
,
834 return expand_binop (mode
, uoptab
, op0
, op1
, target
,
839 /* Generate code to perform an operation specified by BINOPTAB
840 on operands OP0 and OP1, with two results to TARG1 and TARG2.
841 We assume that the order of the operands for the instruction
842 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
843 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
845 Either TARG0 or TARG1 may be zero, but what that means is that
846 that result is not actually wanted. We will generate it into
847 a dummy pseudo-reg and discard it. They may not both be zero.
849 Returns 1 if this operation can be performed; 0 if not. */
852 expand_twoval_binop (binoptab
, op0
, op1
, targ0
, targ1
, unsignedp
)
858 enum machine_mode mode
= GET_MODE (targ0
? targ0
: targ1
);
859 enum mode_class
class;
860 enum machine_mode wider_mode
;
863 class = GET_MODE_CLASS (mode
);
865 op0
= protect_from_queue (op0
, 0);
866 op1
= protect_from_queue (op1
, 0);
870 op0
= force_not_mem (op0
);
871 op1
= force_not_mem (op1
);
874 /* If we are inside an appropriately-short loop and one operand is an
875 expensive constant, force it into a register. */
876 if (CONSTANT_P (op0
) && preserve_subexpressions_p ()
877 && rtx_cost (op0
, binoptab
->code
) > 2)
878 op0
= force_reg (mode
, op0
);
880 if (CONSTANT_P (op1
) && preserve_subexpressions_p ()
881 && rtx_cost (op1
, binoptab
->code
) > 2)
882 op1
= force_reg (mode
, op1
);
885 targ0
= protect_from_queue (targ0
, 1);
887 targ0
= gen_reg_rtx (mode
);
889 targ1
= protect_from_queue (targ1
, 1);
891 targ1
= gen_reg_rtx (mode
);
893 /* Record where to go back to if we fail. */
894 last
= get_last_insn ();
896 if (binoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
898 int icode
= (int) binoptab
->handlers
[(int) mode
].insn_code
;
899 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
900 enum machine_mode mode1
= insn_operand_mode
[icode
][2];
902 rtx xop0
= op0
, xop1
= op1
;
904 /* In case this insn wants input operands in modes different from the
905 result, convert the operands. */
906 if (GET_MODE (op0
) != VOIDmode
&& GET_MODE (op0
) != mode0
)
907 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
909 if (GET_MODE (op1
) != VOIDmode
&& GET_MODE (op1
) != mode1
)
910 xop1
= convert_to_mode (mode1
, xop1
, unsignedp
);
912 /* Now, if insn doesn't accept these operands, put them into pseudos. */
913 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
914 xop0
= copy_to_mode_reg (mode0
, xop0
);
916 if (! (*insn_operand_predicate
[icode
][2]) (xop1
, mode1
))
917 xop1
= copy_to_mode_reg (mode1
, xop1
);
919 /* We could handle this, but we should always be called with a pseudo
920 for our targets and all insns should take them as outputs. */
921 if (! (*insn_operand_predicate
[icode
][0]) (targ0
, mode
)
922 || ! (*insn_operand_predicate
[icode
][3]) (targ1
, mode
))
925 pat
= GEN_FCN (icode
) (targ0
, xop0
, xop1
, targ1
);
932 delete_insns_since (last
);
935 /* It can't be done in this mode. Can we do it in a wider mode? */
937 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
939 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
940 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
942 if (binoptab
->handlers
[(int) wider_mode
].insn_code
945 register rtx t0
= gen_reg_rtx (wider_mode
);
946 register rtx t1
= gen_reg_rtx (wider_mode
);
948 if (expand_twoval_binop (binoptab
,
949 convert_to_mode (wider_mode
, op0
,
951 convert_to_mode (wider_mode
, op1
,
955 convert_move (targ0
, t0
, unsignedp
);
956 convert_move (targ1
, t1
, unsignedp
);
960 delete_insns_since (last
);
968 /* Generate code to perform an operation specified by UNOPTAB
969 on operand OP0, with result having machine-mode MODE.
971 UNSIGNEDP is for the case where we have to widen the operands
972 to perform the operation. It says to use zero-extension.
974 If TARGET is nonzero, the value
975 is generated there, if it is convenient to do so.
976 In all cases an rtx is returned for the locus of the value;
977 this may or may not be TARGET. */
980 expand_unop (mode
, unoptab
, op0
, target
, unsignedp
)
981 enum machine_mode mode
;
987 enum mode_class
class;
988 enum machine_mode wider_mode
;
990 rtx last
= get_last_insn ();
993 class = GET_MODE_CLASS (mode
);
995 op0
= protect_from_queue (op0
, 0);
999 op0
= force_not_mem (op0
);
1003 target
= protect_from_queue (target
, 1);
1005 if (unoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1007 int icode
= (int) unoptab
->handlers
[(int) mode
].insn_code
;
1008 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
1014 temp
= gen_reg_rtx (mode
);
1016 if (GET_MODE (xop0
) != VOIDmode
1017 && GET_MODE (xop0
) != mode0
)
1018 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
1020 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
1022 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
1023 xop0
= copy_to_mode_reg (mode0
, xop0
);
1025 if (! (*insn_operand_predicate
[icode
][0]) (temp
, mode
))
1026 temp
= gen_reg_rtx (mode
);
1028 pat
= GEN_FCN (icode
) (temp
, xop0
);
1031 if (GET_CODE (pat
) == SEQUENCE
1032 && ! add_equal_note (pat
, temp
, unoptab
->code
, xop0
, 0))
1034 delete_insns_since (last
);
1035 return expand_unop (mode
, unoptab
, op0
, 0, unsignedp
);
1043 delete_insns_since (last
);
1046 /* These can be done a word at a time. */
1047 if (unoptab
== one_cmpl_optab
1048 && class == MODE_INT
1049 && GET_MODE_SIZE (mode
) > UNITS_PER_WORD
1050 && unoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
1055 if (target
== 0 || target
== op0
)
1056 target
= gen_reg_rtx (mode
);
1060 /* Do the actual arithmetic. */
1061 for (i
= 0; i
< GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
; i
++)
1063 rtx target_piece
= operand_subword (target
, i
, 1, mode
);
1064 rtx x
= expand_unop (word_mode
, unoptab
,
1065 operand_subword_force (op0
, i
, mode
),
1066 target_piece
, unsignedp
);
1067 if (target_piece
!= x
)
1068 emit_move_insn (target_piece
, x
);
1071 insns
= get_insns ();
1074 emit_no_conflict_block (insns
, target
, op0
, 0,
1075 gen_rtx (unoptab
->code
, mode
, op0
));
1079 if (unoptab
->handlers
[(int) mode
].libfunc
)
1082 rtx funexp
= unoptab
->handlers
[(int) mode
].libfunc
;
1086 /* Pass 1 for NO_QUEUE so we don't lose any increments
1087 if the libcall is cse'd or moved. */
1088 emit_library_call (unoptab
->handlers
[(int) mode
].libfunc
,
1089 1, mode
, 1, op0
, mode
);
1090 insns
= get_insns ();
1093 target
= gen_reg_rtx (mode
);
1094 emit_libcall_block (insns
, target
, hard_libcall_value (mode
),
1095 gen_rtx (unoptab
->code
, mode
, op0
));
1100 /* It can't be done in this mode. Can we do it in a wider mode? */
1102 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1104 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1105 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1107 if ((unoptab
->handlers
[(int) wider_mode
].insn_code
1108 != CODE_FOR_nothing
)
1109 || unoptab
->handlers
[(int) wider_mode
].libfunc
)
1113 /* For certain operations, we need not actually extend
1114 the narrow operand, as long as we will truncate the
1115 results to the same narrowness. */
1117 if ((unoptab
== neg_optab
|| unoptab
== one_cmpl_optab
)
1118 && class == MODE_INT
)
1119 xop0
= gen_rtx (SUBREG
, wider_mode
, force_reg (mode
, xop0
), 0);
1121 xop0
= convert_to_mode (wider_mode
, xop0
, unsignedp
);
1123 temp
= expand_unop (wider_mode
, unoptab
, xop0
, 0, unsignedp
);
1127 if (class != MODE_INT
)
1130 target
= gen_reg_rtx (mode
);
1131 convert_move (target
, temp
, 0);
1135 return gen_lowpart (mode
, temp
);
1138 delete_insns_since (last
);
1146 /* Generate an instruction whose insn-code is INSN_CODE,
1147 with two operands: an output TARGET and an input OP0.
1148 TARGET *must* be nonzero, and the output is always stored there.
1149 CODE is an rtx code such that (CODE OP0) is an rtx that describes
1150 the value that is stored into TARGET. */
1153 emit_unop_insn (icode
, target
, op0
, code
)
1160 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
1163 temp
= target
= protect_from_queue (target
, 1);
1165 op0
= protect_from_queue (op0
, 0);
1168 op0
= force_not_mem (op0
);
1170 /* Now, if insn does not accept our operands, put them into pseudos. */
1172 if (! (*insn_operand_predicate
[icode
][1]) (op0
, mode0
))
1173 op0
= copy_to_mode_reg (mode0
, op0
);
1175 if (! (*insn_operand_predicate
[icode
][0]) (temp
, GET_MODE (temp
))
1176 || (flag_force_mem
&& GET_CODE (temp
) == MEM
))
1177 temp
= gen_reg_rtx (GET_MODE (temp
));
1179 pat
= GEN_FCN (icode
) (temp
, op0
);
1181 if (GET_CODE (pat
) == SEQUENCE
&& code
!= UNKNOWN
)
1182 add_equal_note (pat
, temp
, code
, op0
, 0);
1187 emit_move_insn (target
, temp
);
1190 /* Emit code to perform a series of operations on a multi-word quantity, one
1193 Such a block is preceded by a CLOBBER of the output, consists of multiple
1194 insns, each setting one word of the output, and followed by a SET copying
1195 the output to itself.
1197 Each of the insns setting words of the output receives a REG_NO_CONFLICT
1198 note indicating that it doesn't conflict with the (also multi-word)
1199 inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
1202 INSNS is a block of code generated to perform the operation, not including
1203 the CLOBBER and final copy. All insns that compute intermediate values
1204 are first emitted, followed by the block as described above. Only
1205 INSNs are allowed in the block; no library calls or jumps may be
1208 TARGET, OP0, and OP1 are the output and inputs of the operations,
1209 respectively. OP1 may be zero for a unary operation.
1211 EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
1214 If TARGET is not a register, INSNS is simply emitted with no special
1217 The final insn emitted is returned. */
1220 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv
)
1226 rtx prev
, next
, first
, last
, insn
;
1228 if (GET_CODE (target
) != REG
|| reload_in_progress
)
1229 return emit_insns (insns
);
1231 /* First emit all insns that do not store into words of the output and remove
1232 these from the list. */
1233 for (insn
= insns
; insn
; insn
= next
)
1238 next
= NEXT_INSN (insn
);
1240 if (GET_CODE (insn
) != INSN
)
1243 if (GET_CODE (PATTERN (insn
)) == SET
)
1244 set
= PATTERN (insn
);
1245 else if (GET_CODE (PATTERN (insn
)) == PARALLEL
)
1247 for (i
= 0; i
< XVECLEN (PATTERN (insn
), 0); i
++)
1248 if (GET_CODE (XVECEXP (PATTERN (insn
), 0, i
)) == SET
)
1250 set
= XVECEXP (PATTERN (insn
), 0, i
);
1258 if (! reg_overlap_mentioned_p (target
, SET_DEST (set
)))
1260 if (PREV_INSN (insn
))
1261 NEXT_INSN (PREV_INSN (insn
)) = next
;
1266 PREV_INSN (next
) = PREV_INSN (insn
);
1272 prev
= get_last_insn ();
1274 /* Now write the CLOBBER of the output, followed by the setting of each
1275 of the words, followed by the final copy. */
1276 if (target
!= op0
&& target
!= op1
)
1277 emit_insn (gen_rtx (CLOBBER
, VOIDmode
, target
));
1279 for (insn
= insns
; insn
; insn
= next
)
1281 next
= NEXT_INSN (insn
);
1284 if (op1
&& GET_CODE (op1
) == REG
)
1285 REG_NOTES (insn
) = gen_rtx (EXPR_LIST
, REG_NO_CONFLICT
, op1
,
1288 if (op0
&& GET_CODE (op0
) == REG
)
1289 REG_NOTES (insn
) = gen_rtx (EXPR_LIST
, REG_NO_CONFLICT
, op0
,
1293 last
= emit_move_insn (target
, target
);
1295 REG_NOTES (last
) = gen_rtx (EXPR_LIST
, REG_EQUAL
, equiv
, REG_NOTES (last
));
1298 first
= get_insns ();
1300 first
= NEXT_INSN (prev
);
1302 /* Encapsulate the block so it gets manipulated as a unit. */
1303 REG_NOTES (first
) = gen_rtx (INSN_LIST
, REG_LIBCALL
, last
,
1305 REG_NOTES (last
) = gen_rtx (INSN_LIST
, REG_RETVAL
, first
, REG_NOTES (last
));
1310 /* Emit code to make a call to a constant function or a library call.
1312 INSNS is a list containing all insns emitted in the call.
1313 These insns leave the result in RESULT. Our block is to copy RESULT
1314 to TARGET, which is logically equivalent to EQUIV.
1316 We first emit any insns that set a pseudo on the assumption that these are
1317 loading constants into registers; doing so allows them to be safely cse'ed
1318 between blocks. Then we emit all the other insns in the block, followed by
1319 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
1320 note with an operand of EQUIV.
1322 Moving assignments to pseudos outside of the block is done to improve
1323 the generated code, but is not required to generate correct code,
1324 hence being unable to move an assignment is not grounds for not making
1325 a libcall block. There are two reasons why it is safe to leave these
1326 insns inside the block: First, we know that these pseudos cannot be
1327 used in generated RTL outside the block since they are created for
1328 temporary purposes within the block. Second, CSE will not record the
1329 values of anything set inside a libcall block, so we know they must
1330 be dead at the end of the block.
1332 Except for the first group of insns (the ones setting pseudos), the
1333 block is delimited by REG_RETVAL and REG_LIBCALL notes. */
1336 emit_libcall_block (insns
, target
, result
, equiv
)
1342 rtx prev
, next
, first
, last
, insn
;
1344 /* First emit all insns that set pseudos. Remove them from the list as
1345 we go. Avoid insns that set pseudo which were referenced in previous
1346 insns. These can be generated by move_by_pieces, for example,
1347 to update an address. */
1349 for (insn
= insns
; insn
; insn
= next
)
1351 rtx set
= single_set (insn
);
1353 next
= NEXT_INSN (insn
);
1355 if (set
!= 0 && GET_CODE (SET_DEST (set
)) == REG
1356 && REGNO (SET_DEST (set
)) >= FIRST_PSEUDO_REGISTER
1358 || (! reg_mentioned_p (SET_DEST (set
), PATTERN (insns
))
1359 && ! reg_used_between_p (SET_DEST (set
), insns
, insn
))))
1361 if (PREV_INSN (insn
))
1362 NEXT_INSN (PREV_INSN (insn
)) = next
;
1367 PREV_INSN (next
) = PREV_INSN (insn
);
1373 prev
= get_last_insn ();
1375 /* Write the remaining insns followed by the final copy. */
1377 for (insn
= insns
; insn
; insn
= next
)
1379 next
= NEXT_INSN (insn
);
1384 last
= emit_move_insn (target
, result
);
1385 REG_NOTES (last
) = gen_rtx (EXPR_LIST
, REG_EQUAL
, equiv
, REG_NOTES (last
));
1388 first
= get_insns ();
1390 first
= NEXT_INSN (prev
);
1392 /* Encapsulate the block so it gets manipulated as a unit. */
1393 REG_NOTES (first
) = gen_rtx (INSN_LIST
, REG_LIBCALL
, last
,
1395 REG_NOTES (last
) = gen_rtx (INSN_LIST
, REG_RETVAL
, first
, REG_NOTES (last
));
1398 /* Generate code to store zero in X. */
1404 emit_move_insn (x
, const0_rtx
);
1407 /* Generate code to store 1 in X
1408 assuming it contains zero beforehand. */
1411 emit_0_to_1_insn (x
)
1414 emit_move_insn (x
, const1_rtx
);
1417 /* Generate code to compare X with Y
1418 so that the condition codes are set.
1420 MODE is the mode of the inputs (in case they are const_int).
1421 UNSIGNEDP nonzero says that X and Y are unsigned;
1422 this matters if they need to be widened.
1424 If they have mode BLKmode, then SIZE specifies the size of both X and Y,
1425 and ALIGN specifies the known shared alignment of X and Y.
1427 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
1428 It is ignored for fixed-point and block comparisons;
1429 it is used only for floating-point comparisons. */
1432 emit_cmp_insn (x
, y
, comparison
, size
, mode
, unsignedp
, align
)
1434 enum rtx_code comparison
;
1436 enum machine_mode mode
;
1440 enum mode_class
class;
1441 enum machine_mode wider_mode
;
1443 class = GET_MODE_CLASS (mode
);
1445 /* They could both be VOIDmode if both args are immediate constants,
1446 but we should fold that at an earlier stage.
1447 With no special code here, this will call abort,
1448 reminding the programmer to implement such folding. */
1450 if (mode
!= BLKmode
&& flag_force_mem
)
1452 x
= force_not_mem (x
);
1453 y
= force_not_mem (y
);
1456 /* If we are inside an appropriately-short loop and one operand is an
1457 expensive constant, force it into a register. */
1458 if (CONSTANT_P (x
) && preserve_subexpressions_p () && rtx_cost (x
, COMPARE
) > 2)
1459 x
= force_reg (mode
, x
);
1461 if (CONSTANT_P (y
) && preserve_subexpressions_p () && rtx_cost (y
, COMPARE
) > 2)
1462 y
= force_reg (mode
, y
);
1464 /* Don't let both operands fail to indicate the mode. */
1465 if (GET_MODE (x
) == VOIDmode
&& GET_MODE (y
) == VOIDmode
)
1466 x
= force_reg (mode
, x
);
1468 /* Handle all BLKmode compares. */
1470 if (mode
== BLKmode
)
1473 x
= protect_from_queue (x
, 0);
1474 y
= protect_from_queue (y
, 0);
1478 #ifdef HAVE_cmpstrqi
1480 && GET_CODE (size
) == CONST_INT
1481 && INTVAL (size
) < (1 << GET_MODE_BITSIZE (QImode
)))
1483 enum machine_mode result_mode
1484 = insn_operand_mode
[(int) CODE_FOR_cmpstrqi
][0];
1485 rtx result
= gen_reg_rtx (result_mode
);
1486 emit_insn (gen_cmpstrqi (result
, x
, y
, size
,
1487 gen_rtx (CONST_INT
, VOIDmode
, align
)));
1488 emit_cmp_insn (result
, const0_rtx
, comparison
, 0, result_mode
, 0, 0);
1492 #ifdef HAVE_cmpstrhi
1494 && GET_CODE (size
) == CONST_INT
1495 && INTVAL (size
) < (1 << GET_MODE_BITSIZE (HImode
)))
1497 enum machine_mode result_mode
1498 = insn_operand_mode
[(int) CODE_FOR_cmpstrhi
][0];
1499 rtx result
= gen_reg_rtx (result_mode
);
1500 emit_insn (gen_cmpstrhi (result
, x
, y
, size
,
1501 gen_rtx (CONST_INT
, VOIDmode
, align
)));
1502 emit_cmp_insn (result
, const0_rtx
, comparison
, 0, result_mode
, 0, 0);
1506 #ifdef HAVE_cmpstrsi
1509 enum machine_mode result_mode
1510 = insn_operand_mode
[(int) CODE_FOR_cmpstrsi
][0];
1511 rtx result
= gen_reg_rtx (result_mode
);
1512 emit_insn (gen_cmpstrsi (result
, x
, y
,
1513 convert_to_mode (SImode
, size
, 1),
1514 gen_rtx (CONST_INT
, VOIDmode
, align
)));
1515 emit_cmp_insn (result
, const0_rtx
, comparison
, 0, result_mode
, 0, 0);
1520 #ifdef TARGET_MEM_FUNCTIONS
1521 emit_library_call (memcmp_libfunc
, 1,
1522 TYPE_MODE (integer_type_node
), 3,
1523 XEXP (x
, 0), Pmode
, XEXP (y
, 0), Pmode
,
1526 emit_library_call (bcmp_libfunc
, 1,
1527 TYPE_MODE (integer_type_node
), 3,
1528 XEXP (x
, 0), Pmode
, XEXP (y
, 0), Pmode
,
1531 emit_cmp_insn (hard_libcall_value (TYPE_MODE (integer_type_node
)),
1532 const0_rtx
, comparison
, 0,
1533 TYPE_MODE (integer_type_node
), 0, 0);
1538 /* Handle some compares against zero. */
1540 if (y
== CONST0_RTX (mode
)
1541 && tst_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1543 int icode
= (int) tst_optab
->handlers
[(int) mode
].insn_code
;
1546 x
= protect_from_queue (x
, 0);
1547 y
= protect_from_queue (y
, 0);
1549 /* Now, if insn does accept these operands, put them into pseudos. */
1550 if (! (*insn_operand_predicate
[icode
][0])
1551 (x
, insn_operand_mode
[icode
][0]))
1552 x
= copy_to_mode_reg (insn_operand_mode
[icode
][0], x
);
1554 emit_insn (GEN_FCN (icode
) (x
));
1558 /* Handle compares for which there is a directly suitable insn. */
1560 if (cmp_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1562 int icode
= (int) cmp_optab
->handlers
[(int) mode
].insn_code
;
1565 x
= protect_from_queue (x
, 0);
1566 y
= protect_from_queue (y
, 0);
1568 /* Now, if insn doesn't accept these operands, put them into pseudos. */
1569 if (! (*insn_operand_predicate
[icode
][0])
1570 (x
, insn_operand_mode
[icode
][0]))
1571 x
= copy_to_mode_reg (insn_operand_mode
[icode
][0], x
);
1573 if (! (*insn_operand_predicate
[icode
][1])
1574 (y
, insn_operand_mode
[icode
][1]))
1575 y
= copy_to_mode_reg (insn_operand_mode
[icode
][1], y
);
1577 emit_insn (GEN_FCN (icode
) (x
, y
));
1581 /* Try widening if we can find a direct insn that way. */
1583 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1585 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1586 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1588 if (cmp_optab
->handlers
[(int) wider_mode
].insn_code
1589 != CODE_FOR_nothing
)
1591 x
= convert_to_mode (wider_mode
, x
, unsignedp
);
1592 y
= convert_to_mode (wider_mode
, y
, unsignedp
);
1593 emit_cmp_insn (x
, y
, comparison
, 0,
1594 wider_mode
, unsignedp
, align
);
1600 /* Handle a lib call just for the mode we are using. */
1602 if (cmp_optab
->handlers
[(int) mode
].libfunc
1603 && class != MODE_FLOAT
)
1605 rtx libfunc
= cmp_optab
->handlers
[(int) mode
].libfunc
;
1606 /* If we want unsigned, and this mode has a distinct unsigned
1607 comparison routine, use that. */
1608 if (unsignedp
&& ucmp_optab
->handlers
[(int) mode
].libfunc
)
1609 libfunc
= ucmp_optab
->handlers
[(int) mode
].libfunc
;
1611 emit_library_call (libfunc
, 1,
1612 SImode
, 2, x
, mode
, y
, mode
);
1614 /* Integer comparison returns a result that must be compared against 1,
1615 so that even if we do an unsigned compare afterward,
1616 there is still a value that can represent the result "less than". */
1618 emit_cmp_insn (hard_libcall_value (SImode
), const1_rtx
,
1619 comparison
, 0, SImode
, unsignedp
, 0);
1623 if (class == MODE_FLOAT
)
1624 emit_float_lib_cmp (x
, y
, comparison
);
1630 /* Nonzero if a compare of mode MODE can be done straightforwardly
1631 (without splitting it into pieces). */
1634 can_compare_p (mode
)
1635 enum machine_mode mode
;
1639 if (cmp_optab
->handlers
[(int)mode
].insn_code
!= CODE_FOR_nothing
)
1641 mode
= GET_MODE_WIDER_MODE (mode
);
1642 } while (mode
!= VOIDmode
);
1647 /* Emit a library call comparison between floating point X and Y.
1648 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
1651 emit_float_lib_cmp (x
, y
, comparison
)
1653 enum rtx_code comparison
;
1655 enum machine_mode mode
= GET_MODE (x
);
1662 libfunc
= eqsf2_libfunc
;
1666 libfunc
= nesf2_libfunc
;
1670 libfunc
= gtsf2_libfunc
;
1674 libfunc
= gesf2_libfunc
;
1678 libfunc
= ltsf2_libfunc
;
1682 libfunc
= lesf2_libfunc
;
1685 else if (mode
== DFmode
)
1689 libfunc
= eqdf2_libfunc
;
1693 libfunc
= nedf2_libfunc
;
1697 libfunc
= gtdf2_libfunc
;
1701 libfunc
= gedf2_libfunc
;
1705 libfunc
= ltdf2_libfunc
;
1709 libfunc
= ledf2_libfunc
;
1714 enum machine_mode wider_mode
;
1716 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1717 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1719 if ((cmp_optab
->handlers
[(int) wider_mode
].insn_code
1720 != CODE_FOR_nothing
)
1721 || (cmp_optab
->handlers
[(int) wider_mode
].libfunc
!= 0))
1723 x
= convert_to_mode (wider_mode
, x
, 0);
1724 y
= convert_to_mode (wider_mode
, y
, 0);
1725 emit_float_lib_cmp (x
, y
, comparison
);
1732 emit_library_call (libfunc
, 1,
1733 SImode
, 2, x
, mode
, y
, mode
);
1735 emit_cmp_insn (hard_libcall_value (SImode
), const0_rtx
, comparison
,
1739 /* Generate code to indirectly jump to a location given in the rtx LOC. */
1742 emit_indirect_jump (loc
)
1745 if (! ((*insn_operand_predicate
[(int)CODE_FOR_indirect_jump
][0])
1747 loc
= copy_to_mode_reg (insn_operand_mode
[(int)CODE_FOR_indirect_jump
][0],
1750 emit_jump_insn (gen_indirect_jump (loc
));
1753 /* These three functions generate an insn body and return it
1754 rather than emitting the insn.
1756 They do not protect from queued increments,
1757 because they may be used 1) in protect_from_queue itself
1758 and 2) in other passes where there is no queue. */
1760 /* Generate and return an insn body to add Y to X. */
1763 gen_add2_insn (x
, y
)
1766 int icode
= (int) add_optab
->handlers
[(int) GET_MODE (x
)].insn_code
;
1768 if (! (*insn_operand_predicate
[icode
][0]) (x
, insn_operand_mode
[icode
][0])
1769 || ! (*insn_operand_predicate
[icode
][1]) (x
, insn_operand_mode
[icode
][1])
1770 || ! (*insn_operand_predicate
[icode
][2]) (y
, insn_operand_mode
[icode
][2]))
1773 return (GEN_FCN (icode
) (x
, x
, y
));
1777 have_add2_insn (mode
)
1778 enum machine_mode mode
;
1780 return add_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
;
1783 /* Generate and return an insn body to subtract Y from X. */
1786 gen_sub2_insn (x
, y
)
1789 int icode
= (int) sub_optab
->handlers
[(int) GET_MODE (x
)].insn_code
;
1791 if (! (*insn_operand_predicate
[icode
][0]) (x
, insn_operand_mode
[icode
][0])
1792 || ! (*insn_operand_predicate
[icode
][1]) (x
, insn_operand_mode
[icode
][1])
1793 || ! (*insn_operand_predicate
[icode
][2]) (y
, insn_operand_mode
[icode
][2]))
1796 return (GEN_FCN (icode
) (x
, x
, y
));
1800 have_sub2_insn (mode
)
1801 enum machine_mode mode
;
1803 return sub_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
;
1806 /* Generate the body of an instruction to copy Y into X. */
1809 gen_move_insn (x
, y
)
1812 register enum machine_mode mode
= GET_MODE (x
);
1813 enum insn_code insn_code
;
1815 if (mode
== VOIDmode
)
1816 mode
= GET_MODE (y
);
1818 insn_code
= mov_optab
->handlers
[(int) mode
].insn_code
;
1820 /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
1821 find a mode to do it in. If we have a movcc, use it. Otherwise,
1822 find the MODE_INT mode of the same width. */
1824 if (insn_code
== CODE_FOR_nothing
)
1826 enum machine_mode tmode
= VOIDmode
;
1829 if (GET_MODE_CLASS (mode
) == MODE_CC
&& mode
!= CCmode
1830 && mov_optab
->handlers
[(int) CCmode
].insn_code
!= CODE_FOR_nothing
)
1832 else if (GET_MODE_CLASS (mode
) == MODE_CC
)
1833 for (tmode
= QImode
; tmode
!= VOIDmode
;
1834 tmode
= GET_MODE_WIDER_MODE (tmode
))
1835 if (GET_MODE_SIZE (tmode
) == GET_MODE_SIZE (mode
))
1838 if (tmode
== VOIDmode
)
1841 /* Get X and Y in TMODE. We can't use gen_lowpart here because it
1842 may call change_address which is not appropriate if we were
1843 called when a reload was in progress. We don't have to worry
1844 about changing the address since the size in bytes is supposed to
1845 be the same. Copy the MEM to change the mode and move any
1846 substitutions from the old MEM to the new one. */
1848 if (reload_in_progress
)
1850 x
= gen_lowpart_common (tmode
, x1
);
1851 if (x
== 0 && GET_CODE (x1
) == MEM
)
1853 x
= gen_rtx (MEM
, tmode
, XEXP (x1
, 0));
1854 RTX_UNCHANGING_P (x
) = RTX_UNCHANGING_P (x1
);
1855 MEM_IN_STRUCT_P (x
) = MEM_IN_STRUCT_P (x1
);
1856 MEM_VOLATILE_P (x
) = MEM_VOLATILE_P (x1
);
1857 copy_replacements (x1
, x
);
1860 y
= gen_lowpart_common (tmode
, y1
);
1861 if (y
== 0 && GET_CODE (y1
) == MEM
)
1863 y
= gen_rtx (MEM
, tmode
, XEXP (y1
, 0));
1864 RTX_UNCHANGING_P (y
) = RTX_UNCHANGING_P (y1
);
1865 MEM_IN_STRUCT_P (y
) = MEM_IN_STRUCT_P (y1
);
1866 MEM_VOLATILE_P (y
) = MEM_VOLATILE_P (y1
);
1867 copy_replacements (y1
, y
);
1872 x
= gen_lowpart (tmode
, x
);
1873 y
= gen_lowpart (tmode
, y
);
1876 insn_code
= mov_optab
->handlers
[(int) tmode
].insn_code
;
1879 return (GEN_FCN (insn_code
) (x
, y
));
1882 /* Tables of patterns for extending one integer mode to another. */
1883 static enum insn_code extendtab
[MAX_MACHINE_MODE
][MAX_MACHINE_MODE
][2];
1885 /* Return the insn code used to extend FROM_MODE to TO_MODE.
1886 UNSIGNEDP specifies zero-extension instead of sign-extension. If
1887 no such operation exists, CODE_FOR_nothing will be returned. */
1890 can_extend_p (to_mode
, from_mode
, unsignedp
)
1891 enum machine_mode to_mode
, from_mode
;
1894 return extendtab
[(int) to_mode
][(int) from_mode
][unsignedp
];
1897 /* Generate the body of an insn to extend Y (with mode MFROM)
1898 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
1901 gen_extend_insn (x
, y
, mto
, mfrom
, unsignedp
)
1903 enum machine_mode mto
, mfrom
;
1906 return (GEN_FCN (extendtab
[(int) mto
][(int) mfrom
][unsignedp
]) (x
, y
));
1914 for (p
= extendtab
[0][0];
1915 p
< extendtab
[0][0] + sizeof extendtab
/ sizeof extendtab
[0][0][0];
1917 *p
= CODE_FOR_nothing
;
1919 #ifdef HAVE_extendditi2
1920 if (HAVE_extendditi2
)
1921 extendtab
[(int) TImode
][(int) DImode
][0] = CODE_FOR_extendditi2
;
1923 #ifdef HAVE_extendsiti2
1924 if (HAVE_extendsiti2
)
1925 extendtab
[(int) TImode
][(int) SImode
][0] = CODE_FOR_extendsiti2
;
1927 #ifdef HAVE_extendhiti2
1928 if (HAVE_extendhiti2
)
1929 extendtab
[(int) TImode
][(int) HImode
][0] = CODE_FOR_extendhiti2
;
1931 #ifdef HAVE_extendqiti2
1932 if (HAVE_extendqiti2
)
1933 extendtab
[(int) TImode
][(int) QImode
][0] = CODE_FOR_extendqiti2
;
1935 #ifdef HAVE_extendsidi2
1936 if (HAVE_extendsidi2
)
1937 extendtab
[(int) DImode
][(int) SImode
][0] = CODE_FOR_extendsidi2
;
1939 #ifdef HAVE_extendhidi2
1940 if (HAVE_extendhidi2
)
1941 extendtab
[(int) DImode
][(int) HImode
][0] = CODE_FOR_extendhidi2
;
1943 #ifdef HAVE_extendqidi2
1944 if (HAVE_extendqidi2
)
1945 extendtab
[(int) DImode
][(int) QImode
][0] = CODE_FOR_extendqidi2
;
1947 #ifdef HAVE_extendhisi2
1948 if (HAVE_extendhisi2
)
1949 extendtab
[(int) SImode
][(int) HImode
][0] = CODE_FOR_extendhisi2
;
1951 #ifdef HAVE_extendqisi2
1952 if (HAVE_extendqisi2
)
1953 extendtab
[(int) SImode
][(int) QImode
][0] = CODE_FOR_extendqisi2
;
1955 #ifdef HAVE_extendqihi2
1956 if (HAVE_extendqihi2
)
1957 extendtab
[(int) HImode
][(int) QImode
][0] = CODE_FOR_extendqihi2
;
1960 #ifdef HAVE_zero_extendditi2
1961 if (HAVE_zero_extendsiti2
)
1962 extendtab
[(int) TImode
][(int) DImode
][1] = CODE_FOR_zero_extendditi2
;
1964 #ifdef HAVE_zero_extendsiti2
1965 if (HAVE_zero_extendsiti2
)
1966 extendtab
[(int) TImode
][(int) SImode
][1] = CODE_FOR_zero_extendsiti2
;
1968 #ifdef HAVE_zero_extendhiti2
1969 if (HAVE_zero_extendhiti2
)
1970 extendtab
[(int) TImode
][(int) HImode
][1] = CODE_FOR_zero_extendhiti2
;
1972 #ifdef HAVE_zero_extendqiti2
1973 if (HAVE_zero_extendqiti2
)
1974 extendtab
[(int) TImode
][(int) QImode
][1] = CODE_FOR_zero_extendqiti2
;
1976 #ifdef HAVE_zero_extendsidi2
1977 if (HAVE_zero_extendsidi2
)
1978 extendtab
[(int) DImode
][(int) SImode
][1] = CODE_FOR_zero_extendsidi2
;
1980 #ifdef HAVE_zero_extendhidi2
1981 if (HAVE_zero_extendhidi2
)
1982 extendtab
[(int) DImode
][(int) HImode
][1] = CODE_FOR_zero_extendhidi2
;
1984 #ifdef HAVE_zero_extendqidi2
1985 if (HAVE_zero_extendqidi2
)
1986 extendtab
[(int) DImode
][(int) QImode
][1] = CODE_FOR_zero_extendqidi2
;
1988 #ifdef HAVE_zero_extendhisi2
1989 if (HAVE_zero_extendhisi2
)
1990 extendtab
[(int) SImode
][(int) HImode
][1] = CODE_FOR_zero_extendhisi2
;
1992 #ifdef HAVE_zero_extendqisi2
1993 if (HAVE_zero_extendqisi2
)
1994 extendtab
[(int) SImode
][(int) QImode
][1] = CODE_FOR_zero_extendqisi2
;
1996 #ifdef HAVE_zero_extendqihi2
1997 if (HAVE_zero_extendqihi2
)
1998 extendtab
[(int) HImode
][(int) QImode
][1] = CODE_FOR_zero_extendqihi2
;
2002 /* can_fix_p and can_float_p say whether the target machine
2003 can directly convert a given fixed point type to
2004 a given floating point type, or vice versa.
2005 The returned value is the CODE_FOR_... value to use,
2006 or CODE_FOR_nothing if these modes cannot be directly converted. */
2008 static enum insn_code fixtab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
2009 static enum insn_code fixtrunctab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
2010 static enum insn_code floattab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
2012 /* *TRUNCP_PTR is set to 1 if it is necessary to output
2013 an explicit FTRUNC insn before the fix insn; otherwise 0. */
2015 static enum insn_code
2016 can_fix_p (fixmode
, fltmode
, unsignedp
, truncp_ptr
)
2017 enum machine_mode fltmode
, fixmode
;
2022 if (fixtrunctab
[(int) fltmode
][(int) fixmode
][unsignedp
] != CODE_FOR_nothing
)
2023 return fixtrunctab
[(int) fltmode
][(int) fixmode
][unsignedp
];
2025 if (ftrunc_optab
->handlers
[(int) fltmode
].insn_code
!= CODE_FOR_nothing
)
2028 return fixtab
[(int) fltmode
][(int) fixmode
][unsignedp
];
2030 return CODE_FOR_nothing
;
2033 static enum insn_code
2034 can_float_p (fltmode
, fixmode
, unsignedp
)
2035 enum machine_mode fixmode
, fltmode
;
2038 return floattab
[(int) fltmode
][(int) fixmode
][unsignedp
];
2045 for (p
= fixtab
[0][0];
2046 p
< fixtab
[0][0] + sizeof fixtab
/ sizeof (fixtab
[0][0][0]);
2048 *p
= CODE_FOR_nothing
;
2049 for (p
= fixtrunctab
[0][0];
2050 p
< fixtrunctab
[0][0] + sizeof fixtrunctab
/ sizeof (fixtrunctab
[0][0][0]);
2052 *p
= CODE_FOR_nothing
;
2054 #ifdef HAVE_fixsfqi2
2056 fixtab
[(int) SFmode
][(int) QImode
][0] = CODE_FOR_fixsfqi2
;
2058 #ifdef HAVE_fixsfhi2
2060 fixtab
[(int) SFmode
][(int) HImode
][0] = CODE_FOR_fixsfhi2
;
2062 #ifdef HAVE_fixsfsi2
2064 fixtab
[(int) SFmode
][(int) SImode
][0] = CODE_FOR_fixsfsi2
;
2066 #ifdef HAVE_fixsfdi2
2068 fixtab
[(int) SFmode
][(int) DImode
][0] = CODE_FOR_fixsfdi2
;
2071 #ifdef HAVE_fixdfqi2
2073 fixtab
[(int) DFmode
][(int) QImode
][0] = CODE_FOR_fixdfqi2
;
2075 #ifdef HAVE_fixdfhi2
2077 fixtab
[(int) DFmode
][(int) HImode
][0] = CODE_FOR_fixdfhi2
;
2079 #ifdef HAVE_fixdfsi2
2081 fixtab
[(int) DFmode
][(int) SImode
][0] = CODE_FOR_fixdfsi2
;
2083 #ifdef HAVE_fixdfdi2
2085 fixtab
[(int) DFmode
][(int) DImode
][0] = CODE_FOR_fixdfdi2
;
2087 #ifdef HAVE_fixdfti2
2089 fixtab
[(int) DFmode
][(int) TImode
][0] = CODE_FOR_fixdfti2
;
2092 #ifdef HAVE_fixtfqi2
2094 fixtab
[(int) TFmode
][(int) QImode
][0] = CODE_FOR_fixtfqi2
;
2096 #ifdef HAVE_fixtfhi2
2098 fixtab
[(int) TFmode
][(int) HImode
][0] = CODE_FOR_fixtfhi2
;
2100 #ifdef HAVE_fixtfsi2
2102 fixtab
[(int) TFmode
][(int) SImode
][0] = CODE_FOR_fixtfsi2
;
2104 #ifdef HAVE_fixtfdi2
2106 fixtab
[(int) TFmode
][(int) DImode
][0] = CODE_FOR_fixtfdi2
;
2108 #ifdef HAVE_fixtfti2
2110 fixtab
[(int) TFmode
][(int) TImode
][0] = CODE_FOR_fixtfti2
;
2113 #ifdef HAVE_fixunssfqi2
2114 if (HAVE_fixunssfqi2
)
2115 fixtab
[(int) SFmode
][(int) QImode
][1] = CODE_FOR_fixunssfqi2
;
2117 #ifdef HAVE_fixunssfhi2
2118 if (HAVE_fixunssfhi2
)
2119 fixtab
[(int) SFmode
][(int) HImode
][1] = CODE_FOR_fixunssfhi2
;
2121 #ifdef HAVE_fixunssfsi2
2122 if (HAVE_fixunssfsi2
)
2123 fixtab
[(int) SFmode
][(int) SImode
][1] = CODE_FOR_fixunssfsi2
;
2125 #ifdef HAVE_fixunssfdi2
2126 if (HAVE_fixunssfdi2
)
2127 fixtab
[(int) SFmode
][(int) DImode
][1] = CODE_FOR_fixunssfdi2
;
2130 #ifdef HAVE_fixunsdfqi2
2131 if (HAVE_fixunsdfqi2
)
2132 fixtab
[(int) DFmode
][(int) QImode
][1] = CODE_FOR_fixunsdfqi2
;
2134 #ifdef HAVE_fixunsdfhi2
2135 if (HAVE_fixunsdfhi2
)
2136 fixtab
[(int) DFmode
][(int) HImode
][1] = CODE_FOR_fixunsdfhi2
;
2138 #ifdef HAVE_fixunsdfsi2
2139 if (HAVE_fixunsdfsi2
)
2140 fixtab
[(int) DFmode
][(int) SImode
][1] = CODE_FOR_fixunsdfsi2
;
2142 #ifdef HAVE_fixunsdfdi2
2143 if (HAVE_fixunsdfdi2
)
2144 fixtab
[(int) DFmode
][(int) DImode
][1] = CODE_FOR_fixunsdfdi2
;
2146 #ifdef HAVE_fixunsdfti2
2147 if (HAVE_fixunsdfti2
)
2148 fixtab
[(int) DFmode
][(int) TImode
][1] = CODE_FOR_fixunsdfti2
;
2151 #ifdef HAVE_fixunstfqi2
2152 if (HAVE_fixunstfqi2
)
2153 fixtab
[(int) TFmode
][(int) QImode
][1] = CODE_FOR_fixunstfqi2
;
2155 #ifdef HAVE_fixunstfhi2
2156 if (HAVE_fixunstfhi2
)
2157 fixtab
[(int) TFmode
][(int) HImode
][1] = CODE_FOR_fixunstfhi2
;
2159 #ifdef HAVE_fixunstfsi2
2160 if (HAVE_fixunstfsi2
)
2161 fixtab
[(int) TFmode
][(int) SImode
][1] = CODE_FOR_fixunstfsi2
;
2163 #ifdef HAVE_fixunstfdi2
2164 if (HAVE_fixunstfdi2
)
2165 fixtab
[(int) TFmode
][(int) DImode
][1] = CODE_FOR_fixunstfdi2
;
2167 #ifdef HAVE_fixunstfti2
2168 if (HAVE_fixunstfti2
)
2169 fixtab
[(int) TFmode
][(int) TImode
][1] = CODE_FOR_fixunstfti2
;
2172 #ifdef HAVE_fix_truncsfqi2
2173 if (HAVE_fix_truncsfqi2
)
2174 fixtrunctab
[(int) SFmode
][(int) QImode
][0] = CODE_FOR_fix_truncsfqi2
;
2176 #ifdef HAVE_fix_truncsfhi2
2177 if (HAVE_fix_truncsfhi2
)
2178 fixtrunctab
[(int) SFmode
][(int) HImode
][0] = CODE_FOR_fix_truncsfhi2
;
2180 #ifdef HAVE_fix_truncsfsi2
2181 if (HAVE_fix_truncsfsi2
)
2182 fixtrunctab
[(int) SFmode
][(int) SImode
][0] = CODE_FOR_fix_truncsfsi2
;
2184 #ifdef HAVE_fix_truncsfdi2
2185 if (HAVE_fix_truncsfdi2
)
2186 fixtrunctab
[(int) SFmode
][(int) DImode
][0] = CODE_FOR_fix_truncsfdi2
;
2189 #ifdef HAVE_fix_truncdfqi2
2190 if (HAVE_fix_truncdfsi2
)
2191 fixtrunctab
[(int) DFmode
][(int) QImode
][0] = CODE_FOR_fix_truncdfqi2
;
2193 #ifdef HAVE_fix_truncdfhi2
2194 if (HAVE_fix_truncdfhi2
)
2195 fixtrunctab
[(int) DFmode
][(int) HImode
][0] = CODE_FOR_fix_truncdfhi2
;
2197 #ifdef HAVE_fix_truncdfsi2
2198 if (HAVE_fix_truncdfsi2
)
2199 fixtrunctab
[(int) DFmode
][(int) SImode
][0] = CODE_FOR_fix_truncdfsi2
;
2201 #ifdef HAVE_fix_truncdfdi2
2202 if (HAVE_fix_truncdfdi2
)
2203 fixtrunctab
[(int) DFmode
][(int) DImode
][0] = CODE_FOR_fix_truncdfdi2
;
2205 #ifdef HAVE_fix_truncdfti2
2206 if (HAVE_fix_truncdfti2
)
2207 fixtrunctab
[(int) DFmode
][(int) TImode
][0] = CODE_FOR_fix_truncdfti2
;
2210 #ifdef HAVE_fix_trunctfqi2
2211 if (HAVE_fix_trunctfqi2
)
2212 fixtrunctab
[(int) TFmode
][(int) QImode
][0] = CODE_FOR_fix_trunctfqi2
;
2214 #ifdef HAVE_fix_trunctfhi2
2215 if (HAVE_fix_trunctfhi2
)
2216 fixtrunctab
[(int) TFmode
][(int) HImode
][0] = CODE_FOR_fix_trunctfhi2
;
2218 #ifdef HAVE_fix_trunctfsi2
2219 if (HAVE_fix_trunctfsi2
)
2220 fixtrunctab
[(int) TFmode
][(int) SImode
][0] = CODE_FOR_fix_trunctfsi2
;
2222 #ifdef HAVE_fix_trunctfdi2
2223 if (HAVE_fix_trunctfdi2
)
2224 fixtrunctab
[(int) TFmode
][(int) DImode
][0] = CODE_FOR_fix_trunctfdi2
;
2226 #ifdef HAVE_fix_trunctfti2
2227 if (HAVE_fix_trunctfti2
)
2228 fixtrunctab
[(int) TFmode
][(int) TImode
][0] = CODE_FOR_fix_trunctfti2
;
2231 #ifdef HAVE_fixuns_truncsfqi2
2232 if (HAVE_fixuns_truncsfqi2
)
2233 fixtrunctab
[(int) SFmode
][(int) QImode
][1] = CODE_FOR_fixuns_truncsfqi2
;
2235 #ifdef HAVE_fixuns_truncsfhi2
2236 if (HAVE_fixuns_truncsfhi2
)
2237 fixtrunctab
[(int) SFmode
][(int) HImode
][1] = CODE_FOR_fixuns_truncsfhi2
;
2239 #ifdef HAVE_fixuns_truncsfsi2
2240 if (HAVE_fixuns_truncsfsi2
)
2241 fixtrunctab
[(int) SFmode
][(int) SImode
][1] = CODE_FOR_fixuns_truncsfsi2
;
2243 #ifdef HAVE_fixuns_truncsfdi2
2244 if (HAVE_fixuns_truncsfdi2
)
2245 fixtrunctab
[(int) SFmode
][(int) DImode
][1] = CODE_FOR_fixuns_truncsfdi2
;
2248 #ifdef HAVE_fixuns_truncdfqi2
2249 if (HAVE_fixuns_truncdfqi2
)
2250 fixtrunctab
[(int) DFmode
][(int) QImode
][1] = CODE_FOR_fixuns_truncdfqi2
;
2252 #ifdef HAVE_fixuns_truncdfhi2
2253 if (HAVE_fixuns_truncdfhi2
)
2254 fixtrunctab
[(int) DFmode
][(int) HImode
][1] = CODE_FOR_fixuns_truncdfhi2
;
2256 #ifdef HAVE_fixuns_truncdfsi2
2257 if (HAVE_fixuns_truncdfsi2
)
2258 fixtrunctab
[(int) DFmode
][(int) SImode
][1] = CODE_FOR_fixuns_truncdfsi2
;
2260 #ifdef HAVE_fixuns_truncdfdi2
2261 if (HAVE_fixuns_truncdfdi2
)
2262 fixtrunctab
[(int) DFmode
][(int) DImode
][1] = CODE_FOR_fixuns_truncdfdi2
;
2264 #ifdef HAVE_fixuns_truncdfti2
2265 if (HAVE_fixuns_truncdfti2
)
2266 fixtrunctab
[(int) DFmode
][(int) TImode
][1] = CODE_FOR_fixuns_truncdfti2
;
2269 #ifdef HAVE_fixuns_trunctfqi2
2270 if (HAVE_fixuns_trunctfqi2
)
2271 fixtrunctab
[(int) TFmode
][(int) QImode
][1] = CODE_FOR_fixuns_trunctfqi2
;
2273 #ifdef HAVE_fixuns_trunctfhi2
2274 if (HAVE_fixuns_trunctfhi2
)
2275 fixtrunctab
[(int) TFmode
][(int) HImode
][1] = CODE_FOR_fixuns_trunctfhi2
;
2277 #ifdef HAVE_fixuns_trunctfsi2
2278 if (HAVE_fixuns_trunctfsi2
)
2279 fixtrunctab
[(int) TFmode
][(int) SImode
][1] = CODE_FOR_fixuns_trunctfsi2
;
2281 #ifdef HAVE_fixuns_trunctfdi2
2282 if (HAVE_fixuns_trunctfdi2
)
2283 fixtrunctab
[(int) TFmode
][(int) DImode
][1] = CODE_FOR_fixuns_trunctfdi2
;
2285 #ifdef HAVE_fixuns_trunctfti2
2286 if (HAVE_fixuns_trunctfti2
)
2287 fixtrunctab
[(int) TFmode
][(int) TImode
][1] = CODE_FOR_fixuns_trunctfti2
;
2290 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
2291 /* This flag says the same insns that convert to a signed fixnum
2292 also convert validly to an unsigned one. */
2296 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
2297 for (j
= 0; j
< NUM_MACHINE_MODES
; j
++)
2298 fixtrunctab
[i
][j
][1] = fixtrunctab
[i
][j
][0];
2307 for (p
= floattab
[0][0];
2308 p
< floattab
[0][0] + sizeof floattab
/ sizeof (floattab
[0][0][0]);
2310 *p
= CODE_FOR_nothing
;
2312 #ifdef HAVE_floatqisf2
2313 if (HAVE_floatqisf2
)
2314 floattab
[(int) SFmode
][(int) QImode
][0] = CODE_FOR_floatqisf2
;
2316 #ifdef HAVE_floathisf2
2317 if (HAVE_floathisf2
)
2318 floattab
[(int) SFmode
][(int) HImode
][0] = CODE_FOR_floathisf2
;
2320 #ifdef HAVE_floatsisf2
2321 if (HAVE_floatsisf2
)
2322 floattab
[(int) SFmode
][(int) SImode
][0] = CODE_FOR_floatsisf2
;
2324 #ifdef HAVE_floatdisf2
2325 if (HAVE_floatdisf2
)
2326 floattab
[(int) SFmode
][(int) DImode
][0] = CODE_FOR_floatdisf2
;
2328 #ifdef HAVE_floattisf2
2329 if (HAVE_floattisf2
)
2330 floattab
[(int) SFmode
][(int) TImode
][0] = CODE_FOR_floattisf2
;
2333 #ifdef HAVE_floatqidf2
2334 if (HAVE_floatqidf2
)
2335 floattab
[(int) DFmode
][(int) QImode
][0] = CODE_FOR_floatqidf2
;
2337 #ifdef HAVE_floathidf2
2338 if (HAVE_floathidf2
)
2339 floattab
[(int) DFmode
][(int) HImode
][0] = CODE_FOR_floathidf2
;
2341 #ifdef HAVE_floatsidf2
2342 if (HAVE_floatsidf2
)
2343 floattab
[(int) DFmode
][(int) SImode
][0] = CODE_FOR_floatsidf2
;
2345 #ifdef HAVE_floatdidf2
2346 if (HAVE_floatdidf2
)
2347 floattab
[(int) DFmode
][(int) DImode
][0] = CODE_FOR_floatdidf2
;
2349 #ifdef HAVE_floattidf2
2350 if (HAVE_floattidf2
)
2351 floattab
[(int) DFmode
][(int) TImode
][0] = CODE_FOR_floattidf2
;
2354 #ifdef HAVE_floatqitf2
2355 if (HAVE_floatqitf2
)
2356 floattab
[(int) TFmode
][(int) QImode
][0] = CODE_FOR_floatqitf2
;
2358 #ifdef HAVE_floathitf2
2359 if (HAVE_floathitf2
)
2360 floattab
[(int) TFmode
][(int) HImode
][0] = CODE_FOR_floathitf2
;
2362 #ifdef HAVE_floatsitf2
2363 if (HAVE_floatsitf2
)
2364 floattab
[(int) TFmode
][(int) SImode
][0] = CODE_FOR_floatsitf2
;
2366 #ifdef HAVE_floatditf2
2367 if (HAVE_floatditf2
)
2368 floattab
[(int) TFmode
][(int) DImode
][0] = CODE_FOR_floatditf2
;
2370 #ifdef HAVE_floattitf2
2371 if (HAVE_floattitf2
)
2372 floattab
[(int) TFmode
][(int) TImode
][0] = CODE_FOR_floattitf2
;
2375 #ifdef HAVE_floatunsqisf2
2376 if (HAVE_floatunsqisf2
)
2377 floattab
[(int) SFmode
][(int) QImode
][1] = CODE_FOR_floatunsqisf2
;
2379 #ifdef HAVE_floatunshisf2
2380 if (HAVE_floatunshisf2
)
2381 floattab
[(int) SFmode
][(int) HImode
][1] = CODE_FOR_floatunshisf2
;
2383 #ifdef HAVE_floatunssisf2
2384 if (HAVE_floatunssisf2
)
2385 floattab
[(int) SFmode
][(int) SImode
][1] = CODE_FOR_floatunssisf2
;
2387 #ifdef HAVE_floatunsdisf2
2388 if (HAVE_floatunsdisf2
)
2389 floattab
[(int) SFmode
][(int) DImode
][1] = CODE_FOR_floatunsdisf2
;
2391 #ifdef HAVE_floatunstisf2
2392 if (HAVE_floatunstisf2
)
2393 floattab
[(int) SFmode
][(int) TImode
][1] = CODE_FOR_floatunstisf2
;
2396 #ifdef HAVE_floatunsqidf2
2397 if (HAVE_floatunsqidf2
)
2398 floattab
[(int) DFmode
][(int) QImode
][1] = CODE_FOR_floatunsqidf2
;
2400 #ifdef HAVE_floatunshidf2
2401 if (HAVE_floatunshidf2
)
2402 floattab
[(int) DFmode
][(int) HImode
][1] = CODE_FOR_floatunshidf2
;
2404 #ifdef HAVE_floatunssidf2
2405 if (HAVE_floatunssidf2
)
2406 floattab
[(int) DFmode
][(int) SImode
][1] = CODE_FOR_floatunssidf2
;
2408 #ifdef HAVE_floatunsdidf2
2409 if (HAVE_floatunsdidf2
)
2410 floattab
[(int) DFmode
][(int) DImode
][1] = CODE_FOR_floatunsdidf2
;
2412 #ifdef HAVE_floatunstidf2
2413 if (HAVE_floatunstidf2
)
2414 floattab
[(int) DFmode
][(int) TImode
][1] = CODE_FOR_floatunstidf2
;
2417 #ifdef HAVE_floatunsqitf2
2418 if (HAVE_floatunsqitf2
)
2419 floattab
[(int) TFmode
][(int) QImode
][1] = CODE_FOR_floatunsqitf2
;
2421 #ifdef HAVE_floatunshitf2
2422 if (HAVE_floatunshitf2
)
2423 floattab
[(int) TFmode
][(int) HImode
][1] = CODE_FOR_floatunshitf2
;
2425 #ifdef HAVE_floatunssitf2
2426 if (HAVE_floatunssitf2
)
2427 floattab
[(int) TFmode
][(int) SImode
][1] = CODE_FOR_floatunssitf2
;
2429 #ifdef HAVE_floatunsditf2
2430 if (HAVE_floatunsditf2
)
2431 floattab
[(int) TFmode
][(int) DImode
][1] = CODE_FOR_floatunsditf2
;
2433 #ifdef HAVE_floatunstitf2
2434 if (HAVE_floatunstitf2
)
2435 floattab
[(int) TFmode
][(int) TImode
][1] = CODE_FOR_floatunstitf2
;
2439 /* Generate code to convert FROM to floating point
2440 and store in TO. FROM must be fixed point and not VOIDmode.
2441 UNSIGNEDP nonzero means regard FROM as unsigned.
2442 Normally this is done by correcting the final value
2443 if it is negative. */
2446 expand_float (to
, from
, unsignedp
)
2450 enum insn_code icode
;
2451 register rtx target
= to
;
2452 enum machine_mode fmode
, imode
;
2454 /* Crash now, because we won't be able to decide which mode to use. */
2455 if (GET_MODE (from
) == VOIDmode
)
2458 /* Look for an insn to do the conversion. Do it in the specified
2459 modes if possible; otherwise convert either input, output or both to
2460 wider mode. If the integer mode is wider than the mode of FROM,
2461 we can do the conversion signed even if the input is unsigned. */
2463 for (imode
= GET_MODE (from
); imode
!= VOIDmode
;
2464 imode
= GET_MODE_WIDER_MODE (imode
))
2465 for (fmode
= GET_MODE (to
); fmode
!= VOIDmode
;
2466 fmode
= GET_MODE_WIDER_MODE (fmode
))
2468 int doing_unsigned
= unsignedp
;
2470 icode
= can_float_p (fmode
, imode
, unsignedp
);
2471 if (icode
== CODE_FOR_nothing
&& imode
!= GET_MODE (from
) && unsignedp
)
2472 icode
= can_float_p (fmode
, imode
, 0), doing_unsigned
= 0;
2474 if (icode
!= CODE_FOR_nothing
)
2476 to
= protect_from_queue (to
, 1);
2478 if (imode
!= GET_MODE (from
))
2479 from
= convert_to_mode (imode
, from
, unsignedp
);
2481 from
= protect_from_queue (from
, 0);
2483 if (fmode
!= GET_MODE (to
))
2484 target
= gen_reg_rtx (fmode
);
2486 emit_unop_insn (icode
, target
, from
,
2487 doing_unsigned
? UNSIGNED_FLOAT
: FLOAT
);
2490 convert_move (to
, target
, 0);
2495 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
2497 /* Unsigned integer, and no way to convert directly.
2498 Convert as signed, then conditionally adjust the result. */
2501 rtx label
= gen_label_rtx ();
2503 REAL_VALUE_TYPE offset
;
2507 to
= protect_from_queue (to
, 1);
2508 from
= protect_from_queue (from
, 0);
2511 from
= force_not_mem (from
);
2513 /* If we are about to do some arithmetic to correct for an
2514 unsigned operand, do it in a pseudo-register. */
2516 if (GET_CODE (to
) != REG
|| REGNO (to
) <= LAST_VIRTUAL_REGISTER
)
2517 target
= gen_reg_rtx (GET_MODE (to
));
2519 /* Convert as signed integer to floating. */
2520 expand_float (target
, from
, 0);
2522 /* If FROM is negative (and therefore TO is negative),
2523 correct its value by 2**bitwidth. */
2525 do_pending_stack_adjust ();
2526 emit_cmp_insn (from
, const0_rtx
, GE
, 0, GET_MODE (from
), 0, 0);
2527 emit_jump_insn (gen_bge (label
));
2528 /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
2529 Rather than setting up a dconst_dot_5, let's hope SCO
2531 offset
= REAL_VALUE_LDEXP (dconst1
, GET_MODE_BITSIZE (GET_MODE (from
)));
2532 temp
= expand_binop (GET_MODE (to
), add_optab
, target
,
2533 immed_real_const_1 (offset
, GET_MODE (to
)),
2534 target
, 0, OPTAB_LIB_WIDEN
);
2536 emit_move_insn (target
, temp
);
2537 do_pending_stack_adjust ();
2543 /* No hardware instruction available; call a library
2544 to convert from SImode or DImode into SFmode or DFmode. */
2549 to
= protect_from_queue (to
, 1);
2551 if (GET_MODE_SIZE (GET_MODE (from
)) < GET_MODE_SIZE (SImode
))
2552 from
= convert_to_mode (SImode
, from
, unsignedp
);
2554 from
= protect_from_queue (from
, 0);
2557 from
= force_not_mem (from
);
2559 if (GET_MODE (to
) == SFmode
)
2561 if (GET_MODE (from
) == SImode
)
2562 libfcn
= floatsisf_libfunc
;
2563 else if (GET_MODE (from
) == DImode
)
2564 libfcn
= floatdisf_libfunc
;
2568 else if (GET_MODE (to
) == DFmode
)
2570 if (GET_MODE (from
) == SImode
)
2571 libfcn
= floatsidf_libfunc
;
2572 else if (GET_MODE (from
) == DImode
)
2573 libfcn
= floatdidf_libfunc
;
2582 emit_library_call (libfcn
, 1, GET_MODE (to
), 1, from
, GET_MODE (from
));
2583 insns
= get_insns ();
2586 emit_libcall_block (insns
, target
, hard_libcall_value (GET_MODE (to
)),
2587 gen_rtx (FLOAT
, GET_MODE (to
), from
));
2590 /* Copy result to requested destination
2591 if we have been computing in a temp location. */
2595 if (GET_MODE (target
) == GET_MODE (to
))
2596 emit_move_insn (to
, target
);
2598 convert_move (to
, target
, 0);
2602 /* expand_fix: generate code to convert FROM to fixed point
2603 and store in TO. FROM must be floating point. */
2609 rtx temp
= gen_reg_rtx (GET_MODE (x
));
2610 return expand_unop (GET_MODE (x
), ftrunc_optab
, x
, temp
, 0);
2614 expand_fix (to
, from
, unsignedp
)
2615 register rtx to
, from
;
2618 enum insn_code icode
;
2619 register rtx target
= to
;
2620 enum machine_mode fmode
, imode
;
2624 /* We first try to find a pair of modes, one real and one integer, at
2625 least as wide as FROM and TO, respectively, in which we can open-code
2626 this conversion. If the integer mode is wider than the mode of TO,
2627 we can do the conversion either signed or unsigned. */
2629 for (imode
= GET_MODE (to
); imode
!= VOIDmode
;
2630 imode
= GET_MODE_WIDER_MODE (imode
))
2631 for (fmode
= GET_MODE (from
); fmode
!= VOIDmode
;
2632 fmode
= GET_MODE_WIDER_MODE (fmode
))
2634 int doing_unsigned
= unsignedp
;
2636 icode
= can_fix_p (imode
, fmode
, unsignedp
, &must_trunc
);
2637 if (icode
== CODE_FOR_nothing
&& imode
!= GET_MODE (to
) && unsignedp
)
2638 icode
= can_fix_p (imode
, fmode
, 0, &must_trunc
), doing_unsigned
= 0;
2640 if (icode
!= CODE_FOR_nothing
)
2642 to
= protect_from_queue (to
, 1);
2644 if (fmode
!= GET_MODE (from
))
2645 from
= convert_to_mode (fmode
, from
, 0);
2647 from
= protect_from_queue (from
, 0);
2650 from
= ftruncify (from
);
2652 if (imode
!= GET_MODE (to
))
2653 target
= gen_reg_rtx (imode
);
2655 emit_unop_insn (icode
, target
, from
,
2656 doing_unsigned
? UNSIGNED_FIX
: FIX
);
2658 convert_move (to
, target
, unsignedp
);
2663 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
2664 /* For an unsigned conversion, there is one more way to do it.
2665 If we have a signed conversion, we generate code that compares
2666 the real value to the largest representable positive number. If if
2667 is smaller, the conversion is done normally. Otherwise, subtract
2668 one plus the highest signed number, convert, and add it back.
2670 We only need to check all real modes, since we know we didn't find
2671 anything with a wider integer mode. */
2673 if (unsignedp
&& GET_MODE_BITSIZE (GET_MODE (to
)) <= HOST_BITS_PER_INT
)
2674 for (fmode
= GET_MODE (from
); fmode
!= VOIDmode
;
2675 fmode
= GET_MODE_WIDER_MODE (fmode
))
2676 /* Make sure we won't lose significant bits doing this. */
2677 if (GET_MODE_BITSIZE (fmode
) > GET_MODE_BITSIZE (GET_MODE (to
))
2678 && CODE_FOR_nothing
!= can_fix_p (GET_MODE (to
), fmode
, 0,
2681 int bitsize
= GET_MODE_BITSIZE (GET_MODE (to
));
2682 REAL_VALUE_TYPE offset
= REAL_VALUE_LDEXP (dconst1
, bitsize
- 1);
2683 rtx limit
= immed_real_const_1 (offset
, fmode
);
2684 rtx lab1
= gen_label_rtx ();
2685 rtx lab2
= gen_label_rtx ();
2689 to
= protect_from_queue (to
, 1);
2690 from
= protect_from_queue (from
, 0);
2693 from
= force_not_mem (from
);
2695 if (fmode
!= GET_MODE (from
))
2696 from
= convert_to_mode (fmode
, from
, 0);
2698 /* See if we need to do the subtraction. */
2699 do_pending_stack_adjust ();
2700 emit_cmp_insn (from
, limit
, GE
, 0, GET_MODE (from
), 0, 0);
2701 emit_jump_insn (gen_bge (lab1
));
2703 /* If not, do the signed "fix" and branch around fixup code. */
2704 expand_fix (to
, from
, 0);
2705 emit_jump_insn (gen_jump (lab2
));
2708 /* Otherwise, subtract 2**(N-1), convert to signed number,
2709 then add 2**(N-1). Do the addition using XOR since this
2710 will often generate better code. */
2712 target
= expand_binop (GET_MODE (from
), sub_optab
, from
, limit
,
2713 0, 0, OPTAB_LIB_WIDEN
);
2714 expand_fix (to
, target
, 0);
2715 target
= expand_binop (GET_MODE (to
), xor_optab
, to
,
2716 gen_rtx (CONST_INT
, VOIDmode
,
2717 1 << (bitsize
- 1)),
2718 to
, 1, OPTAB_LIB_WIDEN
);
2721 emit_move_insn (to
, target
);
2725 /* Make a place for a REG_NOTE and add it. */
2726 insn
= emit_move_insn (to
, to
);
2727 REG_NOTES (insn
) = gen_rtx (EXPR_LIST
, REG_EQUAL
,
2728 gen_rtx (UNSIGNED_FIX
, GET_MODE (to
),
2729 from
), REG_NOTES (insn
));
2735 /* We can't do it with an insn, so use a library call. But first ensure
2736 that the mode of TO is at least as wide as SImode, since those are the
2737 only library calls we know about. */
2739 if (GET_MODE_SIZE (GET_MODE (to
)) < GET_MODE_SIZE (SImode
))
2741 target
= gen_reg_rtx (SImode
);
2743 expand_fix (target
, from
, unsignedp
);
2745 else if (GET_MODE (from
) == SFmode
)
2747 if (GET_MODE (to
) == SImode
)
2748 libfcn
= unsignedp
? fixunssfsi_libfunc
: fixsfsi_libfunc
;
2749 else if (GET_MODE (to
) == DImode
)
2750 libfcn
= unsignedp
? fixunssfdi_libfunc
: fixsfdi_libfunc
;
2754 else if (GET_MODE (from
) == DFmode
)
2756 if (GET_MODE (to
) == SImode
)
2757 libfcn
= unsignedp
? fixunsdfsi_libfunc
: fixdfsi_libfunc
;
2758 else if (GET_MODE (to
) == DImode
)
2759 libfcn
= unsignedp
? fixunsdfdi_libfunc
: fixdfdi_libfunc
;
2770 to
= protect_from_queue (to
, 1);
2771 from
= protect_from_queue (from
, 0);
2774 from
= force_not_mem (from
);
2778 emit_library_call (libfcn
, 1, GET_MODE (to
), 1, from
, GET_MODE (from
));
2779 insns
= get_insns ();
2782 emit_libcall_block (insns
, target
, hard_libcall_value (GET_MODE (to
)),
2783 gen_rtx (unsignedp
? FIX
: UNSIGNED_FIX
,
2784 GET_MODE (to
), from
));
2787 if (GET_MODE (to
) == GET_MODE (target
))
2788 emit_move_insn (to
, target
);
2790 convert_move (to
, target
, 0);
2798 optab op
= (optab
) xmalloc (sizeof (struct optab
));
2800 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
2802 op
->handlers
[i
].insn_code
= CODE_FOR_nothing
;
2803 op
->handlers
[i
].libfunc
= 0;
2808 /* Call this once to initialize the contents of the optabs
2809 appropriately for the current target machine. */
2820 add_optab
= init_optab (PLUS
);
2821 sub_optab
= init_optab (MINUS
);
2822 smul_optab
= init_optab (MULT
);
2823 smul_widen_optab
= init_optab (UNKNOWN
);
2824 umul_widen_optab
= init_optab (UNKNOWN
);
2825 sdiv_optab
= init_optab (DIV
);
2826 sdivmod_optab
= init_optab (UNKNOWN
);
2827 udiv_optab
= init_optab (UDIV
);
2828 udivmod_optab
= init_optab (UNKNOWN
);
2829 smod_optab
= init_optab (MOD
);
2830 umod_optab
= init_optab (UMOD
);
2831 flodiv_optab
= init_optab (DIV
);
2832 ftrunc_optab
= init_optab (UNKNOWN
);
2833 and_optab
= init_optab (AND
);
2834 ior_optab
= init_optab (IOR
);
2835 xor_optab
= init_optab (XOR
);
2836 ashl_optab
= init_optab (ASHIFT
);
2837 ashr_optab
= init_optab (ASHIFTRT
);
2838 lshl_optab
= init_optab (LSHIFT
);
2839 lshr_optab
= init_optab (LSHIFTRT
);
2840 rotl_optab
= init_optab (ROTATE
);
2841 rotr_optab
= init_optab (ROTATERT
);
2842 smin_optab
= init_optab (SMIN
);
2843 smax_optab
= init_optab (SMAX
);
2844 umin_optab
= init_optab (UMIN
);
2845 umax_optab
= init_optab (UMAX
);
2846 mov_optab
= init_optab (UNKNOWN
);
2847 movstrict_optab
= init_optab (UNKNOWN
);
2848 cmp_optab
= init_optab (UNKNOWN
);
2849 ucmp_optab
= init_optab (UNKNOWN
);
2850 tst_optab
= init_optab (UNKNOWN
);
2851 neg_optab
= init_optab (NEG
);
2852 abs_optab
= init_optab (ABS
);
2853 one_cmpl_optab
= init_optab (NOT
);
2854 ffs_optab
= init_optab (FFS
);
2855 sqrt_optab
= init_optab (SQRT
);
2856 strlen_optab
= init_optab (UNKNOWN
);
2860 add_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_addqi3
;
2864 add_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_addhi3
;
2868 add_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_addpsi3
;
2872 add_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_addsi3
;
2876 add_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_adddi3
;
2880 add_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_addti3
;
2884 add_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_addsf3
;
2888 add_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_adddf3
;
2892 add_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_addtf3
;
2894 add_optab
->handlers
[(int) SFmode
].libfunc
2895 = gen_rtx (SYMBOL_REF
, Pmode
, "__addsf3");
2896 add_optab
->handlers
[(int) DFmode
].libfunc
2897 = gen_rtx (SYMBOL_REF
, Pmode
, "__adddf3");
2901 sub_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_subqi3
;
2905 sub_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_subhi3
;
2909 sub_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_subpsi3
;
2913 sub_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_subsi3
;
2917 sub_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_subdi3
;
2921 sub_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_subti3
;
2925 sub_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_subsf3
;
2929 sub_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_subdf3
;
2933 sub_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_subtf3
;
2935 sub_optab
->handlers
[(int) SFmode
].libfunc
2936 = gen_rtx (SYMBOL_REF
, Pmode
, "__subsf3");
2937 sub_optab
->handlers
[(int) DFmode
].libfunc
2938 = gen_rtx (SYMBOL_REF
, Pmode
, "__subdf3");
2942 smul_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_mulqi3
;
2946 smul_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_mulhi3
;
2950 smul_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_mulpsi3
;
2954 smul_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_mulsi3
;
2958 smul_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_muldi3
;
2962 smul_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_multi3
;
2966 smul_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_mulsf3
;
2970 smul_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_muldf3
;
2974 smul_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_multf3
;
2977 #ifdef MULSI3_LIBCALL
2978 smul_optab
->handlers
[(int) SImode
].libfunc
2979 = gen_rtx (SYMBOL_REF
, Pmode
, MULSI3_LIBCALL
);
2981 smul_optab
->handlers
[(int) SImode
].libfunc
2982 = gen_rtx (SYMBOL_REF
, Pmode
, "__mulsi3");
2984 #ifdef MULDI3_LIBCALL
2985 smul_optab
->handlers
[(int) DImode
].libfunc
2986 = gen_rtx (SYMBOL_REF
, Pmode
, MULDI3_LIBCALL
);
2988 smul_optab
->handlers
[(int) DImode
].libfunc
2989 = gen_rtx (SYMBOL_REF
, Pmode
, "__muldi3");
2991 smul_optab
->handlers
[(int) SFmode
].libfunc
2992 = gen_rtx (SYMBOL_REF
, Pmode
, "__mulsf3");
2993 smul_optab
->handlers
[(int) DFmode
].libfunc
2994 = gen_rtx (SYMBOL_REF
, Pmode
, "__muldf3");
2996 #ifdef HAVE_mulqihi3
2998 smul_widen_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_mulqihi3
;
3000 #ifdef HAVE_mulhisi3
3002 smul_widen_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_mulhisi3
;
3004 #ifdef HAVE_mulsidi3
3006 smul_widen_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_mulsidi3
;
3008 #ifdef HAVE_mulditi3
3010 smul_widen_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_mulditi3
;
3013 #ifdef HAVE_umulqihi3
3015 umul_widen_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_umulqihi3
;
3017 #ifdef HAVE_umulhisi3
3019 umul_widen_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_umulhisi3
;
3021 #ifdef HAVE_umulsidi3
3023 umul_widen_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_umulsidi3
;
3025 #ifdef HAVE_umulditi3
3027 umul_widen_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_umulditi3
;
3032 sdiv_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_divqi3
;
3036 sdiv_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_divhi3
;
3040 sdiv_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_divpsi3
;
3044 sdiv_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_divsi3
;
3048 sdiv_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_divdi3
;
3052 sdiv_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_divti3
;
3055 #ifdef DIVSI3_LIBCALL
3056 sdiv_optab
->handlers
[(int) SImode
].libfunc
3057 = gen_rtx (SYMBOL_REF
, Pmode
, DIVSI3_LIBCALL
);
3059 sdiv_optab
->handlers
[(int) SImode
].libfunc
3060 = gen_rtx (SYMBOL_REF
, Pmode
, "__divsi3");
3062 #ifdef DIVDI3_LIBCALL
3063 sdiv_optab
->handlers
[(int) DImode
].libfunc
3064 = gen_rtx (SYMBOL_REF
, Pmode
, DIVDI3_LIBCALL
);
3066 sdiv_optab
->handlers
[(int) DImode
].libfunc
3067 = gen_rtx (SYMBOL_REF
, Pmode
, "__divdi3");
3072 udiv_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_udivqi3
;
3076 udiv_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_udivhi3
;
3078 #ifdef HAVE_udivpsi3
3080 udiv_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_udivpsi3
;
3084 udiv_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_udivsi3
;
3088 udiv_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_udivdi3
;
3092 udiv_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_udivti3
;
3095 #ifdef UDIVSI3_LIBCALL
3096 udiv_optab
->handlers
[(int) SImode
].libfunc
3097 = gen_rtx (SYMBOL_REF
, Pmode
, UDIVSI3_LIBCALL
);
3099 udiv_optab
->handlers
[(int) SImode
].libfunc
3100 = gen_rtx (SYMBOL_REF
, Pmode
, "__udivsi3");
3102 #ifdef UDIVDI3_LIBCALL
3103 udiv_optab
->handlers
[(int) DImode
].libfunc
3104 = gen_rtx (SYMBOL_REF
, Pmode
, UDIVDI3_LIBCALL
);
3106 udiv_optab
->handlers
[(int) DImode
].libfunc
3107 = gen_rtx (SYMBOL_REF
, Pmode
, "__udivdi3");
3110 #ifdef HAVE_divmodqi4
3112 sdivmod_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_divmodqi4
;
3114 #ifdef HAVE_divmodhi4
3116 sdivmod_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_divmodhi4
;
3118 #ifdef HAVE_divmodsi4
3120 sdivmod_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_divmodsi4
;
3122 #ifdef HAVE_divmoddi4
3124 sdivmod_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_divmoddi4
;
3126 #ifdef HAVE_divmodti4
3128 sdivmod_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_divmodti4
;
3131 #ifdef HAVE_udivmodqi4
3132 if (HAVE_udivmodqi4
)
3133 udivmod_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_udivmodqi4
;
3135 #ifdef HAVE_udivmodhi4
3136 if (HAVE_udivmodhi4
)
3137 udivmod_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_udivmodhi4
;
3139 #ifdef HAVE_udivmodsi4
3140 if (HAVE_udivmodsi4
)
3141 udivmod_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_udivmodsi4
;
3143 #ifdef HAVE_udivmoddi4
3144 if (HAVE_udivmoddi4
)
3145 udivmod_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_udivmoddi4
;
3147 #ifdef HAVE_udivmodti4
3148 if (HAVE_udivmodti4
)
3149 udivmod_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_udivmodti4
;
3154 smod_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_modqi3
;
3158 smod_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_modhi3
;
3162 smod_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_modpsi3
;
3166 smod_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_modsi3
;
3170 smod_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_moddi3
;
3174 smod_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_modti3
;
3177 #ifdef MODSI3_LIBCALL
3178 smod_optab
->handlers
[(int) SImode
].libfunc
3179 = gen_rtx (SYMBOL_REF
, Pmode
, MODSI3_LIBCALL
);
3181 smod_optab
->handlers
[(int) SImode
].libfunc
3182 = gen_rtx (SYMBOL_REF
, Pmode
, "__modsi3");
3184 #ifdef MODDI3_LIBCALL
3185 smod_optab
->handlers
[(int) DImode
].libfunc
3186 = gen_rtx (SYMBOL_REF
, Pmode
, MODDI3_LIBCALL
);
3188 smod_optab
->handlers
[(int) DImode
].libfunc
3189 = gen_rtx (SYMBOL_REF
, Pmode
, "__moddi3");
3194 umod_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_umodqi3
;
3198 umod_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_umodhi3
;
3200 #ifdef HAVE_umodpsi3
3202 umod_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_umodpsi3
;
3206 umod_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_umodsi3
;
3210 umod_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_umoddi3
;
3214 umod_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_umodti3
;
3217 #ifdef UMODSI3_LIBCALL
3218 umod_optab
->handlers
[(int) SImode
].libfunc
3219 = gen_rtx (SYMBOL_REF
, Pmode
, UMODSI3_LIBCALL
);
3221 umod_optab
->handlers
[(int) SImode
].libfunc
3222 = gen_rtx (SYMBOL_REF
, Pmode
, "__umodsi3");
3224 #ifdef UMODDI3_LIBCALL
3225 umod_optab
->handlers
[(int) DImode
].libfunc
3226 = gen_rtx (SYMBOL_REF
, Pmode
, UMODDI3_LIBCALL
);
3228 umod_optab
->handlers
[(int) DImode
].libfunc
3229 = gen_rtx (SYMBOL_REF
, Pmode
, "__umoddi3");
3234 flodiv_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_divsf3
;
3238 flodiv_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_divdf3
;
3242 flodiv_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_divtf3
;
3244 flodiv_optab
->handlers
[(int) SFmode
].libfunc
3245 = gen_rtx (SYMBOL_REF
, Pmode
, "__divsf3");
3246 flodiv_optab
->handlers
[(int) DFmode
].libfunc
3247 = gen_rtx (SYMBOL_REF
, Pmode
, "__divdf3");
3249 #ifdef HAVE_ftruncsf2
3251 ftrunc_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_ftruncsf2
;
3253 #ifdef HAVE_ftruncdf2
3255 ftrunc_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_ftruncdf2
;
3257 #ifdef HAVE_ftrunctf2
3259 ftrunc_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_ftrunctf2
;
3264 and_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_andqi3
;
3268 and_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_andhi3
;
3272 and_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_andpsi3
;
3276 and_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_andsi3
;
3280 and_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_anddi3
;
3284 and_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_andti3
;
3289 ior_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_iorqi3
;
3293 ior_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_iorhi3
;
3297 ior_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_iorpsi3
;
3301 ior_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_iorsi3
;
3305 ior_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_iordi3
;
3309 ior_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_iorti3
;
3314 xor_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_xorqi3
;
3318 xor_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_xorhi3
;
3322 xor_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_xorpsi3
;
3326 xor_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_xorsi3
;
3330 xor_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_xordi3
;
3334 xor_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_xorti3
;
3339 ashl_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_ashlqi3
;
3343 ashl_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_ashlhi3
;
3345 #ifdef HAVE_ashlpsi3
3347 ashl_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_ashlpsi3
;
3351 ashl_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_ashlsi3
;
3355 ashl_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_ashldi3
;
3359 ashl_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_ashlti3
;
3361 ashl_optab
->handlers
[(int) SImode
].libfunc
3362 = gen_rtx (SYMBOL_REF
, Pmode
, "__ashlsi3");
3363 ashl_optab
->handlers
[(int) DImode
].libfunc
3364 = gen_rtx (SYMBOL_REF
, Pmode
, "__ashldi3");
3368 ashr_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_ashrqi3
;
3372 ashr_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_ashrhi3
;
3374 #ifdef HAVE_ashrpsi3
3376 ashr_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_ashrpsi3
;
3380 ashr_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_ashrsi3
;
3384 ashr_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_ashrdi3
;
3388 ashr_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_ashrti3
;
3390 ashr_optab
->handlers
[(int) SImode
].libfunc
3391 = gen_rtx (SYMBOL_REF
, Pmode
, "__ashrsi3");
3392 ashr_optab
->handlers
[(int) DImode
].libfunc
3393 = gen_rtx (SYMBOL_REF
, Pmode
, "__ashrdi3");
3397 lshl_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_lshlqi3
;
3401 lshl_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_lshlhi3
;
3403 #ifdef HAVE_lshlpsi3
3405 lshl_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_lshlpsi3
;
3409 lshl_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_lshlsi3
;
3413 lshl_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_lshldi3
;
3417 lshl_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_lshlti3
;
3419 lshl_optab
->handlers
[(int) SImode
].libfunc
3420 = gen_rtx (SYMBOL_REF
, Pmode
, "__lshlsi3");
3421 lshl_optab
->handlers
[(int) DImode
].libfunc
3422 = gen_rtx (SYMBOL_REF
, Pmode
, "__lshldi3");
3426 lshr_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_lshrqi3
;
3430 lshr_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_lshrhi3
;
3432 #ifdef HAVE_lshrpsi3
3434 lshr_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_lshrpsi3
;
3438 lshr_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_lshrsi3
;
3442 lshr_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_lshrdi3
;
3446 lshr_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_lshrti3
;
3448 lshr_optab
->handlers
[(int) SImode
].libfunc
3449 = gen_rtx (SYMBOL_REF
, Pmode
, "__lshrsi3");
3450 lshr_optab
->handlers
[(int) DImode
].libfunc
3451 = gen_rtx (SYMBOL_REF
, Pmode
, "__lshrdi3");
3455 rotl_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_rotlqi3
;
3459 rotl_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_rotlhi3
;
3461 #ifdef HAVE_rotlpsi3
3463 rotl_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_rotlpsi3
;
3467 rotl_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_rotlsi3
;
3471 rotl_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_rotldi3
;
3475 rotl_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_rotlti3
;
3477 rotl_optab
->handlers
[(int) SImode
].libfunc
3478 = gen_rtx (SYMBOL_REF
, Pmode
, "__rotlsi3");
3479 rotl_optab
->handlers
[(int) DImode
].libfunc
3480 = gen_rtx (SYMBOL_REF
, Pmode
, "__rotldi3");
3484 rotr_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_rotrqi3
;
3488 rotr_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_rotrhi3
;
3490 #ifdef HAVE_rotrpsi3
3492 rotr_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_rotrpsi3
;
3496 rotr_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_rotrsi3
;
3500 rotr_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_rotrdi3
;
3504 rotr_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_rotrti3
;
3506 rotr_optab
->handlers
[(int) SImode
].libfunc
3507 = gen_rtx (SYMBOL_REF
, Pmode
, "__rotrsi3");
3508 rotr_optab
->handlers
[(int) DImode
].libfunc
3509 = gen_rtx (SYMBOL_REF
, Pmode
, "__rotrdi3");
3513 smin_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_sminqi3
;
3517 smin_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_sminhi3
;
3521 smin_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_sminsi3
;
3525 smin_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_smindi3
;
3529 smin_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_sminti3
;
3533 smin_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_sminsf3
;
3537 smin_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_smindf3
;
3541 smin_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_smintf3
;
3546 smax_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_smaxqi3
;
3550 smax_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_smaxhi3
;
3554 smax_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_smaxsi3
;
3558 smax_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_smaxdi3
;
3562 smax_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_smaxti3
;
3566 smax_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_smaxsf3
;
3570 smax_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_smaxdf3
;
3574 smax_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_smaxtf3
;
3579 umin_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_uminqi3
;
3583 umin_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_uminhi3
;
3587 umin_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_uminsi3
;
3591 umin_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_umindi3
;
3595 umin_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_uminti3
;
3600 umax_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_umaxqi3
;
3604 umax_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_umaxhi3
;
3608 umax_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_umaxsi3
;
3612 umax_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_umaxdi3
;
3616 umax_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_umaxti3
;
3621 neg_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_negqi2
;
3625 neg_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_neghi2
;
3629 neg_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_negpsi2
;
3633 neg_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_negsi2
;
3637 neg_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_negdi2
;
3641 neg_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_negti2
;
3645 neg_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_negsf2
;
3649 neg_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_negdf2
;
3653 neg_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_negtf2
;
3655 neg_optab
->handlers
[(int) SImode
].libfunc
3656 = gen_rtx (SYMBOL_REF
, Pmode
, "__negsi2");
3657 neg_optab
->handlers
[(int) DImode
].libfunc
3658 = gen_rtx (SYMBOL_REF
, Pmode
, "__negdi2");
3659 neg_optab
->handlers
[(int) SFmode
].libfunc
3660 = gen_rtx (SYMBOL_REF
, Pmode
, "__negsf2");
3661 neg_optab
->handlers
[(int) DFmode
].libfunc
3662 = gen_rtx (SYMBOL_REF
, Pmode
, "__negdf2");
3666 abs_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_absqi2
;
3670 abs_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_abshi2
;
3674 abs_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_abspsi2
;
3678 abs_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_abssi2
;
3682 abs_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_absdi2
;
3686 abs_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_absti2
;
3690 abs_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_abssf2
;
3694 abs_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_absdf2
;
3698 abs_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_abstf2
;
3700 /* No library calls here! If there is no abs instruction,
3701 expand_expr will generate a conditional negation. */
3705 sqrt_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_sqrtqi2
;
3709 sqrt_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_sqrthi2
;
3711 #ifdef HAVE_sqrtpsi2
3713 sqrt_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_sqrtpsi2
;
3717 sqrt_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_sqrtsi2
;
3721 sqrt_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_sqrtdi2
;
3725 sqrt_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_sqrtti2
;
3729 sqrt_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_sqrtsf2
;
3733 sqrt_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_sqrtdf2
;
3737 sqrt_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_sqrttf2
;
3739 /* No library calls here! If there is no sqrt instruction expand_builtin
3740 should force the library call. */
3742 #ifdef HAVE_strlenqi
3744 strlen_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_strlenqi
;
3746 #ifdef HAVE_strlenhi
3748 strlen_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_strlenhi
;
3750 #ifdef HAVE_strlenpsi
3752 strlen_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_strlenpsi
;
3754 #ifdef HAVE_strlensi
3756 strlen_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_strlensi
;
3758 #ifdef HAVE_strlendi
3760 strlen_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_strlendi
;
3762 #ifdef HAVE_strlenti
3764 strlen_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_strlenti
;
3766 /* No library calls here! If there is no strlen instruction expand_builtin
3767 should force the library call. */
3769 #ifdef HAVE_one_cmplqi2
3770 if (HAVE_one_cmplqi2
)
3771 one_cmpl_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_one_cmplqi2
;
3773 #ifdef HAVE_one_cmplhi2
3774 if (HAVE_one_cmplhi2
)
3775 one_cmpl_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_one_cmplhi2
;
3777 #ifdef HAVE_one_cmplpsi2
3778 if (HAVE_one_cmplpsi2
)
3779 one_cmpl_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_one_cmplpsi2
;
3781 #ifdef HAVE_one_cmplsi2
3782 if (HAVE_one_cmplsi2
)
3783 one_cmpl_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_one_cmplsi2
;
3785 #ifdef HAVE_one_cmpldi2
3786 if (HAVE_one_cmpldi2
)
3787 one_cmpl_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_one_cmpldi2
;
3789 #ifdef HAVE_one_cmplti2
3790 if (HAVE_one_cmplti2
)
3791 one_cmpl_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_one_cmplti2
;
3793 one_cmpl_optab
->handlers
[(int) SImode
].libfunc
3794 = gen_rtx (SYMBOL_REF
, Pmode
, "__one_cmplsi2");
3798 ffs_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_ffsqi2
;
3802 ffs_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_ffshi2
;
3806 ffs_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_ffspsi2
;
3810 ffs_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_ffssi2
;
3814 ffs_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_ffsdi2
;
3818 ffs_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_ffsti2
;
3820 ffs_optab
->handlers
[(int) SImode
].libfunc
3821 = gen_rtx (SYMBOL_REF
, Pmode
, "ffs");
3825 mov_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_movqi
;
3829 mov_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_movhi
;
3833 mov_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_movpsi
;
3837 mov_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_movsi
;
3841 mov_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_movdi
;
3845 mov_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_movti
;
3849 mov_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_movsf
;
3853 mov_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_movdf
;
3857 mov_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_movtf
;
3861 mov_optab
->handlers
[(int) CCmode
].insn_code
= CODE_FOR_movcc
;
3864 #ifdef EXTRA_CC_MODES
3868 #ifdef HAVE_movstrictqi
3869 if (HAVE_movstrictqi
)
3870 movstrict_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_movstrictqi
;
3872 #ifdef HAVE_movstricthi
3873 if (HAVE_movstricthi
)
3874 movstrict_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_movstricthi
;
3876 #ifdef HAVE_movstrictpsi
3877 if (HAVE_movstrictpsi
)
3878 movstrict_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_movstrictpsi
;
3880 #ifdef HAVE_movstrictsi
3881 if (HAVE_movstrictsi
)
3882 movstrict_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_movstrictsi
;
3884 #ifdef HAVE_movstrictdi
3885 if (HAVE_movstrictdi
)
3886 movstrict_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_movstrictdi
;
3888 #ifdef HAVE_movstrictti
3889 if (HAVE_movstrictti
)
3890 movstrict_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_movstrictti
;
3895 cmp_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_cmpqi
;
3899 cmp_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_cmphi
;
3903 cmp_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_cmppsi
;
3907 cmp_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_cmpsi
;
3911 cmp_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_cmpdi
;
3915 cmp_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_cmpti
;
3919 cmp_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_cmpsf
;
3923 cmp_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_cmpdf
;
3927 cmp_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_cmptf
;
3931 tst_optab
->handlers
[(int) QImode
].insn_code
= CODE_FOR_tstqi
;
3935 tst_optab
->handlers
[(int) HImode
].insn_code
= CODE_FOR_tsthi
;
3939 tst_optab
->handlers
[(int) PSImode
].insn_code
= CODE_FOR_tstpsi
;
3943 tst_optab
->handlers
[(int) SImode
].insn_code
= CODE_FOR_tstsi
;
3947 tst_optab
->handlers
[(int) DImode
].insn_code
= CODE_FOR_tstdi
;
3951 tst_optab
->handlers
[(int) TImode
].insn_code
= CODE_FOR_tstti
;
3955 tst_optab
->handlers
[(int) SFmode
].insn_code
= CODE_FOR_tstsf
;
3959 tst_optab
->handlers
[(int) DFmode
].insn_code
= CODE_FOR_tstdf
;
3963 tst_optab
->handlers
[(int) TFmode
].insn_code
= CODE_FOR_tsttf
;
3965 /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
3966 cmp_optab
->handlers
[(int) DImode
].libfunc
3967 = gen_rtx (SYMBOL_REF
, Pmode
, "__cmpdi2");
3968 ucmp_optab
->handlers
[(int) DImode
].libfunc
3969 = gen_rtx (SYMBOL_REF
, Pmode
, "__ucmpdi2");
3973 bcc_gen_fctn
[(int) EQ
] = gen_beq
;
3977 bcc_gen_fctn
[(int) NE
] = gen_bne
;
3981 bcc_gen_fctn
[(int) GT
] = gen_bgt
;
3985 bcc_gen_fctn
[(int) GE
] = gen_bge
;
3989 bcc_gen_fctn
[(int) GTU
] = gen_bgtu
;
3993 bcc_gen_fctn
[(int) GEU
] = gen_bgeu
;
3997 bcc_gen_fctn
[(int) LT
] = gen_blt
;
4001 bcc_gen_fctn
[(int) LE
] = gen_ble
;
4005 bcc_gen_fctn
[(int) LTU
] = gen_bltu
;
4009 bcc_gen_fctn
[(int) LEU
] = gen_bleu
;
4012 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
4013 setcc_gen_code
[i
] = CODE_FOR_nothing
;
4017 setcc_gen_code
[(int) EQ
] = CODE_FOR_seq
;
4021 setcc_gen_code
[(int) NE
] = CODE_FOR_sne
;
4025 setcc_gen_code
[(int) GT
] = CODE_FOR_sgt
;
4029 setcc_gen_code
[(int) GE
] = CODE_FOR_sge
;
4033 setcc_gen_code
[(int) GTU
] = CODE_FOR_sgtu
;
4037 setcc_gen_code
[(int) GEU
] = CODE_FOR_sgeu
;
4041 setcc_gen_code
[(int) LT
] = CODE_FOR_slt
;
4045 setcc_gen_code
[(int) LE
] = CODE_FOR_sle
;
4049 setcc_gen_code
[(int) LTU
] = CODE_FOR_sltu
;
4053 setcc_gen_code
[(int) LEU
] = CODE_FOR_sleu
;
4056 extendsfdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extendsfdf2");
4057 truncdfsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__truncdfsf2");
4058 memcpy_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "memcpy");
4059 bcopy_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "bcopy");
4060 memcmp_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "memcmp");
4061 bcmp_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "bcmp");
4062 memset_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "memset");
4063 bzero_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "bzero");
4064 eqsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqsf2");
4065 nesf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__nesf2");
4066 gtsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gtsf2");
4067 gesf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gesf2");
4068 ltsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ltsf2");
4069 lesf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__lesf2");
4070 eqdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqdf2");
4071 nedf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__nedf2");
4072 gtdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gtdf2");
4073 gedf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gedf2");
4074 ltdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ltdf2");
4075 ledf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ledf2");
4076 floatdisf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatdisf");
4077 floatsisf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatsisf");
4078 floatdidf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatdidf");
4079 floatsidf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatsidf");
4080 fixsfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixsfsi");
4081 fixsfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixsfdi");
4082 fixdfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixdfsi");
4083 fixdfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixdfdi");
4084 fixunssfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunssfsi");
4085 fixunssfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunssfdi");
4086 fixunsdfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsdfsi");
4087 fixunsdfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsdfdi");
4092 /* SCO 3.2 apparently has a broken ldexp. */
4105 #endif /* BROKEN_LDEXP */