/* Subroutines used for code generation on Vitesse IQ2000 processors
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC 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 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC 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, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "debug.h"
#include "target.h"
#include "target-def.h"
+#include "langhooks.h"
/* Enumeration for all of the relational tests, so that we can build
arrays indexed by the test type, and not worry about the order
of EQ, NE, etc. */
-enum internal_test {
+enum internal_test
+ {
ITEST_EQ,
ITEST_NE,
ITEST_GT,
struct constant;
-static void iq2000_count_memory_refs PARAMS ((rtx, int));
-static enum internal_test map_test_to_internal_test PARAMS ((enum rtx_code));
-static rtx iq2000_add_large_offset_to_sp PARAMS ((HOST_WIDE_INT));
-static void iq2000_annotate_frame_insn PARAMS ((rtx, rtx));
-static void iq2000_emit_frame_related_store PARAMS ((rtx, rtx,
- HOST_WIDE_INT));
-static struct machine_function * iq2000_init_machine_status PARAMS ((void));
-static void save_restore_insns PARAMS ((int));
-static void abort_with_insn PARAMS ((rtx, const char *))
- ATTRIBUTE_NORETURN;
-static int symbolic_expression_p PARAMS ((rtx));
-static enum processor_type iq2000_parse_cpu PARAMS ((const char *));
-static void iq2000_select_rtx_section PARAMS ((enum machine_mode, rtx,
- unsigned HOST_WIDE_INT));
-static void iq2000_select_section PARAMS ((tree, int, unsigned HOST_WIDE_INT));
-static rtx expand_one_builtin PARAMS ((enum insn_code, rtx, tree, enum rtx_code*,
- int));
\f
/* Structure to be filled in by compute_frame_size with register
save masks, and offsets for the current function. */
struct iq2000_frame_info
{
- long total_size; /* # bytes that the entire frame takes up */
- long var_size; /* # bytes that variables take up */
- long args_size; /* # bytes that outgoing arguments take up */
- long extra_size; /* # bytes of extra gunk */
- int gp_reg_size; /* # bytes needed to store gp regs */
- int fp_reg_size; /* # bytes needed to store fp regs */
- long mask; /* mask of saved gp registers */
- long gp_save_offset; /* offset from vfp to store gp registers */
- long fp_save_offset; /* offset from vfp to store fp registers */
- long gp_sp_offset; /* offset from new sp to store gp registers */
- long fp_sp_offset; /* offset from new sp to store fp registers */
- int initialized; /* != 0 if frame size already calculated */
- int num_gp; /* number of gp registers saved */
-};
-
-struct machine_function
+ long total_size; /* # bytes that the entire frame takes up. */
+ long var_size; /* # bytes that variables take up. */
+ long args_size; /* # bytes that outgoing arguments take up. */
+ long extra_size; /* # bytes of extra gunk. */
+ int gp_reg_size; /* # bytes needed to store gp regs. */
+ int fp_reg_size; /* # bytes needed to store fp regs. */
+ long mask; /* Mask of saved gp registers. */
+ long gp_save_offset; /* Offset from vfp to store gp registers. */
+ long fp_save_offset; /* Offset from vfp to store fp registers. */
+ long gp_sp_offset; /* Offset from new sp to store gp registers. */
+ long fp_sp_offset; /* Offset from new sp to store fp registers. */
+ int initialized; /* != 0 if frame size already calculated. */
+ int num_gp; /* Number of gp registers saved. */
+} iq2000_frame_info;
+
+struct machine_function GTY(())
{
/* Current frame information, calculated by compute_frame_size. */
- struct iq2000_frame_info frame;
+ long total_size; /* # bytes that the entire frame takes up. */
+ long var_size; /* # bytes that variables take up. */
+ long args_size; /* # bytes that outgoing arguments take up. */
+ long extra_size; /* # bytes of extra gunk. */
+ int gp_reg_size; /* # bytes needed to store gp regs. */
+ int fp_reg_size; /* # bytes needed to store fp regs. */
+ long mask; /* Mask of saved gp registers. */
+ long gp_save_offset; /* Offset from vfp to store gp registers. */
+ long fp_save_offset; /* Offset from vfp to store fp registers. */
+ long gp_sp_offset; /* Offset from new sp to store gp registers. */
+ long fp_sp_offset; /* Offset from new sp to store fp registers. */
+ int initialized; /* != 0 if frame size already calculated. */
+ int num_gp; /* Number of gp registers saved. */
};
/* Global variables for machine-dependent things. */
-/* Count the number of .file directives, so that .loc is up to date. */
-int num_source_filenames = 0;
-
-/* Files to separate the text and the data output, so that all of the data
- can be emitted before the text, which will mean that the assembler will
- generate smaller code, based on the global pointer. */
-FILE *asm_out_data_file;
-FILE *asm_out_text_file;
-
-/* The next branch instruction is a branch likely, not branch normal. */
-int iq2000_branch_likely;
-
-/* Count of delay slots and how many are filled. */
-int dslots_load_total;
-int dslots_load_filled;
-int dslots_jump_total;
-int dslots_jump_filled;
-
-/* # of nops needed by previous insn */
-int dslots_number_nops;
+/* List of all IQ2000 punctuation characters used by print_operand. */
+char iq2000_print_operand_punct[256];
-/* Number of 1/2/3 word references to data items (ie, not jal's). */
-int num_refs[3];
+/* The target cpu for optimization and scheduling. */
+enum processor_type iq2000_tune;
-/* registers to check for load delay */
-rtx iq2000_load_reg, iq2000_load_reg2, iq2000_load_reg3, iq2000_load_reg4;
+/* Which instruction set architecture to use. */
+int iq2000_isa;
/* Cached operands, and operator to compare for use in set/branch/trap
on condition codes. */
rtx branch_cmp[2];
-/* what type of branch to use */
+/* What type of branch to use. */
enum cmp_type branch_type;
-/* The target cpu for code generation. */
-enum processor_type iq2000_arch;
+/* Local variables. */
-/* The target cpu for optimization and scheduling. */
-enum processor_type iq2000_tune;
+/* The next branch instruction is a branch likely, not branch normal. */
+static int iq2000_branch_likely;
-/* which instruction set architecture to use. */
-int iq2000_isa;
+/* Count of delay slots and how many are filled. */
+static int dslots_load_total;
+static int dslots_load_filled;
+static int dslots_jump_total;
+
+/* # of nops needed by previous insn. */
+static int dslots_number_nops;
-/* Strings to hold which cpu and instruction set architecture to use. */
-const char *iq2000_cpu_string; /* for -mcpu=<xxx> */
-const char *iq2000_arch_string; /* for -march=<xxx> */
+/* Number of 1/2/3 word references to data items (i.e., not jal's). */
+static int num_refs[3];
+
+/* Registers to check for load delay. */
+static rtx iq2000_load_reg;
+static rtx iq2000_load_reg2;
+static rtx iq2000_load_reg3;
+static rtx iq2000_load_reg4;
/* Mode used for saving/restoring general purpose registers. */
static enum machine_mode gpr_mode;
-/* List of all IQ2000 punctuation characters used by print_operand. */
-char iq2000_print_operand_punct[256];
\f
/* Initialize the GCC target structure. */
-#undef TARGET_INIT_BUILTINS
-#define TARGET_INIT_BUILTINS iq2000_init_builtins
-
-#undef TARGET_EXPAND_BUILTIN
-#define TARGET_EXPAND_BUILTIN iq2000_expand_builtin
-
-#undef TARGET_ASM_SELECT_RTX_SECTION
-#define TARGET_ASM_SELECT_RTX_SECTION iq2000_select_rtx_section
+static struct machine_function* iq2000_init_machine_status (void);
+static bool iq2000_handle_option (size_t, const char *, int);
+static section *iq2000_select_rtx_section (enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT);
+static void iq2000_init_builtins (void);
+static rtx iq2000_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
+static bool iq2000_return_in_memory (tree, tree);
+static void iq2000_setup_incoming_varargs (CUMULATIVE_ARGS *,
+ enum machine_mode, tree, int *,
+ int);
+static bool iq2000_rtx_costs (rtx, int, int, int *);
+static int iq2000_address_cost (rtx);
+static section *iq2000_select_section (tree, int, unsigned HOST_WIDE_INT);
+static bool iq2000_return_in_memory (tree, tree);
+static bool iq2000_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
+ tree, bool);
+static int iq2000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
+ tree, bool);
+
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS iq2000_init_builtins
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN iq2000_expand_builtin
+#undef TARGET_ASM_SELECT_RTX_SECTION
+#define TARGET_ASM_SELECT_RTX_SECTION iq2000_select_rtx_section
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION iq2000_handle_option
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS iq2000_rtx_costs
+#undef TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST iq2000_address_cost
+#undef TARGET_ASM_SELECT_SECTION
+#define TARGET_ASM_SELECT_SECTION iq2000_select_section
+
+/* The assembler supports switchable .bss sections, but
+ iq2000_select_section doesn't yet make use of them. */
+#undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS
+#define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false
+
+#undef TARGET_PROMOTE_FUNCTION_ARGS
+#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
+#undef TARGET_PROMOTE_FUNCTION_RETURN
+#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
+#undef TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
+
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY iq2000_return_in_memory
+#undef TARGET_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE iq2000_pass_by_reference
+#undef TARGET_CALLEE_COPIES
+#define TARGET_CALLEE_COPIES hook_callee_copies_named
+#undef TARGET_ARG_PARTIAL_BYTES
+#define TARGET_ARG_PARTIAL_BYTES iq2000_arg_partial_bytes
+
+#undef TARGET_SETUP_INCOMING_VARARGS
+#define TARGET_SETUP_INCOMING_VARARGS iq2000_setup_incoming_varargs
+#undef TARGET_STRICT_ARGUMENT_NAMING
+#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
struct gcc_target targetm = TARGET_INITIALIZER;
\f
-/* Return 1 if OP can be used as an operand where a register or 16 bit unsigned
- integer is needed. */
-
-int
-uns_arith_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (op))
- return 1;
-
- return register_operand (op, mode);
-}
-
-/* Return 1 if OP can be used as an operand where a 16 bit integer is needed. */
-
-int
-arith_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (GET_CODE (op) == CONST_INT && SMALL_INT (op))
- return 1;
-
- return register_operand (op, mode);
-}
-
-/* Return 1 if OP is a integer which fits in 16 bits */
-
-int
-small_int (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
-}
-
-/* Return 1 if OP is a 32 bit integer which is too big to be loaded with one
- instruction. */
-
-int
-large_int (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- HOST_WIDE_INT value;
-
- if (GET_CODE (op) != CONST_INT)
- return 0;
-
- value = INTVAL (op);
-
- /* ior reg,$r0,value */
- if ((value & ~ ((HOST_WIDE_INT) 0x0000ffff)) == 0)
- return 0;
-
- /* subu reg,$r0,value */
- if (((unsigned HOST_WIDE_INT) (value + 32768)) <= 32767)
- return 0;
-
- /* lui reg,value>>16 */
- if ((value & 0x0000ffff) == 0)
- return 0;
-
- return 1;
-}
-
-/* Return 1 if OP is a register or the constant 0. */
-
-int
-reg_or_0_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- switch (GET_CODE (op))
- {
- case CONST_INT:
- return INTVAL (op) == 0;
-
- case CONST_DOUBLE:
- return op == CONST0_RTX (mode);
-
- case REG:
- case SUBREG:
- return register_operand (op, mode);
-
- default:
- break;
- }
-
- return 0;
-}
-
-/* Return 1 if OP is a memory operand that fits in a single instruction
- (ie, register + small offset). */
-
-int
-simple_memory_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- rtx addr, plus0, plus1;
-
- /* Eliminate non-memory operations */
- if (GET_CODE (op) != MEM)
- return 0;
-
- /* dword operations really put out 2 instructions, so eliminate them. */
- if (GET_MODE_SIZE (GET_MODE (op)) > (unsigned) UNITS_PER_WORD)
- return 0;
-
- /* Decode the address now. */
- addr = XEXP (op, 0);
- switch (GET_CODE (addr))
- {
- case REG:
- case LO_SUM:
- return 1;
-
- case CONST_INT:
- return SMALL_INT (addr);
-
- case PLUS:
- plus0 = XEXP (addr, 0);
- plus1 = XEXP (addr, 1);
- if (GET_CODE (plus0) == REG
- && GET_CODE (plus1) == CONST_INT && SMALL_INT (plus1)
- && SMALL_INT_UNSIGNED (plus1) /* No negative offsets */)
- return 1;
-
- else if (GET_CODE (plus1) == REG
- && GET_CODE (plus0) == CONST_INT && SMALL_INT (plus0)
- && SMALL_INT_UNSIGNED (plus1) /* No negative offsets */)
- return 1;
-
- else
- return 0;
-
- case SYMBOL_REF:
- return 0;
-
- default:
- break;
- }
-
- return 0;
-}
-
-/* Return nonzero if the code of this rtx pattern is EQ or NE. */
-
-int
-equality_op (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (mode != GET_MODE (op))
- return 0;
-
- return GET_CODE (op) == EQ || GET_CODE (op) == NE;
-}
-
-/* Return nonzero if the code is a relational operations (EQ, LE, etc.) */
-
-int
-cmp_op (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (mode != GET_MODE (op))
- return 0;
-
- return GET_RTX_CLASS (GET_CODE (op)) == '<';
-}
-
-/* Return nonzero if the operand is either the PC or a label_ref. */
-
-int
-pc_or_label_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- if (op == pc_rtx)
- return 1;
-
- if (GET_CODE (op) == LABEL_REF)
- return 1;
-
- return 0;
-}
-
-/* Return nonzero if OP is a valid operand for a call instruction. */
-
-int
-call_insn_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- return (CONSTANT_ADDRESS_P (op)
- || (GET_CODE (op) == REG && op != arg_pointer_rtx
- && ! (REGNO (op) >= FIRST_PSEUDO_REGISTER
- && REGNO (op) <= LAST_VIRTUAL_REGISTER)));
-}
-
-/* Return nonzero if OP is valid as a source operand for a move instruction. */
-
-int
-move_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- /* Accept any general operand after reload has started; doing so
- avoids losing if reload does an in-place replacement of a register
- with a SYMBOL_REF or CONST. */
- return (general_operand (op, mode)
- && (! (iq2000_check_split (op, mode))
- || reload_in_progress || reload_completed));
-}
-
-/* Return nonzero if OP is a constant power of 2. */
-
-int
-power_of_2_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- int intval;
-
- if (GET_CODE (op) != CONST_INT)
- return 0;
- else
- intval = INTVAL (op);
-
- return ((intval & ((unsigned)(intval) - 1)) == 0);
-}
-
/* Return nonzero if we split the address into high and low parts. */
int
-iq2000_check_split (address, mode)
- rtx address;
- enum machine_mode mode;
+iq2000_check_split (rtx address, enum machine_mode mode)
{
/* This is the same check used in simple_memory_operand.
We use it here because LO_SUM is not offsettable. */
/* Return nonzero if REG is valid for MODE. */
int
-iq2000_reg_mode_ok_for_base_p (reg, mode, strict)
- rtx reg;
- enum machine_mode mode ATTRIBUTE_UNUSED;
- int strict;
+iq2000_reg_mode_ok_for_base_p (rtx reg,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ int strict)
{
return (strict
? REGNO_MODE_OK_FOR_BASE_P (REGNO (reg), mode)
}
/* Return a nonzero value if XINSN is a legitimate address for a
- memory operand of the indicated MODE. STRICT is non-zero if this
+ memory operand of the indicated MODE. STRICT is nonzero if this
function is called during reload. */
int
-iq2000_legitimate_address_p (mode, xinsn, strict)
- enum machine_mode mode;
- rtx xinsn;
- int strict;
+iq2000_legitimate_address_p (enum machine_mode mode, rtx xinsn, int strict)
{
if (TARGET_DEBUG_A_MODE)
{
if (GET_CODE (xinsn) == LO_SUM)
{
- register rtx xlow0 = XEXP (xinsn, 0);
- register rtx xlow1 = XEXP (xinsn, 1);
+ rtx xlow0 = XEXP (xinsn, 0);
+ rtx xlow1 = XEXP (xinsn, 1);
while (GET_CODE (xlow0) == SUBREG)
xlow0 = SUBREG_REG (xlow0);
if (GET_CODE (xinsn) == PLUS)
{
- register rtx xplus0 = XEXP (xinsn, 0);
- register rtx xplus1 = XEXP (xinsn, 1);
- register enum rtx_code code0;
- register enum rtx_code code1;
+ rtx xplus0 = XEXP (xinsn, 0);
+ rtx xplus1 = XEXP (xinsn, 1);
+ enum rtx_code code0;
+ enum rtx_code code1;
while (GET_CODE (xplus0) == SUBREG)
xplus0 = SUBREG_REG (xplus0);
it needs. */
const char *
-iq2000_fill_delay_slot (ret, type, operands, cur_insn)
- const char *ret; /* normal string to return */
- enum delay_type type; /* type of delay */
- rtx operands[]; /* operands to use */
- rtx cur_insn; /* current insn */
+iq2000_fill_delay_slot (const char *ret, enum delay_type type, rtx operands[],
+ rtx cur_insn)
{
- register rtx set_reg;
- register enum machine_mode mode;
- register rtx next_insn = cur_insn ? NEXT_INSN (cur_insn) : NULL_RTX;
- register int num_nops;
+ rtx set_reg;
+ enum machine_mode mode;
+ rtx next_insn = cur_insn ? NEXT_INSN (cur_insn) : NULL_RTX;
+ int num_nops;
if (type == DELAY_LOAD || type == DELAY_FCMP)
num_nops = 1;
iq2000_load_reg2 = 0;
iq2000_load_reg3 = 0;
iq2000_load_reg4 = 0;
+
return ret;
}
appropriate counter for -mstats. */
static void
-iq2000_count_memory_refs (op, num)
- rtx op;
- int num;
+iq2000_count_memory_refs (rtx op, int num)
{
int additional = 0;
int n_words = 0;
break;
case LABEL_REF:
- n_words = 2; /* always 2 words */
+ n_words = 2; /* Always 2 words. */
break;
case CONST:
num_refs[n_words-1] += num;
}
\f
+/* Abort after printing out a specific insn. */
+
+static void
+abort_with_insn (rtx insn, const char * reason)
+{
+ error (reason);
+ debug_rtx (insn);
+ fancy_abort (__FILE__, __LINE__, __FUNCTION__);
+}
+\f
/* Return the appropriate instructions to move one operand to another. */
const char *
-iq2000_move_1word (operands, insn, unsignedp)
- rtx operands[];
- rtx insn;
- int unsignedp;
+iq2000_move_1word (rtx operands[], rtx insn, int unsignedp)
{
const char *ret = 0;
rtx op0 = operands[0];
\f
/* Provide the costs of an addressing mode that contains ADDR. */
-int
-iq2000_address_cost (addr)
- rtx addr;
+static int
+iq2000_address_cost (rtx addr)
{
switch (GET_CODE (addr))
{
case CONST:
{
rtx offset = const0_rtx;
- addr = eliminate_constant_term (XEXP (addr, 0), &offset);
+
+ addr = eliminate_constant_term (XEXP (addr, 0), & offset);
if (GET_CODE (addr) == LABEL_REF)
return 2;
return 2;
}
- /* ... fall through ... */
+ /* Fall through. */
case SYMBOL_REF:
return SYMBOL_REF_FLAG (addr) ? 1 : 2;
case PLUS:
{
- register rtx plus0 = XEXP (addr, 0);
- register rtx plus1 = XEXP (addr, 1);
+ rtx plus0 = XEXP (addr, 0);
+ rtx plus1 = XEXP (addr, 1);
if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG)
plus0 = XEXP (addr, 1), plus1 = XEXP (addr, 0);
/* Make normal rtx_code into something we can index from an array. */
static enum internal_test
-map_test_to_internal_test (test_code)
- enum rtx_code test_code;
+map_test_to_internal_test (enum rtx_code test_code)
{
enum internal_test test = ITEST_MAX;
return test;
}
\f
-/* Generate the code to compare two integer values. The return value is:
+/* Generate the code to do a TEST_CODE comparison on two integer values CMP0
+ and CMP1. P_INVERT is NULL or ptr if branch needs to reverse its test.
+ The return value RESULT is:
(reg:SI xx) The pseudo register the comparison is in
- 0 No register, generate a simple branch.
-*/
+ 0 No register, generate a simple branch. */
rtx
-gen_int_relational (test_code, result, cmp0, cmp1, p_invert)
- enum rtx_code test_code; /* relational test (EQ, etc) */
- rtx result; /* result to store comp. or 0 if branch */
- rtx cmp0; /* first operand to compare */
- rtx cmp1; /* second operand to compare */
- int *p_invert; /* NULL or ptr to hold whether branch needs */
- /* to reverse its test */
+gen_int_relational (enum rtx_code test_code, rtx result, rtx cmp0, rtx cmp1,
+ int *p_invert)
{
struct cmp_info
{
- enum rtx_code test_code; /* code to use in instruction (LT vs. LTU) */
- int const_low; /* low bound of constant we can accept */
- int const_high; /* high bound of constant we can accept */
- int const_add; /* constant to add (convert LE -> LT) */
- int reverse_regs; /* reverse registers in test */
- int invert_const; /* != 0 if invert value if cmp1 is constant */
- int invert_reg; /* != 0 if invert value if cmp1 is register */
+ enum rtx_code test_code; /* Code to use in instruction (LT vs. LTU). */
+ int const_low; /* Low bound of constant we can accept. */
+ int const_high; /* High bound of constant we can accept. */
+ int const_add; /* Constant to add (convert LE -> LT). */
+ int reverse_regs; /* Reverse registers in test. */
+ int invert_const; /* != 0 if invert value if cmp1 is constant. */
+ int invert_reg; /* != 0 if invert value if cmp1 is register. */
int unsignedp; /* != 0 for unsigned comparisons. */
};
- static struct cmp_info info[ (int)ITEST_MAX ] = {
-
+ static struct cmp_info info[ (int)ITEST_MAX ] =
+ {
{ XOR, 0, 65535, 0, 0, 0, 0, 0 }, /* EQ */
{ XOR, 0, 65535, 0, 0, 1, 1, 0 }, /* NE */
{ LT, -32769, 32766, 1, 1, 1, 0, 0 }, /* GT */
rtx reg2;
test = map_test_to_internal_test (test_code);
- if (test == ITEST_MAX)
- abort ();
+ gcc_assert (test != ITEST_MAX);
p_info = &info[(int) test];
eqne_p = (p_info->test_code == XOR);
if (mode == VOIDmode)
mode = GET_MODE (cmp1);
- /* Eliminate simple branches */
+ /* Eliminate simple branches. */
branch_p = (result == 0);
if (branch_p)
{
if (GET_CODE (cmp0) == REG || GET_CODE (cmp0) == SUBREG)
{
- /* Comparisons against zero are simple branches */
+ /* Comparisons against zero are simple branches. */
if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)
return 0;
return 0;
}
- /* allocate a pseudo to calculate the value in. */
+ /* Allocate a pseudo to calculate the value in. */
result = gen_reg_rtx (mode);
}
else
{
reg = (invert || eqne_p) ? gen_reg_rtx (mode) : result;
- convert_move (reg, gen_rtx (p_info->test_code, mode, cmp0, cmp1), 0);
+ convert_move (reg, gen_rtx_fmt_ee (p_info->test_code, mode, cmp0, cmp1), 0);
}
if (test == ITEST_NE)
{
- convert_move (result, gen_rtx (GTU, mode, reg, const0_rtx), 0);
+ convert_move (result, gen_rtx_GTU (mode, reg, const0_rtx), 0);
if (p_invert != NULL)
*p_invert = 0;
invert = 0;
rtx one;
one = const1_rtx;
- convert_move (result, gen_rtx (XOR, mode, reg, one), 0);
+ convert_move (result, gen_rtx_XOR (mode, reg, one), 0);
}
return result;
The comparison operands are saved away by cmp{si,di,sf,df}. */
void
-gen_conditional_branch (operands, test_code)
- rtx operands[];
- enum rtx_code test_code;
+gen_conditional_branch (rtx operands[], enum rtx_code test_code)
{
enum cmp_type type = branch_type;
rtx cmp0 = branch_cmp[0];
test_code = NE;
}
else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0)
- /* We don't want to build a comparison against a non-zero
+ /* We don't want to build a comparison against a nonzero
constant. */
cmp1 = force_reg (mode, cmp1);
case CMP_DF:
reg = gen_reg_rtx (CCmode);
- /* For cmp0 != cmp1, build cmp0 == cmp1, and test for result == 0 */
+ /* For cmp0 != cmp1, build cmp0 == cmp1, and test for result == 0. */
emit_insn (gen_rtx_SET (VOIDmode, reg,
- gen_rtx (test_code == NE ? EQ : test_code,
- CCmode, cmp0, cmp1)));
+ gen_rtx_fmt_ee (test_code == NE ? EQ : test_code,
+ CCmode, cmp0, cmp1)));
test_code = test_code == NE ? EQ : NE;
mode = CCmode;
break;
default:
- abort_with_insn (gen_rtx (test_code, VOIDmode, cmp0, cmp1), "bad test");
+ abort_with_insn (gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1),
+ "bad test");
}
/* Generate the branch. */
-
label1 = gen_rtx_LABEL_REF (VOIDmode, operands[0]);
label2 = pc_rtx;
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
gen_rtx_IF_THEN_ELSE (VOIDmode,
- gen_rtx (test_code, mode,
- cmp0, cmp1),
+ gen_rtx_fmt_ee (test_code,
+ mode,
+ cmp0, cmp1),
label1, label2)));
}
\f
-/* Initialize CUMULATIVE_ARGS for a function. */
+/* Initialize CUM for a function FNTYPE. */
void
-init_cumulative_args (cum, fntype, libname)
- CUMULATIVE_ARGS *cum; /* argument info to initialize */
- tree fntype; /* tree ptr for function decl */
- rtx libname ATTRIBUTE_UNUSED; /* SYMBOL_REF of library name or 0 */
+init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
+ rtx libname ATTRIBUTE_UNUSED)
{
static CUMULATIVE_ARGS zero_cum;
- tree param, next_param;
+ tree param;
+ tree next_param;
if (TARGET_DEBUG_D_MODE)
{
fprintf (stderr,
- "\ninit_cumulative_args, fntype = 0x%.8lx", (long)fntype);
+ "\ninit_cumulative_args, fntype = 0x%.8lx", (long) fntype);
if (!fntype)
fputc ('\n', stderr);
else
{
tree ret_type = TREE_TYPE (fntype);
+
fprintf (stderr, ", fntype code = %s, ret code = %s\n",
tree_code_name[(int)TREE_CODE (fntype)],
tree_code_name[(int)TREE_CODE (ret_type)]);
}
}
-/* Advance the argument to the next argument position. */
+/* Advance the argument of type TYPE and mode MODE to the next argument
+ position in CUM. */
void
-function_arg_advance (cum, mode, type, named)
- CUMULATIVE_ARGS *cum; /* current arg information */
- enum machine_mode mode; /* current arg mode */
- tree type; /* type of the argument or 0 if lib support */
- int named; /* whether or not the argument was named */
+function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
+ int named)
{
if (TARGET_DEBUG_D_MODE)
{
"function_adv({gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",
cum->gp_reg_found, cum->arg_number, cum->arg_words,
GET_MODE_NAME (mode));
- fprintf (stderr, HOST_PTR_PRINTF, (const PTR) type);
+ fprintf (stderr, "%p", (void *) type);
fprintf (stderr, ", %d )\n\n", named);
}
break;
default:
- if (GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
- && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
- abort ();
+ gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
+ || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
cum->gp_reg_found = 1;
cum->arg_words += ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
break;
case SFmode:
- cum->arg_words++;
+ cum->arg_words ++;
if (! cum->gp_reg_found && cum->arg_number <= 2)
cum->fp_code += 1 << ((cum->arg_number - 1) * 2);
break;
case HImode:
case SImode:
cum->gp_reg_found = 1;
- cum->arg_words++;
+ cum->arg_words ++;
break;
}
}
-/* Return an RTL expression containing the register for the given mode,
- or 0 if the argument is to be passed on the stack. */
+/* Return an RTL expression containing the register for the given mode MODE
+ and type TYPE in CUM, or 0 if the argument is to be passed on the stack. */
struct rtx_def *
-function_arg (cum, mode, type, named)
- CUMULATIVE_ARGS *cum; /* current arg information */
- enum machine_mode mode; /* current arg mode */
- tree type; /* type of the argument or 0 if lib support */
- int named; /* != 0 for normal args, == 0 for ... args */
+function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
+ int named)
{
rtx ret;
int regbase = -1;
"function_arg( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",
cum->gp_reg_found, cum->arg_number, cum->arg_words,
GET_MODE_NAME (mode));
- fprintf (stderr, HOST_PTR_PRINTF, (const PTR) type);
+ fprintf (stderr, "%p", (void *) type);
fprintf (stderr, ", %d ) = ", named);
}
break;
default:
- if (GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
- && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
- abort ();
+ gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
+ || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
/* Drops through. */
case BLKmode:
}
else
{
- if (regbase == -1)
- abort ();
+ gcc_assert (regbase != -1);
if (! type || TREE_CODE (type) != RECORD_TYPE
|| ! named || ! TYPE_SIZE_UNIT (type)
/* ??? If this is a packed structure, then the last hunk won't
be 64 bits. */
-
chunks
= tree_low_cst (TYPE_SIZE_UNIT (type), 1) / UNITS_PER_WORD;
if (chunks + *arg_words + bias > (unsigned) MAX_ARGS_IN_REGISTERS)
chunks = MAX_ARGS_IN_REGISTERS - *arg_words - bias;
- /* assign_parms checks the mode of ENTRY_PARM, so we must
+ /* Assign_parms checks the mode of ENTRY_PARM, so we must
use the actual mode here. */
ret = gen_rtx_PARALLEL (mode, rtvec_alloc (chunks));
if (mode == VOIDmode)
{
if (cum->num_adjusts > 0)
- ret = gen_rtx (PARALLEL, (enum machine_mode) cum->fp_code,
+ ret = gen_rtx_PARALLEL ((enum machine_mode) cum->fp_code,
gen_rtvec_v (cum->num_adjusts, cum->adjust));
}
return ret;
}
-int
-function_arg_partial_nregs (cum, mode, type, named)
- CUMULATIVE_ARGS *cum; /* current arg information */
- enum machine_mode mode; /* current arg mode */
- tree type ATTRIBUTE_UNUSED;/* type of the argument or 0 if lib support */
- int named ATTRIBUTE_UNUSED;/* != 0 for normal args, == 0 for ... args */
+static int
+iq2000_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type ATTRIBUTE_UNUSED,
+ bool named ATTRIBUTE_UNUSED)
{
- if (mode == DImode
- && cum->arg_words == MAX_ARGS_IN_REGISTERS - (unsigned)1)
+ if (mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS - 1)
{
if (TARGET_DEBUG_D_MODE)
- fprintf (stderr, "function_arg_partial_nregs = 1\n");
-
- return 1;
+ fprintf (stderr, "iq2000_arg_partial_bytes=%d\n", UNITS_PER_WORD);
+ return UNITS_PER_WORD;
}
return 0;
/* Implement va_start. */
void
-iq2000_va_start (valist, nextarg)
- tree valist;
- rtx nextarg;
+iq2000_va_start (tree valist, rtx nextarg)
{
int int_arg_words;
-
- /* Find out how many non-float named formals */
+ /* Find out how many non-float named formals. */
int gpr_save_area_size;
- /* Note UNITS_PER_WORD is 4 bytes */
+ /* Note UNITS_PER_WORD is 4 bytes. */
int_arg_words = current_function_args_info.arg_words;
+
if (int_arg_words < 8 )
- /* Adjust for the prologue's economy measure */
+ /* Adjust for the prologue's economy measure. */
gpr_save_area_size = (8 - int_arg_words) * UNITS_PER_WORD;
else
gpr_save_area_size = 0;
/* Everything is in the GPR save area, or in the overflow
area which is contiguous with it. */
-
- nextarg = plus_constant (nextarg, -gpr_save_area_size);
+ nextarg = plus_constant (nextarg, - gpr_save_area_size);
std_expand_builtin_va_start (valist, nextarg);
}
+\f
+/* Allocate a chunk of memory for per-function machine-dependent data. */
-/* Implement va_arg. */
-
-rtx
-iq2000_va_arg (valist, type)
- tree valist, type;
+static struct machine_function *
+iq2000_init_machine_status (void)
{
- HOST_WIDE_INT size, rsize;
- rtx addr_rtx;
- tree t;
-
- int indirect;
- rtx r, lab_over = NULL_RTX, lab_false;
- tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff;
- tree ovfl, gtop, ftop, goff, foff;
-
- size = int_size_in_bytes (type);
- rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
- indirect
- = function_arg_pass_by_reference (NULL, TYPE_MODE (type), type, 0);
- if (indirect)
- {
- size = POINTER_SIZE / BITS_PER_UNIT;
- rsize = UNITS_PER_WORD;
- }
-
- addr_rtx = gen_reg_rtx (Pmode);
-
- {
- /* Case of all args in a merged stack. No need to check bounds,
- just advance valist along the stack. */
+ struct machine_function *f;
- tree gpr = valist;
- if (! indirect
- && TYPE_ALIGN (type) > (unsigned) BITS_PER_WORD)
- {
- t = build (PLUS_EXPR, TREE_TYPE (gpr), gpr,
- build_int_2 (2*UNITS_PER_WORD - 1, 0));
- t = build (BIT_AND_EXPR, TREE_TYPE (t), t,
- build_int_2 (-2*UNITS_PER_WORD, -1));
- t = build (MODIFY_EXPR, TREE_TYPE (gpr), gpr, t);
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
- }
+ f = ggc_alloc_cleared (sizeof (struct machine_function));
- t = build (POSTINCREMENT_EXPR, TREE_TYPE (gpr), gpr,
- size_int (rsize));
- r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
- if (r != addr_rtx)
- emit_move_insn (addr_rtx, r);
+ return f;
+}
- /* flush the POSTINCREMENT */
- emit_queue();
+/* Implement TARGET_HANDLE_OPTION. */
- if (indirect)
- {
- r = gen_rtx_MEM (Pmode, addr_rtx);
- set_mem_alias_set (r, get_varargs_alias_set ());
- emit_move_insn (addr_rtx, r);
- }
- else
- {
- if (BYTES_BIG_ENDIAN && rsize != size)
- addr_rtx = plus_constant (addr_rtx, rsize - size);
- }
- return addr_rtx;
- }
-
- /* Not a simple merged stack. Need ptrs and indexes left by va_start. */
-
- f_ovfl = TYPE_FIELDS (va_list_type_node);
- f_gtop = TREE_CHAIN (f_ovfl);
- f_ftop = TREE_CHAIN (f_gtop);
- f_goff = TREE_CHAIN (f_ftop);
- f_foff = TREE_CHAIN (f_goff);
-
- ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl);
- gtop = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop);
- ftop = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop);
- goff = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff);
- foff = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff);
-
- lab_false = gen_label_rtx ();
- lab_over = gen_label_rtx ();
-
- if (TREE_CODE (type) == REAL_TYPE)
- {
-
- /* Emit code to branch if foff == 0. */
- r = expand_expr (foff, NULL_RTX, TYPE_MODE (TREE_TYPE (foff)),
- EXPAND_NORMAL);
- emit_cmp_and_jump_insns (r, const0_rtx, EQ,
- const1_rtx, GET_MODE (r), 1, lab_false);
-
- /* Emit code for addr_rtx = ftop - foff */
- t = build (MINUS_EXPR, TREE_TYPE (ftop), ftop, foff );
- r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
- if (r != addr_rtx)
- emit_move_insn (addr_rtx, r);
-
- /* Emit code for foff-=8.
- Advances the offset up FPR save area by one double */
- t = build (MINUS_EXPR, TREE_TYPE (foff), foff, build_int_2 (8, 0));
- t = build (MODIFY_EXPR, TREE_TYPE (foff), foff, t);
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
-
- emit_queue();
- emit_jump (lab_over);
- emit_barrier ();
- emit_label (lab_false);
-
- /* If a 4-byte int is followed by an 8-byte float, then
- natural alignment causes a 4 byte gap.
- So, dynamically adjust ovfl up to a multiple of 8. */
- t = build (BIT_AND_EXPR, TREE_TYPE (ovfl), ovfl,
- build_int_2 (7, 0));
- t = build (PLUS_EXPR, TREE_TYPE (ovfl), ovfl, t);
- t = build (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
-
- /* Emit code for addr_rtx = the ovfl pointer into overflow area.
- Postincrement the ovfl pointer by 8. */
- t = build (POSTINCREMENT_EXPR, TREE_TYPE(ovfl), ovfl,
- size_int (8));
- r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
- if (r != addr_rtx)
- emit_move_insn (addr_rtx, r);
-
- emit_queue();
- emit_label (lab_over);
- return addr_rtx;
- }
- else
+static bool
+iq2000_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
+{
+ switch (code)
{
- /* not REAL_TYPE */
- int step_size;
+ case OPT_mcpu_:
+ if (strcmp (arg, "iq10") == 0)
+ iq2000_tune = PROCESSOR_IQ10;
+ else if (strcmp (arg, "iq2000") == 0)
+ iq2000_tune = PROCESSOR_IQ2000;
+ else
+ return false;
+ return true;
- if (TREE_CODE (type) == INTEGER_TYPE
- && TYPE_PRECISION (type) == 64)
- {
- /* int takes 32 bits of the GPR save area, but
- longlong takes an aligned 64 bits. So, emit code
- to zero the low order bits of goff, thus aligning
- the later calculation of (gtop-goff) upwards. */
- t = build (BIT_AND_EXPR, TREE_TYPE (goff), goff,
- build_int_2 (-8, -1));
- t = build (MODIFY_EXPR, TREE_TYPE (goff), goff, t);
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
- }
+ case OPT_march_:
+ /* This option has no effect at the moment. */
+ return (strcmp (arg, "default") == 0
+ || strcmp (arg, "DEFAULT") == 0
+ || strcmp (arg, "iq2000") == 0);
- /* Emit code to branch if goff == 0. */
- r = expand_expr (goff, NULL_RTX, TYPE_MODE (TREE_TYPE (goff)),
- EXPAND_NORMAL);
- emit_cmp_and_jump_insns (r, const0_rtx, EQ,
- const1_rtx, GET_MODE (r), 1, lab_false);
-
- /* Emit code for addr_rtx = gtop - goff. */
- t = build (MINUS_EXPR, TREE_TYPE (gtop), gtop, goff);
- r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
- if (r != addr_rtx)
- emit_move_insn (addr_rtx, r);
-
- if (TYPE_PRECISION (type) == 64)
- step_size = 8;
- else
- step_size = UNITS_PER_WORD;
-
- /* Emit code for goff = goff - step_size.
- Advances the offset up GPR save area over the item. */
- t = build (MINUS_EXPR, TREE_TYPE (goff), goff,
- build_int_2 (step_size, 0));
- t = build (MODIFY_EXPR, TREE_TYPE (goff), goff, t);
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
-
- emit_queue();
- emit_jump (lab_over);
- emit_barrier ();
- emit_label (lab_false);
-
- /* Emit code for addr_rtx -> overflow area, postinc by step_size */
- t = build (POSTINCREMENT_EXPR, TREE_TYPE(ovfl), ovfl,
- size_int (step_size));
- r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
- if (r != addr_rtx)
- emit_move_insn (addr_rtx, r);
-
- emit_queue();
- emit_label (lab_over);
-
- if (indirect)
- {
- r = gen_rtx_MEM (Pmode, addr_rtx);
- set_mem_alias_set (r, get_varargs_alias_set ());
- emit_move_insn (addr_rtx, r);
- }
- else
- {
- if (BYTES_BIG_ENDIAN && rsize != size)
- addr_rtx = plus_constant (addr_rtx, rsize - size);
- }
- return addr_rtx;
+ default:
+ return true;
}
}
-\f
-/* Abort after printing out a specific insn. */
-static void
-abort_with_insn (insn, reason)
- rtx insn;
- const char *reason;
-{
- error (reason);
- debug_rtx (insn);
- abort ();
-}
-\f
/* Detect any conflicts in the switches. */
void
-override_options ()
+override_options (void)
{
- register enum processor_type iq2000_cpu;
-
target_flags &= ~MASK_GPOPT;
iq2000_isa = IQ2000_ISA_DEFAULT;
/* Identify the processor type. */
- if (iq2000_cpu_string != 0)
- {
- iq2000_cpu = iq2000_parse_cpu (iq2000_cpu_string);
- if (iq2000_cpu == PROCESSOR_DEFAULT)
- {
- error ("bad value (%s) for -mcpu= switch", iq2000_arch_string);
- iq2000_cpu_string = "default";
- }
- iq2000_arch = iq2000_cpu;
- iq2000_tune = iq2000_cpu;
- }
-
- if (iq2000_arch_string == 0
- || ! strcmp (iq2000_arch_string, "default")
- || ! strcmp (iq2000_arch_string, "DEFAULT"))
- {
- switch (iq2000_isa)
- {
- default:
- iq2000_arch_string = "iq2000";
- iq2000_arch = PROCESSOR_IQ2000;
- break;
- }
- }
- else
- {
- iq2000_arch = iq2000_parse_cpu (iq2000_arch_string);
- if (iq2000_arch == PROCESSOR_DEFAULT)
- {
- error ("bad value (%s) for -march= switch", iq2000_arch_string);
- iq2000_arch_string = "default";
- }
- if (iq2000_arch == PROCESSOR_IQ10)
- {
- error ("The compiler does not support -march=%s.", iq2000_arch_string);
- iq2000_arch_string = "default";
- }
- }
-
iq2000_print_operand_punct['?'] = 1;
iq2000_print_operand_punct['#'] = 1;
iq2000_print_operand_punct['&'] = 1;
gpr_mode = SImode;
/* Function to allocate machine-dependent function status. */
- init_machine_status = &iq2000_init_machine_status;
-}
-
-/* Allocate a chunk of memory for per-function machine-dependent data. */
-
-static struct machine_function *
-iq2000_init_machine_status ()
-{
- return ((struct machine_function *)
- ggc_alloc_cleared (sizeof (struct machine_function)));
+ init_machine_status = iq2000_init_machine_status;
}
\f
/* The arg pointer (which is eliminated) points to the virtual frame pointer,
pointer after the initial adjustments. */
HOST_WIDE_INT
-iq2000_debugger_offset (addr, offset)
- rtx addr;
- HOST_WIDE_INT offset;
+iq2000_debugger_offset (rtx addr, HOST_WIDE_INT offset)
{
rtx offset2 = const0_rtx;
- rtx reg = eliminate_constant_term (addr, &offset2);
+ rtx reg = eliminate_constant_term (addr, & offset2);
if (offset == 0)
offset = INTVAL (offset2);
if (reg == stack_pointer_rtx || reg == frame_pointer_rtx
|| reg == hard_frame_pointer_rtx)
{
- HOST_WIDE_INT frame_size = (!cfun->machine->frame.initialized)
+ HOST_WIDE_INT frame_size = (!cfun->machine->initialized)
? compute_frame_size (get_frame_size ())
- : cfun->machine->frame.total_size;
+ : cfun->machine->total_size;
offset = offset - frame_size;
}
of load delays, and also to update the delay slot statistics. */
void
-final_prescan_insn (insn, opvec, noperands)
- rtx insn;
- rtx opvec[] ATTRIBUTE_UNUSED;
- int noperands ATTRIBUTE_UNUSED;
+final_prescan_insn (rtx insn, rtx opvec[] ATTRIBUTE_UNUSED,
+ int noperands ATTRIBUTE_UNUSED)
{
if (dslots_number_nops > 0)
{
rtx pattern = PATTERN (insn);
int length = get_attr_length (insn);
- /* Do we need to emit a NOP? */
+ /* Do we need to emit a NOP? */
if (length == 0
|| (iq2000_load_reg != 0 && reg_mentioned_p (iq2000_load_reg, pattern))
|| (iq2000_load_reg2 != 0 && reg_mentioned_p (iq2000_load_reg2, pattern))
fputs ("\tnop\n", asm_out_file);
else
- dslots_load_filled++;
+ dslots_load_filled ++;
while (--dslots_number_nops > 0)
fputs ("\tnop\n", asm_out_file);
iq2000_load_reg4 = 0;
}
- if ((GET_CODE (insn) == JUMP_INSN
+ if ( (GET_CODE (insn) == JUMP_INSN
|| GET_CODE (insn) == CALL_INSN
|| (GET_CODE (PATTERN (insn)) == RETURN))
&& NEXT_INSN (PREV_INSN (insn)) == insn)
{
rtx nop_insn = emit_insn_after (gen_nop (), insn);
+
INSN_ADDRESSES_NEW (nop_insn, -1);
}
if (TARGET_STATS
&& (GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == CALL_INSN))
- dslots_jump_total++;
+ dslots_jump_total ++;
}
\f
/* Return the bytes needed to compute the frame pointer from the current
- stack pointer.
+ stack pointer where SIZE is the # of var. bytes allocated.
IQ2000 stack frames look like:
| arguments passed |
| in registers, even |
low SP->| if not passed. |
- memory +-----------------------+
-
-*/
+ memory +-----------------------+ */
HOST_WIDE_INT
-compute_frame_size (size)
- HOST_WIDE_INT size; /* # of var. bytes allocated */
+compute_frame_size (HOST_WIDE_INT size)
{
int regno;
- HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up */
- HOST_WIDE_INT var_size; /* # bytes that variables take up */
- HOST_WIDE_INT args_size; /* # bytes that outgoing arguments take up */
- HOST_WIDE_INT extra_size; /* # extra bytes */
- HOST_WIDE_INT gp_reg_rounded; /* # bytes needed to store gp after rounding */
- HOST_WIDE_INT gp_reg_size; /* # bytes needed to store gp regs */
- HOST_WIDE_INT fp_reg_size; /* # bytes needed to store fp regs */
- long mask; /* mask of saved gp registers */
- int fp_inc; /* 1 or 2 depending on the size of fp regs */
- long fp_bits; /* bitmask to use for each fp register */
+ HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up. */
+ HOST_WIDE_INT var_size; /* # bytes that variables take up. */
+ HOST_WIDE_INT args_size; /* # bytes that outgoing arguments take up. */
+ HOST_WIDE_INT extra_size; /* # extra bytes. */
+ HOST_WIDE_INT gp_reg_rounded; /* # bytes needed to store gp after rounding. */
+ HOST_WIDE_INT gp_reg_size; /* # bytes needed to store gp regs. */
+ HOST_WIDE_INT fp_reg_size; /* # bytes needed to store fp regs. */
+ long mask; /* mask of saved gp registers. */
+ int fp_inc; /* 1 or 2 depending on the size of fp regs. */
+ long fp_bits; /* bitmask to use for each fp register. */
gp_reg_size = 0;
fp_reg_size = 0;
args_size = IQ2000_STACK_ALIGN (current_function_outgoing_args_size);
/* If a function dynamically allocates the stack and
- has 0 for STACK_DYNAMIC_OFFSET then allocate some stack space */
-
+ has 0 for STACK_DYNAMIC_OFFSET then allocate some stack space. */
if (args_size == 0 && current_function_calls_alloca)
args_size = 4 * UNITS_PER_WORD;
/* We need to restore these for the handler. */
if (current_function_calls_eh_return)
{
- int i;
+ unsigned int i;
+
for (i = 0; ; ++i)
{
regno = EH_RETURN_DATA_REGNO (i);
- if (regno == (signed int) INVALID_REGNUM)
+ if (regno == (int) INVALID_REGNUM)
break;
gp_reg_size += GET_MODE_SIZE (gpr_mode);
mask |= 1L << (regno - GP_REG_FIRST);
total_size += IQ2000_STACK_ALIGN (current_function_pretend_args_size);
/* Save other computed information. */
- cfun->machine->frame.total_size = total_size;
- cfun->machine->frame.var_size = var_size;
- cfun->machine->frame.args_size = args_size;
- cfun->machine->frame.extra_size = extra_size;
- cfun->machine->frame.gp_reg_size = gp_reg_size;
- cfun->machine->frame.fp_reg_size = fp_reg_size;
- cfun->machine->frame.mask = mask;
- cfun->machine->frame.initialized = reload_completed;
- cfun->machine->frame.num_gp = gp_reg_size / UNITS_PER_WORD;
+ cfun->machine->total_size = total_size;
+ cfun->machine->var_size = var_size;
+ cfun->machine->args_size = args_size;
+ cfun->machine->extra_size = extra_size;
+ cfun->machine->gp_reg_size = gp_reg_size;
+ cfun->machine->fp_reg_size = fp_reg_size;
+ cfun->machine->mask = mask;
+ cfun->machine->initialized = reload_completed;
+ cfun->machine->num_gp = gp_reg_size / UNITS_PER_WORD;
if (mask)
{
offset = (args_size + extra_size + var_size
+ gp_reg_size - GET_MODE_SIZE (gpr_mode));
- cfun->machine->frame.gp_sp_offset = offset;
- cfun->machine->frame.gp_save_offset = offset - total_size;
+ cfun->machine->gp_sp_offset = offset;
+ cfun->machine->gp_save_offset = offset - total_size;
}
else
{
- cfun->machine->frame.gp_sp_offset = 0;
- cfun->machine->frame.gp_save_offset = 0;
+ cfun->machine->gp_sp_offset = 0;
+ cfun->machine->gp_save_offset = 0;
}
- cfun->machine->frame.fp_sp_offset = 0;
- cfun->machine->frame.fp_save_offset = 0;
+ cfun->machine->fp_sp_offset = 0;
+ cfun->machine->fp_save_offset = 0;
/* Ok, we're done. */
return total_size;
the stack pointer or hard frame pointer. */
int
-iq2000_initial_elimination_offset (from, to)
- int from;
- int to ATTRIBUTE_UNUSED;
+iq2000_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED)
{
int offset;
if ((from) == FRAME_POINTER_REGNUM)
(offset) = 0;
else if ((from) == ARG_POINTER_REGNUM)
- (offset) = (cfun->machine->frame.total_size);
+ (offset) = (cfun->machine->total_size);
else if ((from) == RETURN_ADDRESS_POINTER_REGNUM)
- {
- if (leaf_function_p ())
- (offset) = 0;
- else (offset) = cfun->machine->frame.gp_sp_offset
- + ((UNITS_PER_WORD - (POINTER_SIZE / BITS_PER_UNIT))
- * (BYTES_BIG_ENDIAN != 0));
- }
+ {
+ if (leaf_function_p ())
+ (offset) = 0;
+ else (offset) = cfun->machine->gp_sp_offset
+ + ((UNITS_PER_WORD - (POINTER_SIZE / BITS_PER_UNIT))
+ * (BYTES_BIG_ENDIAN != 0));
+ }
return offset;
}
OFFSET is too large to add in a single instruction. */
static rtx
-iq2000_add_large_offset_to_sp (offset)
- HOST_WIDE_INT offset;
+iq2000_add_large_offset_to_sp (HOST_WIDE_INT offset)
{
rtx reg = gen_rtx_REG (Pmode, IQ2000_TEMP2_REGNUM);
rtx offset_rtx = GEN_INT (offset);
operation DWARF_PATTERN. */
static void
-iq2000_annotate_frame_insn (insn, dwarf_pattern)
- rtx insn, dwarf_pattern;
+iq2000_annotate_frame_insn (rtx insn, rtx dwarf_pattern)
{
RTX_FRAME_RELATED_P (insn) = 1;
REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR,
frame related and note that it stores REG at (SP + OFFSET). */
static void
-iq2000_emit_frame_related_store (mem, reg, offset)
- rtx mem;
- rtx reg;
- HOST_WIDE_INT offset;
+iq2000_emit_frame_related_store (rtx mem, rtx reg, HOST_WIDE_INT offset)
{
rtx dwarf_address = plus_constant (stack_pointer_rtx, offset);
rtx dwarf_mem = gen_rtx_MEM (GET_MODE (reg), dwarf_address);
gen_rtx_SET (GET_MODE (reg), dwarf_mem, reg));
}
+/* Emit instructions to save/restore registers, as determined by STORE_P. */
+
static void
-save_restore_insns (store_p)
- int store_p; /* true if this is prologue */
+save_restore_insns (int store_p)
{
- long mask = cfun->machine->frame.mask;
+ long mask = cfun->machine->mask;
int regno;
rtx base_reg_rtx;
HOST_WIDE_INT base_offset;
HOST_WIDE_INT gp_offset;
HOST_WIDE_INT end_offset;
- if (frame_pointer_needed
- && ! BITSET_P (mask, HARD_FRAME_POINTER_REGNUM - GP_REG_FIRST))
- abort ();
+ gcc_assert (!frame_pointer_needed
+ || BITSET_P (mask, HARD_FRAME_POINTER_REGNUM - GP_REG_FIRST));
if (mask == 0)
{
the constant created in the prologue/epilogue to adjust the stack
frame. */
- gp_offset = cfun->machine->frame.gp_sp_offset;
+ gp_offset = cfun->machine->gp_sp_offset;
end_offset
- = gp_offset - (cfun->machine->frame.gp_reg_size
+ = gp_offset - (cfun->machine->gp_reg_size
- GET_MODE_SIZE (gpr_mode));
if (gp_offset < 0 || end_offset < 0)
internal_error
- ("gp_offset (%ld) or end_offset (%ld) is less than zero.",
+ ("gp_offset (%ld) or end_offset (%ld) is less than zero",
(long) gp_offset, (long) end_offset);
else if (gp_offset < 32768)
{
int regno;
int reg_save_count = 0;
+
for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--)
if (BITSET_P (mask, regno - GP_REG_FIRST)) reg_save_count += 1;
base_offset = gp_offset - ((reg_save_count - 1) * 4);
{
rtx reg_rtx;
rtx mem_rtx
- = gen_rtx (MEM, gpr_mode,
- gen_rtx (PLUS, Pmode, base_reg_rtx,
+ = gen_rtx_MEM (gpr_mode,
+ gen_rtx_PLUS (Pmode, base_reg_rtx,
GEN_INT (gp_offset - base_offset)));
- if (! current_function_calls_eh_return)
- RTX_UNCHANGING_P (mem_rtx) = 1;
-
- reg_rtx = gen_rtx (REG, gpr_mode, regno);
+ reg_rtx = gen_rtx_REG (gpr_mode, regno);
if (store_p)
iq2000_emit_frame_related_store (mem_rtx, reg_rtx, gp_offset);
/* Expand the prologue into a bunch of separate insns. */
void
-iq2000_expand_prologue ()
+iq2000_expand_prologue (void)
{
int regno;
HOST_WIDE_INT tsize;
int store_args_on_stack = (iq2000_can_use_return_insn ());
/* If struct value address is treated as the first argument. */
- if (aggregate_value_p (DECL_RESULT (fndecl))
+ if (aggregate_value_p (DECL_RESULT (fndecl), fndecl)
&& ! current_function_returns_pcc_struct
- && struct_value_incoming_rtx == 0)
+ && targetm.calls.struct_value_rtx (TREE_TYPE (fndecl), 1) == 0)
{
tree type = build_pointer_type (fntype);
tree function_result_decl = build_decl (PARM_DECL, NULL_TREE, type);
variable arguments.
This is only needed if store_args_on_stack is true. */
-
- INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX, 0);
+ INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX, 0, 0);
regno = GP_ARG_FIRST;
for (cur_arg = fnargs; cur_arg != 0; cur_arg = next_arg)
{
int words;
- if (GET_CODE (entry_parm) != REG)
- abort ();
+ gcc_assert (GET_CODE (entry_parm) == REG);
- /* passed in a register, so will get homed automatically */
+ /* Passed in a register, so will get homed automatically. */
if (GET_MODE (entry_parm) == BLKmode)
words = (int_size_in_bytes (passed_type) + 3) / 4;
else
Function_arg has encoded a PARALLEL rtx, holding a vector of
adjustments to be made as the next_arg_reg variable, so we split up the
insns, and emit them separately. */
-
next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1);
if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL)
{
PUT_CODE (SET_SRC (pattern), ASHIFTRT);
insn = emit_insn (pattern);
-
- /* Global life information isn't valid at this point, so we
- can't check whether these shifts are actually used. Mark
- them MAYBE_DEAD so that flow2 will remove them, and not
- complain about dead code in the prologue. */
- REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
- REG_NOTES (insn));
}
}
for (; regno <= GP_ARG_LAST; regno++)
{
if (offset != 0)
- ptr = gen_rtx (PLUS, Pmode, stack_pointer_rtx, GEN_INT (offset));
- emit_move_insn (gen_rtx (MEM, gpr_mode, ptr),
- gen_rtx (REG, gpr_mode, regno));
+ ptr = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
+ emit_move_insn (gen_rtx_MEM (gpr_mode, ptr),
+ gen_rtx_REG (gpr_mode, regno));
offset += GET_MODE_SIZE (gpr_mode);
}
if (tsize > 32767)
{
- adjustment_rtx = gen_rtx (REG, Pmode, IQ2000_TEMP1_REGNUM);
+ adjustment_rtx = gen_rtx_REG (Pmode, IQ2000_TEMP1_REGNUM);
emit_move_insn (adjustment_rtx, tsize_rtx);
}
else
/* Expand the epilogue into a bunch of separate insns. */
void
-iq2000_expand_epilogue ()
+iq2000_expand_epilogue (void)
{
- HOST_WIDE_INT tsize = cfun->machine->frame.total_size;
+ HOST_WIDE_INT tsize = cfun->machine->total_size;
rtx tsize_rtx = GEN_INT (tsize);
rtx tmp_rtx = (rtx)0;
if (iq2000_can_use_return_insn ())
{
- emit_insn (gen_return ());
+ emit_jump_insn (gen_return ());
return;
}
if (current_function_calls_eh_return)
{
/* Perform the additional bump for __throw. */
- emit_move_insn (gen_rtx (REG, Pmode, HARD_FRAME_POINTER_REGNUM),
+ emit_move_insn (gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM),
stack_pointer_rtx);
- emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, Pmode,
+ emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode,
HARD_FRAME_POINTER_REGNUM)));
emit_jump_insn (gen_eh_return_internal ());
}
else
- emit_jump_insn (gen_return_internal (gen_rtx (REG, Pmode,
+ emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode,
GP_REG_FIRST + 31)));
}
void
-iq2000_expand_eh_return (address)
- rtx address;
+iq2000_expand_eh_return (rtx address)
{
- HOST_WIDE_INT gp_offset = cfun->machine->frame.gp_sp_offset;
+ HOST_WIDE_INT gp_offset = cfun->machine->gp_sp_offset;
rtx scratch;
scratch = plus_constant (stack_pointer_rtx, gp_offset);
was created. */
int
-iq2000_can_use_return_insn ()
+iq2000_can_use_return_insn (void)
{
if (! reload_completed)
return 0;
- if (regs_ever_live[31] || profile_flag)
+ if (df_regs_ever_live_p (31) || profile_flag)
return 0;
- if (cfun->machine->frame.initialized)
- return cfun->machine->frame.total_size == 0;
+ if (cfun->machine->initialized)
+ return cfun->machine->total_size == 0;
return compute_frame_size (get_frame_size ()) == 0;
}
\f
-/* Returns non-zero if X contains a SYMBOL_REF. */
+/* Returns nonzero if X contains a SYMBOL_REF. */
static int
-symbolic_expression_p (x)
- rtx x;
+symbolic_expression_p (rtx x)
{
if (GET_CODE (x) == SYMBOL_REF)
return 1;
if (GET_CODE (x) == CONST)
return symbolic_expression_p (XEXP (x, 0));
- if (GET_RTX_CLASS (GET_CODE (x)) == '1')
+ if (UNARY_P (x))
return symbolic_expression_p (XEXP (x, 0));
- if (GET_RTX_CLASS (GET_CODE (x)) == 'c'
- || GET_RTX_CLASS (GET_CODE (x)) == '2')
+ if (ARITHMETIC_P (x))
return (symbolic_expression_p (XEXP (x, 0))
|| symbolic_expression_p (XEXP (x, 1)));
/* Choose the section to use for the constant rtx expression X that has
mode MODE. */
-static void
-iq2000_select_rtx_section (mode, x, align)
- enum machine_mode mode;
- rtx x ATTRIBUTE_UNUSED;
- unsigned HOST_WIDE_INT align;
+static section *
+iq2000_select_rtx_section (enum machine_mode mode, rtx x ATTRIBUTE_UNUSED,
+ unsigned HOST_WIDE_INT align)
{
/* For embedded applications, always put constants in read-only data,
in order to reduce RAM usage. */
- /* For embedded applications, always put constants in read-only data,
- in order to reduce RAM usage. */
- mergeable_constant_section (mode, align, 0);
+ return mergeable_constant_section (mode, align, 0);
}
/* Choose the section to use for DECL. RELOC is true if its value contains
ENCODE_SECTION_INFO in iq2000.h so that references to these symbols
are done correctly. */
-static void
-iq2000_select_section (decl, reloc, align)
- tree decl;
- int reloc ATTRIBUTE_UNUSED;
- unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
+static section *
+iq2000_select_section (tree decl, int reloc ATTRIBUTE_UNUSED,
+ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
{
if (TARGET_EMBEDDED_DATA)
{
/* For embedded applications, always put an object in read-only data
if possible, in order to reduce RAM usage. */
-
- if (((TREE_CODE (decl) == VAR_DECL
- && TREE_READONLY (decl) && !TREE_SIDE_EFFECTS (decl)
- && DECL_INITIAL (decl)
- && (DECL_INITIAL (decl) == error_mark_node
- || TREE_CONSTANT (DECL_INITIAL (decl))))
- /* Deal with calls from output_constant_def_contents. */
- || (TREE_CODE (decl) != VAR_DECL
- && (TREE_CODE (decl) != STRING_CST
- || !flag_writable_strings))))
- readonly_data_section ();
+ if ((TREE_CODE (decl) == VAR_DECL
+ && TREE_READONLY (decl) && !TREE_SIDE_EFFECTS (decl)
+ && DECL_INITIAL (decl)
+ && (DECL_INITIAL (decl) == error_mark_node
+ || TREE_CONSTANT (DECL_INITIAL (decl))))
+ /* Deal with calls from output_constant_def_contents. */
+ || TREE_CODE (decl) != VAR_DECL)
+ return readonly_data_section;
else
- data_section ();
+ return data_section;
}
else
{
/* For hosted applications, always put an object in small data if
possible, as this gives the best performance. */
-
- if (((TREE_CODE (decl) == VAR_DECL
- && TREE_READONLY (decl) && !TREE_SIDE_EFFECTS (decl)
- && DECL_INITIAL (decl)
- && (DECL_INITIAL (decl) == error_mark_node
- || TREE_CONSTANT (DECL_INITIAL (decl))))
- /* Deal with calls from output_constant_def_contents. */
- || (TREE_CODE (decl) != VAR_DECL
- && (TREE_CODE (decl) != STRING_CST
- || !flag_writable_strings))))
- readonly_data_section ();
+ if ((TREE_CODE (decl) == VAR_DECL
+ && TREE_READONLY (decl) && !TREE_SIDE_EFFECTS (decl)
+ && DECL_INITIAL (decl)
+ && (DECL_INITIAL (decl) == error_mark_node
+ || TREE_CONSTANT (DECL_INITIAL (decl))))
+ /* Deal with calls from output_constant_def_contents. */
+ || TREE_CODE (decl) != VAR_DECL)
+ return readonly_data_section;
else
- data_section ();
+ return data_section;
}
}
/* Return register to use for a function return value with VALTYPE for function
FUNC. */
rtx
-iq2000_function_value (valtype, func)
- tree valtype;
- tree func ATTRIBUTE_UNUSED;
+iq2000_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
{
int reg = GP_RETURN;
enum machine_mode mode = TYPE_MODE (valtype);
- int unsignedp = TREE_UNSIGNED (valtype);
+ int unsignedp = TYPE_UNSIGNED (valtype);
- /* Since we define PROMOTE_FUNCTION_RETURN, we must promote the mode
- just as PROMOTE_MODE does. */
+ /* Since we define TARGET_PROMOTE_FUNCTION_RETURN that returns true,
+ we must promote the mode just as PROMOTE_MODE does. */
mode = promote_mode (valtype, mode, &unsignedp, 1);
return gen_rtx_REG (mode, reg);
}
\f
-/* The implementation of FUNCTION_ARG_PASS_BY_REFERENCE. Return
- nonzero when an argument must be passed by reference. */
+/* Return true when an argument must be passed by reference. */
-int
-function_arg_pass_by_reference (cum, mode, type, named)
- CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;
- enum machine_mode mode;
- tree type;
- int named ATTRIBUTE_UNUSED;
+static bool
+iq2000_pass_by_reference (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, bool named ATTRIBUTE_UNUSED)
{
int size;
/* We must pass by reference if we would be both passing in registers
and the stack. This is because any subsequent partial arg would be
handled incorrectly in this case. */
-
- if (cum && MUST_PASS_IN_STACK (mode, type))
+ if (cum && targetm.calls.must_pass_in_stack (mode, type))
{
/* Don't pass the actual CUM to FUNCTION_ARG, because we would
get double copies of any offsets generated for small structs
passed in registers. */
CUMULATIVE_ARGS temp;
+
temp = *cum;
if (FUNCTION_ARG (temp, mode, type, named) != 0)
return 1;
attributes in the machine-description file. */
int
-iq2000_adjust_insn_length (insn, length)
- rtx insn;
- int length;
+iq2000_adjust_insn_length (rtx insn, int length)
{
/* A unconditional jump has an unfilled delay slot if it is not part
- of a sequence. A conditional jump normally has a delay slot */
+ of a sequence. A conditional jump normally has a delay slot. */
if (simplejump_p (insn)
- || ((GET_CODE (insn) == JUMP_INSN
- || GET_CODE (insn) == CALL_INSN)))
+ || ( (GET_CODE (insn) == JUMP_INSN
+ || GET_CODE (insn) == CALL_INSN)))
length += 4;
return length;
INSN is the branch instruction. OPERANDS[0] is the condition.
OPERANDS[1] is the target of the branch. OPERANDS[2] is the target
of the first operand to the condition. If TWO_OPERANDS_P is
- non-zero the comparison takes two operands; OPERANDS[3] will be the
+ nonzero the comparison takes two operands; OPERANDS[3] will be the
second operand.
- If INVERTED_P is non-zero we are to branch if the condition does
- not hold. If FLOAT_P is non-zero this is a floating-point comparison.
+ If INVERTED_P is nonzero we are to branch if the condition does
+ not hold. If FLOAT_P is nonzero this is a floating-point comparison.
LENGTH is the length (in bytes) of the sequence we are to generate.
That tells us whether to generate a simple conditional branch, or a
reversed conditional branch around a `jr' instruction. */
char *
-iq2000_output_conditional_branch (insn,
- operands,
- two_operands_p,
- float_p,
- inverted_p,
- length)
- rtx insn;
- rtx *operands;
- int two_operands_p;
- int float_p;
- int inverted_p;
- int length;
+iq2000_output_conditional_branch (rtx insn, rtx * operands, int two_operands_p,
+ int float_p, int inverted_p, int length)
{
static char buffer[200];
/* The kind of comparison we are doing. */
enum rtx_code code = GET_CODE (operands[0]);
- /* Non-zero if the opcode for the comparison needs a `z' indicating
- that it is a comparision against zero. */
+ /* Nonzero if the opcode for the comparison needs a `z' indicating
+ that it is a comparison against zero. */
int need_z_p;
/* A string to use in the assembly output to represent the first
operand. */
/* The operand-printing string for the inverted comparison. */
const char *inverted_comp = (float_p ? "%W0" : "%N0");
- /* likely variants of each branch instruction annul the instruction
+ /* Likely variants of each branch instruction annul the instruction
in the delay slot if the branch is not taken. */
iq2000_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
subtract B from A and then look at the sign bit. But, if we
are doing an unsigned comparison, and B is zero, we don't
have to do the subtraction. Instead, we can just check to
- see if A is non-zero. Thus, we change the CODE here to
+ see if A is nonzero. Thus, we change the CODE here to
reflect the simpler comparison operation. */
switch (code)
{
char *c;
c = strchr (buffer, '\0');
- /* Generate the reversed comparision. This takes four
+ /* Generate the reversed comparison. This takes four
bytes. */
if (float_p)
sprintf (c, "b%s\t%%Z2%s",
}
default:
- abort ();
+ gcc_unreachable ();
}
/* NOTREACHED */
return 0;
}
-static enum processor_type
-iq2000_parse_cpu (cpu_string)
- const char *cpu_string;
-{
- const char *p = cpu_string;
- enum processor_type cpu;
-
- cpu = PROCESSOR_DEFAULT;
- switch (p[2])
- {
- case '1':
- if (!strcmp (p, "iq10"))
- cpu = PROCESSOR_IQ10;
- break;
- case '2':
- if (!strcmp (p, "iq2000"))
- cpu = PROCESSOR_IQ2000;
- break;
- }
-
- return cpu;
-}
-
-#define def_builtin(NAME, TYPE, CODE) \
- builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE)
+#define def_builtin(NAME, TYPE, CODE) \
+ add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
+ NULL, NULL_TREE)
-void
-iq2000_init_builtins ()
+static void
+iq2000_init_builtins (void)
{
tree endlink = void_list_node;
tree void_ftype, void_ftype_int, void_ftype_int_int;
def_builtin ("__builtin_syscall", void_ftype, IQ2000_BUILTIN_SYSCALL);
}
-/* Builtin for ICODE having ARGCOUNT args in ARGLIST where each arg
- has an rtx CODE */
+/* Builtin for ICODE having ARGCOUNT args in EXP where each arg
+ has an rtx CODE. */
static rtx
-expand_one_builtin (icode, target, arglist, code, argcount)
- enum insn_code icode;
- rtx target;
- tree arglist;
- enum rtx_code *code;
- int argcount;
+expand_one_builtin (enum insn_code icode, rtx target, tree exp,
+ enum rtx_code *code, int argcount)
{
rtx pat;
tree arg [5];
mode[0] = insn_data[icode].operand[0].mode;
for (i = 0; i < argcount; i++)
{
- arg[i] = TREE_VALUE (arglist);
- arglist = TREE_CHAIN (arglist);
+ arg[i] = CALL_EXPR_ARG (exp, i);
op[i] = expand_expr (arg[i], NULL_RTX, VOIDmode, 0);
mode[i] = insn_data[icode].operand[i].mode;
if (code[i] == CONST_INT && GET_CODE (op[i]) != CONST_INT)
- error ("argument `%d' is not a constant", i + 1);
+ error ("argument %qd is not a constant", i + 1);
if (code[i] == REG
&& ! (*insn_data[icode].operand[i].predicate) (op[i], mode[i]))
op[i] = copy_to_mode_reg (mode[i], op[i]);
pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (! pat)
SUBTARGET may be used as the target for computing one of EXP's operands.
IGNORE is nonzero if the value is to be ignored. */
-rtx
-iq2000_expand_builtin (exp, target, subtarget, mode, ignore)
- tree exp;
- rtx target;
- rtx subtarget ATTRIBUTE_UNUSED;
- enum machine_mode mode ATTRIBUTE_UNUSED;
- int ignore ATTRIBUTE_UNUSED;
+static rtx
+iq2000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ int ignore ATTRIBUTE_UNUSED)
{
- tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
- tree arglist = TREE_OPERAND (exp, 1);
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
int fcode = DECL_FUNCTION_CODE (fndecl);
enum rtx_code code [5];
break;
case IQ2000_BUILTIN_ADO16:
- return expand_one_builtin (CODE_FOR_ado16, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_ado16, target, exp, code, 2);
case IQ2000_BUILTIN_RAM:
code[1] = CONST_INT;
code[2] = CONST_INT;
code[3] = CONST_INT;
- return expand_one_builtin (CODE_FOR_ram, target, arglist, code, 4);
+ return expand_one_builtin (CODE_FOR_ram, target, exp, code, 4);
case IQ2000_BUILTIN_CHKHDR:
- return expand_one_builtin (CODE_FOR_chkhdr, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_chkhdr, target, exp, code, 2);
case IQ2000_BUILTIN_PKRL:
- return expand_one_builtin (CODE_FOR_pkrl, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_pkrl, target, exp, code, 2);
case IQ2000_BUILTIN_CFC0:
code[0] = CONST_INT;
- return expand_one_builtin (CODE_FOR_cfc0, target, arglist, code, 1);
+ return expand_one_builtin (CODE_FOR_cfc0, target, exp, code, 1);
case IQ2000_BUILTIN_CFC1:
code[0] = CONST_INT;
- return expand_one_builtin (CODE_FOR_cfc1, target, arglist, code, 1);
+ return expand_one_builtin (CODE_FOR_cfc1, target, exp, code, 1);
case IQ2000_BUILTIN_CFC2:
code[0] = CONST_INT;
- return expand_one_builtin (CODE_FOR_cfc2, target, arglist, code, 1);
+ return expand_one_builtin (CODE_FOR_cfc2, target, exp, code, 1);
case IQ2000_BUILTIN_CFC3:
code[0] = CONST_INT;
- return expand_one_builtin (CODE_FOR_cfc3, target, arglist, code, 1);
+ return expand_one_builtin (CODE_FOR_cfc3, target, exp, code, 1);
case IQ2000_BUILTIN_CTC0:
code[1] = CONST_INT;
- return expand_one_builtin (CODE_FOR_ctc0, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_ctc0, target, exp, code, 2);
case IQ2000_BUILTIN_CTC1:
code[1] = CONST_INT;
- return expand_one_builtin (CODE_FOR_ctc1, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_ctc1, target, exp, code, 2);
case IQ2000_BUILTIN_CTC2:
code[1] = CONST_INT;
- return expand_one_builtin (CODE_FOR_ctc2, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_ctc2, target, exp, code, 2);
case IQ2000_BUILTIN_CTC3:
code[1] = CONST_INT;
- return expand_one_builtin (CODE_FOR_ctc3, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_ctc3, target, exp, code, 2);
case IQ2000_BUILTIN_MFC0:
code[0] = CONST_INT;
- return expand_one_builtin (CODE_FOR_mfc0, target, arglist, code, 1);
+ return expand_one_builtin (CODE_FOR_mfc0, target, exp, code, 1);
case IQ2000_BUILTIN_MFC1:
code[0] = CONST_INT;
- return expand_one_builtin (CODE_FOR_mfc1, target, arglist, code, 1);
+ return expand_one_builtin (CODE_FOR_mfc1, target, exp, code, 1);
case IQ2000_BUILTIN_MFC2:
code[0] = CONST_INT;
- return expand_one_builtin (CODE_FOR_mfc2, target, arglist, code, 1);
+ return expand_one_builtin (CODE_FOR_mfc2, target, exp, code, 1);
case IQ2000_BUILTIN_MFC3:
code[0] = CONST_INT;
- return expand_one_builtin (CODE_FOR_mfc3, target, arglist, code, 1);
+ return expand_one_builtin (CODE_FOR_mfc3, target, exp, code, 1);
case IQ2000_BUILTIN_MTC0:
code[1] = CONST_INT;
- return expand_one_builtin (CODE_FOR_mtc0, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_mtc0, target, exp, code, 2);
case IQ2000_BUILTIN_MTC1:
code[1] = CONST_INT;
- return expand_one_builtin (CODE_FOR_mtc1, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_mtc1, target, exp, code, 2);
case IQ2000_BUILTIN_MTC2:
code[1] = CONST_INT;
- return expand_one_builtin (CODE_FOR_mtc2, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_mtc2, target, exp, code, 2);
case IQ2000_BUILTIN_MTC3:
code[1] = CONST_INT;
- return expand_one_builtin (CODE_FOR_mtc3, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_mtc3, target, exp, code, 2);
case IQ2000_BUILTIN_LUR:
- return expand_one_builtin (CODE_FOR_lur, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_lur, target, exp, code, 2);
case IQ2000_BUILTIN_RB:
- return expand_one_builtin (CODE_FOR_rb, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_rb, target, exp, code, 2);
case IQ2000_BUILTIN_RX:
- return expand_one_builtin (CODE_FOR_rx, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_rx, target, exp, code, 2);
case IQ2000_BUILTIN_SRRD:
- return expand_one_builtin (CODE_FOR_srrd, target, arglist, code, 1);
+ return expand_one_builtin (CODE_FOR_srrd, target, exp, code, 1);
case IQ2000_BUILTIN_SRWR:
- return expand_one_builtin (CODE_FOR_srwr, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_srwr, target, exp, code, 2);
case IQ2000_BUILTIN_WB:
- return expand_one_builtin (CODE_FOR_wb, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_wb, target, exp, code, 2);
case IQ2000_BUILTIN_WX:
- return expand_one_builtin (CODE_FOR_wx, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_wx, target, exp, code, 2);
case IQ2000_BUILTIN_LUC32L:
- return expand_one_builtin (CODE_FOR_luc32l, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_luc32l, target, exp, code, 2);
case IQ2000_BUILTIN_LUC64:
- return expand_one_builtin (CODE_FOR_luc64, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_luc64, target, exp, code, 2);
case IQ2000_BUILTIN_LUC64L:
- return expand_one_builtin (CODE_FOR_luc64l, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_luc64l, target, exp, code, 2);
case IQ2000_BUILTIN_LUK:
- return expand_one_builtin (CODE_FOR_luk, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_luk, target, exp, code, 2);
case IQ2000_BUILTIN_LULCK:
- return expand_one_builtin (CODE_FOR_lulck, target, arglist, code, 1);
+ return expand_one_builtin (CODE_FOR_lulck, target, exp, code, 1);
case IQ2000_BUILTIN_LUM32:
- return expand_one_builtin (CODE_FOR_lum32, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_lum32, target, exp, code, 2);
case IQ2000_BUILTIN_LUM32L:
- return expand_one_builtin (CODE_FOR_lum32l, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_lum32l, target, exp, code, 2);
case IQ2000_BUILTIN_LUM64:
- return expand_one_builtin (CODE_FOR_lum64, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_lum64, target, exp, code, 2);
case IQ2000_BUILTIN_LUM64L:
- return expand_one_builtin (CODE_FOR_lum64l, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_lum64l, target, exp, code, 2);
case IQ2000_BUILTIN_LURL:
- return expand_one_builtin (CODE_FOR_lurl, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_lurl, target, exp, code, 2);
case IQ2000_BUILTIN_MRGB:
code[2] = CONST_INT;
- return expand_one_builtin (CODE_FOR_mrgb, target, arglist, code, 3);
+ return expand_one_builtin (CODE_FOR_mrgb, target, exp, code, 3);
case IQ2000_BUILTIN_SRRDL:
- return expand_one_builtin (CODE_FOR_srrdl, target, arglist, code, 1);
+ return expand_one_builtin (CODE_FOR_srrdl, target, exp, code, 1);
case IQ2000_BUILTIN_SRULCK:
- return expand_one_builtin (CODE_FOR_srulck, target, arglist, code, 1);
+ return expand_one_builtin (CODE_FOR_srulck, target, exp, code, 1);
case IQ2000_BUILTIN_SRWRU:
- return expand_one_builtin (CODE_FOR_srwru, target, arglist, code, 2);
+ return expand_one_builtin (CODE_FOR_srwru, target, exp, code, 2);
case IQ2000_BUILTIN_TRAPQFL:
- return expand_one_builtin (CODE_FOR_trapqfl, target, arglist, code, 0);
+ return expand_one_builtin (CODE_FOR_trapqfl, target, exp, code, 0);
case IQ2000_BUILTIN_TRAPQNE:
- return expand_one_builtin (CODE_FOR_trapqne, target, arglist, code, 0);
+ return expand_one_builtin (CODE_FOR_trapqne, target, exp, code, 0);
case IQ2000_BUILTIN_TRAPREL:
- return expand_one_builtin (CODE_FOR_traprel, target, arglist, code, 1);
+ return expand_one_builtin (CODE_FOR_traprel, target, exp, code, 1);
case IQ2000_BUILTIN_WBU:
- return expand_one_builtin (CODE_FOR_wbu, target, arglist, code, 3);
+ return expand_one_builtin (CODE_FOR_wbu, target, exp, code, 3);
case IQ2000_BUILTIN_SYSCALL:
- return expand_one_builtin (CODE_FOR_syscall, target, arglist, code, 0);
+ return expand_one_builtin (CODE_FOR_syscall, target, exp, code, 0);
}
return NULL_RTX;
}
\f
-void
-iq2000_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
- CUMULATIVE_ARGS cum;
- int mode ATTRIBUTE_UNUSED;
- tree type ATTRIBUTE_UNUSED;
- int * pretend_size;
- int no_rtl;
+/* Worker function for TARGET_RETURN_IN_MEMORY. */
+
+static bool
+iq2000_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
+{
+ return ((int_size_in_bytes (type) > (2 * UNITS_PER_WORD))
+ || (int_size_in_bytes (type) == -1));
+}
+
+/* Worker function for TARGET_SETUP_INCOMING_VARARGS. */
+
+static void
+iq2000_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ tree type ATTRIBUTE_UNUSED, int * pretend_size,
+ int no_rtl)
{
- unsigned int iq2000_off = (! (cum).last_arg_fp);
- unsigned int iq2000_fp_off = ((cum).last_arg_fp);
- if (((cum).arg_words < MAX_ARGS_IN_REGISTERS - iq2000_off))
+ unsigned int iq2000_off = ! cum->last_arg_fp;
+ unsigned int iq2000_fp_off = cum->last_arg_fp;
+
+ if ((cum->arg_words < MAX_ARGS_IN_REGISTERS - iq2000_off))
{
int iq2000_save_gp_regs
- = MAX_ARGS_IN_REGISTERS - (cum).arg_words - iq2000_off;
+ = MAX_ARGS_IN_REGISTERS - cum->arg_words - iq2000_off;
int iq2000_save_fp_regs
- = (MAX_ARGS_IN_REGISTERS - (cum).fp_arg_words - iq2000_fp_off);
+ = (MAX_ARGS_IN_REGISTERS - cum->fp_arg_words - iq2000_fp_off);
if (iq2000_save_gp_regs < 0)
iq2000_save_gp_regs = 0;
if (! (no_rtl))
{
- if ((cum).arg_words < MAX_ARGS_IN_REGISTERS - iq2000_off)
+ if (cum->arg_words < MAX_ARGS_IN_REGISTERS - iq2000_off)
{
rtx ptr, mem;
ptr = plus_constant (virtual_incoming_args_rtx,
* UNITS_PER_WORD));
mem = gen_rtx_MEM (BLKmode, ptr);
move_block_from_reg
- ((cum).arg_words + GP_ARG_FIRST + iq2000_off,
+ (cum->arg_words + GP_ARG_FIRST + iq2000_off,
mem,
iq2000_save_gp_regs);
}
\f
/* A C compound statement to output to stdio stream STREAM the
assembler syntax for an instruction operand that is a memory
- reference whose address is ADDR. ADDR is an RTL expression.
-*/
+ reference whose address is ADDR. ADDR is an RTL expression. */
void
-print_operand_address (file, addr)
- FILE *file;
- rtx addr;
+print_operand_address (FILE * file, rtx addr)
{
if (!addr)
error ("PRINT_OPERAND_ADDRESS, null pointer");
case LO_SUM:
{
- register rtx arg0 = XEXP (addr, 0);
- register rtx arg1 = XEXP (addr, 1);
+ rtx arg0 = XEXP (addr, 0);
+ rtx arg1 = XEXP (addr, 1);
if (GET_CODE (arg0) != REG)
abort_with_insn (addr,
case PLUS:
{
- register rtx reg = 0;
- register rtx offset = 0;
- register rtx arg0 = XEXP (addr, 0);
- register rtx arg1 = XEXP (addr, 1);
+ rtx reg = 0;
+ rtx offset = 0;
+ rtx arg0 = XEXP (addr, 0);
+ rtx arg1 = XEXP (addr, 1);
if (GET_CODE (arg0) == REG)
{
}
}
\f
-/* A C compound statement to output to stdio stream STREAM the
- assembler syntax for an instruction operand X. X is an RTL
- expression.
+/* A C compound statement to output to stdio stream FILE the
+ assembler syntax for an instruction operand OP.
- CODE is a value that can be used to specify one of several ways
+ LETTER is a value that can be used to specify one of several ways
of printing the operand. It is used when identical operands
- must be printed differently depending on the context. CODE
+ must be printed differently depending on the context. LETTER
comes from the `%' specification that was used to request
printing of the operand. If the specification was just `%DIGIT'
- then CODE is 0; if the specification was `%LTR DIGIT' then CODE
+ then LETTER is 0; if the specification was `%LTR DIGIT' then LETTER
is the ASCII code for LTR.
- If X is a register, this macro should print the register's name.
+ If OP is a register, this macro should print the register's name.
The names can be found in an array `reg_names' whose type is
`char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
When the machine description has a specification `%PUNCT' (a `%'
followed by a punctuation character), this macro is called with
- a null pointer for X and the punctuation character for CODE.
+ a null pointer for X and the punctuation character for LETTER.
The IQ2000 specific codes are:
'+' Print the name of the gp register (gp or $28). */
void
-print_operand (file, op, letter)
- FILE *file; /* file to write to */
- rtx op; /* operand to print */
- int letter; /* %<letter> or 0 */
+print_operand (FILE *file, rtx op, int letter)
{
- register enum rtx_code code;
+ enum rtx_code code;
if (PRINT_OPERAND_PUNCT_VALID_P (letter))
{
else if (letter == 'Z')
{
- register int regnum;
-
- if (code != REG)
- abort ();
-
- regnum = REGNO (op);
- abort ();
-
- fprintf (file, "%s,", reg_names[regnum]);
+ gcc_unreachable ();
}
else if (code == REG || code == SUBREG)
{
- register int regnum;
+ int regnum;
if (code == REG)
regnum = REGNO (op);
else
output_addr_const (file, op);
}
+
+static bool
+iq2000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int * total)
+{
+ enum machine_mode mode = GET_MODE (x);
+
+ switch (code)
+ {
+ case MEM:
+ {
+ int num_words = (GET_MODE_SIZE (mode) > UNITS_PER_WORD) ? 2 : 1;
+
+ if (simple_memory_operand (x, mode))
+ return COSTS_N_INSNS (num_words);
+
+ * total = COSTS_N_INSNS (2 * num_words);
+ break;
+ }
+
+ case FFS:
+ * total = COSTS_N_INSNS (6);
+ break;
+
+ case AND:
+ case IOR:
+ case XOR:
+ case NOT:
+ * total = COSTS_N_INSNS (mode == DImode ? 2 : 1);
+ break;
+
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ if (mode == DImode)
+ * total = COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT) ? 4 : 12);
+ else
+ * total = COSTS_N_INSNS (1);
+ break;
+
+ case ABS:
+ if (mode == SFmode || mode == DFmode)
+ * total = COSTS_N_INSNS (1);
+ else
+ * total = COSTS_N_INSNS (4);
+ break;
+
+ case PLUS:
+ case MINUS:
+ if (mode == SFmode || mode == DFmode)
+ * total = COSTS_N_INSNS (6);
+ else if (mode == DImode)
+ * total = COSTS_N_INSNS (4);
+ else
+ * total = COSTS_N_INSNS (1);
+ break;
+
+ case NEG:
+ * total = (mode == DImode) ? 4 : 1;
+ break;
+
+ case MULT:
+ if (mode == SFmode)
+ * total = COSTS_N_INSNS (7);
+ else if (mode == DFmode)
+ * total = COSTS_N_INSNS (8);
+ else
+ * total = COSTS_N_INSNS (10);
+ break;
+
+ case DIV:
+ case MOD:
+ if (mode == SFmode)
+ * total = COSTS_N_INSNS (23);
+ else if (mode == DFmode)
+ * total = COSTS_N_INSNS (36);
+ else
+ * total = COSTS_N_INSNS (69);
+ break;
+
+ case UDIV:
+ case UMOD:
+ * total = COSTS_N_INSNS (69);
+ break;
+
+ case SIGN_EXTEND:
+ * total = COSTS_N_INSNS (2);
+ break;
+
+ case ZERO_EXTEND:
+ * total = COSTS_N_INSNS (1);
+ break;
+
+ case CONST_INT:
+ * total = 0;
+ break;
+
+ case LABEL_REF:
+ * total = COSTS_N_INSNS (2);
+ break;
+
+ case CONST:
+ {
+ rtx offset = const0_rtx;
+ rtx symref = eliminate_constant_term (XEXP (x, 0), & offset);
+
+ if (GET_CODE (symref) == LABEL_REF)
+ * total = COSTS_N_INSNS (2);
+ else if (GET_CODE (symref) != SYMBOL_REF)
+ * total = COSTS_N_INSNS (4);
+ /* Let's be paranoid.... */
+ else if (INTVAL (offset) < -32768 || INTVAL (offset) > 32767)
+ * total = COSTS_N_INSNS (2);
+ else
+ * total = COSTS_N_INSNS (SYMBOL_REF_FLAG (symref) ? 1 : 2);
+ break;
+ }
+
+ case SYMBOL_REF:
+ * total = COSTS_N_INSNS (SYMBOL_REF_FLAG (x) ? 1 : 2);
+ break;
+
+ case CONST_DOUBLE:
+ {
+ rtx high, low;
+
+ split_double (x, & high, & low);
+
+ * total = COSTS_N_INSNS ( (high == CONST0_RTX (GET_MODE (high))
+ || low == CONST0_RTX (GET_MODE (low)))
+ ? 2 : 4);
+ break;
+ }
+
+ default:
+ return false;
+ }
+ return true;
+}
+
+#include "gt-iq2000.h"