diff options
Diffstat (limited to 'gcc-1.40/optabs.c')
| -rw-r--r-- | gcc-1.40/optabs.c | 2228 |
1 files changed, 2228 insertions, 0 deletions
diff --git a/gcc-1.40/optabs.c b/gcc-1.40/optabs.c new file mode 100644 index 0000000..aaf5475 --- /dev/null +++ b/gcc-1.40/optabs.c @@ -0,0 +1,2228 @@ +/* Expand the basic unary and binary arithmetic operations, for GNU compiler. + Copyright (C) 1987, 1988 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 1, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +#include "config.h" +#include "rtl.h" +#include "tree.h" +#include "flags.h" +#include "insn-flags.h" +#include "insn-codes.h" +#include "expr.h" +#include "insn-config.h" +#include "recog.h" + +/* In ANSI C we could write MODE + 1, but traditional C compilers + seem to reject it. */ +#define INC_MODE(MODE) (enum machine_mode) ((int)(MODE) + 1) + +/* Each optab contains info on how this target machine + can perform a particular operation + for all sizes and kinds of operands. + + The operation to be performed is often specified + by passing one of these optabs as an argument. + + See expr.h for documentation of these optabs. */ + +optab add_optab; +optab sub_optab; +optab smul_optab; +optab umul_optab; +optab smul_widen_optab; +optab umul_widen_optab; +optab sdiv_optab; +optab sdivmod_optab; +optab udiv_optab; +optab udivmod_optab; +optab smod_optab; +optab umod_optab; +optab flodiv_optab; +optab ftrunc_optab; +optab and_optab; +optab andcb_optab; +optab ior_optab; +optab xor_optab; +optab ashl_optab; +optab lshr_optab; +optab lshl_optab; +optab ashr_optab; +optab rotl_optab; +optab rotr_optab; + +optab mov_optab; +optab movstrict_optab; + +optab neg_optab; +optab abs_optab; +optab one_cmpl_optab; +optab ffs_optab; + +optab cmp_optab; +optab ucmp_optab; /* Used only for libcalls for unsigned comparisons. */ +optab tst_optab; + +/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...) + gives the gen_function to make a branch to test that condition. */ + +rtxfun bcc_gen_fctn[NUM_RTX_CODE]; + +/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...) + gives the gen_function to make a store-condition insn + to test that condition. */ + +rtxfun setcc_gen_fctn[NUM_RTX_CODE]; + +/* Generate code to perform an operation specified by BINOPTAB + on operands OP0 and OP1, with result having machine-mode MODE. + + UNSIGNEDP is for the case where we have to widen the operands + to perform the operation. It says to use zero-extension. + + If TARGET is nonzero, the value + is generated there, if it is convenient to do so. + In all cases an rtx is returned for the locus of the value; + this may or may not be TARGET. */ + +rtx +expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) + enum machine_mode mode; + optab binoptab; + rtx op0, op1; + rtx target; + int unsignedp; + enum optab_methods methods; +{ + enum mode_class class; + enum machine_mode wider_mode; + register rtx temp; + rtx last; + + class = GET_MODE_CLASS (mode); + + op0 = protect_from_queue (op0, 0); + op1 = protect_from_queue (op1, 0); + if (target) + target = protect_from_queue (target, 1); + +#if 0 + /* We may get better code by generating the result in a register + when the target is not one of the operands. */ + if (target && ! rtx_equal_p (target, op1) && ! rtx_equal_p (target, op0)) + target_is_not_an_operand = 1; +#endif + + if (flag_force_mem) + { + op0 = force_not_mem (op0); + op1 = force_not_mem (op1); + } + + /* Record where to delete back to if we backtrack. */ + last = get_last_insn (); + + /* If operation is commutative, + try to make the first operand a register. + Even better, try to make it the same as the target. + Also try to make the last operand a constant. */ + if (binoptab == add_optab + || binoptab == and_optab + || binoptab == ior_optab + || binoptab == xor_optab + || binoptab == smul_optab + || binoptab == umul_optab + || binoptab == smul_widen_optab + || binoptab == umul_widen_optab) + { + if (((target == 0 || GET_CODE (target) == REG) + ? ((GET_CODE (op1) == REG + && GET_CODE (op0) != REG) + || target == op1) + : rtx_equal_p (op1, target)) + || + GET_CODE (op0) == CONST_INT) + { + temp = op1; + op1 = op0; + op0 = temp; + } + } + + /* If we can do it with a three-operand insn, do so. */ + + if (methods != OPTAB_MUST_WIDEN + && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing) + { + int icode = (int) binoptab->handlers[(int) mode].insn_code; + enum machine_mode mode0 = insn_operand_mode[icode][1]; + enum machine_mode mode1 = insn_operand_mode[icode][2]; + rtx pat; + rtx xop0 = op0, xop1 = op1; + + if (target) + temp = target; + else + temp = gen_reg_rtx (mode); + + /* In case the insn wants input operands in modes different from + the result, convert the operands. */ + + if (GET_MODE (op0) != VOIDmode + && GET_MODE (op0) != mode0) + xop0 = convert_to_mode (mode0, xop0, unsignedp); + + if (GET_MODE (xop1) != VOIDmode + && GET_MODE (xop1) != mode1) + xop1 = convert_to_mode (mode1, xop1, unsignedp); + + /* Now, if insn requires register operands, put operands into regs. */ + + if (! (*insn_operand_predicate[icode][1]) (xop0, mode0)) + xop0 = force_reg (mode0, xop0); + + if (! (*insn_operand_predicate[icode][2]) (xop1, mode1)) + xop1 = force_reg (mode1, xop1); + + if (! (*insn_operand_predicate[icode][0]) (temp, mode)) + temp = gen_reg_rtx (mode); + + pat = GEN_FCN (icode) (temp, xop0, xop1); + if (pat) + { + emit_insn (pat); + return temp; + } + else + delete_insns_since (last); + } + + /* It can't be open-coded in this mode. + Use a library call if one is available and caller says that's ok. */ + + if (binoptab->handlers[(int) mode].lib_call + && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN)) + { + rtx insn_before, insn_first, insn_last; + rtx funexp = gen_rtx (SYMBOL_REF, Pmode, + binoptab->handlers[(int) mode].lib_call); + + /* Pass the address through a pseudoreg, if desired, + before the "beginning" of the library call. + So this insn isn't "part of" the library call, in case that + is deleted, or cse'd. */ +#ifndef NO_FUNCTION_CSE + if (! flag_no_function_cse) + funexp = copy_to_mode_reg (Pmode, funexp); +#endif + + insn_before = get_last_insn (); + + /* Cannot pass FUNEXP since emit_library_call insists + on getting a SYMBOL_REF. But cse will make this SYMBOL_REF + be replaced with the copy we made just above. */ + /* Pass 1 for NO_QUEUE so we don't lose any increments + if the libcall is cse'd or moved. */ + emit_library_call (gen_rtx (SYMBOL_REF, Pmode, + binoptab->handlers[(int) mode].lib_call), + 1, mode, 2, op0, mode, op1, mode); + target = hard_libcall_value (mode); + temp = copy_to_reg (target); + + if (insn_before == 0) + insn_first = get_insns (); + else + insn_first = NEXT_INSN (insn_before); + insn_last = get_last_insn (); + + REG_NOTES (insn_last) + = gen_rtx (EXPR_LIST, REG_EQUAL, + gen_rtx (binoptab->code, mode, op0, op1), + gen_rtx (INSN_LIST, REG_RETVAL, insn_first, + REG_NOTES (insn_last))); + REG_NOTES (insn_first) + = gen_rtx (INSN_LIST, REG_LIBCALL, insn_last, + REG_NOTES (insn_first)); + return temp; + } + + delete_insns_since (last); + + /* It can't be done in this mode. Can we do it in a wider mode? */ + + if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN + || methods == OPTAB_MUST_WIDEN)) + return 0; /* Caller says, don't even try. */ + + /* Compute the value of METHODS to pass to recursive calls. + Don't allow widening to be tried recursively. */ + + methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT); + + /* Widening is now independent of specific machine modes. + It is assumed that widening may be performed to any + higher numbered mode in the same mode class. */ + + if (class == MODE_INT || class == MODE_FLOAT) + { + for (wider_mode = INC_MODE (mode); + ((int) wider_mode < (int) MAX_MACHINE_MODE + && GET_MODE_CLASS (wider_mode) == class); + wider_mode = INC_MODE (wider_mode)) + { + if ((binoptab->handlers[(int) wider_mode].insn_code + != CODE_FOR_nothing) + || (methods == OPTAB_LIB + && binoptab->handlers[(int) wider_mode].lib_call)) + { + rtx xop0 = op0, xop1 = op1; + int no_extend = 0; + + /* For certain operations, we need not actually extend + the narrow operands, as long as we will truncate + the results to the same narrowness. */ + + if (binoptab == ior_optab || binoptab == and_optab + || binoptab == xor_optab || binoptab == andcb_optab + || binoptab == add_optab || binoptab == sub_optab + || binoptab == smul_optab || binoptab == umul_optab + || binoptab == ashl_optab || binoptab == lshl_optab) + no_extend = 1; + + if (GET_MODE (xop0) != VOIDmode) + { + if (no_extend) + { + temp = force_reg (GET_MODE (xop0), xop0); + xop0 = gen_rtx (SUBREG, wider_mode, temp, 0); + } + else + { + temp = gen_reg_rtx (wider_mode); + convert_move (temp, xop0, unsignedp); + xop0 = temp; + } + } + if (GET_MODE (xop1) != VOIDmode) + { + if (no_extend) + { + temp = force_reg (GET_MODE (xop1), xop1); + xop1 = gen_rtx (SUBREG, wider_mode, temp, 0); + } + else + { + temp = gen_reg_rtx (wider_mode); + convert_move (temp, xop1, unsignedp); + xop1 = temp; + } + } + + temp = expand_binop (wider_mode, binoptab, xop0, xop1, 0, + unsignedp, methods); + if (temp) + { + if (class == MODE_FLOAT) + { + if (target == 0) + target = gen_reg_rtx (mode); + convert_move (target, temp, 0); + return target; + } + else + return gen_lowpart (mode, temp); + } + else + delete_insns_since (last); + } + } + } + + return 0; +} + +/* Expand a binary operator which has both signed and unsigned forms. + UOPTAB is the optab for unsigned operations, and SOPTAB is for + signed operations. + + If we widen unsigned operands, we may use a signed wider operation instead + of an unsigned wider operation, since the result would be the same. */ + +rtx +sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods) + enum machine_mode mode; + optab uoptab, soptab; + rtx op0, op1, target; + int unsignedp; + enum optab_methods methods; +{ + register rtx temp; + optab direct_optab = unsignedp ? uoptab : soptab; + struct optab wide_soptab; + + /* Do it without widening, if possible. */ + temp = expand_binop (mode, direct_optab, op0, op1, target, + unsignedp, OPTAB_DIRECT); + if (temp || methods == OPTAB_DIRECT) + return temp; + + /* Try widening to a signed int. Make a fake signed optab that + hides any signed insn for direct use. */ + wide_soptab = *soptab; + wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing; + wide_soptab.handlers[(int) mode].lib_call = 0; + + temp = expand_binop (mode, &wide_soptab, op0, op1, target, + unsignedp, OPTAB_WIDEN); + + /* For unsigned operands, try widening to an unsigned int. */ + if (temp == 0 && unsignedp) + temp = expand_binop (mode, uoptab, op0, op1, target, + unsignedp, OPTAB_WIDEN); + if (temp || methods == OPTAB_WIDEN) + return temp; + + /* Use the right width lib call if that exists. */ + temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB); + if (temp || methods == OPTAB_LIB) + return temp; + + /* Must widen and use a lib call, use either signed or unsigned. */ + temp = expand_binop (mode, &wide_soptab, op0, op1, target, + unsignedp, methods); + if (temp != 0) + return temp; + if (unsignedp) + return expand_binop (mode, uoptab, op0, op1, target, + unsignedp, methods); + return 0; +} + +/* Generate code to perform an operation specified by BINOPTAB + on operands OP0 and OP1, with two results to TARG1 and TARG2. + We assume that the order of the operands for the instruction + is TARG0, OP0, OP1, TARG1, which would fit a pattern like + [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))]. + + Either TARG0 or TARG1 may be zero, but what that means is that + that result is not actually wanted. We will generate it into + a dummy pseudo-reg and discard it. They may not both be zero. + + Returns 1 if this operation can be performed; 0 if not. */ + +int +expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp) + optab binoptab; + rtx op0, op1; + rtx targ0, targ1; + int unsignedp; +{ + enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1); + enum mode_class class; + enum machine_mode wider_mode; + + class = GET_MODE_CLASS (mode); + + op0 = protect_from_queue (op0, 0); + op1 = protect_from_queue (op1, 0); + + if (flag_force_mem) + { + op0 = force_not_mem (op0); + op1 = force_not_mem (op1); + } + + if (targ0) + targ0 = protect_from_queue (targ0, 1); + else + targ0 = gen_reg_rtx (mode); + if (targ1) + targ1 = protect_from_queue (targ1, 1); + else + targ1 = gen_reg_rtx (mode); + + if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing) + { + emit_insn (GEN_FCN (binoptab->handlers[(int) mode].insn_code) + (targ0, op0, op1, targ1)); + return 1; + } + + /* It can't be done in this mode. Can we do it in a wider mode? */ + + if (class == MODE_INT || class == MODE_FLOAT) + { + for (wider_mode = INC_MODE (mode); + ((int) wider_mode < (int) MAX_MACHINE_MODE + && GET_MODE_CLASS (wider_mode) == class); + wider_mode = INC_MODE (wider_mode)) + { + if (binoptab->handlers[(int) wider_mode].insn_code + != CODE_FOR_nothing) + { + expand_twoval_binop_convert (binoptab, wider_mode, op0, op1, + targ0, targ1, unsignedp); + return 1; + } + } + } + return 0; +} + +int +expand_twoval_binop_convert (binoptab, mode, op0, op1, targ0, targ1, unsignedp) + register optab binoptab; + register rtx op0, op1, targ0, targ1; + int unsignedp; +{ + register rtx t0 = gen_reg_rtx (SImode); + register rtx t1 = gen_reg_rtx (SImode); + register rtx temp; + + temp = gen_reg_rtx (SImode); + convert_move (temp, op0, unsignedp); + op0 = temp; + temp = gen_reg_rtx (SImode); + convert_move (temp, op1, unsignedp); + op1 = temp; + + expand_twoval_binop (binoptab, op0, op1, t0, t1, unsignedp); + convert_move (targ0, t0, unsignedp); + convert_move (targ1, t1, unsignedp); + return 1; +} + +/* Generate code to perform an operation specified by UNOPTAB + on operand OP0, with result having machine-mode MODE. + + UNSIGNEDP is for the case where we have to widen the operands + to perform the operation. It says to use zero-extension. + + If TARGET is nonzero, the value + is generated there, if it is convenient to do so. + In all cases an rtx is returned for the locus of the value; + this may or may not be TARGET. */ + +rtx +expand_unop (mode, unoptab, op0, target, unsignedp) + enum machine_mode mode; + optab unoptab; + rtx op0; + rtx target; + int unsignedp; +{ + enum mode_class class; + enum machine_mode wider_mode; + register rtx temp; + + class = GET_MODE_CLASS (mode); + + op0 = protect_from_queue (op0, 0); + + if (flag_force_mem) + { + op0 = force_not_mem (op0); + } + + if (target) + target = protect_from_queue (target, 1); + + if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing) + { + int icode = (int) unoptab->handlers[(int) mode].insn_code; + enum machine_mode mode0 = insn_operand_mode[icode][1]; + + if (target) + temp = target; + else + temp = gen_reg_rtx (mode); + + if (GET_MODE (op0) != VOIDmode + && GET_MODE (op0) != mode0) + op0 = convert_to_mode (mode0, op0, unsignedp); + + /* Now, if insn requires register operands, put operands into regs. */ + + if (! (*insn_operand_predicate[icode][1]) (op0, mode0)) + op0 = force_reg (mode0, op0); + + if (! (*insn_operand_predicate[icode][0]) (temp, mode)) + temp = gen_reg_rtx (mode); + + emit_insn (GEN_FCN (icode) (temp, op0)); + return temp; + } + else if (unoptab->handlers[(int) mode].lib_call) + { + rtx insn_before, insn_last; + rtx funexp = gen_rtx (SYMBOL_REF, Pmode, + unoptab->handlers[(int) mode].lib_call); + + /* Pass the address through a pseudoreg, if desired, + before the "beginning" of the library call (for deletion). */ +#ifndef NO_FUNCTION_CSE + if (! flag_no_function_cse) + funexp = copy_to_mode_reg (Pmode, funexp); +#endif + + insn_before = get_last_insn (); + + /* Cannot pass FUNEXP since emit_library_call insists + on getting a SYMBOL_REF. But cse will make this SYMBOL_REF + be replaced with the copy we made just above. */ + /* Pass 1 for NO_QUEUE so we don't lose any increments + if the libcall is cse'd or moved. */ + emit_library_call (gen_rtx (SYMBOL_REF, Pmode, + unoptab->handlers[(int) mode].lib_call), + 1, mode, 1, op0, mode); + target = hard_libcall_value (mode); + temp = copy_to_reg (target); + insn_last = get_last_insn (); + REG_NOTES (insn_last) + = gen_rtx (EXPR_LIST, REG_EQUAL, + gen_rtx (unoptab->code, mode, op0), + gen_rtx (INSN_LIST, REG_RETVAL, + NEXT_INSN (insn_before), + REG_NOTES (insn_last))); + REG_NOTES (NEXT_INSN (insn_before)) + = gen_rtx (INSN_LIST, REG_LIBCALL, insn_last, + REG_NOTES (NEXT_INSN (insn_before))); + return temp; + } + + /* It can't be done in this mode. Can we do it in a wider mode? */ + + if (class == MODE_INT || class == MODE_FLOAT) + { + for (wider_mode = INC_MODE (mode); + ((int) wider_mode < (int) MAX_MACHINE_MODE + && GET_MODE_CLASS (wider_mode) == class); + wider_mode = INC_MODE (wider_mode)) + { + if ((unoptab->handlers[(int) wider_mode].insn_code + != CODE_FOR_nothing) + || unoptab->handlers[(int) wider_mode].lib_call) + { + if (GET_MODE (op0) != VOIDmode) + { + temp = gen_reg_rtx (wider_mode); + convert_move (temp, op0, unsignedp); + op0 = temp; + } + + target = expand_unop (wider_mode, unoptab, op0, 0, unsignedp); + if (class == MODE_FLOAT) + { + if (target == 0) + target = gen_reg_rtx (mode); + convert_move (target, temp, 0); + return target; + } + else + return gen_lowpart (mode, target); + } + } + } + + return 0; +} + +/* Generate an instruction whose insn-code is INSN_CODE, + with two operands: an output TARGET and an input OP0. + TARGET *must* be nonzero, and the output is always stored there. + CODE is an rtx code such that (CODE OP0) is an rtx that describes + the value that is stored into TARGET. */ + +void +emit_unop_insn (icode, target, op0, code) + int icode; + rtx target; + rtx op0; + enum rtx_code code; +{ + register rtx temp; + enum machine_mode mode0 = insn_operand_mode[icode][1]; + rtx insn; + rtx prev_insn; + + temp = target = protect_from_queue (target, 1); + + op0 = protect_from_queue (op0, 0); + + if (flag_force_mem) + op0 = force_not_mem (op0); + + /* Now, if insn requires register operands, put operands into regs. */ + + if (! (*insn_operand_predicate[icode][1]) (op0, mode0)) + op0 = force_reg (mode0, op0); + + if (! (*insn_operand_predicate[icode][0]) (temp, GET_MODE (temp)) + || (flag_force_mem && GET_CODE (temp) == MEM)) + temp = gen_reg_rtx (GET_MODE (temp)); + + prev_insn = get_last_insn (); + insn = emit_insn (GEN_FCN (icode) (temp, op0)); + + /* If we just made a multi-insn sequence, + record in the last insn an equivalent expression for its value + and a pointer to the first insn. This makes cse possible. */ + if (code != UNKNOWN && PREV_INSN (insn) != prev_insn) + REG_NOTES (insn) + = gen_rtx (EXPR_LIST, REG_EQUAL, + gen_rtx (code, GET_MODE (temp), op0), + REG_NOTES (insn)); + + if (temp != target) + emit_move_insn (target, temp); +} + +/* Generate code to store zero in X. */ + +void +emit_clr_insn (x) + rtx x; +{ + emit_move_insn (x, const0_rtx); +} + +/* Generate code to store 1 in X + assuming it contains zero beforehand. */ + +void +emit_0_to_1_insn (x) + rtx x; +{ + emit_move_insn (x, const1_rtx); +} + +/* Generate code to compare X with Y + so that the condition codes are set. + + UNSIGNEDP nonzero says that X and Y are unsigned; + this matters if they need to be widened. + + If they have mode BLKmode, then SIZE specifies the size of both X and Y, + and ALIGN specifies the known shared alignment of X and Y. */ + +void +emit_cmp_insn (x, y, size, unsignedp, align) + rtx x, y; + rtx size; + int unsignedp; + int align; +{ + enum machine_mode mode = GET_MODE (x); + enum mode_class class; + enum machine_mode wider_mode; + + if (mode == VOIDmode) mode = GET_MODE (y); + /* They could both be VOIDmode if both args are immediate constants, + but we should fold that at an earlier stage. + With no special code here, this will call abort, + reminding the programmer to implement such folding. */ + + class = GET_MODE_CLASS (mode); + + if (mode != BLKmode && flag_force_mem) + { + x = force_not_mem (x); + y = force_not_mem (y); + } + + /* Handle all BLKmode compares. */ + + if (mode == BLKmode) + { + emit_queue (); + x = protect_from_queue (x, 0); + y = protect_from_queue (y, 0); + + if (size == 0) + abort (); +#ifdef HAVE_cmpstrqi + if (HAVE_cmpstrqi + && GET_CODE (size) == CONST_INT + && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode))) + emit_insn (gen_cmpstrqi (x, y, size, + gen_rtx (CONST_INT, VOIDmode, align))); + else +#endif +#ifdef HAVE_cmpstrhi + if (HAVE_cmpstrhi + && GET_CODE (size) == CONST_INT + && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode))) + emit_insn (gen_cmpstrhi (x, y, size, + gen_rtx (CONST_INT, VOIDmode, align))); + else +#endif +#ifdef HAVE_cmpstrsi + if (HAVE_cmpstrsi) + emit_insn (gen_cmpstrsi (x, y, convert_to_mode (SImode, size, 1), + gen_rtx (CONST_INT, VOIDmode, align))); + else +#endif + { +#ifdef TARGET_MEM_FUNCTIONS + emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcmp"), 0, + SImode, 3, + XEXP (x, 0), Pmode, XEXP (y, 0), Pmode, + size, Pmode); +#else + emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcmp"), 0, + SImode, 3, + XEXP (x, 0), Pmode, XEXP (y, 0), Pmode, + size, Pmode); +#endif + emit_cmp_insn (hard_libcall_value (SImode), const0_rtx, 0, 0, 0); + } + return; + } + + /* Handle some compares against zero. */ + + if (y == CONST0_RTX (mode) + && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) + { + int icode = (int) tst_optab->handlers[(int) mode].insn_code; + + emit_queue (); + x = protect_from_queue (x, 0); + y = protect_from_queue (y, 0); + + /* Now, if insn requires register operands, put operands into regs. */ + if (! (*insn_operand_predicate[icode][0]) + (x, insn_operand_mode[icode][0])) + x = force_reg (insn_operand_mode[icode][0], x); + + emit_insn (GEN_FCN (icode) (x)); + return; + } + + /* Handle compares for which there is a directly suitable insn. */ + + if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) + { + int icode = (int) cmp_optab->handlers[(int) mode].insn_code; + + emit_queue (); + x = protect_from_queue (x, 0); + y = protect_from_queue (y, 0); + + /* Now, if insn requires register operands, put operands into regs. */ + if (! (*insn_operand_predicate[icode][0]) + (x, insn_operand_mode[icode][0])) + x = force_reg (insn_operand_mode[icode][0], x); + + if (! (*insn_operand_predicate[icode][1]) + (y, insn_operand_mode[icode][1])) + y = force_reg (insn_operand_mode[icode][1], y); + + emit_insn (GEN_FCN (icode) (x, y)); + return; + } + + /* Try widening if we can find a direct insn that way. */ + + if (class == MODE_INT || class == MODE_FLOAT) + { + for (wider_mode = INC_MODE (mode); + ((int) wider_mode < (int) MAX_MACHINE_MODE + && GET_MODE_CLASS (wider_mode) == class); + wider_mode = INC_MODE (wider_mode)) + { + if (cmp_optab->handlers[(int) wider_mode].insn_code + != CODE_FOR_nothing) + { + x = convert_to_mode (wider_mode, x, unsignedp); + y = convert_to_mode (wider_mode, y, unsignedp); + emit_cmp_insn (x, y, 0, unsignedp, align); + return; + } + } + } + + /* Handle a lib call just for the mode we are using. */ + + if (cmp_optab->handlers[(int) mode].lib_call) + { + char *string = cmp_optab->handlers[(int) mode].lib_call; + /* If we want unsigned, and this mode has a distinct unsigned + comparison routine, use that. */ + if (unsignedp && ucmp_optab->handlers[(int) mode].lib_call) + string = ucmp_optab->handlers[(int) mode].lib_call; + + emit_library_call (gen_rtx (SYMBOL_REF, Pmode, string), 0, + SImode, 2, x, mode, y, mode); + + /* Integer comparison returns a result that must be compared against 1, + so that even if we do an unsigned compare afterward, + there is still a value that can represent the result "less than". */ + if (GET_MODE_CLASS (mode) == MODE_INT) + emit_cmp_insn (hard_libcall_value (SImode), const1_rtx, 0, unsignedp, 0); + else + emit_cmp_insn (hard_libcall_value (SImode), const0_rtx, 0, 0, 0); + return; + } + + /* Try widening and then using a libcall. */ + + if (class == MODE_FLOAT) + { + for (wider_mode = INC_MODE (mode); + ((int) wider_mode < (int) MAX_MACHINE_MODE + && GET_MODE_CLASS (wider_mode) == class); + wider_mode = INC_MODE (wider_mode)) + { + if ((cmp_optab->handlers[(int) wider_mode].insn_code + != CODE_FOR_nothing) + || (cmp_optab->handlers[(int) wider_mode].lib_call != 0)) + { + x = convert_to_mode (wider_mode, x, unsignedp); + y = convert_to_mode (wider_mode, y, unsignedp); + emit_cmp_insn (x, y, 0, unsignedp, align); + } + } + return; + } + + abort (); +} + +/* These three functions generate an insn body and return it + rather than emitting the insn. + + They do not protect from queued increments, + because they may be used 1) in protect_from_queue itself + and 2) in other passes where there is no queue. */ + +/* Generate and return an insn body to add Y to X. */ + +rtx +gen_add2_insn (x, y) + rtx x, y; +{ + return (GEN_FCN (add_optab->handlers[(int) GET_MODE (x)].insn_code) + (x, x, y)); +} + +int +have_add2_insn (mode) + enum machine_mode mode; +{ + return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing; +} + +/* Generate and return an insn body to subtract Y from X. */ + +rtx +gen_sub2_insn (x, y) + rtx x, y; +{ + return (GEN_FCN (sub_optab->handlers[(int) GET_MODE (x)].insn_code) + (x, x, y)); +} + +int +have_sub2_insn (mode) + enum machine_mode mode; +{ + return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing; +} + +/* Generate the body of an instruction to copy Y into X. */ + +rtx +gen_move_insn (x, y) + rtx x, y; +{ + register enum machine_mode mode = GET_MODE (x); + if (mode == VOIDmode) + mode = GET_MODE (y); + return (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y)); +} + +#if 0 +/* Tables of patterns for extending one integer mode to another. */ +enum insn_code zero_extend_optab[MAX_MACHINE_MODE][MAX_MACHINE_MODE]; +enum insn_code sign_extend_optab[MAX_MACHINE_MODE][MAX_MACHINE_MODE]; + +/* Generate the body of an insn to extend Y (with mode MFROM) + into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */ + +rtx +gen_extend_insn (x, y, mto, mfrom, unsignedp) + rtx x, y; + enum machine_mode mto, mfrom; + int unsignedp; +{ + return (GEN_FCN ((unsignedp ? zero_extend_optab : sign_extend_optab) + [(int)mto][(int)mfrom]) + (x, y)); +} + +static void +init_extends () +{ + bzero (sign_extend_optab, sizeof sign_extend_optab); + bzero (zero_extend_optab, sizeof zero_extend_optab); + sign_extend_optab[(int) SImode][(int) HImode] = CODE_FOR_extendhisi2; + sign_extend_optab[(int) SImode][(int) QImode] = CODE_FOR_extendqisi2; + sign_extend_optab[(int) HImode][(int) QImode] = CODE_FOR_extendqihi2; + zero_extend_optab[(int) SImode][(int) HImode] = CODE_FOR_zero_extendhisi2; + zero_extend_optab[(int) SImode][(int) QImode] = CODE_FOR_zero_extendqisi2; + zero_extend_optab[(int) HImode][(int) QImode] = CODE_FOR_zero_extendqihi2; +} +#endif + +/* can_fix_p and can_float_p say whether the target machine + can directly convert a given fixed point type to + a given floating point type, or vice versa. + The returned value is the CODE_FOR_... value to use, + or CODE_FOR_nothing if these modes cannot be directly converted. */ + +static enum insn_code fixtab[2][2][2]; +static enum insn_code fixtrunctab[2][2][2]; +static enum insn_code floattab[2][2]; + +/* *TRUNCP_PTR is set to 1 if it is necessary to output + an explicit FTRUNC insn before the fix insn; otherwise 0. */ + +static enum insn_code +can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr) + enum machine_mode fltmode, fixmode; + int unsignedp; + int *truncp_ptr; +{ + *truncp_ptr = 0; + if (fixtrunctab[fltmode != SFmode][fixmode == DImode][unsignedp] + != CODE_FOR_nothing) + return fixtrunctab[fltmode != SFmode][fixmode == DImode][unsignedp]; + if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing) + { + *truncp_ptr = 1; + return fixtab[fltmode != SFmode][fixmode == DImode][unsignedp]; + } + return CODE_FOR_nothing; +} + +static enum insn_code +can_float_p (fltmode, fixmode) + enum machine_mode fixmode, fltmode; +{ + return floattab[fltmode != SFmode][fixmode == DImode]; +} + +void +init_fixtab () +{ + enum insn_code *p; + for (p = fixtab[0][0]; + p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]); + p++) + *p = CODE_FOR_nothing; + for (p = fixtrunctab[0][0]; + p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]); + p++) + *p = CODE_FOR_nothing; + +#ifdef HAVE_fixsfsi2 + if (HAVE_fixsfsi2) + fixtab[0][0][0] = CODE_FOR_fixsfsi2; +#endif +#ifdef HAVE_fixsfdi2 + if (HAVE_fixsfdi2) + fixtab[0][1][0] = CODE_FOR_fixsfdi2; +#endif +#ifdef HAVE_fixdfsi2 + if (HAVE_fixdfsi2) + fixtab[1][0][0] = CODE_FOR_fixdfsi2; +#endif +#ifdef HAVE_fixdfdi2 + if (HAVE_fixdfdi2) + fixtab[1][1][0] = CODE_FOR_fixdfdi2; +#endif + +#ifdef HAVE_fixunssfsi2 + if (HAVE_fixunssfsi2) + fixtab[0][0][1] = CODE_FOR_fixunssfsi2; +#endif +#ifdef HAVE_fixunssfdi2 + if (HAVE_fixunssfdi2) + fixtab[0][1][1] = CODE_FOR_fixunssfdi2; +#endif +#ifdef HAVE_fixunsdfsi2 + if (HAVE_fixunsdfsi2) + fixtab[1][0][1] = CODE_FOR_fixunsdfsi2; +#endif +#ifdef HAVE_fixunsdfdi2 + if (HAVE_fixunsdfdi2) + fixtab[1][1][1] = CODE_FOR_fixunsdfdi2; +#endif + +#ifdef HAVE_fix_truncsfsi2 + if (HAVE_fix_truncsfsi2) + fixtrunctab[0][0][0] = CODE_FOR_fix_truncsfsi2; +#endif +#ifdef HAVE_fix_truncsfdi2 + if (HAVE_fix_truncsfdi2) + fixtrunctab[0][1][0] = CODE_FOR_fix_truncsfdi2; +#endif +#ifdef HAVE_fix_truncdfsi2 + if (HAVE_fix_truncdfsi2) + fixtrunctab[1][0][0] = CODE_FOR_fix_truncdfsi2; +#endif +#ifdef HAVE_fix_truncdfdi2 + if (HAVE_fix_truncdfdi2) + fixtrunctab[1][1][0] = CODE_FOR_fix_truncdfdi2; +#endif + +#ifdef HAVE_fixuns_truncsfsi2 + if (HAVE_fixuns_truncsfsi2) + fixtrunctab[0][0][1] = CODE_FOR_fixuns_truncsfsi2; +#endif +#ifdef HAVE_fixuns_truncsfdi2 + if (HAVE_fixuns_truncsfdi2) + fixtrunctab[0][1][1] = CODE_FOR_fixuns_truncsfdi2; +#endif +#ifdef HAVE_fixuns_truncdfsi2 + if (HAVE_fixuns_truncdfsi2) + fixtrunctab[1][0][1] = CODE_FOR_fixuns_truncdfsi2; +#endif +#ifdef HAVE_fixuns_truncdfdi2 + if (HAVE_fixuns_truncdfdi2) + fixtrunctab[1][1][1] = CODE_FOR_fixuns_truncdfdi2; +#endif + +#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC + /* This flag says the same insns that convert to a signed fixnum + also convert validly to an unsigned one. */ + { + int i; + int j; + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) + fixtrunctab[i][j][1] = fixtrunctab[i][j][0]; + } +#endif +} + +void +init_floattab () +{ + enum insn_code *p; + for (p = floattab[0]; + p < floattab[0] + sizeof floattab / sizeof (floattab[0][0]); + p++) + *p = CODE_FOR_nothing; + +#ifdef HAVE_floatsisf2 + if (HAVE_floatsisf2) + floattab[0][0] = CODE_FOR_floatsisf2; +#endif +#ifdef HAVE_floatdisf2 + if (HAVE_floatdisf2) + floattab[0][1] = CODE_FOR_floatdisf2; +#endif +#ifdef HAVE_floatsidf2 + if (HAVE_floatsidf2) + floattab[1][0] = CODE_FOR_floatsidf2; +#endif +#ifdef HAVE_floatdidf2 + if (HAVE_floatdidf2) + floattab[1][1] = CODE_FOR_floatdidf2; +#endif +} + +/* Generate code to convert FROM to floating point + and store in TO. FROM must be fixed point. + UNSIGNEDP nonzero means regard FROM as unsigned. + Normally this is done by correcting the final value + if it is negative. */ + +void +expand_float (real_to, from, unsignedp) + rtx real_to, from; + int unsignedp; +{ + enum insn_code icode; + register rtx to; + + /* Constants should get converted in `fold'. + We lose here since we don't know the mode. */ + if (GET_MODE (from) == VOIDmode) + abort (); + + to = real_to = protect_from_queue (real_to, 1); + from = protect_from_queue (from, 0); + + if (flag_force_mem) + { + from = force_not_mem (from); + } + + /* If we are about to do some arithmetic to correct for an + unsigned operand, do it in a pseudo-register. */ + + if (unsignedp + && ! (GET_CODE (to) == REG && REGNO (to) >= FIRST_PSEUDO_REGISTER)) + to = gen_reg_rtx (GET_MODE (to)); + + /* Now do the basic conversion. Do it in the specified modes if possible; + otherwise convert either input, output or both with wider mode; + otherwise use a library call. */ + + if ((icode = can_float_p (GET_MODE (to), GET_MODE (from))) + != CODE_FOR_nothing) + { + emit_unop_insn (icode, to, from, FLOAT); + } + else if (GET_MODE (to) == SFmode + && ((icode = can_float_p (DFmode, GET_MODE (from))) + != CODE_FOR_nothing)) + { + to = gen_reg_rtx (DFmode); + emit_unop_insn (icode, to, from, FLOAT); + } + /* If we can't float a SI, maybe we can float a DI. + If so, convert to DI and then float. */ + else if (GET_MODE (from) != DImode + && (can_float_p (GET_MODE (to), DImode) != CODE_FOR_nothing + || can_float_p (DFmode, DImode) != CODE_FOR_nothing)) + { + register rtx tem = gen_reg_rtx (DImode); + convert_move (tem, from, unsignedp); + from = tem; + /* If we extend FROM then we don't need to correct + the final value for unsignedness. */ + unsignedp = 0; + + if ((icode = can_float_p (GET_MODE (to), GET_MODE (from))) + != CODE_FOR_nothing) + { + emit_unop_insn (icode, to, from, FLOAT); + } + else if ((icode = can_float_p (DFmode, DImode)) + != CODE_FOR_nothing) + { + to = gen_reg_rtx (DFmode); + emit_unop_insn (icode, to, from, FLOAT); + } + } + /* No hardware instruction available; call a library + to convert from SImode or DImode into DFmode. */ + else + { + if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode)) + { + from = convert_to_mode (SImode, from, unsignedp); + unsignedp = 0; + } + emit_library_call (gen_rtx (SYMBOL_REF, Pmode, + (GET_MODE (from) == SImode ? "__floatsidf" + : "__floatdidf")), + 0, DFmode, 1, from, GET_MODE (from)); + to = copy_to_reg (hard_libcall_value (DFmode)); + } + + /* If FROM was unsigned but we treated it as signed, + then in the case where it is negative (and therefore TO is negative), + correct its value by 2**bitwidth. */ + + if (unsignedp) + { + rtx label = gen_label_rtx (); + rtx temp; + REAL_VALUE_TYPE offset; + + do_pending_stack_adjust (); + emit_cmp_insn (to, GET_MODE (to) == DFmode ? dconst0_rtx : fconst0_rtx, + 0, 0, 0); + emit_jump_insn (gen_bge (label)); + offset = REAL_VALUE_LDEXP (1.0, GET_MODE_BITSIZE (GET_MODE (from))); + temp = expand_binop (GET_MODE (to), add_optab, to, + immed_real_const_1 (offset, GET_MODE (to)), + to, 0, OPTAB_LIB_WIDEN); + if (temp != to) + emit_move_insn (to, temp); + do_pending_stack_adjust (); + emit_label (label); + } + + /* Copy result to requested destination + if we have been computing in a temp location. */ + + if (to != real_to) + { + if (GET_MODE (real_to) == GET_MODE (to)) + emit_move_insn (real_to, to); + else + convert_move (real_to, to, 0); + } +} + +/* expand_fix: generate code to convert FROM to fixed point + and store in TO. FROM must be floating point. */ + +static rtx +ftruncify (x) + rtx x; +{ + rtx temp = gen_reg_rtx (GET_MODE (x)); + return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0); +} + +void +expand_fix (to, from, unsignedp) + register rtx to, from; + int unsignedp; +{ + enum insn_code icode; + register rtx target; + int must_trunc = 0; + + while (1) + { + icode = can_fix_p (GET_MODE (to), GET_MODE (from), unsignedp, &must_trunc); + if (icode != CODE_FOR_nothing) + { + if (must_trunc) + from = ftruncify (from); + + emit_unop_insn (icode, to, from, FIX); + return; + } + +#if 0 /* Turned off. It fails because the positive numbers + that become temporarily negative are rounded up instead of down. */ + + /* If no insns for unsigned conversion, + we can go via a signed number. + But make sure we won't overflow in the compiler. */ + if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_INT + /* Make sure we won't lose significant bits doing this. */ + && GET_MODE_BITSIZE (GET_MODE (from)) > GET_MODE_BITSIZE (GET_MODE (to))) + { + icode = can_fix_p (GET_MODE (to), GET_MODE (from), + 0, &must_trunc); + + if (icode != CODE_FOR_nothing) + { + REAL_VALUE_TYPE offset; + rtx temp, temp1; + int bitsize = GET_MODE_BITSIZE (GET_MODE (to)); + + if (must_trunc) + from = ftruncify (from); + + /* Subtract 2**(N-1), convert to signed number, + then add 2**(N-1). */ + offset = REAL_VALUE_LDEXP (1.0, bitsize - 1); + temp = expand_binop (GET_MODE (from), sub_optab, from, + immed_real_const_1 (offset, GET_MODE (from)), + 0, 0, OPTAB_LIB_WIDEN); + + temp1 = gen_reg_rtx (GET_MODE (to)); + emit_unop_insn (icode, temp1, temp, FIX); + temp = expand_binop (GET_MODE (to), add_optab, temp1, + gen_rtx (CONST_INT, VOIDmode, + 1 << (bitsize - 1)), + to, 1, OPTAB_LIB_WIDEN); + if (temp != to) + emit_move_insn (to, temp); + return; + } + } +#endif + icode = can_fix_p (DImode, GET_MODE (from), unsignedp, &must_trunc); + + if (GET_MODE (to) != DImode && icode != CODE_FOR_nothing) + { + register rtx temp = gen_reg_rtx (DImode); + + if (must_trunc) + from = ftruncify (from); + emit_unop_insn (icode, temp, from, FIX); + convert_move (to, temp, unsignedp); + return; + } + + /* If FROM is not DFmode, convert to DFmode and try again from there. */ + if (GET_MODE (from) == DFmode) + break; + + from = convert_to_mode (DFmode, from, 0); + } + + /* We can't do it with an insn, so use a library call. + The mode of FROM is known to be DFmode. */ + + to = protect_from_queue (to, 1); + from = protect_from_queue (from, 0); + + if (flag_force_mem) + from = force_not_mem (from); + + if (GET_MODE (to) != DImode) + { + emit_library_call (gen_rtx (SYMBOL_REF, Pmode, + unsignedp ? "__fixunsdfsi" + : "__fixdfsi"), + 0, SImode, 1, from, DFmode); + target = hard_libcall_value (SImode); + } + else + { + emit_library_call (gen_rtx (SYMBOL_REF, Pmode, + unsignedp ? "__fixunsdfdi" + : "__fixdfdi"), + 0, DImode, 1, from, DFmode); + target = hard_libcall_value (DImode); + } + + if (GET_MODE (to) == GET_MODE (target)) + emit_move_insn (to, target); + else + convert_move (to, target, 0); +} + +static optab +init_optab (code) + enum rtx_code code; +{ + int i; + optab op = (optab) malloc (sizeof (struct optab)); + op->code = code; + for (i = 0; i < NUM_MACHINE_MODES; i++) + { + op->handlers[i].insn_code = CODE_FOR_nothing; + op->handlers[i].lib_call = 0; + } + return op; +} + +/* Call this once to initialize the contents of the optabs + appropriately for the current target machine. */ + +void +init_optabs () +{ + init_fixtab (); + init_floattab (); + init_comparisons (); +/* init_extends (); */ + + add_optab = init_optab (PLUS); + sub_optab = init_optab (MINUS); + smul_optab = init_optab (MULT); + umul_optab = init_optab (UMULT); + smul_widen_optab = init_optab (MULT); + umul_widen_optab = init_optab (UMULT); + sdiv_optab = init_optab (DIV); + sdivmod_optab = init_optab (UNKNOWN); + udiv_optab = init_optab (UDIV); + udivmod_optab = init_optab (UNKNOWN); + smod_optab = init_optab (MOD); + umod_optab = init_optab (UMOD); + flodiv_optab = init_optab (DIV); + ftrunc_optab = init_optab (UNKNOWN); + and_optab = init_optab (AND); + andcb_optab = init_optab (UNKNOWN); + ior_optab = init_optab (IOR); + xor_optab = init_optab (XOR); + ashl_optab = init_optab (ASHIFT); + ashr_optab = init_optab (ASHIFTRT); + lshl_optab = init_optab (LSHIFT); + lshr_optab = init_optab (LSHIFTRT); + rotl_optab = init_optab (ROTATE); + rotr_optab = init_optab (ROTATERT); + mov_optab = init_optab (UNKNOWN); + movstrict_optab = init_optab (UNKNOWN); + cmp_optab = init_optab (UNKNOWN); + ucmp_optab = init_optab (UNKNOWN); + tst_optab = init_optab (UNKNOWN); + neg_optab = init_optab (NEG); + abs_optab = init_optab (ABS); + one_cmpl_optab = init_optab (NOT); + ffs_optab = init_optab (FFS); + +#ifdef HAVE_addqi3 + if (HAVE_addqi3) + add_optab->handlers[(int) QImode].insn_code = CODE_FOR_addqi3; +#endif +#ifdef HAVE_addhi3 + if (HAVE_addhi3) + add_optab->handlers[(int) HImode].insn_code = CODE_FOR_addhi3; +#endif +#ifdef HAVE_addsi3 + if (HAVE_addsi3) + add_optab->handlers[(int) SImode].insn_code = CODE_FOR_addsi3; +#endif +#ifdef HAVE_adddi3 + if (HAVE_adddi3) + add_optab->handlers[(int) DImode].insn_code = CODE_FOR_adddi3; +#endif +#ifdef HAVE_addsf3 + if (HAVE_addsf3) + add_optab->handlers[(int) SFmode].insn_code = CODE_FOR_addsf3; +#endif +#ifdef HAVE_adddf3 + if (HAVE_adddf3) + add_optab->handlers[(int) DFmode].insn_code = CODE_FOR_adddf3; +#endif + add_optab->handlers[(int) DImode].lib_call = "__adddi3"; + add_optab->handlers[(int) SFmode].lib_call = "__addsf3"; + add_optab->handlers[(int) DFmode].lib_call = "__adddf3"; + +#ifdef HAVE_subqi3 + if (HAVE_subqi3) + sub_optab->handlers[(int) QImode].insn_code = CODE_FOR_subqi3; +#endif +#ifdef HAVE_subhi3 + if (HAVE_subhi3) + sub_optab->handlers[(int) HImode].insn_code = CODE_FOR_subhi3; +#endif +#ifdef HAVE_subsi3 + if (HAVE_subsi3) + sub_optab->handlers[(int) SImode].insn_code = CODE_FOR_subsi3; +#endif +#ifdef HAVE_subdi3 + if (HAVE_subdi3) + sub_optab->handlers[(int) DImode].insn_code = CODE_FOR_subdi3; +#endif +#ifdef HAVE_subsf3 + if (HAVE_subsf3) + sub_optab->handlers[(int) SFmode].insn_code = CODE_FOR_subsf3; +#endif +#ifdef HAVE_subdf3 + if (HAVE_subdf3) + sub_optab->handlers[(int) DFmode].insn_code = CODE_FOR_subdf3; +#endif + sub_optab->handlers[(int) DImode].lib_call = "__subdi3"; + sub_optab->handlers[(int) SFmode].lib_call = "__subsf3"; + sub_optab->handlers[(int) DFmode].lib_call = "__subdf3"; + +#ifdef HAVE_mulqi3 + if (HAVE_mulqi3) + smul_optab->handlers[(int) QImode].insn_code = CODE_FOR_mulqi3; +#endif +#ifdef HAVE_mulhi3 + if (HAVE_mulhi3) + smul_optab->handlers[(int) HImode].insn_code = CODE_FOR_mulhi3; +#endif +#ifdef HAVE_mulsi3 + if (HAVE_mulsi3) + smul_optab->handlers[(int) SImode].insn_code = CODE_FOR_mulsi3; +#endif +#ifdef HAVE_muldi3 + if (HAVE_muldi3) + smul_optab->handlers[(int) DImode].insn_code = CODE_FOR_muldi3; +#endif +#ifdef HAVE_mulsf3 + if (HAVE_mulsf3) + smul_optab->handlers[(int) SFmode].insn_code = CODE_FOR_mulsf3; +#endif +#ifdef HAVE_muldf3 + if (HAVE_muldf3) + smul_optab->handlers[(int) DFmode].insn_code = CODE_FOR_muldf3; +#endif + +#ifdef MULSI3_LIBCALL + smul_optab->handlers[(int) SImode].lib_call = MULSI3_LIBCALL; +#else + smul_optab->handlers[(int) SImode].lib_call = "__mulsi3"; +#endif + smul_optab->handlers[(int) DImode].lib_call = "__muldi3"; + smul_optab->handlers[(int) SFmode].lib_call = "__mulsf3"; + smul_optab->handlers[(int) DFmode].lib_call = "__muldf3"; + +#ifdef HAVE_mulqihi3 + if (HAVE_mulqihi3) + smul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_mulqihi3; +#endif +#ifdef HAVE_mulhisi3 + if (HAVE_mulhisi3) + smul_widen_optab->handlers[(int) SImode].insn_code = CODE_FOR_mulhisi3; +#endif +#ifdef HAVE_mulsidi3 + if (HAVE_mulsidi3) + smul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_mulsidi3; +#endif + +#ifdef HAVE_umulqi3 + if (HAVE_umulqi3) + umul_optab->handlers[(int) QImode].insn_code = CODE_FOR_umulqi3; +#endif +#ifdef HAVE_umulhi3 + if (HAVE_umulhi3) + umul_optab->handlers[(int) HImode].insn_code = CODE_FOR_umulhi3; +#endif +#ifdef HAVE_umulsi3 + if (HAVE_umulsi3) + umul_optab->handlers[(int) SImode].insn_code = CODE_FOR_umulsi3; +#endif +#ifdef HAVE_umuldi3 + if (HAVE_umuldi3) + umul_optab->handlers[(int) DImode].insn_code = CODE_FOR_umuldi3; +#endif +#ifdef HAVE_umulsf3 + if (HAVE_umulsf3) + umul_optab->handlers[(int) SFmode].insn_code = CODE_FOR_umulsf3; +#endif +#ifdef HAVE_umuldf3 + if (HAVE_umuldf3) + umul_optab->handlers[(int) DFmode].insn_code = CODE_FOR_umuldf3; +#endif + +#ifdef UMULSI3_LIBCALL + umul_optab->handlers[(int) SImode].lib_call = UMULSI3_LIBCALL; +#else + umul_optab->handlers[(int) SImode].lib_call = "__umulsi3"; +#endif + umul_optab->handlers[(int) DImode].lib_call = "__umuldi3"; + umul_optab->handlers[(int) SFmode].lib_call = "__umulsf3"; + umul_optab->handlers[(int) DFmode].lib_call = "__umuldf3"; + +#ifdef HAVE_umulqihi3 + if (HAVE_umulqihi3) + umul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_umulqihi3; +#endif +#ifdef HAVE_umulhisi3 + if (HAVE_umulhisi3) + umul_widen_optab->handlers[(int) SImode].insn_code = CODE_FOR_umulhisi3; +#endif +#ifdef HAVE_umulsidi3 + if (HAVE_umulsidi3) + umul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_umulsidi3; +#endif + +#ifdef HAVE_divqi3 + if (HAVE_divqi3) + sdiv_optab->handlers[(int) QImode].insn_code = CODE_FOR_divqi3; +#endif +#ifdef HAVE_divhi3 + if (HAVE_divhi3) + sdiv_optab->handlers[(int) HImode].insn_code = CODE_FOR_divhi3; +#endif +#ifdef HAVE_divsi3 + if (HAVE_divsi3) + sdiv_optab->handlers[(int) SImode].insn_code = CODE_FOR_divsi3; +#endif +#ifdef HAVE_divdi3 + if (HAVE_divdi3) + sdiv_optab->handlers[(int) DImode].insn_code = CODE_FOR_divdi3; +#endif + +#ifdef DIVSI3_LIBCALL + sdiv_optab->handlers[(int) SImode].lib_call = DIVSI3_LIBCALL; +#else + sdiv_optab->handlers[(int) SImode].lib_call = "__divsi3"; +#endif + sdiv_optab->handlers[(int) DImode].lib_call = "__divdi3"; + +#ifdef HAVE_udivqi3 + if (HAVE_udivqi3) + udiv_optab->handlers[(int) QImode].insn_code = CODE_FOR_udivqi3; +#endif +#ifdef HAVE_udivhi3 + if (HAVE_udivhi3) + udiv_optab->handlers[(int) HImode].insn_code = CODE_FOR_udivhi3; +#endif +#ifdef HAVE_udivsi3 + if (HAVE_udivsi3) + udiv_optab->handlers[(int) SImode].insn_code = CODE_FOR_udivsi3; +#endif +#ifdef HAVE_udivdi3 + if (HAVE_udivdi3) + udiv_optab->handlers[(int) DImode].insn_code = CODE_FOR_udivdi3; +#endif + +#ifdef UDIVSI3_LIBCALL + udiv_optab->handlers[(int) SImode].lib_call = UDIVSI3_LIBCALL; +#else + udiv_optab->handlers[(int) SImode].lib_call = "__udivsi3"; +#endif + udiv_optab->handlers[(int) DImode].lib_call = "__udivdi3"; + +#ifdef HAVE_divmodqi4 + if (HAVE_divmodqi4) + sdivmod_optab->handlers[(int) QImode].insn_code = CODE_FOR_divmodqi4; +#endif +#ifdef HAVE_divmodhi4 + if (HAVE_divmodhi4) + sdivmod_optab->handlers[(int) HImode].insn_code = CODE_FOR_divmodhi4; +#endif +#ifdef HAVE_divmodsi4 + if (HAVE_divmodsi4) + sdivmod_optab->handlers[(int) SImode].insn_code = CODE_FOR_divmodsi4; +#endif +#ifdef HAVE_divmoddi4 + if (HAVE_divmoddi4) + sdivmod_optab->handlers[(int) DImode].insn_code = CODE_FOR_divmoddi4; +#endif + +#ifdef HAVE_udivmodqi4 + if (HAVE_udivmodqi4) + udivmod_optab->handlers[(int) QImode].insn_code = CODE_FOR_udivmodqi4; +#endif +#ifdef HAVE_udivmodhi4 + if (HAVE_udivmodhi4) + udivmod_optab->handlers[(int) HImode].insn_code = CODE_FOR_udivmodhi4; +#endif +#ifdef HAVE_udivmodsi4 + if (HAVE_udivmodsi4) + udivmod_optab->handlers[(int) SImode].insn_code = CODE_FOR_udivmodsi4; +#endif +#ifdef HAVE_udivmoddi4 + if (HAVE_udivmoddi4) + udivmod_optab->handlers[(int) DImode].insn_code = CODE_FOR_udivmoddi4; +#endif + +#ifdef HAVE_modqi3 + if (HAVE_modqi3) + smod_optab->handlers[(int) QImode].insn_code = CODE_FOR_modqi3; +#endif +#ifdef HAVE_modhi3 + if (HAVE_modhi3) + smod_optab->handlers[(int) HImode].insn_code = CODE_FOR_modhi3; +#endif +#ifdef HAVE_modsi3 + if (HAVE_modsi3) + smod_optab->handlers[(int) SImode].insn_code = CODE_FOR_modsi3; +#endif +#ifdef HAVE_moddi3 + if (HAVE_moddi3) + smod_optab->handlers[(int) DImode].insn_code = CODE_FOR_moddi3; +#endif + +#ifdef MODSI3_LIBCALL + smod_optab->handlers[(int) SImode].lib_call = MODSI3_LIBCALL; +#else + smod_optab->handlers[(int) SImode].lib_call = "__modsi3"; +#endif + smod_optab->handlers[(int) DImode].lib_call = "__moddi3"; + +#ifdef HAVE_umodqi3 + if (HAVE_umodqi3) + umod_optab->handlers[(int) QImode].insn_code = CODE_FOR_umodqi3; +#endif +#ifdef HAVE_umodhi3 + if (HAVE_umodhi3) + umod_optab->handlers[(int) HImode].insn_code = CODE_FOR_umodhi3; +#endif +#ifdef HAVE_umodsi3 + if (HAVE_umodsi3) + umod_optab->handlers[(int) SImode].insn_code = CODE_FOR_umodsi3; +#endif +#ifdef HAVE_umoddi3 + if (HAVE_umoddi3) + umod_optab->handlers[(int) DImode].insn_code = CODE_FOR_umoddi3; +#endif + +#ifdef UMODSI3_LIBCALL + umod_optab->handlers[(int) SImode].lib_call = UMODSI3_LIBCALL; +#else + umod_optab->handlers[(int) SImode].lib_call = "__umodsi3"; +#endif + umod_optab->handlers[(int) DImode].lib_call = "__umoddi3"; + +#ifdef HAVE_divsf3 + if (HAVE_divsf3) + flodiv_optab->handlers[(int) SFmode].insn_code = CODE_FOR_divsf3; +#endif +#ifdef HAVE_divdf3 + if (HAVE_divdf3) + flodiv_optab->handlers[(int) DFmode].insn_code = CODE_FOR_divdf3; +#endif + flodiv_optab->handlers[(int) SFmode].lib_call = "__divsf3"; + flodiv_optab->handlers[(int) DFmode].lib_call = "__divdf3"; + +#ifdef HAVE_ftruncsf2 + if (HAVE_ftruncsf2) + ftrunc_optab->handlers[(int) SFmode].insn_code = CODE_FOR_ftruncsf2; +#endif +#ifdef HAVE_ftruncdf2 + if (HAVE_ftruncdf2) + ftrunc_optab->handlers[(int) DFmode].insn_code = CODE_FOR_ftruncdf2; +#endif + +#ifdef HAVE_andqi3 + if (HAVE_andqi3) + and_optab->handlers[(int) QImode].insn_code = CODE_FOR_andqi3; +#endif +#ifdef HAVE_andhi3 + if (HAVE_andhi3) + and_optab->handlers[(int) HImode].insn_code = CODE_FOR_andhi3; +#endif +#ifdef HAVE_andsi3 + if (HAVE_andsi3) + and_optab->handlers[(int) SImode].insn_code = CODE_FOR_andsi3; +#endif +#ifdef HAVE_anddi3 + if (HAVE_anddi3) + and_optab->handlers[(int) DImode].insn_code = CODE_FOR_anddi3; +#endif + and_optab->handlers[(int) DImode].lib_call = "__anddi3"; + +#ifdef HAVE_andcbqi3 + if (HAVE_andcbqi3) + andcb_optab->handlers[(int) QImode].insn_code = CODE_FOR_andcbqi3; +#endif +#ifdef HAVE_andcbhi3 + if (HAVE_andcbhi3) + andcb_optab->handlers[(int) HImode].insn_code = CODE_FOR_andcbhi3; +#endif +#ifdef HAVE_andcbsi3 + if (HAVE_andcbsi3) + andcb_optab->handlers[(int) SImode].insn_code = CODE_FOR_andcbsi3; +#endif +#ifdef HAVE_andcbdi3 + if (HAVE_andcbdi3) + andcb_optab->handlers[(int) DImode].insn_code = CODE_FOR_andcbdi3; +#endif + andcb_optab->handlers[(int) DImode].lib_call = "__andcbdi3"; + +#ifdef HAVE_iorqi3 + if (HAVE_iorqi3) + ior_optab->handlers[(int) QImode].insn_code = CODE_FOR_iorqi3; +#endif +#ifdef HAVE_iorhi3 + if (HAVE_iorhi3) + ior_optab->handlers[(int) HImode].insn_code = CODE_FOR_iorhi3; +#endif +#ifdef HAVE_iorsi3 + if (HAVE_iorsi3) + ior_optab->handlers[(int) SImode].insn_code = CODE_FOR_iorsi3; +#endif +#ifdef HAVE_iordi3 + if (HAVE_iordi3) + ior_optab->handlers[(int) DImode].insn_code = CODE_FOR_iordi3; +#endif + ior_optab->handlers[(int) DImode].lib_call = "__iordi3"; + +#ifdef HAVE_xorqi3 + if (HAVE_xorqi3) + xor_optab->handlers[(int) QImode].insn_code = CODE_FOR_xorqi3; +#endif +#ifdef HAVE_xorhi3 + if (HAVE_xorhi3) + xor_optab->handlers[(int) HImode].insn_code = CODE_FOR_xorhi3; +#endif +#ifdef HAVE_xorsi3 + if (HAVE_xorsi3) + xor_optab->handlers[(int) SImode].insn_code = CODE_FOR_xorsi3; +#endif +#ifdef HAVE_xordi3 + if (HAVE_xordi3) + xor_optab->handlers[(int) DImode].insn_code = CODE_FOR_xordi3; +#endif + xor_optab->handlers[(int) DImode].lib_call = "__xordi3"; + +#ifdef HAVE_ashlqi3 + if (HAVE_ashlqi3) + ashl_optab->handlers[(int) QImode].insn_code = CODE_FOR_ashlqi3; +#endif +#ifdef HAVE_ashlhi3 + if (HAVE_ashlhi3) + ashl_optab->handlers[(int) HImode].insn_code = CODE_FOR_ashlhi3; +#endif +#ifdef HAVE_ashlsi3 + if (HAVE_ashlsi3) + ashl_optab->handlers[(int) SImode].insn_code = CODE_FOR_ashlsi3; +#endif +#ifdef HAVE_ashldi3 + if (HAVE_ashldi3) + ashl_optab->handlers[(int) DImode].insn_code = CODE_FOR_ashldi3; +#endif + ashl_optab->handlers[(int) SImode].lib_call = "__ashlsi3"; + ashl_optab->handlers[(int) DImode].lib_call = "__ashldi3"; + +#ifdef HAVE_ashrqi3 + if (HAVE_ashrqi3) + ashr_optab->handlers[(int) QImode].insn_code = CODE_FOR_ashrqi3; +#endif +#ifdef HAVE_ashrhi3 + if (HAVE_ashrhi3) + ashr_optab->handlers[(int) HImode].insn_code = CODE_FOR_ashrhi3; +#endif +#ifdef HAVE_ashrsi3 + if (HAVE_ashrsi3) + ashr_optab->handlers[(int) SImode].insn_code = CODE_FOR_ashrsi3; +#endif +#ifdef HAVE_ashrdi3 + if (HAVE_ashrdi3) + ashr_optab->handlers[(int) DImode].insn_code = CODE_FOR_ashrdi3; +#endif + ashr_optab->handlers[(int) SImode].lib_call = "__ashrsi3"; + ashr_optab->handlers[(int) DImode].lib_call = "__ashrdi3"; + +#ifdef HAVE_lshlqi3 + if (HAVE_lshlqi3) + lshl_optab->handlers[(int) QImode].insn_code = CODE_FOR_lshlqi3; +#endif +#ifdef HAVE_lshlhi3 + if (HAVE_lshlhi3) + lshl_optab->handlers[(int) HImode].insn_code = CODE_FOR_lshlhi3; +#endif +#ifdef HAVE_lshlsi3 + if (HAVE_lshlsi3) + lshl_optab->handlers[(int) SImode].insn_code = CODE_FOR_lshlsi3; +#endif +#ifdef HAVE_lshldi3 + if (HAVE_lshldi3) + lshl_optab->handlers[(int) DImode].insn_code = CODE_FOR_lshldi3; +#endif + lshl_optab->handlers[(int) SImode].lib_call = "__lshlsi3"; + lshl_optab->handlers[(int) DImode].lib_call = "__lshldi3"; + +#ifdef HAVE_lshrqi3 + if (HAVE_lshrqi3) + lshr_optab->handlers[(int) QImode].insn_code = CODE_FOR_lshrqi3; +#endif +#ifdef HAVE_lshrhi3 + if (HAVE_lshrhi3) + lshr_optab->handlers[(int) HImode].insn_code = CODE_FOR_lshrhi3; +#endif +#ifdef HAVE_lshrsi3 + if (HAVE_lshrsi3) + lshr_optab->handlers[(int) SImode].insn_code = CODE_FOR_lshrsi3; +#endif +#ifdef HAVE_lshrdi3 + if (HAVE_lshrdi3) + lshr_optab->handlers[(int) DImode].insn_code = CODE_FOR_lshrdi3; +#endif + lshr_optab->handlers[(int) SImode].lib_call = "__lshrsi3"; + lshr_optab->handlers[(int) DImode].lib_call = "__lshrdi3"; + +#ifdef HAVE_rotlqi3 + if (HAVE_rotlqi3) + rotl_optab->handlers[(int) QImode].insn_code = CODE_FOR_rotlqi3; +#endif +#ifdef HAVE_rotlhi3 + if (HAVE_rotlhi3) + rotl_optab->handlers[(int) HImode].insn_code = CODE_FOR_rotlhi3; +#endif +#ifdef HAVE_rotlsi3 + if (HAVE_rotlsi3) + rotl_optab->handlers[(int) SImode].insn_code = CODE_FOR_rotlsi3; +#endif +#ifdef HAVE_rotldi3 + if (HAVE_rotldi3) + rotl_optab->handlers[(int) DImode].insn_code = CODE_FOR_rotldi3; +#endif + rotl_optab->handlers[(int) SImode].lib_call = "__rotlsi3"; + rotl_optab->handlers[(int) DImode].lib_call = "__rotldi3"; + +#ifdef HAVE_rotrqi3 + if (HAVE_rotrqi3) + rotr_optab->handlers[(int) QImode].insn_code = CODE_FOR_rotrqi3; +#endif +#ifdef HAVE_rotrhi3 + if (HAVE_rotrhi3) + rotr_optab->handlers[(int) HImode].insn_code = CODE_FOR_rotrhi3; +#endif +#ifdef HAVE_rotrsi3 + if (HAVE_rotrsi3) + rotr_optab->handlers[(int) SImode].insn_code = CODE_FOR_rotrsi3; +#endif +#ifdef HAVE_rotrdi3 + if (HAVE_rotrdi3) + rotr_optab->handlers[(int) DImode].insn_code = CODE_FOR_rotrdi3; +#endif + rotr_optab->handlers[(int) SImode].lib_call = "__rotrsi3"; + rotr_optab->handlers[(int) DImode].lib_call = "__rotrdi3"; + +#ifdef HAVE_negqi2 + if (HAVE_negqi2) + neg_optab->handlers[(int) QImode].insn_code = CODE_FOR_negqi2; +#endif +#ifdef HAVE_neghi2 + if (HAVE_neghi2) + neg_optab->handlers[(int) HImode].insn_code = CODE_FOR_neghi2; +#endif +#ifdef HAVE_negsi2 + if (HAVE_negsi2) + neg_optab->handlers[(int) SImode].insn_code = CODE_FOR_negsi2; +#endif +#ifdef HAVE_negdi2 + if (HAVE_negdi2) + neg_optab->handlers[(int) DImode].insn_code = CODE_FOR_negdi2; +#endif +#ifdef HAVE_negsf2 + if (HAVE_negsf2) + neg_optab->handlers[(int) SFmode].insn_code = CODE_FOR_negsf2; +#endif +#ifdef HAVE_negdf2 + if (HAVE_negdf2) + neg_optab->handlers[(int) DFmode].insn_code = CODE_FOR_negdf2; +#endif + neg_optab->handlers[(int) SImode].lib_call = "__negsi2"; + neg_optab->handlers[(int) DImode].lib_call = "__negdi2"; + neg_optab->handlers[(int) SFmode].lib_call = "__negsf2"; + neg_optab->handlers[(int) DFmode].lib_call = "__negdf2"; + +#ifdef HAVE_absqi2 + if (HAVE_absqi2) + abs_optab->handlers[(int) QImode].insn_code = CODE_FOR_absqi2; +#endif +#ifdef HAVE_abshi2 + if (HAVE_abshi2) + abs_optab->handlers[(int) HImode].insn_code = CODE_FOR_abshi2; +#endif +#ifdef HAVE_abssi2 + if (HAVE_abssi2) + abs_optab->handlers[(int) SImode].insn_code = CODE_FOR_abssi2; +#endif +#ifdef HAVE_absdi2 + if (HAVE_absdi2) + abs_optab->handlers[(int) DImode].insn_code = CODE_FOR_absdi2; +#endif +#ifdef HAVE_abssf2 + if (HAVE_abssf2) + abs_optab->handlers[(int) SFmode].insn_code = CODE_FOR_abssf2; +#endif +#ifdef HAVE_absdf2 + if (HAVE_absdf2) + abs_optab->handlers[(int) DFmode].insn_code = CODE_FOR_absdf2; +#endif + /* No library calls here! If there is no abs instruction, + expand_expr will generate a conditional negation. */ + +#ifdef HAVE_one_cmplqi2 + if (HAVE_one_cmplqi2) + one_cmpl_optab->handlers[(int) QImode].insn_code = CODE_FOR_one_cmplqi2; +#endif +#ifdef HAVE_one_cmplhi2 + if (HAVE_one_cmplhi2) + one_cmpl_optab->handlers[(int) HImode].insn_code = CODE_FOR_one_cmplhi2; +#endif +#ifdef HAVE_one_cmplsi2 + if (HAVE_one_cmplsi2) + one_cmpl_optab->handlers[(int) SImode].insn_code = CODE_FOR_one_cmplsi2; +#endif +#ifdef HAVE_one_cmpldi2 + if (HAVE_one_cmpldi2) + one_cmpl_optab->handlers[(int) DImode].insn_code = CODE_FOR_one_cmpldi2; +#endif + one_cmpl_optab->handlers[(int) SImode].lib_call = "__one_cmplsi2"; + one_cmpl_optab->handlers[(int) DImode].lib_call = "__one_cmpldi2"; + +#ifdef HAVE_ffsqi2 + if (HAVE_ffsqi2) + ffs_optab->handlers[(int) QImode].insn_code = CODE_FOR_ffsqi2; +#endif +#ifdef HAVE_ffshi2 + if (HAVE_ffshi2) + ffs_optab->handlers[(int) HImode].insn_code = CODE_FOR_ffshi2; +#endif +#ifdef HAVE_ffssi2 + if (HAVE_ffssi2) + ffs_optab->handlers[(int) SImode].insn_code = CODE_FOR_ffssi2; +#endif +#ifdef HAVE_ffsdi2 + if (HAVE_ffsdi2) + ffs_optab->handlers[(int) DImode].insn_code = CODE_FOR_ffsdi2; +#endif + ffs_optab->handlers[(int) SImode].lib_call = "ffs"; + +#ifdef HAVE_movqi + if (HAVE_movqi) + mov_optab->handlers[(int) QImode].insn_code = CODE_FOR_movqi; +#endif +#ifdef HAVE_movhi + if (HAVE_movhi) + mov_optab->handlers[(int) HImode].insn_code = CODE_FOR_movhi; +#endif +#ifdef HAVE_movsi + if (HAVE_movsi) + mov_optab->handlers[(int) SImode].insn_code = CODE_FOR_movsi; +#endif +#ifdef HAVE_movdi + if (HAVE_movdi) + mov_optab->handlers[(int) DImode].insn_code = CODE_FOR_movdi; +#endif +#ifdef HAVE_movti + if (HAVE_movti) + mov_optab->handlers[(int) TImode].insn_code = CODE_FOR_movti; +#endif +#ifdef HAVE_movsf + if (HAVE_movsf) + mov_optab->handlers[(int) SFmode].insn_code = CODE_FOR_movsf; +#endif +#ifdef HAVE_movdf + if (HAVE_movdf) + mov_optab->handlers[(int) DFmode].insn_code = CODE_FOR_movdf; +#endif +#ifdef HAVE_movtf + if (HAVE_movtf) + mov_optab->handlers[(int) TFmode].insn_code = CODE_FOR_movtf; +#endif + +#ifdef HAVE_movstrictqi + if (HAVE_movstrictqi) + movstrict_optab->handlers[(int) QImode].insn_code = CODE_FOR_movstrictqi; +#endif +#ifdef HAVE_movstricthi + if (HAVE_movstricthi) + movstrict_optab->handlers[(int) HImode].insn_code = CODE_FOR_movstricthi; +#endif +#ifdef HAVE_movstrictsi + if (HAVE_movstrictsi) + movstrict_optab->handlers[(int) SImode].insn_code = CODE_FOR_movstrictsi; +#endif +#ifdef HAVE_movstrictdi + if (HAVE_movstrictdi) + movstrict_optab->handlers[(int) DImode].insn_code = CODE_FOR_movstrictdi; +#endif + +#ifdef HAVE_cmpqi + if (HAVE_cmpqi) + cmp_optab->handlers[(int) QImode].insn_code = CODE_FOR_cmpqi; +#endif +#ifdef HAVE_cmphi + if (HAVE_cmphi) + cmp_optab->handlers[(int) HImode].insn_code = CODE_FOR_cmphi; +#endif +#ifdef HAVE_cmpsi + if (HAVE_cmpsi) + cmp_optab->handlers[(int) SImode].insn_code = CODE_FOR_cmpsi; +#endif +#ifdef HAVE_cmpdi + if (HAVE_cmpdi) + cmp_optab->handlers[(int) DImode].insn_code = CODE_FOR_cmpdi; +#endif +#ifdef HAVE_cmpsf + if (HAVE_cmpsf) + cmp_optab->handlers[(int) SFmode].insn_code = CODE_FOR_cmpsf; +#endif +#ifdef HAVE_cmpdf + if (HAVE_cmpdf) + cmp_optab->handlers[(int) DFmode].insn_code = CODE_FOR_cmpdf; +#endif +#ifdef HAVE_tstqi + if (HAVE_tstqi) + tst_optab->handlers[(int) QImode].insn_code = CODE_FOR_tstqi; +#endif +#ifdef HAVE_tsthi + if (HAVE_tsthi) + tst_optab->handlers[(int) HImode].insn_code = CODE_FOR_tsthi; +#endif +#ifdef HAVE_tstsi + if (HAVE_tstsi) + tst_optab->handlers[(int) SImode].insn_code = CODE_FOR_tstsi; +#endif +#ifdef HAVE_tstdi + if (HAVE_tstdi) + tst_optab->handlers[(int) DImode].insn_code = CODE_FOR_tstdi; +#endif +#ifdef HAVE_tstsf + if (HAVE_tstsf) + tst_optab->handlers[(int) SFmode].insn_code = CODE_FOR_tstsf; +#endif +#ifdef HAVE_tstdf + if (HAVE_tstdf) + tst_optab->handlers[(int) DFmode].insn_code = CODE_FOR_tstdf; +#endif + /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */ + cmp_optab->handlers[(int) DImode].lib_call = "__cmpdi2"; + ucmp_optab->handlers[(int) DImode].lib_call = "__ucmpdi2"; + cmp_optab->handlers[(int) SFmode].lib_call = "__cmpsf2"; + cmp_optab->handlers[(int) DFmode].lib_call = "__cmpdf2"; + +#if HAVE_beq + if (HAVE_beq) + bcc_gen_fctn[(int) EQ] = gen_beq; +#endif +#if HAVE_bne + if (HAVE_bne) + bcc_gen_fctn[(int) NE] = gen_bne; +#endif +#if HAVE_bgt + if (HAVE_bgt) + bcc_gen_fctn[(int) GT] = gen_bgt; +#endif +#if HAVE_bge + if (HAVE_bge) + bcc_gen_fctn[(int) GE] = gen_bge; +#endif +#if HAVE_bgtu + if (HAVE_bgtu) + bcc_gen_fctn[(int) GTU] = gen_bgtu; +#endif +#if HAVE_bgeu + if (HAVE_bgeu) + bcc_gen_fctn[(int) GEU] = gen_bgeu; +#endif +#if HAVE_blt + if (HAVE_blt) + bcc_gen_fctn[(int) LT] = gen_blt; +#endif +#if HAVE_ble + if (HAVE_ble) + bcc_gen_fctn[(int) LE] = gen_ble; +#endif +#if HAVE_bltu + if (HAVE_bltu) + bcc_gen_fctn[(int) LTU] = gen_bltu; +#endif +#if HAVE_bleu + if (HAVE_bleu) + bcc_gen_fctn[(int) LEU] = gen_bleu; +#endif + +#if HAVE_seq + if (HAVE_seq) + setcc_gen_fctn[(int) EQ] = gen_seq; +#endif +#if HAVE_sne + if (HAVE_sne) + setcc_gen_fctn[(int) NE] = gen_sne; +#endif +#if HAVE_sgt + if (HAVE_sgt) + setcc_gen_fctn[(int) GT] = gen_sgt; +#endif +#if HAVE_sge + if (HAVE_sge) + setcc_gen_fctn[(int) GE] = gen_sge; +#endif +#if HAVE_sgtu + if (HAVE_sgtu) + setcc_gen_fctn[(int) GTU] = gen_sgtu; +#endif +#if HAVE_sgeu + if (HAVE_sgeu) + setcc_gen_fctn[(int) GEU] = gen_sgeu; +#endif +#if HAVE_slt + if (HAVE_slt) + setcc_gen_fctn[(int) LT] = gen_slt; +#endif +#if HAVE_sle + if (HAVE_sle) + setcc_gen_fctn[(int) LE] = gen_sle; +#endif +#if HAVE_sltu + if (HAVE_sltu) + setcc_gen_fctn[(int) LTU] = gen_sltu; +#endif +#if HAVE_sleu + if (HAVE_sleu) + setcc_gen_fctn[(int) LEU] = gen_sleu; +#endif +} |
