1 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2 Copyright (C) 1987, 88, 92, 93, 94, 95, 1996 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, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
26 #include "insn-flags.h"
27 #include "insn-codes.h"
29 #include "insn-config.h"
34 /* Each optab contains info on how this target machine
35 can perform a particular operation
36 for all sizes and kinds of operands.
38 The operation to be performed is often specified
39 by passing one of these optabs as an argument.
41 See expr.h for documentation of these optabs. */
46 optab smul_highpart_optab
;
47 optab umul_highpart_optab
;
48 optab smul_widen_optab
;
49 optab umul_widen_optab
;
72 optab movstrict_optab
;
83 optab ucmp_optab
; /* Used only for libcalls for unsigned comparisons. */
88 /* Tables of patterns for extending one integer mode to another. */
89 enum insn_code extendtab
[MAX_MACHINE_MODE
][MAX_MACHINE_MODE
][2];
91 /* Tables of patterns for converting between fixed and floating point. */
92 enum insn_code fixtab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
93 enum insn_code fixtrunctab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
94 enum insn_code floattab
[NUM_MACHINE_MODES
][NUM_MACHINE_MODES
][2];
96 /* Contains the optab used for each rtx code. */
97 optab code_to_optab
[NUM_RTX_CODE
+ 1];
99 /* SYMBOL_REF rtx's for the library functions that are called
100 implicitly and not via optabs. */
102 rtx extendsfdf2_libfunc
;
103 rtx extendsfxf2_libfunc
;
104 rtx extendsftf2_libfunc
;
105 rtx extenddfxf2_libfunc
;
106 rtx extenddftf2_libfunc
;
108 rtx truncdfsf2_libfunc
;
109 rtx truncxfsf2_libfunc
;
110 rtx trunctfsf2_libfunc
;
111 rtx truncxfdf2_libfunc
;
112 rtx trunctfdf2_libfunc
;
158 rtx floatsisf_libfunc
;
159 rtx floatdisf_libfunc
;
160 rtx floattisf_libfunc
;
162 rtx floatsidf_libfunc
;
163 rtx floatdidf_libfunc
;
164 rtx floattidf_libfunc
;
166 rtx floatsixf_libfunc
;
167 rtx floatdixf_libfunc
;
168 rtx floattixf_libfunc
;
170 rtx floatsitf_libfunc
;
171 rtx floatditf_libfunc
;
172 rtx floattitf_libfunc
;
190 rtx fixunssfsi_libfunc
;
191 rtx fixunssfdi_libfunc
;
192 rtx fixunssfti_libfunc
;
194 rtx fixunsdfsi_libfunc
;
195 rtx fixunsdfdi_libfunc
;
196 rtx fixunsdfti_libfunc
;
198 rtx fixunsxfsi_libfunc
;
199 rtx fixunsxfdi_libfunc
;
200 rtx fixunsxfti_libfunc
;
202 rtx fixunstfsi_libfunc
;
203 rtx fixunstfdi_libfunc
;
204 rtx fixunstfti_libfunc
;
206 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
207 gives the gen_function to make a branch to test that condition. */
209 rtxfun bcc_gen_fctn
[NUM_RTX_CODE
];
211 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
212 gives the insn code to make a store-condition insn
213 to test that condition. */
215 enum insn_code setcc_gen_code
[NUM_RTX_CODE
];
217 #ifdef HAVE_conditional_move
218 /* Indexed by the machine mode, gives the insn code to make a conditional
219 move insn. This is not indexed by the rtx-code like bcc_gen_fctn and
220 setcc_gen_code to cut down on the number of named patterns. Consider a day
221 when a lot more rtx codes are conditional (eg: for the ARM). */
223 enum insn_code movcc_gen_code
[NUM_MACHINE_MODES
];
226 static int add_equal_note
PROTO((rtx
, rtx
, enum rtx_code
, rtx
, rtx
));
227 static rtx widen_operand
PROTO((rtx
, enum machine_mode
,
228 enum machine_mode
, int, int));
229 static enum insn_code can_fix_p
PROTO((enum machine_mode
, enum machine_mode
,
231 static enum insn_code can_float_p
PROTO((enum machine_mode
, enum machine_mode
,
233 static rtx ftruncify
PROTO((rtx
));
234 static optab init_optab
PROTO((enum rtx_code
));
235 static void init_libfuncs
PROTO((optab
, int, int, char *, int));
236 static void init_integral_libfuncs
PROTO((optab
, char *, int));
237 static void init_floating_libfuncs
PROTO((optab
, char *, int));
238 static void init_complex_libfuncs
PROTO((optab
, char *, int));
240 /* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
241 the result of operation CODE applied to OP0 (and OP1 if it is a binary
244 If the last insn does not set TARGET, don't do anything, but return 1.
246 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
247 don't add the REG_EQUAL note but return 0. Our caller can then try
248 again, ensuring that TARGET is not one of the operands. */
251 add_equal_note (seq
, target
, code
, op0
, op1
)
261 if ((GET_RTX_CLASS (code
) != '1' && GET_RTX_CLASS (code
) != '2'
262 && GET_RTX_CLASS (code
) != 'c' && GET_RTX_CLASS (code
) != '<')
263 || GET_CODE (seq
) != SEQUENCE
264 || (set
= single_set (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1))) == 0
265 || GET_CODE (target
) == ZERO_EXTRACT
266 || (! rtx_equal_p (SET_DEST (set
), target
)
267 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
269 && (GET_CODE (SET_DEST (set
)) != STRICT_LOW_PART
270 || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set
), 0)),
274 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
275 besides the last insn. */
276 if (reg_overlap_mentioned_p (target
, op0
)
277 || (op1
&& reg_overlap_mentioned_p (target
, op1
)))
278 for (i
= XVECLEN (seq
, 0) - 2; i
>= 0; i
--)
279 if (reg_set_p (target
, XVECEXP (seq
, 0, i
)))
282 if (GET_RTX_CLASS (code
) == '1')
283 note
= gen_rtx (code
, GET_MODE (target
), copy_rtx (op0
));
285 note
= gen_rtx (code
, GET_MODE (target
), copy_rtx (op0
), copy_rtx (op1
));
287 REG_NOTES (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1))
288 = gen_rtx (EXPR_LIST
, REG_EQUAL
, note
,
289 REG_NOTES (XVECEXP (seq
, 0, XVECLEN (seq
, 0) - 1)));
294 /* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP
295 says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need
296 not actually do a sign-extend or zero-extend, but can leave the
297 higher-order bits of the result rtx undefined, for example, in the case
298 of logical operations, but not right shifts. */
301 widen_operand (op
, mode
, oldmode
, unsignedp
, no_extend
)
303 enum machine_mode mode
, oldmode
;
309 /* If we must extend do so. If OP is either a constant or a SUBREG
310 for a promoted object, also extend since it will be more efficient to
313 || GET_MODE (op
) == VOIDmode
314 || (GET_CODE (op
) == SUBREG
&& SUBREG_PROMOTED_VAR_P (op
)))
315 return convert_modes (mode
, oldmode
, op
, unsignedp
);
317 /* If MODE is no wider than a single word, we return a paradoxical
319 if (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
)
320 return gen_rtx (SUBREG
, mode
, force_reg (GET_MODE (op
), op
), 0);
322 /* Otherwise, get an object of MODE, clobber it, and set the low-order
325 result
= gen_reg_rtx (mode
);
326 emit_insn (gen_rtx (CLOBBER
, VOIDmode
, result
));
327 emit_move_insn (gen_lowpart (GET_MODE (op
), result
), op
);
331 /* Generate code to perform an operation specified by BINOPTAB
332 on operands OP0 and OP1, with result having machine-mode MODE.
334 UNSIGNEDP is for the case where we have to widen the operands
335 to perform the operation. It says to use zero-extension.
337 If TARGET is nonzero, the value
338 is generated there, if it is convenient to do so.
339 In all cases an rtx is returned for the locus of the value;
340 this may or may not be TARGET. */
343 expand_binop (mode
, binoptab
, op0
, op1
, target
, unsignedp
, methods
)
344 enum machine_mode mode
;
349 enum optab_methods methods
;
351 enum optab_methods next_methods
352 = (methods
== OPTAB_LIB
|| methods
== OPTAB_LIB_WIDEN
353 ? OPTAB_WIDEN
: methods
);
354 enum mode_class
class;
355 enum machine_mode wider_mode
;
357 int commutative_op
= 0;
358 int shift_op
= (binoptab
->code
== ASHIFT
359 || binoptab
->code
== ASHIFTRT
360 || binoptab
->code
== LSHIFTRT
361 || binoptab
->code
== ROTATE
362 || binoptab
->code
== ROTATERT
);
363 rtx entry_last
= get_last_insn ();
366 class = GET_MODE_CLASS (mode
);
368 op0
= protect_from_queue (op0
, 0);
369 op1
= protect_from_queue (op1
, 0);
371 target
= protect_from_queue (target
, 1);
375 op0
= force_not_mem (op0
);
376 op1
= force_not_mem (op1
);
379 /* If subtracting an integer constant, convert this into an addition of
380 the negated constant. */
382 if (binoptab
== sub_optab
&& GET_CODE (op1
) == CONST_INT
)
384 op1
= negate_rtx (mode
, op1
);
385 binoptab
= add_optab
;
388 /* If we are inside an appropriately-short loop and one operand is an
389 expensive constant, force it into a register. */
390 if (CONSTANT_P (op0
) && preserve_subexpressions_p ()
391 && rtx_cost (op0
, binoptab
->code
) > 2)
392 op0
= force_reg (mode
, op0
);
394 if (CONSTANT_P (op1
) && preserve_subexpressions_p ()
395 && ! shift_op
&& rtx_cost (op1
, binoptab
->code
) > 2)
396 op1
= force_reg (mode
, op1
);
398 /* Record where to delete back to if we backtrack. */
399 last
= get_last_insn ();
401 /* If operation is commutative,
402 try to make the first operand a register.
403 Even better, try to make it the same as the target.
404 Also try to make the last operand a constant. */
405 if (GET_RTX_CLASS (binoptab
->code
) == 'c'
406 || binoptab
== smul_widen_optab
407 || binoptab
== umul_widen_optab
408 || binoptab
== smul_highpart_optab
409 || binoptab
== umul_highpart_optab
)
413 if (((target
== 0 || GET_CODE (target
) == REG
)
414 ? ((GET_CODE (op1
) == REG
415 && GET_CODE (op0
) != REG
)
417 : rtx_equal_p (op1
, target
))
418 || GET_CODE (op0
) == CONST_INT
)
426 /* If we can do it with a three-operand insn, do so. */
428 if (methods
!= OPTAB_MUST_WIDEN
429 && binoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
431 int icode
= (int) binoptab
->handlers
[(int) mode
].insn_code
;
432 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
433 enum machine_mode mode1
= insn_operand_mode
[icode
][2];
435 rtx xop0
= op0
, xop1
= op1
;
440 temp
= gen_reg_rtx (mode
);
442 /* If it is a commutative operator and the modes would match
443 if we would swap the operands, we can save the conversions. */
446 if (GET_MODE (op0
) != mode0
&& GET_MODE (op1
) != mode1
447 && GET_MODE (op0
) == mode1
&& GET_MODE (op1
) == mode0
)
451 tmp
= op0
; op0
= op1
; op1
= tmp
;
452 tmp
= xop0
; xop0
= xop1
; xop1
= tmp
;
456 /* In case the insn wants input operands in modes different from
457 the result, convert the operands. */
459 if (GET_MODE (op0
) != VOIDmode
460 && GET_MODE (op0
) != mode0
461 && mode0
!= VOIDmode
)
462 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
464 if (GET_MODE (xop1
) != VOIDmode
465 && GET_MODE (xop1
) != mode1
466 && mode1
!= VOIDmode
)
467 xop1
= convert_to_mode (mode1
, xop1
, unsignedp
);
469 /* Now, if insn's predicates don't allow our operands, put them into
472 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
)
473 && mode0
!= VOIDmode
)
474 xop0
= copy_to_mode_reg (mode0
, xop0
);
476 if (! (*insn_operand_predicate
[icode
][2]) (xop1
, mode1
)
477 && mode1
!= VOIDmode
)
478 xop1
= copy_to_mode_reg (mode1
, xop1
);
480 if (! (*insn_operand_predicate
[icode
][0]) (temp
, mode
))
481 temp
= gen_reg_rtx (mode
);
483 pat
= GEN_FCN (icode
) (temp
, xop0
, xop1
);
486 /* If PAT is a multi-insn sequence, try to add an appropriate
487 REG_EQUAL note to it. If we can't because TEMP conflicts with an
488 operand, call ourselves again, this time without a target. */
489 if (GET_CODE (pat
) == SEQUENCE
490 && ! add_equal_note (pat
, temp
, binoptab
->code
, xop0
, xop1
))
492 delete_insns_since (last
);
493 return expand_binop (mode
, binoptab
, op0
, op1
, NULL_RTX
,
501 delete_insns_since (last
);
504 /* If this is a multiply, see if we can do a widening operation that
505 takes operands of this mode and makes a wider mode. */
507 if (binoptab
== smul_optab
&& GET_MODE_WIDER_MODE (mode
) != VOIDmode
508 && (((unsignedp
? umul_widen_optab
: smul_widen_optab
)
509 ->handlers
[(int) GET_MODE_WIDER_MODE (mode
)].insn_code
)
510 != CODE_FOR_nothing
))
512 temp
= expand_binop (GET_MODE_WIDER_MODE (mode
),
513 unsignedp
? umul_widen_optab
: smul_widen_optab
,
514 op0
, op1
, NULL_RTX
, unsignedp
, OPTAB_DIRECT
);
518 if (GET_MODE_CLASS (mode
) == MODE_INT
)
519 return gen_lowpart (mode
, temp
);
521 return convert_to_mode (mode
, temp
, unsignedp
);
525 /* Look for a wider mode of the same class for which we think we
526 can open-code the operation. Check for a widening multiply at the
527 wider mode as well. */
529 if ((class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
530 && methods
!= OPTAB_DIRECT
&& methods
!= OPTAB_LIB
)
531 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
532 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
534 if (binoptab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
535 || (binoptab
== smul_optab
536 && GET_MODE_WIDER_MODE (wider_mode
) != VOIDmode
537 && (((unsignedp
? umul_widen_optab
: smul_widen_optab
)
538 ->handlers
[(int) GET_MODE_WIDER_MODE (wider_mode
)].insn_code
)
539 != CODE_FOR_nothing
)))
541 rtx xop0
= op0
, xop1
= op1
;
544 /* For certain integer operations, we need not actually extend
545 the narrow operands, as long as we will truncate
546 the results to the same narrowness. */
548 if ((binoptab
== ior_optab
|| binoptab
== and_optab
549 || binoptab
== xor_optab
550 || binoptab
== add_optab
|| binoptab
== sub_optab
551 || binoptab
== smul_optab
|| binoptab
== ashl_optab
)
552 && class == MODE_INT
)
555 xop0
= widen_operand (xop0
, wider_mode
, mode
, unsignedp
, no_extend
);
557 /* The second operand of a shift must always be extended. */
558 xop1
= widen_operand (xop1
, wider_mode
, mode
, unsignedp
,
559 no_extend
&& binoptab
!= ashl_optab
);
561 temp
= expand_binop (wider_mode
, binoptab
, xop0
, xop1
, NULL_RTX
,
562 unsignedp
, OPTAB_DIRECT
);
565 if (class != MODE_INT
)
568 target
= gen_reg_rtx (mode
);
569 convert_move (target
, temp
, 0);
573 return gen_lowpart (mode
, temp
);
576 delete_insns_since (last
);
580 /* These can be done a word at a time. */
581 if ((binoptab
== and_optab
|| binoptab
== ior_optab
|| binoptab
== xor_optab
)
583 && GET_MODE_SIZE (mode
) > UNITS_PER_WORD
584 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
590 /* If TARGET is the same as one of the operands, the REG_EQUAL note
591 won't be accurate, so use a new target. */
592 if (target
== 0 || target
== op0
|| target
== op1
)
593 target
= gen_reg_rtx (mode
);
597 /* Do the actual arithmetic. */
598 for (i
= 0; i
< GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
; i
++)
600 rtx target_piece
= operand_subword (target
, i
, 1, mode
);
601 rtx x
= expand_binop (word_mode
, binoptab
,
602 operand_subword_force (op0
, i
, mode
),
603 operand_subword_force (op1
, i
, mode
),
604 target_piece
, unsignedp
, next_methods
);
609 if (target_piece
!= x
)
610 emit_move_insn (target_piece
, x
);
613 insns
= get_insns ();
616 if (i
== GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
)
618 if (binoptab
->code
!= UNKNOWN
)
620 = gen_rtx (binoptab
->code
, mode
, copy_rtx (op0
), copy_rtx (op1
));
624 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv_value
);
629 /* Synthesize double word shifts from single word shifts. */
630 if ((binoptab
== lshr_optab
|| binoptab
== ashl_optab
631 || binoptab
== ashr_optab
)
633 && GET_CODE (op1
) == CONST_INT
634 && GET_MODE_SIZE (mode
) == 2 * UNITS_PER_WORD
635 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
636 && ashl_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
637 && lshr_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
639 rtx insns
, inter
, equiv_value
;
640 rtx into_target
, outof_target
;
641 rtx into_input
, outof_input
;
642 int shift_count
, left_shift
, outof_word
;
644 /* If TARGET is the same as one of the operands, the REG_EQUAL note
645 won't be accurate, so use a new target. */
646 if (target
== 0 || target
== op0
|| target
== op1
)
647 target
= gen_reg_rtx (mode
);
651 shift_count
= INTVAL (op1
);
653 /* OUTOF_* is the word we are shifting bits away from, and
654 INTO_* is the word that we are shifting bits towards, thus
655 they differ depending on the direction of the shift and
658 left_shift
= binoptab
== ashl_optab
;
659 outof_word
= left_shift
^ ! WORDS_BIG_ENDIAN
;
661 outof_target
= operand_subword (target
, outof_word
, 1, mode
);
662 into_target
= operand_subword (target
, 1 - outof_word
, 1, mode
);
664 outof_input
= operand_subword_force (op0
, outof_word
, mode
);
665 into_input
= operand_subword_force (op0
, 1 - outof_word
, mode
);
667 if (shift_count
>= BITS_PER_WORD
)
669 inter
= expand_binop (word_mode
, binoptab
,
671 GEN_INT (shift_count
- BITS_PER_WORD
),
672 into_target
, unsignedp
, next_methods
);
674 if (inter
!= 0 && inter
!= into_target
)
675 emit_move_insn (into_target
, inter
);
677 /* For a signed right shift, we must fill the word we are shifting
678 out of with copies of the sign bit. Otherwise it is zeroed. */
679 if (inter
!= 0 && binoptab
!= ashr_optab
)
680 inter
= CONST0_RTX (word_mode
);
682 inter
= expand_binop (word_mode
, binoptab
,
684 GEN_INT (BITS_PER_WORD
- 1),
685 outof_target
, unsignedp
, next_methods
);
687 if (inter
!= 0 && inter
!= outof_target
)
688 emit_move_insn (outof_target
, inter
);
693 optab reverse_unsigned_shift
, unsigned_shift
;
695 /* For a shift of less then BITS_PER_WORD, to compute the carry,
696 we must do a logical shift in the opposite direction of the
699 reverse_unsigned_shift
= (left_shift
? lshr_optab
: ashl_optab
);
701 /* For a shift of less than BITS_PER_WORD, to compute the word
702 shifted towards, we need to unsigned shift the orig value of
705 unsigned_shift
= (left_shift
? ashl_optab
: lshr_optab
);
707 carries
= expand_binop (word_mode
, reverse_unsigned_shift
,
709 GEN_INT (BITS_PER_WORD
- shift_count
),
710 0, unsignedp
, next_methods
);
715 inter
= expand_binop (word_mode
, unsigned_shift
, into_input
,
716 op1
, 0, unsignedp
, next_methods
);
719 inter
= expand_binop (word_mode
, ior_optab
, carries
, inter
,
720 into_target
, unsignedp
, next_methods
);
722 if (inter
!= 0 && inter
!= into_target
)
723 emit_move_insn (into_target
, inter
);
726 inter
= expand_binop (word_mode
, binoptab
, outof_input
,
727 op1
, outof_target
, unsignedp
, next_methods
);
729 if (inter
!= 0 && inter
!= outof_target
)
730 emit_move_insn (outof_target
, inter
);
733 insns
= get_insns ();
738 if (binoptab
->code
!= UNKNOWN
)
739 equiv_value
= gen_rtx (binoptab
->code
, mode
, op0
, op1
);
743 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv_value
);
748 /* Synthesize double word rotates from single word shifts. */
749 if ((binoptab
== rotl_optab
|| binoptab
== rotr_optab
)
751 && GET_CODE (op1
) == CONST_INT
752 && GET_MODE_SIZE (mode
) == 2 * UNITS_PER_WORD
753 && ashl_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
754 && lshr_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
756 rtx insns
, equiv_value
;
757 rtx into_target
, outof_target
;
758 rtx into_input
, outof_input
;
760 int shift_count
, left_shift
, outof_word
;
762 /* If TARGET is the same as one of the operands, the REG_EQUAL note
763 won't be accurate, so use a new target. */
764 if (target
== 0 || target
== op0
|| target
== op1
)
765 target
= gen_reg_rtx (mode
);
769 shift_count
= INTVAL (op1
);
771 /* OUTOF_* is the word we are shifting bits away from, and
772 INTO_* is the word that we are shifting bits towards, thus
773 they differ depending on the direction of the shift and
776 left_shift
= (binoptab
== rotl_optab
);
777 outof_word
= left_shift
^ ! WORDS_BIG_ENDIAN
;
779 outof_target
= operand_subword (target
, outof_word
, 1, mode
);
780 into_target
= operand_subword (target
, 1 - outof_word
, 1, mode
);
782 outof_input
= operand_subword_force (op0
, outof_word
, mode
);
783 into_input
= operand_subword_force (op0
, 1 - outof_word
, mode
);
785 if (shift_count
== BITS_PER_WORD
)
787 /* This is just a word swap. */
788 emit_move_insn (outof_target
, into_input
);
789 emit_move_insn (into_target
, outof_input
);
794 rtx into_temp1
, into_temp2
, outof_temp1
, outof_temp2
;
795 rtx first_shift_count
, second_shift_count
;
796 optab reverse_unsigned_shift
, unsigned_shift
;
798 reverse_unsigned_shift
= (left_shift
^ (shift_count
< BITS_PER_WORD
)
799 ? lshr_optab
: ashl_optab
);
801 unsigned_shift
= (left_shift
^ (shift_count
< BITS_PER_WORD
)
802 ? ashl_optab
: lshr_optab
);
804 if (shift_count
> BITS_PER_WORD
)
806 first_shift_count
= GEN_INT (shift_count
- BITS_PER_WORD
);
807 second_shift_count
= GEN_INT (2*BITS_PER_WORD
- shift_count
);
811 first_shift_count
= GEN_INT (BITS_PER_WORD
- shift_count
);
812 second_shift_count
= GEN_INT (shift_count
);
815 into_temp1
= expand_binop (word_mode
, unsigned_shift
,
816 outof_input
, first_shift_count
,
817 NULL_RTX
, unsignedp
, next_methods
);
818 into_temp2
= expand_binop (word_mode
, reverse_unsigned_shift
,
819 into_input
, second_shift_count
,
820 into_target
, unsignedp
, next_methods
);
822 if (into_temp1
!= 0 && into_temp2
!= 0)
823 inter
= expand_binop (word_mode
, ior_optab
, into_temp1
, into_temp2
,
824 into_target
, unsignedp
, next_methods
);
828 if (inter
!= 0 && inter
!= into_target
)
829 emit_move_insn (into_target
, inter
);
831 outof_temp1
= expand_binop (word_mode
, unsigned_shift
,
832 into_input
, first_shift_count
,
833 NULL_RTX
, unsignedp
, next_methods
);
834 outof_temp2
= expand_binop (word_mode
, reverse_unsigned_shift
,
835 outof_input
, second_shift_count
,
836 outof_target
, unsignedp
, next_methods
);
838 if (inter
!= 0 && outof_temp1
!= 0 && outof_temp2
!= 0)
839 inter
= expand_binop (word_mode
, ior_optab
,
840 outof_temp1
, outof_temp2
,
841 outof_target
, unsignedp
, next_methods
);
843 if (inter
!= 0 && inter
!= outof_target
)
844 emit_move_insn (outof_target
, inter
);
847 insns
= get_insns ();
852 if (binoptab
->code
!= UNKNOWN
)
853 equiv_value
= gen_rtx (binoptab
->code
, mode
, op0
, op1
);
857 /* We can't make this a no conflict block if this is a word swap,
858 because the word swap case fails if the input and output values
859 are in the same register. */
860 if (shift_count
!= BITS_PER_WORD
)
861 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv_value
);
870 /* These can be done a word at a time by propagating carries. */
871 if ((binoptab
== add_optab
|| binoptab
== sub_optab
)
873 && GET_MODE_SIZE (mode
) >= 2 * UNITS_PER_WORD
874 && binoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
877 rtx carry_tmp
= gen_reg_rtx (word_mode
);
878 optab otheroptab
= binoptab
== add_optab
? sub_optab
: add_optab
;
879 int nwords
= GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
;
880 rtx carry_in
, carry_out
;
883 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
884 value is one of those, use it. Otherwise, use 1 since it is the
885 one easiest to get. */
886 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
887 int normalizep
= STORE_FLAG_VALUE
;
892 /* Prepare the operands. */
893 xop0
= force_reg (mode
, op0
);
894 xop1
= force_reg (mode
, op1
);
896 if (target
== 0 || GET_CODE (target
) != REG
897 || target
== xop0
|| target
== xop1
)
898 target
= gen_reg_rtx (mode
);
900 /* Indicate for flow that the entire target reg is being set. */
901 if (GET_CODE (target
) == REG
)
902 emit_insn (gen_rtx (CLOBBER
, VOIDmode
, target
));
904 /* Do the actual arithmetic. */
905 for (i
= 0; i
< nwords
; i
++)
907 int index
= (WORDS_BIG_ENDIAN
? nwords
- i
- 1 : i
);
908 rtx target_piece
= operand_subword (target
, index
, 1, mode
);
909 rtx op0_piece
= operand_subword_force (xop0
, index
, mode
);
910 rtx op1_piece
= operand_subword_force (xop1
, index
, mode
);
913 /* Main add/subtract of the input operands. */
914 x
= expand_binop (word_mode
, binoptab
,
915 op0_piece
, op1_piece
,
916 target_piece
, unsignedp
, next_methods
);
922 /* Store carry from main add/subtract. */
923 carry_out
= gen_reg_rtx (word_mode
);
924 carry_out
= emit_store_flag_force (carry_out
,
925 (binoptab
== add_optab
928 word_mode
, 1, normalizep
);
933 /* Add/subtract previous carry to main result. */
934 x
= expand_binop (word_mode
,
935 normalizep
== 1 ? binoptab
: otheroptab
,
937 target_piece
, 1, next_methods
);
940 else if (target_piece
!= x
)
941 emit_move_insn (target_piece
, x
);
945 /* THIS CODE HAS NOT BEEN TESTED. */
946 /* Get out carry from adding/subtracting carry in. */
947 carry_tmp
= emit_store_flag_force (carry_tmp
,
948 binoptab
== add_optab
951 word_mode
, 1, normalizep
);
953 /* Logical-ior the two poss. carry together. */
954 carry_out
= expand_binop (word_mode
, ior_optab
,
955 carry_out
, carry_tmp
,
956 carry_out
, 0, next_methods
);
962 carry_in
= carry_out
;
965 if (i
== GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
)
967 rtx temp
= emit_move_insn (target
, target
);
969 REG_NOTES (temp
) = gen_rtx (EXPR_LIST
, REG_EQUAL
,
970 gen_rtx (binoptab
->code
, mode
,
977 delete_insns_since (last
);
980 /* If we want to multiply two two-word values and have normal and widening
981 multiplies of single-word values, we can do this with three smaller
982 multiplications. Note that we do not make a REG_NO_CONFLICT block here
983 because we are not operating on one word at a time.
985 The multiplication proceeds as follows:
986 _______________________
987 [__op0_high_|__op0_low__]
988 _______________________
989 * [__op1_high_|__op1_low__]
990 _______________________________________________
991 _______________________
992 (1) [__op0_low__*__op1_low__]
993 _______________________
994 (2a) [__op0_low__*__op1_high_]
995 _______________________
996 (2b) [__op0_high_*__op1_low__]
997 _______________________
998 (3) [__op0_high_*__op1_high_]
1001 This gives a 4-word result. Since we are only interested in the
1002 lower 2 words, partial result (3) and the upper words of (2a) and
1003 (2b) don't need to be calculated. Hence (2a) and (2b) can be
1004 calculated using non-widening multiplication.
1006 (1), however, needs to be calculated with an unsigned widening
1007 multiplication. If this operation is not directly supported we
1008 try using a signed widening multiplication and adjust the result.
1009 This adjustment works as follows:
1011 If both operands are positive then no adjustment is needed.
1013 If the operands have different signs, for example op0_low < 0 and
1014 op1_low >= 0, the instruction treats the most significant bit of
1015 op0_low as a sign bit instead of a bit with significance
1016 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
1017 with 2**BITS_PER_WORD - op0_low, and two's complements the
1018 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
1021 Similarly, if both operands are negative, we need to add
1022 (op0_low + op1_low) * 2**BITS_PER_WORD.
1024 We use a trick to adjust quickly. We logically shift op0_low right
1025 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
1026 op0_high (op1_high) before it is used to calculate 2b (2a). If no
1027 logical shift exists, we do an arithmetic right shift and subtract
1030 if (binoptab
== smul_optab
1031 && class == MODE_INT
1032 && GET_MODE_SIZE (mode
) == 2 * UNITS_PER_WORD
1033 && smul_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
1034 && add_optab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
1035 && ((umul_widen_optab
->handlers
[(int) mode
].insn_code
1036 != CODE_FOR_nothing
)
1037 || (smul_widen_optab
->handlers
[(int) mode
].insn_code
1038 != CODE_FOR_nothing
)))
1040 int low
= (WORDS_BIG_ENDIAN
? 1 : 0);
1041 int high
= (WORDS_BIG_ENDIAN
? 0 : 1);
1042 rtx op0_high
= operand_subword_force (op0
, high
, mode
);
1043 rtx op0_low
= operand_subword_force (op0
, low
, mode
);
1044 rtx op1_high
= operand_subword_force (op1
, high
, mode
);
1045 rtx op1_low
= operand_subword_force (op1
, low
, mode
);
1050 /* If the target is the same as one of the inputs, don't use it. This
1051 prevents problems with the REG_EQUAL note. */
1052 if (target
== op0
|| target
== op1
1053 || (target
!= 0 && GET_CODE (target
) != REG
))
1056 /* Multiply the two lower words to get a double-word product.
1057 If unsigned widening multiplication is available, use that;
1058 otherwise use the signed form and compensate. */
1060 if (umul_widen_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1062 product
= expand_binop (mode
, umul_widen_optab
, op0_low
, op1_low
,
1063 target
, 1, OPTAB_DIRECT
);
1065 /* If we didn't succeed, delete everything we did so far. */
1067 delete_insns_since (last
);
1069 op0_xhigh
= op0_high
, op1_xhigh
= op1_high
;
1073 && smul_widen_optab
->handlers
[(int) mode
].insn_code
1074 != CODE_FOR_nothing
)
1076 rtx wordm1
= GEN_INT (BITS_PER_WORD
- 1);
1077 product
= expand_binop (mode
, smul_widen_optab
, op0_low
, op1_low
,
1078 target
, 1, OPTAB_DIRECT
);
1079 op0_xhigh
= expand_binop (word_mode
, lshr_optab
, op0_low
, wordm1
,
1080 NULL_RTX
, 1, next_methods
);
1082 op0_xhigh
= expand_binop (word_mode
, add_optab
, op0_high
,
1083 op0_xhigh
, op0_xhigh
, 0, next_methods
);
1086 op0_xhigh
= expand_binop (word_mode
, ashr_optab
, op0_low
, wordm1
,
1087 NULL_RTX
, 0, next_methods
);
1089 op0_xhigh
= expand_binop (word_mode
, sub_optab
, op0_high
,
1090 op0_xhigh
, op0_xhigh
, 0,
1094 op1_xhigh
= expand_binop (word_mode
, lshr_optab
, op1_low
, wordm1
,
1095 NULL_RTX
, 1, next_methods
);
1097 op1_xhigh
= expand_binop (word_mode
, add_optab
, op1_high
,
1098 op1_xhigh
, op1_xhigh
, 0, next_methods
);
1101 op1_xhigh
= expand_binop (word_mode
, ashr_optab
, op1_low
, wordm1
,
1102 NULL_RTX
, 0, next_methods
);
1104 op1_xhigh
= expand_binop (word_mode
, sub_optab
, op1_high
,
1105 op1_xhigh
, op1_xhigh
, 0,
1110 /* If we have been able to directly compute the product of the
1111 low-order words of the operands and perform any required adjustments
1112 of the operands, we proceed by trying two more multiplications
1113 and then computing the appropriate sum.
1115 We have checked above that the required addition is provided.
1116 Full-word addition will normally always succeed, especially if
1117 it is provided at all, so we don't worry about its failure. The
1118 multiplication may well fail, however, so we do handle that. */
1120 if (product
&& op0_xhigh
&& op1_xhigh
)
1122 rtx product_high
= operand_subword (product
, high
, 1, mode
);
1123 rtx temp
= expand_binop (word_mode
, binoptab
, op0_low
, op1_xhigh
,
1124 NULL_RTX
, 0, OPTAB_DIRECT
);
1127 temp
= expand_binop (word_mode
, add_optab
, temp
, product_high
,
1128 product_high
, 0, next_methods
);
1130 if (temp
!= 0 && temp
!= product_high
)
1131 emit_move_insn (product_high
, temp
);
1134 temp
= expand_binop (word_mode
, binoptab
, op1_low
, op0_xhigh
,
1135 NULL_RTX
, 0, OPTAB_DIRECT
);
1138 temp
= expand_binop (word_mode
, add_optab
, temp
,
1139 product_high
, product_high
,
1142 if (temp
!= 0 && temp
!= product_high
)
1143 emit_move_insn (product_high
, temp
);
1147 temp
= emit_move_insn (product
, product
);
1148 REG_NOTES (temp
) = gen_rtx (EXPR_LIST
, REG_EQUAL
,
1149 gen_rtx (MULT
, mode
, copy_rtx (op0
),
1157 /* If we get here, we couldn't do it for some reason even though we
1158 originally thought we could. Delete anything we've emitted in
1161 delete_insns_since (last
);
1164 /* We need to open-code the complex type operations: '+, -, * and /' */
1166 /* At this point we allow operations between two similar complex
1167 numbers, and also if one of the operands is not a complex number
1168 but rather of MODE_FLOAT or MODE_INT. However, the caller
1169 must make sure that the MODE of the non-complex operand matches
1170 the SUBMODE of the complex operand. */
1172 if (class == MODE_COMPLEX_FLOAT
|| class == MODE_COMPLEX_INT
)
1174 rtx real0
= 0, imag0
= 0;
1175 rtx real1
= 0, imag1
= 0;
1176 rtx realr
, imagr
, res
;
1181 /* Find the correct mode for the real and imaginary parts */
1182 enum machine_mode submode
1183 = mode_for_size (GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
,
1184 class == MODE_COMPLEX_INT
? MODE_INT
: MODE_FLOAT
,
1187 if (submode
== BLKmode
)
1191 target
= gen_reg_rtx (mode
);
1195 realr
= gen_realpart (submode
, target
);
1196 imagr
= gen_imagpart (submode
, target
);
1198 if (GET_MODE (op0
) == mode
)
1200 real0
= gen_realpart (submode
, op0
);
1201 imag0
= gen_imagpart (submode
, op0
);
1206 if (GET_MODE (op1
) == mode
)
1208 real1
= gen_realpart (submode
, op1
);
1209 imag1
= gen_imagpart (submode
, op1
);
1214 if (real0
== 0 || real1
== 0 || ! (imag0
!= 0|| imag1
!= 0))
1217 switch (binoptab
->code
)
1220 /* (a+ib) + (c+id) = (a+c) + i(b+d) */
1222 /* (a+ib) - (c+id) = (a-c) + i(b-d) */
1223 res
= expand_binop (submode
, binoptab
, real0
, real1
,
1224 realr
, unsignedp
, methods
);
1228 else if (res
!= realr
)
1229 emit_move_insn (realr
, res
);
1232 res
= expand_binop (submode
, binoptab
, imag0
, imag1
,
1233 imagr
, unsignedp
, methods
);
1236 else if (binoptab
->code
== MINUS
)
1237 res
= expand_unop (submode
, neg_optab
, imag1
, imagr
, unsignedp
);
1243 else if (res
!= imagr
)
1244 emit_move_insn (imagr
, res
);
1250 /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */
1256 /* Don't fetch these from memory more than once. */
1257 real0
= force_reg (submode
, real0
);
1258 real1
= force_reg (submode
, real1
);
1259 imag0
= force_reg (submode
, imag0
);
1260 imag1
= force_reg (submode
, imag1
);
1262 temp1
= expand_binop (submode
, binoptab
, real0
, real1
, NULL_RTX
,
1263 unsignedp
, methods
);
1265 temp2
= expand_binop (submode
, binoptab
, imag0
, imag1
, NULL_RTX
,
1266 unsignedp
, methods
);
1268 if (temp1
== 0 || temp2
== 0)
1271 res
= expand_binop (submode
, sub_optab
, temp1
, temp2
,
1272 realr
, unsignedp
, methods
);
1276 else if (res
!= realr
)
1277 emit_move_insn (realr
, res
);
1279 temp1
= expand_binop (submode
, binoptab
, real0
, imag1
,
1280 NULL_RTX
, unsignedp
, methods
);
1282 temp2
= expand_binop (submode
, binoptab
, real1
, imag0
,
1283 NULL_RTX
, unsignedp
, methods
);
1285 if (temp1
== 0 || temp2
== 0)
1288 res
= expand_binop (submode
, add_optab
, temp1
, temp2
,
1289 imagr
, unsignedp
, methods
);
1293 else if (res
!= imagr
)
1294 emit_move_insn (imagr
, res
);
1300 /* Don't fetch these from memory more than once. */
1301 real0
= force_reg (submode
, real0
);
1302 real1
= force_reg (submode
, real1
);
1304 res
= expand_binop (submode
, binoptab
, real0
, real1
,
1305 realr
, unsignedp
, methods
);
1308 else if (res
!= realr
)
1309 emit_move_insn (realr
, res
);
1312 res
= expand_binop (submode
, binoptab
,
1313 real1
, imag0
, imagr
, unsignedp
, methods
);
1315 res
= expand_binop (submode
, binoptab
,
1316 real0
, imag1
, imagr
, unsignedp
, methods
);
1320 else if (res
!= imagr
)
1321 emit_move_insn (imagr
, res
);
1328 /* (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) */
1332 /* (a+ib) / (c+i0) = (a/c) + i(b/c) */
1334 /* Don't fetch these from memory more than once. */
1335 real1
= force_reg (submode
, real1
);
1337 /* Simply divide the real and imaginary parts by `c' */
1338 if (class == MODE_COMPLEX_FLOAT
)
1339 res
= expand_binop (submode
, binoptab
, real0
, real1
,
1340 realr
, unsignedp
, methods
);
1342 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
1343 real0
, real1
, realr
, unsignedp
);
1347 else if (res
!= realr
)
1348 emit_move_insn (realr
, res
);
1350 if (class == MODE_COMPLEX_FLOAT
)
1351 res
= expand_binop (submode
, binoptab
, imag0
, real1
,
1352 imagr
, unsignedp
, methods
);
1354 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
1355 imag0
, real1
, imagr
, unsignedp
);
1359 else if (res
!= imagr
)
1360 emit_move_insn (imagr
, res
);
1366 /* Divisor is of complex type:
1373 /* Don't fetch these from memory more than once. */
1374 real0
= force_reg (submode
, real0
);
1375 real1
= force_reg (submode
, real1
);
1378 imag0
= force_reg (submode
, imag0
);
1380 imag1
= force_reg (submode
, imag1
);
1382 /* Divisor: c*c + d*d */
1383 temp1
= expand_binop (submode
, smul_optab
, real1
, real1
,
1384 NULL_RTX
, unsignedp
, methods
);
1386 temp2
= expand_binop (submode
, smul_optab
, imag1
, imag1
,
1387 NULL_RTX
, unsignedp
, methods
);
1389 if (temp1
== 0 || temp2
== 0)
1392 divisor
= expand_binop (submode
, add_optab
, temp1
, temp2
,
1393 NULL_RTX
, unsignedp
, methods
);
1399 /* ((a)(c-id))/divisor */
1400 /* (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)) */
1402 /* Calculate the dividend */
1403 real_t
= expand_binop (submode
, smul_optab
, real0
, real1
,
1404 NULL_RTX
, unsignedp
, methods
);
1406 imag_t
= expand_binop (submode
, smul_optab
, real0
, imag1
,
1407 NULL_RTX
, unsignedp
, methods
);
1409 if (real_t
== 0 || imag_t
== 0)
1412 imag_t
= expand_unop (submode
, neg_optab
, imag_t
,
1413 NULL_RTX
, unsignedp
);
1417 /* ((a+ib)(c-id))/divider */
1418 /* Calculate the dividend */
1419 temp1
= expand_binop (submode
, smul_optab
, real0
, real1
,
1420 NULL_RTX
, unsignedp
, methods
);
1422 temp2
= expand_binop (submode
, smul_optab
, imag0
, imag1
,
1423 NULL_RTX
, unsignedp
, methods
);
1425 if (temp1
== 0 || temp2
== 0)
1428 real_t
= expand_binop (submode
, add_optab
, temp1
, temp2
,
1429 NULL_RTX
, unsignedp
, methods
);
1431 temp1
= expand_binop (submode
, smul_optab
, imag0
, real1
,
1432 NULL_RTX
, unsignedp
, methods
);
1434 temp2
= expand_binop (submode
, smul_optab
, real0
, imag1
,
1435 NULL_RTX
, unsignedp
, methods
);
1437 if (temp1
== 0 || temp2
== 0)
1440 imag_t
= expand_binop (submode
, sub_optab
, temp1
, temp2
,
1441 NULL_RTX
, unsignedp
, methods
);
1443 if (real_t
== 0 || imag_t
== 0)
1447 if (class == MODE_COMPLEX_FLOAT
)
1448 res
= expand_binop (submode
, binoptab
, real_t
, divisor
,
1449 realr
, unsignedp
, methods
);
1451 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
1452 real_t
, divisor
, realr
, unsignedp
);
1456 else if (res
!= realr
)
1457 emit_move_insn (realr
, res
);
1459 if (class == MODE_COMPLEX_FLOAT
)
1460 res
= expand_binop (submode
, binoptab
, imag_t
, divisor
,
1461 imagr
, unsignedp
, methods
);
1463 res
= expand_divmod (0, TRUNC_DIV_EXPR
, submode
,
1464 imag_t
, divisor
, imagr
, unsignedp
);
1468 else if (res
!= imagr
)
1469 emit_move_insn (imagr
, res
);
1484 if (binoptab
->code
!= UNKNOWN
)
1486 = gen_rtx (binoptab
->code
, mode
, copy_rtx (op0
), copy_rtx (op1
));
1490 emit_no_conflict_block (seq
, target
, op0
, op1
, equiv_value
);
1496 /* It can't be open-coded in this mode.
1497 Use a library call if one is available and caller says that's ok. */
1499 if (binoptab
->handlers
[(int) mode
].libfunc
1500 && (methods
== OPTAB_LIB
|| methods
== OPTAB_LIB_WIDEN
))
1503 rtx funexp
= binoptab
->handlers
[(int) mode
].libfunc
;
1505 enum machine_mode op1_mode
= mode
;
1512 op1_mode
= word_mode
;
1513 /* Specify unsigned here,
1514 since negative shift counts are meaningless. */
1515 op1x
= convert_to_mode (word_mode
, op1
, 1);
1518 if (GET_MODE (op0
) != VOIDmode
1519 && GET_MODE (op0
) != mode
)
1520 op0
= convert_to_mode (mode
, op0
, unsignedp
);
1522 /* Pass 1 for NO_QUEUE so we don't lose any increments
1523 if the libcall is cse'd or moved. */
1524 value
= emit_library_call_value (binoptab
->handlers
[(int) mode
].libfunc
,
1525 NULL_RTX
, 1, mode
, 2,
1526 op0
, mode
, op1x
, op1_mode
);
1528 insns
= get_insns ();
1531 target
= gen_reg_rtx (mode
);
1532 emit_libcall_block (insns
, target
, value
,
1533 gen_rtx (binoptab
->code
, mode
, op0
, op1
));
1538 delete_insns_since (last
);
1540 /* It can't be done in this mode. Can we do it in a wider mode? */
1542 if (! (methods
== OPTAB_WIDEN
|| methods
== OPTAB_LIB_WIDEN
1543 || methods
== OPTAB_MUST_WIDEN
))
1545 /* Caller says, don't even try. */
1546 delete_insns_since (entry_last
);
1550 /* Compute the value of METHODS to pass to recursive calls.
1551 Don't allow widening to be tried recursively. */
1553 methods
= (methods
== OPTAB_LIB_WIDEN
? OPTAB_LIB
: OPTAB_DIRECT
);
1555 /* Look for a wider mode of the same class for which it appears we can do
1558 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1560 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1561 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1563 if ((binoptab
->handlers
[(int) wider_mode
].insn_code
1564 != CODE_FOR_nothing
)
1565 || (methods
== OPTAB_LIB
1566 && binoptab
->handlers
[(int) wider_mode
].libfunc
))
1568 rtx xop0
= op0
, xop1
= op1
;
1571 /* For certain integer operations, we need not actually extend
1572 the narrow operands, as long as we will truncate
1573 the results to the same narrowness. */
1575 if ((binoptab
== ior_optab
|| binoptab
== and_optab
1576 || binoptab
== xor_optab
1577 || binoptab
== add_optab
|| binoptab
== sub_optab
1578 || binoptab
== smul_optab
|| binoptab
== ashl_optab
)
1579 && class == MODE_INT
)
1582 xop0
= widen_operand (xop0
, wider_mode
, mode
,
1583 unsignedp
, no_extend
);
1585 /* The second operand of a shift must always be extended. */
1586 xop1
= widen_operand (xop1
, wider_mode
, mode
, unsignedp
,
1587 no_extend
&& binoptab
!= ashl_optab
);
1589 temp
= expand_binop (wider_mode
, binoptab
, xop0
, xop1
, NULL_RTX
,
1590 unsignedp
, methods
);
1593 if (class != MODE_INT
)
1596 target
= gen_reg_rtx (mode
);
1597 convert_move (target
, temp
, 0);
1601 return gen_lowpart (mode
, temp
);
1604 delete_insns_since (last
);
1609 delete_insns_since (entry_last
);
1613 /* Expand a binary operator which has both signed and unsigned forms.
1614 UOPTAB is the optab for unsigned operations, and SOPTAB is for
1617 If we widen unsigned operands, we may use a signed wider operation instead
1618 of an unsigned wider operation, since the result would be the same. */
1621 sign_expand_binop (mode
, uoptab
, soptab
, op0
, op1
, target
, unsignedp
, methods
)
1622 enum machine_mode mode
;
1623 optab uoptab
, soptab
;
1624 rtx op0
, op1
, target
;
1626 enum optab_methods methods
;
1629 optab direct_optab
= unsignedp
? uoptab
: soptab
;
1630 struct optab wide_soptab
;
1632 /* Do it without widening, if possible. */
1633 temp
= expand_binop (mode
, direct_optab
, op0
, op1
, target
,
1634 unsignedp
, OPTAB_DIRECT
);
1635 if (temp
|| methods
== OPTAB_DIRECT
)
1638 /* Try widening to a signed int. Make a fake signed optab that
1639 hides any signed insn for direct use. */
1640 wide_soptab
= *soptab
;
1641 wide_soptab
.handlers
[(int) mode
].insn_code
= CODE_FOR_nothing
;
1642 wide_soptab
.handlers
[(int) mode
].libfunc
= 0;
1644 temp
= expand_binop (mode
, &wide_soptab
, op0
, op1
, target
,
1645 unsignedp
, OPTAB_WIDEN
);
1647 /* For unsigned operands, try widening to an unsigned int. */
1648 if (temp
== 0 && unsignedp
)
1649 temp
= expand_binop (mode
, uoptab
, op0
, op1
, target
,
1650 unsignedp
, OPTAB_WIDEN
);
1651 if (temp
|| methods
== OPTAB_WIDEN
)
1654 /* Use the right width lib call if that exists. */
1655 temp
= expand_binop (mode
, direct_optab
, op0
, op1
, target
, unsignedp
, OPTAB_LIB
);
1656 if (temp
|| methods
== OPTAB_LIB
)
1659 /* Must widen and use a lib call, use either signed or unsigned. */
1660 temp
= expand_binop (mode
, &wide_soptab
, op0
, op1
, target
,
1661 unsignedp
, methods
);
1665 return expand_binop (mode
, uoptab
, op0
, op1
, target
,
1666 unsignedp
, methods
);
1670 /* Generate code to perform an operation specified by BINOPTAB
1671 on operands OP0 and OP1, with two results to TARG1 and TARG2.
1672 We assume that the order of the operands for the instruction
1673 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
1674 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
1676 Either TARG0 or TARG1 may be zero, but what that means is that
1677 that result is not actually wanted. We will generate it into
1678 a dummy pseudo-reg and discard it. They may not both be zero.
1680 Returns 1 if this operation can be performed; 0 if not. */
1683 expand_twoval_binop (binoptab
, op0
, op1
, targ0
, targ1
, unsignedp
)
1689 enum machine_mode mode
= GET_MODE (targ0
? targ0
: targ1
);
1690 enum mode_class
class;
1691 enum machine_mode wider_mode
;
1692 rtx entry_last
= get_last_insn ();
1695 class = GET_MODE_CLASS (mode
);
1697 op0
= protect_from_queue (op0
, 0);
1698 op1
= protect_from_queue (op1
, 0);
1702 op0
= force_not_mem (op0
);
1703 op1
= force_not_mem (op1
);
1706 /* If we are inside an appropriately-short loop and one operand is an
1707 expensive constant, force it into a register. */
1708 if (CONSTANT_P (op0
) && preserve_subexpressions_p ()
1709 && rtx_cost (op0
, binoptab
->code
) > 2)
1710 op0
= force_reg (mode
, op0
);
1712 if (CONSTANT_P (op1
) && preserve_subexpressions_p ()
1713 && rtx_cost (op1
, binoptab
->code
) > 2)
1714 op1
= force_reg (mode
, op1
);
1717 targ0
= protect_from_queue (targ0
, 1);
1719 targ0
= gen_reg_rtx (mode
);
1721 targ1
= protect_from_queue (targ1
, 1);
1723 targ1
= gen_reg_rtx (mode
);
1725 /* Record where to go back to if we fail. */
1726 last
= get_last_insn ();
1728 if (binoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1730 int icode
= (int) binoptab
->handlers
[(int) mode
].insn_code
;
1731 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
1732 enum machine_mode mode1
= insn_operand_mode
[icode
][2];
1734 rtx xop0
= op0
, xop1
= op1
;
1736 /* In case this insn wants input operands in modes different from the
1737 result, convert the operands. */
1738 if (GET_MODE (op0
) != VOIDmode
&& GET_MODE (op0
) != mode0
)
1739 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
1741 if (GET_MODE (op1
) != VOIDmode
&& GET_MODE (op1
) != mode1
)
1742 xop1
= convert_to_mode (mode1
, xop1
, unsignedp
);
1744 /* Now, if insn doesn't accept these operands, put them into pseudos. */
1745 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
1746 xop0
= copy_to_mode_reg (mode0
, xop0
);
1748 if (! (*insn_operand_predicate
[icode
][2]) (xop1
, mode1
))
1749 xop1
= copy_to_mode_reg (mode1
, xop1
);
1751 /* We could handle this, but we should always be called with a pseudo
1752 for our targets and all insns should take them as outputs. */
1753 if (! (*insn_operand_predicate
[icode
][0]) (targ0
, mode
)
1754 || ! (*insn_operand_predicate
[icode
][3]) (targ1
, mode
))
1757 pat
= GEN_FCN (icode
) (targ0
, xop0
, xop1
, targ1
);
1764 delete_insns_since (last
);
1767 /* It can't be done in this mode. Can we do it in a wider mode? */
1769 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1771 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1772 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1774 if (binoptab
->handlers
[(int) wider_mode
].insn_code
1775 != CODE_FOR_nothing
)
1777 register rtx t0
= gen_reg_rtx (wider_mode
);
1778 register rtx t1
= gen_reg_rtx (wider_mode
);
1780 if (expand_twoval_binop (binoptab
,
1781 convert_modes (wider_mode
, mode
, op0
,
1783 convert_modes (wider_mode
, mode
, op1
,
1787 convert_move (targ0
, t0
, unsignedp
);
1788 convert_move (targ1
, t1
, unsignedp
);
1792 delete_insns_since (last
);
1797 delete_insns_since (entry_last
);
1801 /* Generate code to perform an operation specified by UNOPTAB
1802 on operand OP0, with result having machine-mode MODE.
1804 UNSIGNEDP is for the case where we have to widen the operands
1805 to perform the operation. It says to use zero-extension.
1807 If TARGET is nonzero, the value
1808 is generated there, if it is convenient to do so.
1809 In all cases an rtx is returned for the locus of the value;
1810 this may or may not be TARGET. */
1813 expand_unop (mode
, unoptab
, op0
, target
, unsignedp
)
1814 enum machine_mode mode
;
1820 enum mode_class
class;
1821 enum machine_mode wider_mode
;
1823 rtx last
= get_last_insn ();
1826 class = GET_MODE_CLASS (mode
);
1828 op0
= protect_from_queue (op0
, 0);
1832 op0
= force_not_mem (op0
);
1836 target
= protect_from_queue (target
, 1);
1838 if (unoptab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
1840 int icode
= (int) unoptab
->handlers
[(int) mode
].insn_code
;
1841 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
1847 temp
= gen_reg_rtx (mode
);
1849 if (GET_MODE (xop0
) != VOIDmode
1850 && GET_MODE (xop0
) != mode0
)
1851 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
1853 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
1855 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
1856 xop0
= copy_to_mode_reg (mode0
, xop0
);
1858 if (! (*insn_operand_predicate
[icode
][0]) (temp
, mode
))
1859 temp
= gen_reg_rtx (mode
);
1861 pat
= GEN_FCN (icode
) (temp
, xop0
);
1864 if (GET_CODE (pat
) == SEQUENCE
1865 && ! add_equal_note (pat
, temp
, unoptab
->code
, xop0
, NULL_RTX
))
1867 delete_insns_since (last
);
1868 return expand_unop (mode
, unoptab
, op0
, NULL_RTX
, unsignedp
);
1876 delete_insns_since (last
);
1879 /* It can't be done in this mode. Can we open-code it in a wider mode? */
1881 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
1882 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
1883 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
1885 if (unoptab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
)
1889 /* For certain operations, we need not actually extend
1890 the narrow operand, as long as we will truncate the
1891 results to the same narrowness. */
1893 xop0
= widen_operand (xop0
, wider_mode
, mode
, unsignedp
,
1894 (unoptab
== neg_optab
1895 || unoptab
== one_cmpl_optab
)
1896 && class == MODE_INT
);
1898 temp
= expand_unop (wider_mode
, unoptab
, xop0
, NULL_RTX
,
1903 if (class != MODE_INT
)
1906 target
= gen_reg_rtx (mode
);
1907 convert_move (target
, temp
, 0);
1911 return gen_lowpart (mode
, temp
);
1914 delete_insns_since (last
);
1918 /* These can be done a word at a time. */
1919 if (unoptab
== one_cmpl_optab
1920 && class == MODE_INT
1921 && GET_MODE_SIZE (mode
) > UNITS_PER_WORD
1922 && unoptab
->handlers
[(int) word_mode
].insn_code
!= CODE_FOR_nothing
)
1927 if (target
== 0 || target
== op0
)
1928 target
= gen_reg_rtx (mode
);
1932 /* Do the actual arithmetic. */
1933 for (i
= 0; i
< GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
; i
++)
1935 rtx target_piece
= operand_subword (target
, i
, 1, mode
);
1936 rtx x
= expand_unop (word_mode
, unoptab
,
1937 operand_subword_force (op0
, i
, mode
),
1938 target_piece
, unsignedp
);
1939 if (target_piece
!= x
)
1940 emit_move_insn (target_piece
, x
);
1943 insns
= get_insns ();
1946 emit_no_conflict_block (insns
, target
, op0
, NULL_RTX
,
1947 gen_rtx (unoptab
->code
, mode
, copy_rtx (op0
)));
1951 /* Open-code the complex negation operation. */
1952 else if (unoptab
== neg_optab
1953 && (class == MODE_COMPLEX_FLOAT
|| class == MODE_COMPLEX_INT
))
1959 /* Find the correct mode for the real and imaginary parts */
1960 enum machine_mode submode
1961 = mode_for_size (GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
,
1962 class == MODE_COMPLEX_INT
? MODE_INT
: MODE_FLOAT
,
1965 if (submode
== BLKmode
)
1969 target
= gen_reg_rtx (mode
);
1973 target_piece
= gen_imagpart (submode
, target
);
1974 x
= expand_unop (submode
, unoptab
,
1975 gen_imagpart (submode
, op0
),
1976 target_piece
, unsignedp
);
1977 if (target_piece
!= x
)
1978 emit_move_insn (target_piece
, x
);
1980 target_piece
= gen_realpart (submode
, target
);
1981 x
= expand_unop (submode
, unoptab
,
1982 gen_realpart (submode
, op0
),
1983 target_piece
, unsignedp
);
1984 if (target_piece
!= x
)
1985 emit_move_insn (target_piece
, x
);
1990 emit_no_conflict_block (seq
, target
, op0
, 0,
1991 gen_rtx (unoptab
->code
, mode
, copy_rtx (op0
)));
1995 /* Now try a library call in this mode. */
1996 if (unoptab
->handlers
[(int) mode
].libfunc
)
1999 rtx funexp
= unoptab
->handlers
[(int) mode
].libfunc
;
2004 /* Pass 1 for NO_QUEUE so we don't lose any increments
2005 if the libcall is cse'd or moved. */
2006 value
= emit_library_call_value (unoptab
->handlers
[(int) mode
].libfunc
,
2007 NULL_RTX
, 1, mode
, 1, op0
, mode
);
2008 insns
= get_insns ();
2011 target
= gen_reg_rtx (mode
);
2012 emit_libcall_block (insns
, target
, value
,
2013 gen_rtx (unoptab
->code
, mode
, op0
));
2018 /* It can't be done in this mode. Can we do it in a wider mode? */
2020 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
2022 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2023 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2025 if ((unoptab
->handlers
[(int) wider_mode
].insn_code
2026 != CODE_FOR_nothing
)
2027 || unoptab
->handlers
[(int) wider_mode
].libfunc
)
2031 /* For certain operations, we need not actually extend
2032 the narrow operand, as long as we will truncate the
2033 results to the same narrowness. */
2035 xop0
= widen_operand (xop0
, wider_mode
, mode
, unsignedp
,
2036 (unoptab
== neg_optab
2037 || unoptab
== one_cmpl_optab
)
2038 && class == MODE_INT
);
2040 temp
= expand_unop (wider_mode
, unoptab
, xop0
, NULL_RTX
,
2045 if (class != MODE_INT
)
2048 target
= gen_reg_rtx (mode
);
2049 convert_move (target
, temp
, 0);
2053 return gen_lowpart (mode
, temp
);
2056 delete_insns_since (last
);
2061 /* If there is no negate operation, try doing a subtract from zero.
2062 The US Software GOFAST library needs this. */
2063 if (unoptab
== neg_optab
)
2066 temp
= expand_binop (mode
, sub_optab
, CONST0_RTX (mode
), op0
,
2067 target
, unsignedp
, OPTAB_LIB_WIDEN
);
2075 /* Emit code to compute the absolute value of OP0, with result to
2076 TARGET if convenient. (TARGET may be 0.) The return value says
2077 where the result actually is to be found.
2079 MODE is the mode of the operand; the mode of the result is
2080 different but can be deduced from MODE.
2082 UNSIGNEDP is relevant if extension is needed. */
2085 expand_abs (mode
, op0
, target
, unsignedp
, safe
)
2086 enum machine_mode mode
;
2094 /* First try to do it with a special abs instruction. */
2095 temp
= expand_unop (mode
, abs_optab
, op0
, target
, 0);
2099 /* If this machine has expensive jumps, we can do integer absolute
2100 value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
2101 where W is the width of MODE. */
2103 if (GET_MODE_CLASS (mode
) == MODE_INT
&& BRANCH_COST
>= 2)
2105 rtx extended
= expand_shift (RSHIFT_EXPR
, mode
, op0
,
2106 size_int (GET_MODE_BITSIZE (mode
) - 1),
2109 temp
= expand_binop (mode
, xor_optab
, extended
, op0
, target
, 0,
2112 temp
= expand_binop (mode
, sub_optab
, temp
, extended
, target
, 0,
2119 /* If that does not win, use conditional jump and negate. */
2121 /* It is safe to use the target if it is the same
2122 as the source if this is also a pseudo register */
2123 if (op0
== target
&& GET_CODE (op0
) == REG
2124 && REGNO (op0
) >= FIRST_PSEUDO_REGISTER
)
2127 op1
= gen_label_rtx ();
2128 if (target
== 0 || ! safe
2129 || GET_MODE (target
) != mode
2130 || (GET_CODE (target
) == MEM
&& MEM_VOLATILE_P (target
))
2131 || (GET_CODE (target
) == REG
2132 && REGNO (target
) < FIRST_PSEUDO_REGISTER
))
2133 target
= gen_reg_rtx (mode
);
2135 emit_move_insn (target
, op0
);
2138 /* If this mode is an integer too wide to compare properly,
2139 compare word by word. Rely on CSE to optimize constant cases. */
2140 if (GET_MODE_CLASS (mode
) == MODE_INT
&& ! can_compare_p (mode
))
2141 do_jump_by_parts_greater_rtx (mode
, 0, target
, const0_rtx
,
2145 temp
= compare_from_rtx (target
, CONST0_RTX (mode
), GE
, 0, mode
,
2147 if (temp
== const1_rtx
)
2149 else if (temp
!= const0_rtx
)
2151 if (bcc_gen_fctn
[(int) GET_CODE (temp
)] != 0)
2152 emit_jump_insn ((*bcc_gen_fctn
[(int) GET_CODE (temp
)]) (op1
));
2158 op0
= expand_unop (mode
, neg_optab
, target
, target
, 0);
2160 emit_move_insn (target
, op0
);
2166 /* Emit code to compute the absolute value of OP0, with result to
2167 TARGET if convenient. (TARGET may be 0.) The return value says
2168 where the result actually is to be found.
2170 MODE is the mode of the operand; the mode of the result is
2171 different but can be deduced from MODE.
2173 UNSIGNEDP is relevant for complex integer modes. */
2176 expand_complex_abs (mode
, op0
, target
, unsignedp
)
2177 enum machine_mode mode
;
2182 enum mode_class
class = GET_MODE_CLASS (mode
);
2183 enum machine_mode wider_mode
;
2185 rtx entry_last
= get_last_insn ();
2189 /* Find the correct mode for the real and imaginary parts. */
2190 enum machine_mode submode
2191 = mode_for_size (GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
,
2192 class == MODE_COMPLEX_INT
? MODE_INT
: MODE_FLOAT
,
2195 if (submode
== BLKmode
)
2198 op0
= protect_from_queue (op0
, 0);
2202 op0
= force_not_mem (op0
);
2205 last
= get_last_insn ();
2208 target
= protect_from_queue (target
, 1);
2210 if (abs_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
2212 int icode
= (int) abs_optab
->handlers
[(int) mode
].insn_code
;
2213 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
2219 temp
= gen_reg_rtx (submode
);
2221 if (GET_MODE (xop0
) != VOIDmode
2222 && GET_MODE (xop0
) != mode0
)
2223 xop0
= convert_to_mode (mode0
, xop0
, unsignedp
);
2225 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
2227 if (! (*insn_operand_predicate
[icode
][1]) (xop0
, mode0
))
2228 xop0
= copy_to_mode_reg (mode0
, xop0
);
2230 if (! (*insn_operand_predicate
[icode
][0]) (temp
, submode
))
2231 temp
= gen_reg_rtx (submode
);
2233 pat
= GEN_FCN (icode
) (temp
, xop0
);
2236 if (GET_CODE (pat
) == SEQUENCE
2237 && ! add_equal_note (pat
, temp
, abs_optab
->code
, xop0
, NULL_RTX
))
2239 delete_insns_since (last
);
2240 return expand_unop (mode
, abs_optab
, op0
, NULL_RTX
, unsignedp
);
2248 delete_insns_since (last
);
2251 /* It can't be done in this mode. Can we open-code it in a wider mode? */
2253 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2254 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2256 if (abs_optab
->handlers
[(int) wider_mode
].insn_code
!= CODE_FOR_nothing
)
2260 xop0
= convert_modes (wider_mode
, mode
, xop0
, unsignedp
);
2261 temp
= expand_complex_abs (wider_mode
, xop0
, NULL_RTX
, unsignedp
);
2265 if (class != MODE_COMPLEX_INT
)
2268 target
= gen_reg_rtx (submode
);
2269 convert_move (target
, temp
, 0);
2273 return gen_lowpart (submode
, temp
);
2276 delete_insns_since (last
);
2280 /* Open-code the complex absolute-value operation
2281 if we can open-code sqrt. Otherwise it's not worth while. */
2282 if (sqrt_optab
->handlers
[(int) submode
].insn_code
!= CODE_FOR_nothing
)
2284 rtx real
, imag
, total
;
2286 real
= gen_realpart (submode
, op0
);
2287 imag
= gen_imagpart (submode
, op0
);
2289 /* Square both parts. */
2290 real
= expand_mult (submode
, real
, real
, NULL_RTX
, 0);
2291 imag
= expand_mult (submode
, imag
, imag
, NULL_RTX
, 0);
2293 /* Sum the parts. */
2294 total
= expand_binop (submode
, add_optab
, real
, imag
, NULL_RTX
,
2295 0, OPTAB_LIB_WIDEN
);
2297 /* Get sqrt in TARGET. Set TARGET to where the result is. */
2298 target
= expand_unop (submode
, sqrt_optab
, total
, target
, 0);
2300 delete_insns_since (last
);
2305 /* Now try a library call in this mode. */
2306 if (abs_optab
->handlers
[(int) mode
].libfunc
)
2309 rtx funexp
= abs_optab
->handlers
[(int) mode
].libfunc
;
2314 /* Pass 1 for NO_QUEUE so we don't lose any increments
2315 if the libcall is cse'd or moved. */
2316 value
= emit_library_call_value (abs_optab
->handlers
[(int) mode
].libfunc
,
2317 NULL_RTX
, 1, submode
, 1, op0
, mode
);
2318 insns
= get_insns ();
2321 target
= gen_reg_rtx (submode
);
2322 emit_libcall_block (insns
, target
, value
,
2323 gen_rtx (abs_optab
->code
, mode
, op0
));
2328 /* It can't be done in this mode. Can we do it in a wider mode? */
2330 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2331 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2333 if ((abs_optab
->handlers
[(int) wider_mode
].insn_code
2334 != CODE_FOR_nothing
)
2335 || abs_optab
->handlers
[(int) wider_mode
].libfunc
)
2339 xop0
= convert_modes (wider_mode
, mode
, xop0
, unsignedp
);
2341 temp
= expand_complex_abs (wider_mode
, xop0
, NULL_RTX
, unsignedp
);
2345 if (class != MODE_COMPLEX_INT
)
2348 target
= gen_reg_rtx (submode
);
2349 convert_move (target
, temp
, 0);
2353 return gen_lowpart (submode
, temp
);
2356 delete_insns_since (last
);
2360 delete_insns_since (entry_last
);
2364 /* Generate an instruction whose insn-code is INSN_CODE,
2365 with two operands: an output TARGET and an input OP0.
2366 TARGET *must* be nonzero, and the output is always stored there.
2367 CODE is an rtx code such that (CODE OP0) is an rtx that describes
2368 the value that is stored into TARGET. */
2371 emit_unop_insn (icode
, target
, op0
, code
)
2378 enum machine_mode mode0
= insn_operand_mode
[icode
][1];
2381 temp
= target
= protect_from_queue (target
, 1);
2383 op0
= protect_from_queue (op0
, 0);
2385 /* Sign extension from memory is often done specially on RISC
2386 machines, so forcing into a register here can pessimize code. */
2387 if (flag_force_mem
&& code
!= SIGN_EXTEND
)
2388 op0
= force_not_mem (op0
);
2390 /* Now, if insn does not accept our operands, put them into pseudos. */
2392 if (! (*insn_operand_predicate
[icode
][1]) (op0
, mode0
))
2393 op0
= copy_to_mode_reg (mode0
, op0
);
2395 if (! (*insn_operand_predicate
[icode
][0]) (temp
, GET_MODE (temp
))
2396 || (flag_force_mem
&& GET_CODE (temp
) == MEM
))
2397 temp
= gen_reg_rtx (GET_MODE (temp
));
2399 pat
= GEN_FCN (icode
) (temp
, op0
);
2401 if (GET_CODE (pat
) == SEQUENCE
&& code
!= UNKNOWN
)
2402 add_equal_note (pat
, temp
, code
, op0
, NULL_RTX
);
2407 emit_move_insn (target
, temp
);
2410 /* Emit code to perform a series of operations on a multi-word quantity, one
2413 Such a block is preceded by a CLOBBER of the output, consists of multiple
2414 insns, each setting one word of the output, and followed by a SET copying
2415 the output to itself.
2417 Each of the insns setting words of the output receives a REG_NO_CONFLICT
2418 note indicating that it doesn't conflict with the (also multi-word)
2419 inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
2422 INSNS is a block of code generated to perform the operation, not including
2423 the CLOBBER and final copy. All insns that compute intermediate values
2424 are first emitted, followed by the block as described above.
2426 TARGET, OP0, and OP1 are the output and inputs of the operations,
2427 respectively. OP1 may be zero for a unary operation.
2429 EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
2432 If TARGET is not a register, INSNS is simply emitted with no special
2433 processing. Likewise if anything in INSNS is not an INSN or if
2434 there is a libcall block inside INSNS.
2436 The final insn emitted is returned. */
2439 emit_no_conflict_block (insns
, target
, op0
, op1
, equiv
)
2445 rtx prev
, next
, first
, last
, insn
;
2447 if (GET_CODE (target
) != REG
|| reload_in_progress
)
2448 return emit_insns (insns
);
2450 for (insn
= insns
; insn
; insn
= NEXT_INSN (insn
))
2451 if (GET_CODE (insn
) != INSN
2452 || find_reg_note (insn
, REG_LIBCALL
, NULL_RTX
))
2453 return emit_insns (insns
);
2455 /* First emit all insns that do not store into words of the output and remove
2456 these from the list. */
2457 for (insn
= insns
; insn
; insn
= next
)
2462 next
= NEXT_INSN (insn
);
2464 if (GET_CODE (PATTERN (insn
)) == SET
)
2465 set
= PATTERN (insn
);
2466 else if (GET_CODE (PATTERN (insn
)) == PARALLEL
)
2468 for (i
= 0; i
< XVECLEN (PATTERN (insn
), 0); i
++)
2469 if (GET_CODE (XVECEXP (PATTERN (insn
), 0, i
)) == SET
)
2471 set
= XVECEXP (PATTERN (insn
), 0, i
);
2479 if (! reg_overlap_mentioned_p (target
, SET_DEST (set
)))
2481 if (PREV_INSN (insn
))
2482 NEXT_INSN (PREV_INSN (insn
)) = next
;
2487 PREV_INSN (next
) = PREV_INSN (insn
);
2493 prev
= get_last_insn ();
2495 /* Now write the CLOBBER of the output, followed by the setting of each
2496 of the words, followed by the final copy. */
2497 if (target
!= op0
&& target
!= op1
)
2498 emit_insn (gen_rtx (CLOBBER
, VOIDmode
, target
));
2500 for (insn
= insns
; insn
; insn
= next
)
2502 next
= NEXT_INSN (insn
);
2505 if (op1
&& GET_CODE (op1
) == REG
)
2506 REG_NOTES (insn
) = gen_rtx (EXPR_LIST
, REG_NO_CONFLICT
, op1
,
2509 if (op0
&& GET_CODE (op0
) == REG
)
2510 REG_NOTES (insn
) = gen_rtx (EXPR_LIST
, REG_NO_CONFLICT
, op0
,
2514 if (mov_optab
->handlers
[(int) GET_MODE (target
)].insn_code
2515 != CODE_FOR_nothing
)
2517 last
= emit_move_insn (target
, target
);
2520 = gen_rtx (EXPR_LIST
, REG_EQUAL
, equiv
, REG_NOTES (last
));
2523 last
= get_last_insn ();
2526 first
= get_insns ();
2528 first
= NEXT_INSN (prev
);
2530 /* Encapsulate the block so it gets manipulated as a unit. */
2531 REG_NOTES (first
) = gen_rtx (INSN_LIST
, REG_LIBCALL
, last
,
2533 REG_NOTES (last
) = gen_rtx (INSN_LIST
, REG_RETVAL
, first
, REG_NOTES (last
));
2538 /* Emit code to make a call to a constant function or a library call.
2540 INSNS is a list containing all insns emitted in the call.
2541 These insns leave the result in RESULT. Our block is to copy RESULT
2542 to TARGET, which is logically equivalent to EQUIV.
2544 We first emit any insns that set a pseudo on the assumption that these are
2545 loading constants into registers; doing so allows them to be safely cse'ed
2546 between blocks. Then we emit all the other insns in the block, followed by
2547 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
2548 note with an operand of EQUIV.
2550 Moving assignments to pseudos outside of the block is done to improve
2551 the generated code, but is not required to generate correct code,
2552 hence being unable to move an assignment is not grounds for not making
2553 a libcall block. There are two reasons why it is safe to leave these
2554 insns inside the block: First, we know that these pseudos cannot be
2555 used in generated RTL outside the block since they are created for
2556 temporary purposes within the block. Second, CSE will not record the
2557 values of anything set inside a libcall block, so we know they must
2558 be dead at the end of the block.
2560 Except for the first group of insns (the ones setting pseudos), the
2561 block is delimited by REG_RETVAL and REG_LIBCALL notes. */
2564 emit_libcall_block (insns
, target
, result
, equiv
)
2570 rtx prev
, next
, first
, last
, insn
;
2572 /* First emit all insns that set pseudos. Remove them from the list as
2573 we go. Avoid insns that set pseudos which were referenced in previous
2574 insns. These can be generated by move_by_pieces, for example,
2575 to update an address. Similarly, avoid insns that reference things
2576 set in previous insns. */
2578 for (insn
= insns
; insn
; insn
= next
)
2580 rtx set
= single_set (insn
);
2582 next
= NEXT_INSN (insn
);
2584 if (set
!= 0 && GET_CODE (SET_DEST (set
)) == REG
2585 && REGNO (SET_DEST (set
)) >= FIRST_PSEUDO_REGISTER
2587 || (! reg_mentioned_p (SET_DEST (set
), PATTERN (insns
))
2588 && ! reg_used_between_p (SET_DEST (set
), insns
, insn
)
2589 && ! modified_in_p (SET_SRC (set
), insns
)
2590 && ! modified_between_p (SET_SRC (set
), insns
, insn
))))
2592 if (PREV_INSN (insn
))
2593 NEXT_INSN (PREV_INSN (insn
)) = next
;
2598 PREV_INSN (next
) = PREV_INSN (insn
);
2604 prev
= get_last_insn ();
2606 /* Write the remaining insns followed by the final copy. */
2608 for (insn
= insns
; insn
; insn
= next
)
2610 next
= NEXT_INSN (insn
);
2615 last
= emit_move_insn (target
, result
);
2616 REG_NOTES (last
) = gen_rtx (EXPR_LIST
,
2617 REG_EQUAL
, copy_rtx (equiv
), REG_NOTES (last
));
2620 first
= get_insns ();
2622 first
= NEXT_INSN (prev
);
2624 /* Encapsulate the block so it gets manipulated as a unit. */
2625 REG_NOTES (first
) = gen_rtx (INSN_LIST
, REG_LIBCALL
, last
,
2627 REG_NOTES (last
) = gen_rtx (INSN_LIST
, REG_RETVAL
, first
, REG_NOTES (last
));
2630 /* Generate code to store zero in X. */
2636 emit_move_insn (x
, const0_rtx
);
2639 /* Generate code to store 1 in X
2640 assuming it contains zero beforehand. */
2643 emit_0_to_1_insn (x
)
2646 emit_move_insn (x
, const1_rtx
);
2649 /* Generate code to compare X with Y
2650 so that the condition codes are set.
2652 MODE is the mode of the inputs (in case they are const_int).
2653 UNSIGNEDP nonzero says that X and Y are unsigned;
2654 this matters if they need to be widened.
2656 If they have mode BLKmode, then SIZE specifies the size of both X and Y,
2657 and ALIGN specifies the known shared alignment of X and Y.
2659 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
2660 It is ignored for fixed-point and block comparisons;
2661 it is used only for floating-point comparisons. */
2664 emit_cmp_insn (x
, y
, comparison
, size
, mode
, unsignedp
, align
)
2666 enum rtx_code comparison
;
2668 enum machine_mode mode
;
2672 enum mode_class
class;
2673 enum machine_mode wider_mode
;
2675 class = GET_MODE_CLASS (mode
);
2677 /* They could both be VOIDmode if both args are immediate constants,
2678 but we should fold that at an earlier stage.
2679 With no special code here, this will call abort,
2680 reminding the programmer to implement such folding. */
2682 if (mode
!= BLKmode
&& flag_force_mem
)
2684 x
= force_not_mem (x
);
2685 y
= force_not_mem (y
);
2688 /* If we are inside an appropriately-short loop and one operand is an
2689 expensive constant, force it into a register. */
2690 if (CONSTANT_P (x
) && preserve_subexpressions_p () && rtx_cost (x
, COMPARE
) > 2)
2691 x
= force_reg (mode
, x
);
2693 if (CONSTANT_P (y
) && preserve_subexpressions_p () && rtx_cost (y
, COMPARE
) > 2)
2694 y
= force_reg (mode
, y
);
2696 /* Don't let both operands fail to indicate the mode. */
2697 if (GET_MODE (x
) == VOIDmode
&& GET_MODE (y
) == VOIDmode
)
2698 x
= force_reg (mode
, x
);
2700 /* Handle all BLKmode compares. */
2702 if (mode
== BLKmode
)
2705 x
= protect_from_queue (x
, 0);
2706 y
= protect_from_queue (y
, 0);
2710 #ifdef HAVE_cmpstrqi
2712 && GET_CODE (size
) == CONST_INT
2713 && INTVAL (size
) < (1 << GET_MODE_BITSIZE (QImode
)))
2715 enum machine_mode result_mode
2716 = insn_operand_mode
[(int) CODE_FOR_cmpstrqi
][0];
2717 rtx result
= gen_reg_rtx (result_mode
);
2718 emit_insn (gen_cmpstrqi (result
, x
, y
, size
, GEN_INT (align
)));
2719 emit_cmp_insn (result
, const0_rtx
, comparison
, NULL_RTX
,
2724 #ifdef HAVE_cmpstrhi
2726 && GET_CODE (size
) == CONST_INT
2727 && INTVAL (size
) < (1 << GET_MODE_BITSIZE (HImode
)))
2729 enum machine_mode result_mode
2730 = insn_operand_mode
[(int) CODE_FOR_cmpstrhi
][0];
2731 rtx result
= gen_reg_rtx (result_mode
);
2732 emit_insn (gen_cmpstrhi (result
, x
, y
, size
, GEN_INT (align
)));
2733 emit_cmp_insn (result
, const0_rtx
, comparison
, NULL_RTX
,
2738 #ifdef HAVE_cmpstrsi
2741 enum machine_mode result_mode
2742 = insn_operand_mode
[(int) CODE_FOR_cmpstrsi
][0];
2743 rtx result
= gen_reg_rtx (result_mode
);
2744 size
= protect_from_queue (size
, 0);
2745 emit_insn (gen_cmpstrsi (result
, x
, y
,
2746 convert_to_mode (SImode
, size
, 1),
2748 emit_cmp_insn (result
, const0_rtx
, comparison
, NULL_RTX
,
2756 #ifdef TARGET_MEM_FUNCTIONS
2757 emit_library_call (memcmp_libfunc
, 0,
2758 TYPE_MODE (integer_type_node
), 3,
2759 XEXP (x
, 0), Pmode
, XEXP (y
, 0), Pmode
,
2760 convert_to_mode (TYPE_MODE (sizetype
), size
,
2761 TREE_UNSIGNED (sizetype
)),
2762 TYPE_MODE (sizetype
));
2764 emit_library_call (bcmp_libfunc
, 0,
2765 TYPE_MODE (integer_type_node
), 3,
2766 XEXP (x
, 0), Pmode
, XEXP (y
, 0), Pmode
,
2767 convert_to_mode (TYPE_MODE (integer_type_node
),
2769 TREE_UNSIGNED (integer_type_node
)),
2770 TYPE_MODE (integer_type_node
));
2773 /* Immediately move the result of the libcall into a pseudo
2774 register so reload doesn't clobber the value if it needs
2775 the return register for a spill reg. */
2776 result
= gen_reg_rtx (TYPE_MODE (integer_type_node
));
2777 emit_move_insn (result
,
2778 hard_libcall_value (TYPE_MODE (integer_type_node
)));
2779 emit_cmp_insn (result
,
2780 const0_rtx
, comparison
, NULL_RTX
,
2781 TYPE_MODE (integer_type_node
), 0, 0);
2786 /* Handle some compares against zero. */
2788 if (y
== CONST0_RTX (mode
)
2789 && tst_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
2791 int icode
= (int) tst_optab
->handlers
[(int) mode
].insn_code
;
2794 x
= protect_from_queue (x
, 0);
2795 y
= protect_from_queue (y
, 0);
2797 /* Now, if insn does accept these operands, put them into pseudos. */
2798 if (! (*insn_operand_predicate
[icode
][0])
2799 (x
, insn_operand_mode
[icode
][0]))
2800 x
= copy_to_mode_reg (insn_operand_mode
[icode
][0], x
);
2802 emit_insn (GEN_FCN (icode
) (x
));
2806 /* Handle compares for which there is a directly suitable insn. */
2808 if (cmp_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
)
2810 int icode
= (int) cmp_optab
->handlers
[(int) mode
].insn_code
;
2813 x
= protect_from_queue (x
, 0);
2814 y
= protect_from_queue (y
, 0);
2816 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2817 if (! (*insn_operand_predicate
[icode
][0])
2818 (x
, insn_operand_mode
[icode
][0]))
2819 x
= copy_to_mode_reg (insn_operand_mode
[icode
][0], x
);
2821 if (! (*insn_operand_predicate
[icode
][1])
2822 (y
, insn_operand_mode
[icode
][1]))
2823 y
= copy_to_mode_reg (insn_operand_mode
[icode
][1], y
);
2825 emit_insn (GEN_FCN (icode
) (x
, y
));
2829 /* Try widening if we can find a direct insn that way. */
2831 if (class == MODE_INT
|| class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
)
2833 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
2834 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
2836 if (cmp_optab
->handlers
[(int) wider_mode
].insn_code
2837 != CODE_FOR_nothing
)
2839 x
= protect_from_queue (x
, 0);
2840 y
= protect_from_queue (y
, 0);
2841 x
= convert_modes (wider_mode
, mode
, x
, unsignedp
);
2842 y
= convert_modes (wider_mode
, mode
, y
, unsignedp
);
2843 emit_cmp_insn (x
, y
, comparison
, NULL_RTX
,
2844 wider_mode
, unsignedp
, align
);
2850 /* Handle a lib call just for the mode we are using. */
2852 if (cmp_optab
->handlers
[(int) mode
].libfunc
2853 && class != MODE_FLOAT
)
2855 rtx libfunc
= cmp_optab
->handlers
[(int) mode
].libfunc
;
2858 /* If we want unsigned, and this mode has a distinct unsigned
2859 comparison routine, use that. */
2860 if (unsignedp
&& ucmp_optab
->handlers
[(int) mode
].libfunc
)
2861 libfunc
= ucmp_optab
->handlers
[(int) mode
].libfunc
;
2863 emit_library_call (libfunc
, 1,
2864 word_mode
, 2, x
, mode
, y
, mode
);
2866 /* Immediately move the result of the libcall into a pseudo
2867 register so reload doesn't clobber the value if it needs
2868 the return register for a spill reg. */
2869 result
= gen_reg_rtx (word_mode
);
2870 emit_move_insn (result
, hard_libcall_value (word_mode
));
2872 /* Integer comparison returns a result that must be compared against 1,
2873 so that even if we do an unsigned compare afterward,
2874 there is still a value that can represent the result "less than". */
2875 emit_cmp_insn (result
, const1_rtx
,
2876 comparison
, NULL_RTX
, word_mode
, unsignedp
, 0);
2880 if (class == MODE_FLOAT
)
2881 emit_float_lib_cmp (x
, y
, comparison
);
2887 /* Nonzero if a compare of mode MODE can be done straightforwardly
2888 (without splitting it into pieces). */
2891 can_compare_p (mode
)
2892 enum machine_mode mode
;
2896 if (cmp_optab
->handlers
[(int)mode
].insn_code
!= CODE_FOR_nothing
)
2898 mode
= GET_MODE_WIDER_MODE (mode
);
2899 } while (mode
!= VOIDmode
);
2904 /* Emit a library call comparison between floating point X and Y.
2905 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
2908 emit_float_lib_cmp (x
, y
, comparison
)
2910 enum rtx_code comparison
;
2912 enum machine_mode mode
= GET_MODE (x
);
2920 libfunc
= eqhf2_libfunc
;
2924 libfunc
= nehf2_libfunc
;
2928 libfunc
= gthf2_libfunc
;
2932 libfunc
= gehf2_libfunc
;
2936 libfunc
= lthf2_libfunc
;
2940 libfunc
= lehf2_libfunc
;
2943 else if (mode
== SFmode
)
2947 libfunc
= eqsf2_libfunc
;
2951 libfunc
= nesf2_libfunc
;
2955 libfunc
= gtsf2_libfunc
;
2959 libfunc
= gesf2_libfunc
;
2963 libfunc
= ltsf2_libfunc
;
2967 libfunc
= lesf2_libfunc
;
2970 else if (mode
== DFmode
)
2974 libfunc
= eqdf2_libfunc
;
2978 libfunc
= nedf2_libfunc
;
2982 libfunc
= gtdf2_libfunc
;
2986 libfunc
= gedf2_libfunc
;
2990 libfunc
= ltdf2_libfunc
;
2994 libfunc
= ledf2_libfunc
;
2997 else if (mode
== XFmode
)
3001 libfunc
= eqxf2_libfunc
;
3005 libfunc
= nexf2_libfunc
;
3009 libfunc
= gtxf2_libfunc
;
3013 libfunc
= gexf2_libfunc
;
3017 libfunc
= ltxf2_libfunc
;
3021 libfunc
= lexf2_libfunc
;
3024 else if (mode
== TFmode
)
3028 libfunc
= eqtf2_libfunc
;
3032 libfunc
= netf2_libfunc
;
3036 libfunc
= gttf2_libfunc
;
3040 libfunc
= getf2_libfunc
;
3044 libfunc
= lttf2_libfunc
;
3048 libfunc
= letf2_libfunc
;
3053 enum machine_mode wider_mode
;
3055 for (wider_mode
= GET_MODE_WIDER_MODE (mode
); wider_mode
!= VOIDmode
;
3056 wider_mode
= GET_MODE_WIDER_MODE (wider_mode
))
3058 if ((cmp_optab
->handlers
[(int) wider_mode
].insn_code
3059 != CODE_FOR_nothing
)
3060 || (cmp_optab
->handlers
[(int) wider_mode
].libfunc
!= 0))
3062 x
= protect_from_queue (x
, 0);
3063 y
= protect_from_queue (y
, 0);
3064 x
= convert_to_mode (wider_mode
, x
, 0);
3065 y
= convert_to_mode (wider_mode
, y
, 0);
3066 emit_float_lib_cmp (x
, y
, comparison
);
3076 emit_library_call (libfunc
, 1,
3077 word_mode
, 2, x
, mode
, y
, mode
);
3079 /* Immediately move the result of the libcall into a pseudo
3080 register so reload doesn't clobber the value if it needs
3081 the return register for a spill reg. */
3082 result
= gen_reg_rtx (word_mode
);
3083 emit_move_insn (result
, hard_libcall_value (word_mode
));
3085 emit_cmp_insn (result
, const0_rtx
, comparison
,
3086 NULL_RTX
, word_mode
, 0, 0);
3089 /* Generate code to indirectly jump to a location given in the rtx LOC. */
3092 emit_indirect_jump (loc
)
3095 if (! ((*insn_operand_predicate
[(int)CODE_FOR_indirect_jump
][0])
3097 loc
= copy_to_mode_reg (Pmode
, loc
);
3099 emit_jump_insn (gen_indirect_jump (loc
));
3103 #ifdef HAVE_conditional_move
3105 /* Emit a conditional move instruction if the machine supports one for that
3106 condition and machine mode.
3108 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
3109 the mode to use should they be constants. If it is VOIDmode, they cannot
3112 OP2 should be stored in TARGET if the comparison is true, otherwise OP3
3113 should be stored there. MODE is the mode to use should they be constants.
3114 If it is VOIDmode, they cannot both be constants.
3116 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
3117 is not supported. */
3120 emit_conditional_move (target
, code
, op0
, op1
, cmode
, op2
, op3
, mode
,
3125 enum machine_mode cmode
;
3127 enum machine_mode mode
;
3130 rtx tem
, subtarget
, comparison
, insn
;
3131 enum insn_code icode
;
3133 /* If one operand is constant, make it the second one. Only do this
3134 if the other operand is not constant as well. */
3136 if ((CONSTANT_P (op0
) && ! CONSTANT_P (op1
))
3137 || (GET_CODE (op0
) == CONST_INT
&& GET_CODE (op1
) != CONST_INT
))
3142 code
= swap_condition (code
);
3145 if (cmode
== VOIDmode
)
3146 cmode
= GET_MODE (op0
);
3148 if ((CONSTANT_P (op2
) && ! CONSTANT_P (op3
))
3149 || (GET_CODE (op2
) == CONST_INT
&& GET_CODE (op3
) != CONST_INT
))
3154 /* ??? This may not be appropriate (consider IEEE). Perhaps we should
3155 call can_reverse_comparison_p here and bail out if necessary.
3156 It's not clear whether we need to do this canonicalization though. */
3157 code
= reverse_condition (code
);
3160 if (mode
== VOIDmode
)
3161 mode
= GET_MODE (op2
);
3163 icode
= movcc_gen_code
[mode
];
3165 if (icode
== CODE_FOR_nothing
)
3170 op2
= force_not_mem (op2
);
3171 op3
= force_not_mem (op3
);
3175 target
= protect_from_queue (target
, 1);
3177 target
= gen_reg_rtx (mode
);
3183 op2
= protect_from_queue (op2
, 0);
3184 op3
= protect_from_queue (op3
, 0);
3186 /* If the insn doesn't accept these operands, put them in pseudos. */
3188 if (! (*insn_operand_predicate
[icode
][0])
3189 (subtarget
, insn_operand_mode
[icode
][0]))
3190 subtarget
= gen_reg_rtx (insn_operand_mode
[icode
][0]);
3192 if (! (*insn_operand_predicate
[icode
][2])
3193 (op2
, insn_operand_mode
[icode
][2]))
3194 op2
= copy_to_mode_reg (insn_operand_mode
[icode
][2], op2
);
3196 if (! (*insn_operand_predicate
[icode
][3])
3197 (op3
, insn_operand_mode
[icode
][3]))
3198 op3
= copy_to_mode_reg (insn_operand_mode
[icode
][3], op3
);
3200 /* Everything should now be in the suitable form, so emit the compare insn
3201 and then the conditional move. */
3204 = compare_from_rtx (op0
, op1
, code
, unsignedp
, cmode
, NULL_RTX
, 0);
3206 /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)? */
3207 if (GET_CODE (comparison
) != code
)
3208 /* This shouldn't happen. */
3211 insn
= GEN_FCN (icode
) (subtarget
, comparison
, op2
, op3
);
3213 /* If that failed, then give up. */
3219 if (subtarget
!= target
)
3220 convert_move (target
, subtarget
, 0);
3225 /* Return non-zero if a conditional move of mode MODE is supported.
3227 This function is for combine so it can tell whether an insn that looks
3228 like a conditional move is actually supported by the hardware. If we
3229 guess wrong we lose a bit on optimization, but that's it. */
3230 /* ??? sparc64 supports conditionally moving integers values based on fp
3231 comparisons, and vice versa. How do we handle them? */
3234 can_conditionally_move_p (mode
)
3235 enum machine_mode mode
;
3237 if (movcc_gen_code
[mode
] != CODE_FOR_nothing
)
3243 #endif /* HAVE_conditional_move */
3245 /* These three functions generate an insn body and return it
3246 rather than emitting the insn.
3248 They do not protect from queued increments,
3249 because they may be used 1) in protect_from_queue itself
3250 and 2) in other passes where there is no queue. */
3252 /* Generate and return an insn body to add Y to X. */
3255 gen_add2_insn (x
, y
)
3258 int icode
= (int) add_optab
->handlers
[(int) GET_MODE (x
)].insn_code
;
3260 if (! (*insn_operand_predicate
[icode
][0]) (x
, insn_operand_mode
[icode
][0])
3261 || ! (*insn_operand_predicate
[icode
][1]) (x
, insn_operand_mode
[icode
][1])
3262 || ! (*insn_operand_predicate
[icode
][2]) (y
, insn_operand_mode
[icode
][2]))
3265 return (GEN_FCN (icode
) (x
, x
, y
));
3269 have_add2_insn (mode
)
3270 enum machine_mode mode
;
3272 return add_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
;
3275 /* Generate and return an insn body to subtract Y from X. */
3278 gen_sub2_insn (x
, y
)
3281 int icode
= (int) sub_optab
->handlers
[(int) GET_MODE (x
)].insn_code
;
3283 if (! (*insn_operand_predicate
[icode
][0]) (x
, insn_operand_mode
[icode
][0])
3284 || ! (*insn_operand_predicate
[icode
][1]) (x
, insn_operand_mode
[icode
][1])
3285 || ! (*insn_operand_predicate
[icode
][2]) (y
, insn_operand_mode
[icode
][2]))
3288 return (GEN_FCN (icode
) (x
, x
, y
));
3292 have_sub2_insn (mode
)
3293 enum machine_mode mode
;
3295 return sub_optab
->handlers
[(int) mode
].insn_code
!= CODE_FOR_nothing
;
3298 /* Generate the body of an instruction to copy Y into X.
3299 It may be a SEQUENCE, if one insn isn't enough. */
3302 gen_move_insn (x
, y
)
3305 register enum machine_mode mode
= GET_MODE (x
);
3306 enum insn_code insn_code
;
3309 if (mode
== VOIDmode
)
3310 mode
= GET_MODE (y
);
3312 insn_code
= mov_optab
->handlers
[(int) mode
].insn_code
;
3314 /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
3315 find a mode to do it in. If we have a movcc, use it. Otherwise,
3316 find the MODE_INT mode of the same width. */
3318 if (GET_MODE_CLASS (mode
) == MODE_CC
&& insn_code
== CODE_FOR_nothing
)
3320 enum machine_mode tmode
= VOIDmode
;
3324 && mov_optab
->handlers
[(int) CCmode
].insn_code
!= CODE_FOR_nothing
)
3327 for (tmode
= QImode
; tmode
!= VOIDmode
;
3328 tmode
= GET_MODE_WIDER_MODE (tmode
))
3329 if (GET_MODE_SIZE (tmode
) == GET_MODE_SIZE (mode
))
3332 if (tmode
== VOIDmode
)
3335 /* Get X and Y in TMODE. We can't use gen_lowpart here because it
3336 may call change_address which is not appropriate if we were
3337 called when a reload was in progress. We don't have to worry
3338 about changing the address since the size in bytes is supposed to
3339 be the same. Copy the MEM to change the mode and move any
3340 substitutions from the old MEM to the new one. */
3342 if (reload_in_progress
)
3344 x
= gen_lowpart_common (tmode
, x1
);
3345 if (x
== 0 && GET_CODE (x1
) == MEM
)
3347 x
= gen_rtx (MEM
, tmode
, XEXP (x1
, 0));
3348 RTX_UNCHANGING_P (x
) = RTX_UNCHANGING_P (x1
);
3349 MEM_IN_STRUCT_P (x
) = MEM_IN_STRUCT_P (x1
);
3350 MEM_VOLATILE_P (x
) = MEM_VOLATILE_P (x1
);
3351 copy_replacements (x1
, x
);
3354 y
= gen_lowpart_common (tmode
, y1
);
3355 if (y
== 0 && GET_CODE (y1
) == MEM
)
3357 y
= gen_rtx (MEM
, tmode
, XEXP (y1
, 0));
3358 RTX_UNCHANGING_P (y
) = RTX_UNCHANGING_P (y1
);
3359 MEM_IN_STRUCT_P (y
) = MEM_IN_STRUCT_P (y1
);
3360 MEM_VOLATILE_P (y
) = MEM_VOLATILE_P (y1
);
3361 copy_replacements (y1
, y
);
3366 x
= gen_lowpart (tmode
, x
);
3367 y
= gen_lowpart (tmode
, y
);
3370 insn_code
= mov_optab
->handlers
[(int) tmode
].insn_code
;
3371 return (GEN_FCN (insn_code
) (x
, y
));
3375 emit_move_insn_1 (x
, y
);
3376 seq
= gen_sequence ();
3381 /* Return the insn code used to extend FROM_MODE to TO_MODE.
3382 UNSIGNEDP specifies zero-extension instead of sign-extension. If
3383 no such operation exists, CODE_FOR_nothing will be returned. */
3386 can_extend_p (to_mode
, from_mode
, unsignedp
)
3387 enum machine_mode to_mode
, from_mode
;
3390 return extendtab
[(int) to_mode
][(int) from_mode
][unsignedp
];
3393 /* Generate the body of an insn to extend Y (with mode MFROM)
3394 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
3397 gen_extend_insn (x
, y
, mto
, mfrom
, unsignedp
)
3399 enum machine_mode mto
, mfrom
;
3402 return (GEN_FCN (extendtab
[(int) mto
][(int) mfrom
][unsignedp
]) (x
, y
));
3405 /* can_fix_p and can_float_p say whether the target machine
3406 can directly convert a given fixed point type to
3407 a given floating point type, or vice versa.
3408 The returned value is the CODE_FOR_... value to use,
3409 or CODE_FOR_nothing if these modes cannot be directly converted.
3411 *TRUNCP_PTR is set to 1 if it is necessary to output
3412 an explicit FTRUNC insn before the fix insn; otherwise 0. */
3414 static enum insn_code
3415 can_fix_p (fixmode
, fltmode
, unsignedp
, truncp_ptr
)
3416 enum machine_mode fltmode
, fixmode
;
3421 if (fixtrunctab
[(int) fltmode
][(int) fixmode
][unsignedp
] != CODE_FOR_nothing
)
3422 return fixtrunctab
[(int) fltmode
][(int) fixmode
][unsignedp
];
3424 if (ftrunc_optab
->handlers
[(int) fltmode
].insn_code
!= CODE_FOR_nothing
)
3427 return fixtab
[(int) fltmode
][(int) fixmode
][unsignedp
];
3429 return CODE_FOR_nothing
;
3432 static enum insn_code
3433 can_float_p (fltmode
, fixmode
, unsignedp
)
3434 enum machine_mode fixmode
, fltmode
;
3437 return floattab
[(int) fltmode
][(int) fixmode
][unsignedp
];
3440 /* Generate code to convert FROM to floating point
3441 and store in TO. FROM must be fixed point and not VOIDmode.
3442 UNSIGNEDP nonzero means regard FROM as unsigned.
3443 Normally this is done by correcting the final value
3444 if it is negative. */
3447 expand_float (to
, from
, unsignedp
)
3451 enum insn_code icode
;
3452 register rtx target
= to
;
3453 enum machine_mode fmode
, imode
;
3455 /* Crash now, because we won't be able to decide which mode to use. */
3456 if (GET_MODE (from
) == VOIDmode
)
3459 /* Look for an insn to do the conversion. Do it in the specified
3460 modes if possible; otherwise convert either input, output or both to
3461 wider mode. If the integer mode is wider than the mode of FROM,
3462 we can do the conversion signed even if the input is unsigned. */
3464 for (imode
= GET_MODE (from
); imode
!= VOIDmode
;
3465 imode
= GET_MODE_WIDER_MODE (imode
))
3466 for (fmode
= GET_MODE (to
); fmode
!= VOIDmode
;
3467 fmode
= GET_MODE_WIDER_MODE (fmode
))
3469 int doing_unsigned
= unsignedp
;
3471 icode
= can_float_p (fmode
, imode
, unsignedp
);
3472 if (icode
== CODE_FOR_nothing
&& imode
!= GET_MODE (from
) && unsignedp
)
3473 icode
= can_float_p (fmode
, imode
, 0), doing_unsigned
= 0;
3475 if (icode
!= CODE_FOR_nothing
)
3477 to
= protect_from_queue (to
, 1);
3478 from
= protect_from_queue (from
, 0);
3480 if (imode
!= GET_MODE (from
))
3481 from
= convert_to_mode (imode
, from
, unsignedp
);
3483 if (fmode
!= GET_MODE (to
))
3484 target
= gen_reg_rtx (fmode
);
3486 emit_unop_insn (icode
, target
, from
,
3487 doing_unsigned
? UNSIGNED_FLOAT
: FLOAT
);
3490 convert_move (to
, target
, 0);
3495 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3497 /* Unsigned integer, and no way to convert directly.
3498 Convert as signed, then conditionally adjust the result. */
3501 rtx label
= gen_label_rtx ();
3503 REAL_VALUE_TYPE offset
;
3507 to
= protect_from_queue (to
, 1);
3508 from
= protect_from_queue (from
, 0);
3511 from
= force_not_mem (from
);
3513 /* Look for a usable floating mode FMODE wider than the source and at
3514 least as wide as the target. Using FMODE will avoid rounding woes
3515 with unsigned values greater than the signed maximum value. */
3517 for (fmode
= GET_MODE (to
); fmode
!= VOIDmode
;
3518 fmode
= GET_MODE_WIDER_MODE (fmode
))
3519 if (GET_MODE_BITSIZE (GET_MODE (from
)) < GET_MODE_BITSIZE (fmode
)
3520 && can_float_p (fmode
, GET_MODE (from
), 0) != CODE_FOR_nothing
)
3523 if (fmode
== VOIDmode
)
3525 /* There is no such mode. Pretend the target is wide enough. */
3526 fmode
= GET_MODE (to
);
3528 /* Avoid double-rounding when TO is narrower than FROM. */
3529 if ((significand_size (fmode
) + 1)
3530 < GET_MODE_BITSIZE (GET_MODE (from
)))
3533 rtx neglabel
= gen_label_rtx ();
3535 /* Don't use TARGET if it isn't a register, is a hard register,
3536 or is the wrong mode. */
3537 if (GET_CODE (target
) != REG
3538 || REGNO (target
) < FIRST_PSEUDO_REGISTER
3539 || GET_MODE (target
) != fmode
)
3540 target
= gen_reg_rtx (fmode
);
3542 imode
= GET_MODE (from
);
3543 do_pending_stack_adjust ();
3545 /* Test whether the sign bit is set. */
3546 emit_cmp_insn (from
, const0_rtx
, GE
, NULL_RTX
, imode
, 0, 0);
3547 emit_jump_insn (gen_blt (neglabel
));
3549 /* The sign bit is not set. Convert as signed. */
3550 expand_float (target
, from
, 0);
3551 emit_jump_insn (gen_jump (label
));
3554 /* The sign bit is set.
3555 Convert to a usable (positive signed) value by shifting right
3556 one bit, while remembering if a nonzero bit was shifted
3557 out; i.e., compute (from & 1) | (from >> 1). */
3559 emit_label (neglabel
);
3560 temp
= expand_binop (imode
, and_optab
, from
, const1_rtx
,
3561 NULL_RTX
, 1, OPTAB_LIB_WIDEN
);
3562 temp1
= expand_shift (RSHIFT_EXPR
, imode
, from
, integer_one_node
,
3564 temp
= expand_binop (imode
, ior_optab
, temp
, temp1
, temp
, 1,
3566 expand_float (target
, temp
, 0);
3568 /* Multiply by 2 to undo the shift above. */
3569 temp
= expand_binop (fmode
, add_optab
, target
, target
,
3570 target
, 0, OPTAB_LIB_WIDEN
);
3572 emit_move_insn (target
, temp
);
3574 do_pending_stack_adjust ();
3580 /* If we are about to do some arithmetic to correct for an
3581 unsigned operand, do it in a pseudo-register. */
3583 if (GET_MODE (to
) != fmode
3584 || GET_CODE (to
) != REG
|| REGNO (to
) < FIRST_PSEUDO_REGISTER
)
3585 target
= gen_reg_rtx (fmode
);
3587 /* Convert as signed integer to floating. */
3588 expand_float (target
, from
, 0);
3590 /* If FROM is negative (and therefore TO is negative),
3591 correct its value by 2**bitwidth. */
3593 do_pending_stack_adjust ();
3594 emit_cmp_insn (from
, const0_rtx
, GE
, NULL_RTX
, GET_MODE (from
), 0, 0);
3595 emit_jump_insn (gen_bge (label
));
3597 /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
3598 Rather than setting up a dconst_dot_5, let's hope SCO
3600 offset
= REAL_VALUE_LDEXP (dconst1
, GET_MODE_BITSIZE (GET_MODE (from
)));
3601 temp
= expand_binop (fmode
, add_optab
, target
,
3602 CONST_DOUBLE_FROM_REAL_VALUE (offset
, fmode
),
3603 target
, 0, OPTAB_LIB_WIDEN
);
3605 emit_move_insn (target
, temp
);
3607 do_pending_stack_adjust ();
3613 /* No hardware instruction available; call a library routine to convert from
3614 SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */
3620 to
= protect_from_queue (to
, 1);
3621 from
= protect_from_queue (from
, 0);
3623 if (GET_MODE_SIZE (GET_MODE (from
)) < GET_MODE_SIZE (SImode
))
3624 from
= convert_to_mode (SImode
, from
, unsignedp
);
3627 from
= force_not_mem (from
);
3629 if (GET_MODE (to
) == SFmode
)
3631 if (GET_MODE (from
) == SImode
)
3632 libfcn
= floatsisf_libfunc
;
3633 else if (GET_MODE (from
) == DImode
)
3634 libfcn
= floatdisf_libfunc
;
3635 else if (GET_MODE (from
) == TImode
)
3636 libfcn
= floattisf_libfunc
;
3640 else if (GET_MODE (to
) == DFmode
)
3642 if (GET_MODE (from
) == SImode
)
3643 libfcn
= floatsidf_libfunc
;
3644 else if (GET_MODE (from
) == DImode
)
3645 libfcn
= floatdidf_libfunc
;
3646 else if (GET_MODE (from
) == TImode
)
3647 libfcn
= floattidf_libfunc
;
3651 else if (GET_MODE (to
) == XFmode
)
3653 if (GET_MODE (from
) == SImode
)
3654 libfcn
= floatsixf_libfunc
;
3655 else if (GET_MODE (from
) == DImode
)
3656 libfcn
= floatdixf_libfunc
;
3657 else if (GET_MODE (from
) == TImode
)
3658 libfcn
= floattixf_libfunc
;
3662 else if (GET_MODE (to
) == TFmode
)
3664 if (GET_MODE (from
) == SImode
)
3665 libfcn
= floatsitf_libfunc
;
3666 else if (GET_MODE (from
) == DImode
)
3667 libfcn
= floatditf_libfunc
;
3668 else if (GET_MODE (from
) == TImode
)
3669 libfcn
= floattitf_libfunc
;
3678 value
= emit_library_call_value (libfcn
, NULL_RTX
, 1,
3680 1, from
, GET_MODE (from
));
3681 insns
= get_insns ();
3684 emit_libcall_block (insns
, target
, value
,
3685 gen_rtx (FLOAT
, GET_MODE (to
), from
));
3690 /* Copy result to requested destination
3691 if we have been computing in a temp location. */
3695 if (GET_MODE (target
) == GET_MODE (to
))
3696 emit_move_insn (to
, target
);
3698 convert_move (to
, target
, 0);
3702 /* expand_fix: generate code to convert FROM to fixed point
3703 and store in TO. FROM must be floating point. */
3709 rtx temp
= gen_reg_rtx (GET_MODE (x
));
3710 return expand_unop (GET_MODE (x
), ftrunc_optab
, x
, temp
, 0);
3714 expand_fix (to
, from
, unsignedp
)
3715 register rtx to
, from
;
3718 enum insn_code icode
;
3719 register rtx target
= to
;
3720 enum machine_mode fmode
, imode
;
3724 /* We first try to find a pair of modes, one real and one integer, at
3725 least as wide as FROM and TO, respectively, in which we can open-code
3726 this conversion. If the integer mode is wider than the mode of TO,
3727 we can do the conversion either signed or unsigned. */
3729 for (imode
= GET_MODE (to
); imode
!= VOIDmode
;
3730 imode
= GET_MODE_WIDER_MODE (imode
))
3731 for (fmode
= GET_MODE (from
); fmode
!= VOIDmode
;
3732 fmode
= GET_MODE_WIDER_MODE (fmode
))
3734 int doing_unsigned
= unsignedp
;
3736 icode
= can_fix_p (imode
, fmode
, unsignedp
, &must_trunc
);
3737 if (icode
== CODE_FOR_nothing
&& imode
!= GET_MODE (to
) && unsignedp
)
3738 icode
= can_fix_p (imode
, fmode
, 0, &must_trunc
), doing_unsigned
= 0;
3740 if (icode
!= CODE_FOR_nothing
)
3742 to
= protect_from_queue (to
, 1);
3743 from
= protect_from_queue (from
, 0);
3745 if (fmode
!= GET_MODE (from
))
3746 from
= convert_to_mode (fmode
, from
, 0);
3749 from
= ftruncify (from
);
3751 if (imode
!= GET_MODE (to
))
3752 target
= gen_reg_rtx (imode
);
3754 emit_unop_insn (icode
, target
, from
,
3755 doing_unsigned
? UNSIGNED_FIX
: FIX
);
3757 convert_move (to
, target
, unsignedp
);
3762 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3763 /* For an unsigned conversion, there is one more way to do it.
3764 If we have a signed conversion, we generate code that compares
3765 the real value to the largest representable positive number. If if
3766 is smaller, the conversion is done normally. Otherwise, subtract
3767 one plus the highest signed number, convert, and add it back.
3769 We only need to check all real modes, since we know we didn't find
3770 anything with a wider integer mode. */
3772 if (unsignedp
&& GET_MODE_BITSIZE (GET_MODE (to
)) <= HOST_BITS_PER_WIDE_INT
)
3773 for (fmode
= GET_MODE (from
); fmode
!= VOIDmode
;
3774 fmode
= GET_MODE_WIDER_MODE (fmode
))
3775 /* Make sure we won't lose significant bits doing this. */
3776 if (GET_MODE_BITSIZE (fmode
) > GET_MODE_BITSIZE (GET_MODE (to
))
3777 && CODE_FOR_nothing
!= can_fix_p (GET_MODE (to
), fmode
, 0,
3781 REAL_VALUE_TYPE offset
;
3782 rtx limit
, lab1
, lab2
, insn
;
3784 bitsize
= GET_MODE_BITSIZE (GET_MODE (to
));
3785 offset
= REAL_VALUE_LDEXP (dconst1
, bitsize
- 1);
3786 limit
= CONST_DOUBLE_FROM_REAL_VALUE (offset
, fmode
);
3787 lab1
= gen_label_rtx ();
3788 lab2
= gen_label_rtx ();
3791 to
= protect_from_queue (to
, 1);
3792 from
= protect_from_queue (from
, 0);
3795 from
= force_not_mem (from
);
3797 if (fmode
!= GET_MODE (from
))
3798 from
= convert_to_mode (fmode
, from
, 0);
3800 /* See if we need to do the subtraction. */
3801 do_pending_stack_adjust ();
3802 emit_cmp_insn (from
, limit
, GE
, NULL_RTX
, GET_MODE (from
), 0, 0);
3803 emit_jump_insn (gen_bge (lab1
));
3805 /* If not, do the signed "fix" and branch around fixup code. */
3806 expand_fix (to
, from
, 0);
3807 emit_jump_insn (gen_jump (lab2
));
3810 /* Otherwise, subtract 2**(N-1), convert to signed number,
3811 then add 2**(N-1). Do the addition using XOR since this
3812 will often generate better code. */
3814 target
= expand_binop (GET_MODE (from
), sub_optab
, from
, limit
,
3815 NULL_RTX
, 0, OPTAB_LIB_WIDEN
);
3816 expand_fix (to
, target
, 0);
3817 target
= expand_binop (GET_MODE (to
), xor_optab
, to
,
3818 GEN_INT ((HOST_WIDE_INT
) 1 << (bitsize
- 1)),
3819 to
, 1, OPTAB_LIB_WIDEN
);
3822 emit_move_insn (to
, target
);
3826 /* Make a place for a REG_NOTE and add it. */
3827 insn
= emit_move_insn (to
, to
);
3828 REG_NOTES (insn
) = gen_rtx (EXPR_LIST
, REG_EQUAL
,
3829 gen_rtx (UNSIGNED_FIX
, GET_MODE (to
),
3837 /* We can't do it with an insn, so use a library call. But first ensure
3838 that the mode of TO is at least as wide as SImode, since those are the
3839 only library calls we know about. */
3841 if (GET_MODE_SIZE (GET_MODE (to
)) < GET_MODE_SIZE (SImode
))
3843 target
= gen_reg_rtx (SImode
);
3845 expand_fix (target
, from
, unsignedp
);
3847 else if (GET_MODE (from
) == SFmode
)
3849 if (GET_MODE (to
) == SImode
)
3850 libfcn
= unsignedp
? fixunssfsi_libfunc
: fixsfsi_libfunc
;
3851 else if (GET_MODE (to
) == DImode
)
3852 libfcn
= unsignedp
? fixunssfdi_libfunc
: fixsfdi_libfunc
;
3853 else if (GET_MODE (to
) == TImode
)
3854 libfcn
= unsignedp
? fixunssfti_libfunc
: fixsfti_libfunc
;
3858 else if (GET_MODE (from
) == DFmode
)
3860 if (GET_MODE (to
) == SImode
)
3861 libfcn
= unsignedp
? fixunsdfsi_libfunc
: fixdfsi_libfunc
;
3862 else if (GET_MODE (to
) == DImode
)
3863 libfcn
= unsignedp
? fixunsdfdi_libfunc
: fixdfdi_libfunc
;
3864 else if (GET_MODE (to
) == TImode
)
3865 libfcn
= unsignedp
? fixunsdfti_libfunc
: fixdfti_libfunc
;
3869 else if (GET_MODE (from
) == XFmode
)
3871 if (GET_MODE (to
) == SImode
)
3872 libfcn
= unsignedp
? fixunsxfsi_libfunc
: fixxfsi_libfunc
;
3873 else if (GET_MODE (to
) == DImode
)
3874 libfcn
= unsignedp
? fixunsxfdi_libfunc
: fixxfdi_libfunc
;
3875 else if (GET_MODE (to
) == TImode
)
3876 libfcn
= unsignedp
? fixunsxfti_libfunc
: fixxfti_libfunc
;
3880 else if (GET_MODE (from
) == TFmode
)
3882 if (GET_MODE (to
) == SImode
)
3883 libfcn
= unsignedp
? fixunstfsi_libfunc
: fixtfsi_libfunc
;
3884 else if (GET_MODE (to
) == DImode
)
3885 libfcn
= unsignedp
? fixunstfdi_libfunc
: fixtfdi_libfunc
;
3886 else if (GET_MODE (to
) == TImode
)
3887 libfcn
= unsignedp
? fixunstfti_libfunc
: fixtfti_libfunc
;
3899 to
= protect_from_queue (to
, 1);
3900 from
= protect_from_queue (from
, 0);
3903 from
= force_not_mem (from
);
3907 value
= emit_library_call_value (libfcn
, NULL_RTX
, 1, GET_MODE (to
),
3909 1, from
, GET_MODE (from
));
3910 insns
= get_insns ();
3913 emit_libcall_block (insns
, target
, value
,
3914 gen_rtx (unsignedp
? UNSIGNED_FIX
: FIX
,
3915 GET_MODE (to
), from
));
3920 if (GET_MODE (to
) == GET_MODE (target
))
3921 emit_move_insn (to
, target
);
3923 convert_move (to
, target
, 0);
3932 optab op
= (optab
) xmalloc (sizeof (struct optab
));
3934 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
3936 op
->handlers
[i
].insn_code
= CODE_FOR_nothing
;
3937 op
->handlers
[i
].libfunc
= 0;
3940 if (code
!= UNKNOWN
)
3941 code_to_optab
[(int) code
] = op
;
3946 /* Initialize the libfunc fields of an entire group of entries in some
3947 optab. Each entry is set equal to a string consisting of a leading
3948 pair of underscores followed by a generic operation name followed by
3949 a mode name (downshifted to lower case) followed by a single character
3950 representing the number of operands for the given operation (which is
3951 usually one of the characters '2', '3', or '4').
3953 OPTABLE is the table in which libfunc fields are to be initialized.
3954 FIRST_MODE is the first machine mode index in the given optab to
3956 LAST_MODE is the last machine mode index in the given optab to
3958 OPNAME is the generic (string) name of the operation.
3959 SUFFIX is the character which specifies the number of operands for
3960 the given generic operation.
3964 init_libfuncs (optable
, first_mode
, last_mode
, opname
, suffix
)
3965 register optab optable
;
3966 register int first_mode
;
3967 register int last_mode
;
3968 register char *opname
;
3969 register int suffix
;
3972 register unsigned opname_len
= strlen (opname
);
3974 for (mode
= first_mode
; (int) mode
<= (int) last_mode
;
3975 mode
= (enum machine_mode
) ((int) mode
+ 1))
3977 register char *mname
= mode_name
[(int) mode
];
3978 register unsigned mname_len
= strlen (mname
);
3979 register char *libfunc_name
3980 = (char *) xmalloc (2 + opname_len
+ mname_len
+ 1 + 1);
3987 for (q
= opname
; *q
; )
3989 for (q
= mname
; *q
; q
++)
3990 *p
++ = tolower (*q
);
3993 optable
->handlers
[(int) mode
].libfunc
3994 = gen_rtx (SYMBOL_REF
, Pmode
, libfunc_name
);
3998 /* Initialize the libfunc fields of an entire group of entries in some
3999 optab which correspond to all integer mode operations. The parameters
4000 have the same meaning as similarly named ones for the `init_libfuncs'
4001 routine. (See above). */
4004 init_integral_libfuncs (optable
, opname
, suffix
)
4005 register optab optable
;
4006 register char *opname
;
4007 register int suffix
;
4009 init_libfuncs (optable
, SImode
, TImode
, opname
, suffix
);
4012 /* Initialize the libfunc fields of an entire group of entries in some
4013 optab which correspond to all real mode operations. The parameters
4014 have the same meaning as similarly named ones for the `init_libfuncs'
4015 routine. (See above). */
4018 init_floating_libfuncs (optable
, opname
, suffix
)
4019 register optab optable
;
4020 register char *opname
;
4021 register int suffix
;
4023 init_libfuncs (optable
, SFmode
, TFmode
, opname
, suffix
);
4026 /* Initialize the libfunc fields of an entire group of entries in some
4027 optab which correspond to all complex floating modes. The parameters
4028 have the same meaning as similarly named ones for the `init_libfuncs'
4029 routine. (See above). */
4032 init_complex_libfuncs (optable
, opname
, suffix
)
4033 register optab optable
;
4034 register char *opname
;
4035 register int suffix
;
4037 init_libfuncs (optable
, SCmode
, TCmode
, opname
, suffix
);
4040 /* Call this once to initialize the contents of the optabs
4041 appropriately for the current target machine. */
4049 /* Start by initializing all tables to contain CODE_FOR_nothing. */
4051 for (p
= fixtab
[0][0];
4052 p
< fixtab
[0][0] + sizeof fixtab
/ sizeof (fixtab
[0][0][0]);
4054 *p
= CODE_FOR_nothing
;
4056 for (p
= fixtrunctab
[0][0];
4057 p
< fixtrunctab
[0][0] + sizeof fixtrunctab
/ sizeof (fixtrunctab
[0][0][0]);
4059 *p
= CODE_FOR_nothing
;
4061 for (p
= floattab
[0][0];
4062 p
< floattab
[0][0] + sizeof floattab
/ sizeof (floattab
[0][0][0]);
4064 *p
= CODE_FOR_nothing
;
4066 for (p
= extendtab
[0][0];
4067 p
< extendtab
[0][0] + sizeof extendtab
/ sizeof extendtab
[0][0][0];
4069 *p
= CODE_FOR_nothing
;
4071 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
4072 setcc_gen_code
[i
] = CODE_FOR_nothing
;
4074 #ifdef HAVE_conditional_move
4075 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
4076 movcc_gen_code
[i
] = CODE_FOR_nothing
;
4079 add_optab
= init_optab (PLUS
);
4080 sub_optab
= init_optab (MINUS
);
4081 smul_optab
= init_optab (MULT
);
4082 smul_highpart_optab
= init_optab (UNKNOWN
);
4083 umul_highpart_optab
= init_optab (UNKNOWN
);
4084 smul_widen_optab
= init_optab (UNKNOWN
);
4085 umul_widen_optab
= init_optab (UNKNOWN
);
4086 sdiv_optab
= init_optab (DIV
);
4087 sdivmod_optab
= init_optab (UNKNOWN
);
4088 udiv_optab
= init_optab (UDIV
);
4089 udivmod_optab
= init_optab (UNKNOWN
);
4090 smod_optab
= init_optab (MOD
);
4091 umod_optab
= init_optab (UMOD
);
4092 flodiv_optab
= init_optab (DIV
);
4093 ftrunc_optab
= init_optab (UNKNOWN
);
4094 and_optab
= init_optab (AND
);
4095 ior_optab
= init_optab (IOR
);
4096 xor_optab
= init_optab (XOR
);
4097 ashl_optab
= init_optab (ASHIFT
);
4098 ashr_optab
= init_optab (ASHIFTRT
);
4099 lshr_optab
= init_optab (LSHIFTRT
);
4100 rotl_optab
= init_optab (ROTATE
);
4101 rotr_optab
= init_optab (ROTATERT
);
4102 smin_optab
= init_optab (SMIN
);
4103 smax_optab
= init_optab (SMAX
);
4104 umin_optab
= init_optab (UMIN
);
4105 umax_optab
= init_optab (UMAX
);
4106 mov_optab
= init_optab (UNKNOWN
);
4107 movstrict_optab
= init_optab (UNKNOWN
);
4108 cmp_optab
= init_optab (UNKNOWN
);
4109 ucmp_optab
= init_optab (UNKNOWN
);
4110 tst_optab
= init_optab (UNKNOWN
);
4111 neg_optab
= init_optab (NEG
);
4112 abs_optab
= init_optab (ABS
);
4113 one_cmpl_optab
= init_optab (NOT
);
4114 ffs_optab
= init_optab (FFS
);
4115 sqrt_optab
= init_optab (SQRT
);
4116 sin_optab
= init_optab (UNKNOWN
);
4117 cos_optab
= init_optab (UNKNOWN
);
4118 strlen_optab
= init_optab (UNKNOWN
);
4120 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
4122 movstr_optab
[i
] = CODE_FOR_nothing
;
4123 clrstr_optab
[i
] = CODE_FOR_nothing
;
4125 #ifdef HAVE_SECONDARY_RELOADS
4126 reload_in_optab
[i
] = reload_out_optab
[i
] = CODE_FOR_nothing
;
4130 /* Fill in the optabs with the insns we support. */
4133 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
4134 /* This flag says the same insns that convert to a signed fixnum
4135 also convert validly to an unsigned one. */
4136 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
4137 for (j
= 0; j
< NUM_MACHINE_MODES
; j
++)
4138 fixtrunctab
[i
][j
][1] = fixtrunctab
[i
][j
][0];
4141 #ifdef EXTRA_CC_MODES
4145 /* Initialize the optabs with the names of the library functions. */
4146 init_integral_libfuncs (add_optab
, "add", '3');
4147 init_floating_libfuncs (add_optab
, "add", '3');
4148 init_integral_libfuncs (sub_optab
, "sub", '3');
4149 init_floating_libfuncs (sub_optab
, "sub", '3');
4150 init_integral_libfuncs (smul_optab
, "mul", '3');
4151 init_floating_libfuncs (smul_optab
, "mul", '3');
4152 init_integral_libfuncs (sdiv_optab
, "div", '3');
4153 init_integral_libfuncs (udiv_optab
, "udiv", '3');
4154 init_integral_libfuncs (sdivmod_optab
, "divmod", '4');
4155 init_integral_libfuncs (udivmod_optab
, "udivmod", '4');
4156 init_integral_libfuncs (smod_optab
, "mod", '3');
4157 init_integral_libfuncs (umod_optab
, "umod", '3');
4158 init_floating_libfuncs (flodiv_optab
, "div", '3');
4159 init_floating_libfuncs (ftrunc_optab
, "ftrunc", '2');
4160 init_integral_libfuncs (and_optab
, "and", '3');
4161 init_integral_libfuncs (ior_optab
, "ior", '3');
4162 init_integral_libfuncs (xor_optab
, "xor", '3');
4163 init_integral_libfuncs (ashl_optab
, "ashl", '3');
4164 init_integral_libfuncs (ashr_optab
, "ashr", '3');
4165 init_integral_libfuncs (lshr_optab
, "lshr", '3');
4166 init_integral_libfuncs (smin_optab
, "min", '3');
4167 init_floating_libfuncs (smin_optab
, "min", '3');
4168 init_integral_libfuncs (smax_optab
, "max", '3');
4169 init_floating_libfuncs (smax_optab
, "max", '3');
4170 init_integral_libfuncs (umin_optab
, "umin", '3');
4171 init_integral_libfuncs (umax_optab
, "umax", '3');
4172 init_integral_libfuncs (neg_optab
, "neg", '2');
4173 init_floating_libfuncs (neg_optab
, "neg", '2');
4174 init_integral_libfuncs (one_cmpl_optab
, "one_cmpl", '2');
4175 init_integral_libfuncs (ffs_optab
, "ffs", '2');
4177 /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
4178 init_integral_libfuncs (cmp_optab
, "cmp", '2');
4179 init_integral_libfuncs (ucmp_optab
, "ucmp", '2');
4180 init_floating_libfuncs (cmp_optab
, "cmp", '2');
4182 #ifdef MULSI3_LIBCALL
4183 smul_optab
->handlers
[(int) SImode
].libfunc
4184 = gen_rtx (SYMBOL_REF
, Pmode
, MULSI3_LIBCALL
);
4186 #ifdef MULDI3_LIBCALL
4187 smul_optab
->handlers
[(int) DImode
].libfunc
4188 = gen_rtx (SYMBOL_REF
, Pmode
, MULDI3_LIBCALL
);
4191 #ifdef DIVSI3_LIBCALL
4192 sdiv_optab
->handlers
[(int) SImode
].libfunc
4193 = gen_rtx (SYMBOL_REF
, Pmode
, DIVSI3_LIBCALL
);
4195 #ifdef DIVDI3_LIBCALL
4196 sdiv_optab
->handlers
[(int) DImode
].libfunc
4197 = gen_rtx (SYMBOL_REF
, Pmode
, DIVDI3_LIBCALL
);
4200 #ifdef UDIVSI3_LIBCALL
4201 udiv_optab
->handlers
[(int) SImode
].libfunc
4202 = gen_rtx (SYMBOL_REF
, Pmode
, UDIVSI3_LIBCALL
);
4204 #ifdef UDIVDI3_LIBCALL
4205 udiv_optab
->handlers
[(int) DImode
].libfunc
4206 = gen_rtx (SYMBOL_REF
, Pmode
, UDIVDI3_LIBCALL
);
4209 #ifdef MODSI3_LIBCALL
4210 smod_optab
->handlers
[(int) SImode
].libfunc
4211 = gen_rtx (SYMBOL_REF
, Pmode
, MODSI3_LIBCALL
);
4213 #ifdef MODDI3_LIBCALL
4214 smod_optab
->handlers
[(int) DImode
].libfunc
4215 = gen_rtx (SYMBOL_REF
, Pmode
, MODDI3_LIBCALL
);
4218 #ifdef UMODSI3_LIBCALL
4219 umod_optab
->handlers
[(int) SImode
].libfunc
4220 = gen_rtx (SYMBOL_REF
, Pmode
, UMODSI3_LIBCALL
);
4222 #ifdef UMODDI3_LIBCALL
4223 umod_optab
->handlers
[(int) DImode
].libfunc
4224 = gen_rtx (SYMBOL_REF
, Pmode
, UMODDI3_LIBCALL
);
4227 /* Use cabs for DC complex abs, since systems generally have cabs.
4228 Don't define any libcall for SCmode, so that cabs will be used. */
4229 abs_optab
->handlers
[(int) DCmode
].libfunc
4230 = gen_rtx (SYMBOL_REF
, Pmode
, "cabs");
4232 /* The ffs function operates on `int'. */
4233 #ifndef INT_TYPE_SIZE
4234 #define INT_TYPE_SIZE BITS_PER_WORD
4236 ffs_optab
->handlers
[(int) mode_for_size (INT_TYPE_SIZE
, MODE_INT
, 0)] .libfunc
4237 = gen_rtx (SYMBOL_REF
, Pmode
, "ffs");
4239 extendsfdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extendsfdf2");
4240 extendsfxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extendsfxf2");
4241 extendsftf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extendsftf2");
4242 extenddfxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extenddfxf2");
4243 extenddftf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__extenddftf2");
4245 truncdfsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__truncdfsf2");
4246 truncxfsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__truncxfsf2");
4247 trunctfsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__trunctfsf2");
4248 truncxfdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__truncxfdf2");
4249 trunctfdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__trunctfdf2");
4251 memcpy_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "memcpy");
4252 bcopy_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "bcopy");
4253 memcmp_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "memcmp");
4254 bcmp_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gcc_bcmp");
4255 memset_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "memset");
4256 bzero_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "bzero");
4258 throw_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__throw");
4260 eqhf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqhf2");
4261 nehf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__nehf2");
4262 gthf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gthf2");
4263 gehf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gehf2");
4264 lthf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__lthf2");
4265 lehf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__lehf2");
4267 eqsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqsf2");
4268 nesf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__nesf2");
4269 gtsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gtsf2");
4270 gesf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gesf2");
4271 ltsf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ltsf2");
4272 lesf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__lesf2");
4274 eqdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqdf2");
4275 nedf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__nedf2");
4276 gtdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gtdf2");
4277 gedf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gedf2");
4278 ltdf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ltdf2");
4279 ledf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ledf2");
4281 eqxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqxf2");
4282 nexf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__nexf2");
4283 gtxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gtxf2");
4284 gexf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gexf2");
4285 ltxf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__ltxf2");
4286 lexf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__lexf2");
4288 eqtf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__eqtf2");
4289 netf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__netf2");
4290 gttf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__gttf2");
4291 getf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__getf2");
4292 lttf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__lttf2");
4293 letf2_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__letf2");
4295 floatsisf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatsisf");
4296 floatdisf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatdisf");
4297 floattisf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floattisf");
4299 floatsidf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatsidf");
4300 floatdidf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatdidf");
4301 floattidf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floattidf");
4303 floatsixf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatsixf");
4304 floatdixf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatdixf");
4305 floattixf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floattixf");
4307 floatsitf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatsitf");
4308 floatditf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floatditf");
4309 floattitf_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__floattitf");
4311 fixsfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixsfsi");
4312 fixsfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixsfdi");
4313 fixsfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixsfti");
4315 fixdfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixdfsi");
4316 fixdfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixdfdi");
4317 fixdfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixdfti");
4319 fixxfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixxfsi");
4320 fixxfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixxfdi");
4321 fixxfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixxfti");
4323 fixtfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixtfsi");
4324 fixtfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixtfdi");
4325 fixtfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixtfti");
4327 fixunssfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunssfsi");
4328 fixunssfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunssfdi");
4329 fixunssfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunssfti");
4331 fixunsdfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsdfsi");
4332 fixunsdfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsdfdi");
4333 fixunsdfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsdfti");
4335 fixunsxfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsxfsi");
4336 fixunsxfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsxfdi");
4337 fixunsxfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunsxfti");
4339 fixunstfsi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunstfsi");
4340 fixunstfdi_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunstfdi");
4341 fixunstfti_libfunc
= gen_rtx (SYMBOL_REF
, Pmode
, "__fixunstfti");
4343 #ifdef INIT_TARGET_OPTABS
4344 /* Allow the target to add more libcalls or rename some, etc. */
4351 /* SCO 3.2 apparently has a broken ldexp. */
4364 #endif /* BROKEN_LDEXP */