diff options
author | Dan Albert <danalbert@google.com> | 2015-06-17 11:09:54 -0700 |
---|---|---|
committer | Dan Albert <danalbert@google.com> | 2015-06-17 14:15:22 -0700 |
commit | f378ebf14df0952eae870c9865bab8326aa8f137 (patch) | |
tree | 31794503eb2a8c64ea5f313b93100f1163afcffb /gcc-4.4.3/gcc/config/iq2000 | |
parent | 2c58169824949d3a597d9fa81931e001ef9b1bd0 (diff) | |
download | toolchain_gcc-f378ebf14df0952eae870c9865bab8326aa8f137.tar.gz toolchain_gcc-f378ebf14df0952eae870c9865bab8326aa8f137.tar.bz2 toolchain_gcc-f378ebf14df0952eae870c9865bab8326aa8f137.zip |
Delete old versions of GCC.
Change-Id: I710f125d905290e1024cbd67f48299861790c66c
Diffstat (limited to 'gcc-4.4.3/gcc/config/iq2000')
-rw-r--r-- | gcc-4.4.3/gcc/config/iq2000/abi | 232 | ||||
-rw-r--r-- | gcc-4.4.3/gcc/config/iq2000/iq2000-protos.h | 54 | ||||
-rw-r--r-- | gcc-4.4.3/gcc/config/iq2000/iq2000.c | 3345 | ||||
-rw-r--r-- | gcc-4.4.3/gcc/config/iq2000/iq2000.h | 1135 | ||||
-rw-r--r-- | gcc-4.4.3/gcc/config/iq2000/iq2000.md | 2550 | ||||
-rw-r--r-- | gcc-4.4.3/gcc/config/iq2000/iq2000.opt | 44 | ||||
-rw-r--r-- | gcc-4.4.3/gcc/config/iq2000/lib2extra-funcs.c | 17 | ||||
-rw-r--r-- | gcc-4.4.3/gcc/config/iq2000/predicates.md | 232 | ||||
-rw-r--r-- | gcc-4.4.3/gcc/config/iq2000/t-iq2000 | 36 |
9 files changed, 0 insertions, 7645 deletions
diff --git a/gcc-4.4.3/gcc/config/iq2000/abi b/gcc-4.4.3/gcc/config/iq2000/abi deleted file mode 100644 index fa49a82f9..000000000 --- a/gcc-4.4.3/gcc/config/iq2000/abi +++ /dev/null @@ -1,232 +0,0 @@ - IQ2000 ABI - ========= - -Sizes and alignments --------------------- - - Type Size (bytes) Alignment (bytes) - - char 1 1 - short 2 2 - int 4 4 - unsigned 4 4 - long 4 4 - long long 8 8 - float 4 4 - double 8 8 - pointers 4 4 - -* alignment within aggregates (structs and unions) is as above, with - padding added if needed -* aggregates have alignment equal to that of their most aligned - member -* aggregates have sizes which are a multiple of their alignment - - -Floating point --------------- - -All emulated using IEEE floating point conventions. - -Registers ----------------- - -%0 always zero -%1 call clobbered -%2 return value -%3 return value -%4 argument register 1 -%5 argument register 2 -%6 argument register 3 -%7 argument register 4 -%8 argument register 5 -%9 argument register 6 -%10 argument register 7 -%11 argument register 8 -%12 call clobbered -%13 call clobbered -%14 call clobbered -%15 call clobbered -%16 call saved -%17 call saved -%18 call saved -%19 call saved -%20 call saved -%21 call saved -%22 call saved -%23 call saved -%24 call clobbered -%25 call clobbered -%26 reserved -%27 frame ptr -%28 global ptr -%29 stack ptr -%30 reserved -%31 return address - -Stack alignment 8 bytes - -Structures passed <= 32 bits as values, else as pointers - -The IQ2000 Stack ---------------- - -Space is allocated as needed in the stack frame for the following at compile -time: - -* Outgoing parameters beyond the eighth - -* All automatic arrays, automatic data aggregates, automatic - scalars which must be addressable, and automatic scalars for - which there is no room in registers - -* Compiler-generated temporary values (typically when there are - too many for the compiler to keep them all in registers) - -Space can be allocated dynamically (at runtime) in the stack frame for the -following: - -* Memory allocated using the alloca() function of the C library - -Addressable automatic variables on the stack are addressed with positive -offsets relative to %27; dynamically allocated space is addressed with positive -offsets from the pointer returned by alloca(). - -Stack Frame ------------ - - +-----------------------+ - | Caller memory args | - +-----------------------+ <-sp - | Return address | - +-----------------------+ - | Previous FP | - +-----------------------+ - | Saved Registers | - +-----------------------+ - | ... | - +-----------------------+ - | Local Variables | - +-----------------------+ <-fp - | Alloca | - +-----------------------+ - | ... | - +-----------------------+ - | Parameter Word 2 | - +-----------------------+ - | Parameter Word 1 | - +-----------------------+ <-sp - - -Parameter Assignment to Registers ---------------------------------- - -Consider the parameters in a function call as ordered from left (first -parameter) to right. GR contains the number of the next available -general-purpose register. STARG is the address of the next available stack -parameter word. - -INITIALIZE: - Set GR=r4 and STARG to point to parameter word 1. - -SCAN: - If there are no more parameters, terminate. - Otherwise, select one of the following depending on the type - of the next parameter: - - SIMPLE ARG: - - A SIMPLE ARG is one of the following: - - * One of the simple integer types which will fit into a - general-purpose register, - * A pointer to an object of any type, - * A struct or union small enough to fit in a register (<= 32 bits) - * A larger struct or union, which shall be treated as a - pointer to the object or to a copy of the object. - (See below for when copies are made.) - - If GR > r11, go to STACK. Otherwise, load the parameter value into - general-purpose register GR and advance GR to the next general-purpose - register. Values shorter than the register size are sign-extended or - zero-extended depending on whether they are signed or unsigned. Then - go to SCAN. - - DOUBLE or LONG LONG - - If GR > r10, go to STACK. Otherwise, if GR is odd, advance GR to the - next register. Load the 64-bit long long or double value into register - pair GR and GR+1. Advance GR to GR+2 and go to SCAN. - - STACK: - - Parameters not otherwise handled above are passed in the parameter - words of the caller's stack frame. SIMPLE ARGs, as defined above, are - considered to have size and alignment equal to the size of a - general-purpose register, with simple argument types shorter than this - sign- or zero-extended to this width. Round STARG up to a multiple of - the alignment requirement of the parameter and copy the argument - byte-for-byte into STARG, STARG+1, ... STARG+size-1. Set STARG to - STARG+size and go to SCAN. - - -Structure passing ------------------ - -As noted above, code which passes structures and unions by value is implemented -specially. (In this section, "struct" will refer to structs and unions -inclusively.) Structs small enough to fit in a register are passed by value in -a single register or in a stack frame slot the size of a register. Structs -containing a single double or long long component are passed by value in two -registers or in a stack frame slot the size of two registers. Other structs -are handled by passing the address of the structure. In this case, a copy of -the structure will be made if necessary in order to preserve the pass-by-value -semantics. - -Copies of large structs are made under the following rules: - - ANSI mode K&R Mode - --------- -------- -Normal param Callee copies if needed Caller copies -Varargs (...) param Caller copies Caller copies - -In the case of normal (non-varargs) large-struct parameters in ANSI mode, the -callee is responsible for producing the same effect as if a copy of the -structure were passed, preserving the pass-by-value semantics. This may be -accomplished by having the callee make a copy, but in some cases the callee may -be able to determine that a copy is not necessary in order to produce the same -results. In such cases, the callee may choose to avoid making a copy of the -parameter. - - -Varargs handling ----------------- - -No special changes are needed for handling varargs parameters other than the -caller knowing that a copy is needed on struct parameters larger than a -register (see above). - -The varargs macros set up a register save area for the general-purpose -registers to be saved. Because the save area lies between the caller and -callee stack frames, the saved register parameters are contiguous with -parameters passed on the stack. A pointer advances from the register save area -into the caller's stack frame. - - -Function return values ----------------------- - - Type Register - ---- -------- - int r2 - short r2 - long r2 - long long r2-r3 - float r2 - double r2-r3 - struct/union see below - -Structs/unions which will fit into two general-purpose registers are returned -in r2, or in r2-r3 if necessary. Larger structs/unions are handled by the -caller passing as a "hidden" first argument a pointer to space allocated to -receive the return value. diff --git a/gcc-4.4.3/gcc/config/iq2000/iq2000-protos.h b/gcc-4.4.3/gcc/config/iq2000/iq2000-protos.h deleted file mode 100644 index 094bcbf2f..000000000 --- a/gcc-4.4.3/gcc/config/iq2000/iq2000-protos.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Definitions of target machine for GNU compiler for iq2000. - Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. - - This file is part of GCC. - - 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 3, or (at your option) - any later version. - - 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 GCC; see the file COPYING3. If not see - <http://www.gnu.org/licenses/>. */ - -#ifndef GCC_IQ2000_PROTOS_H -#define GCC_IQ2000_PROTOS_H - -extern int iq2000_check_split (rtx, enum machine_mode); -extern int iq2000_reg_mode_ok_for_base_p (rtx, enum machine_mode, int); -extern int iq2000_legitimate_address_p (enum machine_mode, rtx, int); -extern const char * iq2000_fill_delay_slot (const char *, enum delay_type, rtx *, rtx); -extern const char * iq2000_move_1word (rtx *, rtx, int); -extern void override_options (void); -extern HOST_WIDE_INT iq2000_debugger_offset (rtx, HOST_WIDE_INT); -extern void final_prescan_insn (rtx, rtx *, int); -extern HOST_WIDE_INT compute_frame_size (HOST_WIDE_INT); -extern int iq2000_initial_elimination_offset (int, int); -extern void iq2000_expand_prologue (void); -extern void iq2000_expand_epilogue (void); -extern void iq2000_expand_eh_return (rtx); -extern int iq2000_can_use_return_insn (void); -extern int iq2000_adjust_insn_length (rtx, int); -extern char * iq2000_output_conditional_branch (rtx, rtx *, int, int, int, int); -extern void print_operand_address (FILE *, rtx); -extern void print_operand (FILE *, rtx, int); - -#ifdef RTX_CODE -extern rtx gen_int_relational (enum rtx_code, rtx, rtx, rtx, int *); -extern void gen_conditional_branch (rtx *, enum rtx_code); -#endif - -#ifdef TREE_CODE -extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx); -extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int); -extern struct rtx_def * function_arg (CUMULATIVE_ARGS *, enum machine_mode, const_tree, int); -extern rtx iq2000_function_value (const_tree, const_tree); -#endif - -#endif /* ! GCC_IQ2000_PROTOS_H */ diff --git a/gcc-4.4.3/gcc/config/iq2000/iq2000.c b/gcc-4.4.3/gcc/config/iq2000/iq2000.c deleted file mode 100644 index 715338945..000000000 --- a/gcc-4.4.3/gcc/config/iq2000/iq2000.c +++ /dev/null @@ -1,3345 +0,0 @@ -/* Subroutines used for code generation on Vitesse IQ2000 processors - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 - Free Software Foundation, Inc. - -This file is part of GCC. - -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 3, or (at your option) -any later version. - -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 GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include <signal.h> -#include "tm.h" -#include "tree.h" -#include "rtl.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "real.h" -#include "insn-config.h" -#include "conditions.h" -#include "output.h" -#include "insn-attr.h" -#include "flags.h" -#include "function.h" -#include "expr.h" -#include "optabs.h" -#include "libfuncs.h" -#include "recog.h" -#include "toplev.h" -#include "reload.h" -#include "ggc.h" -#include "tm_p.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 - { - ITEST_EQ, - ITEST_NE, - ITEST_GT, - ITEST_GE, - ITEST_LT, - ITEST_LE, - ITEST_GTU, - ITEST_GEU, - ITEST_LTU, - ITEST_LEU, - ITEST_MAX - }; - -struct constant; - - -/* 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. */ -} iq2000_frame_info; - -struct machine_function GTY(()) -{ - /* Current frame information, calculated by compute_frame_size. */ - 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. */ - -/* List of all IQ2000 punctuation characters used by print_operand. */ -char iq2000_print_operand_punct[256]; - -/* The target cpu for optimization and scheduling. */ -enum processor_type iq2000_tune; - -/* 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. */ -enum cmp_type branch_type; - -/* Local variables. */ - -/* The next branch instruction is a branch likely, not branch normal. */ -static int iq2000_branch_likely; - -/* 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; - -/* 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; - - -/* Initialize the GCC target structure. */ -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 (const_tree, const_tree); -static void iq2000_setup_incoming_varargs (CUMULATIVE_ARGS *, - enum machine_mode, tree, int *, - int); -static bool iq2000_rtx_costs (rtx, int, int, int *, bool); -static int iq2000_address_cost (rtx, bool); -static section *iq2000_select_section (tree, int, unsigned HOST_WIDE_INT); -static bool iq2000_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode, - const_tree, bool); -static int iq2000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, - tree, bool); -static void iq2000_va_start (tree, rtx); - -#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_const_tree_true -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true -#undef TARGET_PROMOTE_PROTOTYPES -#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_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 - -#undef TARGET_EXPAND_BUILTIN_VA_START -#define TARGET_EXPAND_BUILTIN_VA_START iq2000_va_start - -struct gcc_target targetm = TARGET_INITIALIZER; - -/* Return nonzero if we split the address into high and low parts. */ - -int -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. */ - if (GET_MODE_SIZE (mode) > (unsigned) UNITS_PER_WORD) - return 0; - - if ((GET_CODE (address) == SYMBOL_REF) - || (GET_CODE (address) == CONST - && GET_CODE (XEXP (XEXP (address, 0), 0)) == SYMBOL_REF) - || GET_CODE (address) == LABEL_REF) - return 1; - - return 0; -} - -/* Return nonzero if REG is valid for MODE. */ - -int -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) - : GP_REG_OR_PSEUDO_NONSTRICT_P (REGNO (reg), mode)); -} - -/* Return a nonzero value if XINSN is a legitimate address for a - memory operand of the indicated MODE. STRICT is nonzero if this - function is called during reload. */ - -int -iq2000_legitimate_address_p (enum machine_mode mode, rtx xinsn, int strict) -{ - if (TARGET_DEBUG_A_MODE) - { - GO_PRINTF2 ("\n========== GO_IF_LEGITIMATE_ADDRESS, %sstrict\n", - strict ? "" : "not "); - GO_DEBUG_RTX (xinsn); - } - - /* Check for constant before stripping off SUBREG, so that we don't - accept (subreg (const_int)) which will fail to reload. */ - if (CONSTANT_ADDRESS_P (xinsn) - && ! (iq2000_check_split (xinsn, mode)) - && ! (GET_CODE (xinsn) == CONST_INT && ! SMALL_INT (xinsn))) - return 1; - - while (GET_CODE (xinsn) == SUBREG) - xinsn = SUBREG_REG (xinsn); - - if (GET_CODE (xinsn) == REG - && iq2000_reg_mode_ok_for_base_p (xinsn, mode, strict)) - return 1; - - if (GET_CODE (xinsn) == LO_SUM) - { - rtx xlow0 = XEXP (xinsn, 0); - rtx xlow1 = XEXP (xinsn, 1); - - while (GET_CODE (xlow0) == SUBREG) - xlow0 = SUBREG_REG (xlow0); - if (GET_CODE (xlow0) == REG - && iq2000_reg_mode_ok_for_base_p (xlow0, mode, strict) - && iq2000_check_split (xlow1, mode)) - return 1; - } - - if (GET_CODE (xinsn) == PLUS) - { - 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); - code0 = GET_CODE (xplus0); - - while (GET_CODE (xplus1) == SUBREG) - xplus1 = SUBREG_REG (xplus1); - code1 = GET_CODE (xplus1); - - if (code0 == REG - && iq2000_reg_mode_ok_for_base_p (xplus0, mode, strict)) - { - if (code1 == CONST_INT && SMALL_INT (xplus1) - && SMALL_INT_UNSIGNED (xplus1) /* No negative offsets */) - return 1; - } - } - - if (TARGET_DEBUG_A_MODE) - GO_PRINTF ("Not a legitimate address\n"); - - /* The address was not legitimate. */ - return 0; -} - -/* Returns an operand string for the given instruction's delay slot, - after updating filled delay slot statistics. - - We assume that operands[0] is the target register that is set. - - In order to check the next insn, most of this functionality is moved - to FINAL_PRESCAN_INSN, and we just set the global variables that - it needs. */ - -const char * -iq2000_fill_delay_slot (const char *ret, enum delay_type type, rtx operands[], - rtx cur_insn) -{ - 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; - - else - num_nops = 0; - - /* Make sure that we don't put nop's after labels. */ - next_insn = NEXT_INSN (cur_insn); - while (next_insn != 0 - && (GET_CODE (next_insn) == NOTE - || GET_CODE (next_insn) == CODE_LABEL)) - next_insn = NEXT_INSN (next_insn); - - dslots_load_total += num_nops; - if (TARGET_DEBUG_C_MODE - || type == DELAY_NONE - || operands == 0 - || cur_insn == 0 - || next_insn == 0 - || GET_CODE (next_insn) == CODE_LABEL - || (set_reg = operands[0]) == 0) - { - dslots_number_nops = 0; - iq2000_load_reg = 0; - iq2000_load_reg2 = 0; - iq2000_load_reg3 = 0; - iq2000_load_reg4 = 0; - - return ret; - } - - set_reg = operands[0]; - if (set_reg == 0) - return ret; - - while (GET_CODE (set_reg) == SUBREG) - set_reg = SUBREG_REG (set_reg); - - mode = GET_MODE (set_reg); - dslots_number_nops = num_nops; - iq2000_load_reg = set_reg; - if (GET_MODE_SIZE (mode) - > (unsigned) (UNITS_PER_WORD)) - iq2000_load_reg2 = gen_rtx_REG (SImode, REGNO (set_reg) + 1); - else - iq2000_load_reg2 = 0; - - return ret; -} - -/* Determine whether a memory reference takes one (based off of the GP - pointer), two (normal), or three (label + reg) instructions, and bump the - appropriate counter for -mstats. */ - -static void -iq2000_count_memory_refs (rtx op, int num) -{ - int additional = 0; - int n_words = 0; - rtx addr, plus0, plus1; - enum rtx_code code0, code1; - int looping; - - if (TARGET_DEBUG_B_MODE) - { - fprintf (stderr, "\n========== iq2000_count_memory_refs:\n"); - debug_rtx (op); - } - - /* Skip MEM if passed, otherwise handle movsi of address. */ - addr = (GET_CODE (op) != MEM) ? op : XEXP (op, 0); - - /* Loop, going through the address RTL. */ - do - { - looping = FALSE; - switch (GET_CODE (addr)) - { - case REG: - case CONST_INT: - case LO_SUM: - break; - - case PLUS: - plus0 = XEXP (addr, 0); - plus1 = XEXP (addr, 1); - code0 = GET_CODE (plus0); - code1 = GET_CODE (plus1); - - if (code0 == REG) - { - additional++; - addr = plus1; - looping = 1; - continue; - } - - if (code0 == CONST_INT) - { - addr = plus1; - looping = 1; - continue; - } - - if (code1 == REG) - { - additional++; - addr = plus0; - looping = 1; - continue; - } - - if (code1 == CONST_INT) - { - addr = plus0; - looping = 1; - continue; - } - - if (code0 == SYMBOL_REF || code0 == LABEL_REF || code0 == CONST) - { - addr = plus0; - looping = 1; - continue; - } - - if (code1 == SYMBOL_REF || code1 == LABEL_REF || code1 == CONST) - { - addr = plus1; - looping = 1; - continue; - } - - break; - - case LABEL_REF: - n_words = 2; /* Always 2 words. */ - break; - - case CONST: - addr = XEXP (addr, 0); - looping = 1; - continue; - - case SYMBOL_REF: - n_words = SYMBOL_REF_FLAG (addr) ? 1 : 2; - break; - - default: - break; - } - } - while (looping); - - if (n_words == 0) - return; - - n_words += additional; - if (n_words > 3) - n_words = 3; - - num_refs[n_words-1] += num; -} - -/* 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__); -} - -/* Return the appropriate instructions to move one operand to another. */ - -const char * -iq2000_move_1word (rtx operands[], rtx insn, int unsignedp) -{ - const char *ret = 0; - rtx op0 = operands[0]; - rtx op1 = operands[1]; - enum rtx_code code0 = GET_CODE (op0); - enum rtx_code code1 = GET_CODE (op1); - enum machine_mode mode = GET_MODE (op0); - int subreg_offset0 = 0; - int subreg_offset1 = 0; - enum delay_type delay = DELAY_NONE; - - while (code0 == SUBREG) - { - subreg_offset0 += subreg_regno_offset (REGNO (SUBREG_REG (op0)), - GET_MODE (SUBREG_REG (op0)), - SUBREG_BYTE (op0), - GET_MODE (op0)); - op0 = SUBREG_REG (op0); - code0 = GET_CODE (op0); - } - - while (code1 == SUBREG) - { - subreg_offset1 += subreg_regno_offset (REGNO (SUBREG_REG (op1)), - GET_MODE (SUBREG_REG (op1)), - SUBREG_BYTE (op1), - GET_MODE (op1)); - op1 = SUBREG_REG (op1); - code1 = GET_CODE (op1); - } - - /* For our purposes, a condition code mode is the same as SImode. */ - if (mode == CCmode) - mode = SImode; - - if (code0 == REG) - { - int regno0 = REGNO (op0) + subreg_offset0; - - if (code1 == REG) - { - int regno1 = REGNO (op1) + subreg_offset1; - - /* Do not do anything for assigning a register to itself */ - if (regno0 == regno1) - ret = ""; - - else if (GP_REG_P (regno0)) - { - if (GP_REG_P (regno1)) - ret = "or\t%0,%%0,%1"; - } - - } - - else if (code1 == MEM) - { - delay = DELAY_LOAD; - - if (TARGET_STATS) - iq2000_count_memory_refs (op1, 1); - - if (GP_REG_P (regno0)) - { - /* For loads, use the mode of the memory item, instead of the - target, so zero/sign extend can use this code as well. */ - switch (GET_MODE (op1)) - { - default: - break; - case SFmode: - ret = "lw\t%0,%1"; - break; - case SImode: - case CCmode: - ret = "lw\t%0,%1"; - break; - case HImode: - ret = (unsignedp) ? "lhu\t%0,%1" : "lh\t%0,%1"; - break; - case QImode: - ret = (unsignedp) ? "lbu\t%0,%1" : "lb\t%0,%1"; - break; - } - } - } - - else if (code1 == CONST_INT - || (code1 == CONST_DOUBLE - && GET_MODE (op1) == VOIDmode)) - { - if (code1 == CONST_DOUBLE) - { - /* This can happen when storing constants into long long - bitfields. Just store the least significant word of - the value. */ - operands[1] = op1 = GEN_INT (CONST_DOUBLE_LOW (op1)); - } - - if (INTVAL (op1) == 0) - { - if (GP_REG_P (regno0)) - ret = "or\t%0,%%0,%z1"; - } - else if (GP_REG_P (regno0)) - { - if (SMALL_INT_UNSIGNED (op1)) - ret = "ori\t%0,%%0,%x1\t\t\t# %1"; - else if (SMALL_INT (op1)) - ret = "addiu\t%0,%%0,%1\t\t\t# %1"; - else - ret = "lui\t%0,%X1\t\t\t# %1\n\tori\t%0,%0,%x1"; - } - } - - else if (code1 == CONST_DOUBLE && mode == SFmode) - { - if (op1 == CONST0_RTX (SFmode)) - { - if (GP_REG_P (regno0)) - ret = "or\t%0,%%0,%."; - } - - else - { - delay = DELAY_LOAD; - ret = "li.s\t%0,%1"; - } - } - - else if (code1 == LABEL_REF) - { - if (TARGET_STATS) - iq2000_count_memory_refs (op1, 1); - - ret = "la\t%0,%a1"; - } - - else if (code1 == SYMBOL_REF || code1 == CONST) - { - if (TARGET_STATS) - iq2000_count_memory_refs (op1, 1); - - ret = "la\t%0,%a1"; - } - - else if (code1 == PLUS) - { - rtx add_op0 = XEXP (op1, 0); - rtx add_op1 = XEXP (op1, 1); - - if (GET_CODE (XEXP (op1, 1)) == REG - && GET_CODE (XEXP (op1, 0)) == CONST_INT) - add_op0 = XEXP (op1, 1), add_op1 = XEXP (op1, 0); - - operands[2] = add_op0; - operands[3] = add_op1; - ret = "add%:\t%0,%2,%3"; - } - - else if (code1 == HIGH) - { - operands[1] = XEXP (op1, 0); - ret = "lui\t%0,%%hi(%1)"; - } - } - - else if (code0 == MEM) - { - if (TARGET_STATS) - iq2000_count_memory_refs (op0, 1); - - if (code1 == REG) - { - int regno1 = REGNO (op1) + subreg_offset1; - - if (GP_REG_P (regno1)) - { - switch (mode) - { - case SFmode: ret = "sw\t%1,%0"; break; - case SImode: ret = "sw\t%1,%0"; break; - case HImode: ret = "sh\t%1,%0"; break; - case QImode: ret = "sb\t%1,%0"; break; - default: break; - } - } - } - - else if (code1 == CONST_INT && INTVAL (op1) == 0) - { - switch (mode) - { - case SFmode: ret = "sw\t%z1,%0"; break; - case SImode: ret = "sw\t%z1,%0"; break; - case HImode: ret = "sh\t%z1,%0"; break; - case QImode: ret = "sb\t%z1,%0"; break; - default: break; - } - } - - else if (code1 == CONST_DOUBLE && op1 == CONST0_RTX (mode)) - { - switch (mode) - { - case SFmode: ret = "sw\t%.,%0"; break; - case SImode: ret = "sw\t%.,%0"; break; - case HImode: ret = "sh\t%.,%0"; break; - case QImode: ret = "sb\t%.,%0"; break; - default: break; - } - } - } - - if (ret == 0) - { - abort_with_insn (insn, "Bad move"); - return 0; - } - - if (delay != DELAY_NONE) - return iq2000_fill_delay_slot (ret, delay, operands, insn); - - return ret; -} - -/* Provide the costs of an addressing mode that contains ADDR. */ - -static int -iq2000_address_cost (rtx addr, bool speed) -{ - switch (GET_CODE (addr)) - { - case LO_SUM: - return 1; - - case LABEL_REF: - return 2; - - case CONST: - { - rtx offset = const0_rtx; - - addr = eliminate_constant_term (XEXP (addr, 0), & offset); - if (GET_CODE (addr) == LABEL_REF) - return 2; - - if (GET_CODE (addr) != SYMBOL_REF) - return 4; - - if (! SMALL_INT (offset)) - return 2; - } - - /* Fall through. */ - - case SYMBOL_REF: - return SYMBOL_REF_FLAG (addr) ? 1 : 2; - - case PLUS: - { - 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); - - if (GET_CODE (plus0) != REG) - break; - - switch (GET_CODE (plus1)) - { - case CONST_INT: - return SMALL_INT (plus1) ? 1 : 2; - - case CONST: - case SYMBOL_REF: - case LABEL_REF: - case HIGH: - case LO_SUM: - return iq2000_address_cost (plus1, speed) + 1; - - default: - break; - } - } - - default: - break; - } - - return 4; -} - -/* Make normal rtx_code into something we can index from an array. */ - -static enum internal_test -map_test_to_internal_test (enum rtx_code test_code) -{ - enum internal_test test = ITEST_MAX; - - switch (test_code) - { - case EQ: test = ITEST_EQ; break; - case NE: test = ITEST_NE; break; - case GT: test = ITEST_GT; break; - case GE: test = ITEST_GE; break; - case LT: test = ITEST_LT; break; - case LE: test = ITEST_LE; break; - case GTU: test = ITEST_GTU; break; - case GEU: test = ITEST_GEU; break; - case LTU: test = ITEST_LTU; break; - case LEU: test = ITEST_LEU; break; - default: break; - } - - return test; -} - -/* 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. */ - -rtx -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. */ - int unsignedp; /* != 0 for unsigned comparisons. */ - }; - - 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 */ - { LT, -32768, 32767, 0, 0, 1, 1, 0 }, /* GE */ - { LT, -32768, 32767, 0, 0, 0, 0, 0 }, /* LT */ - { LT, -32769, 32766, 1, 1, 0, 1, 0 }, /* LE */ - { LTU, -32769, 32766, 1, 1, 1, 0, 1 }, /* GTU */ - { LTU, -32768, 32767, 0, 0, 1, 1, 1 }, /* GEU */ - { LTU, -32768, 32767, 0, 0, 0, 0, 1 }, /* LTU */ - { LTU, -32769, 32766, 1, 1, 0, 1, 1 }, /* LEU */ - }; - - enum internal_test test; - enum machine_mode mode; - struct cmp_info *p_info; - int branch_p; - int eqne_p; - int invert; - rtx reg; - rtx reg2; - - test = map_test_to_internal_test (test_code); - gcc_assert (test != ITEST_MAX); - - p_info = &info[(int) test]; - eqne_p = (p_info->test_code == XOR); - - mode = GET_MODE (cmp0); - if (mode == VOIDmode) - mode = GET_MODE (cmp1); - - /* 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. */ - if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0) - return 0; - - /* Test for beq/bne. */ - if (eqne_p) - return 0; - } - - /* Allocate a pseudo to calculate the value in. */ - result = gen_reg_rtx (mode); - } - - /* Make sure we can handle any constants given to us. */ - if (GET_CODE (cmp0) == CONST_INT) - cmp0 = force_reg (mode, cmp0); - - if (GET_CODE (cmp1) == CONST_INT) - { - HOST_WIDE_INT value = INTVAL (cmp1); - - if (value < p_info->const_low - || value > p_info->const_high) - cmp1 = force_reg (mode, cmp1); - } - - /* See if we need to invert the result. */ - invert = (GET_CODE (cmp1) == CONST_INT - ? p_info->invert_const : p_info->invert_reg); - - if (p_invert != (int *)0) - { - *p_invert = invert; - invert = 0; - } - - /* Comparison to constants, may involve adding 1 to change a LT into LE. - Comparison between two registers, may involve switching operands. */ - if (GET_CODE (cmp1) == CONST_INT) - { - if (p_info->const_add != 0) - { - HOST_WIDE_INT new_const = INTVAL (cmp1) + p_info->const_add; - - /* If modification of cmp1 caused overflow, - we would get the wrong answer if we follow the usual path; - thus, x > 0xffffffffU would turn into x > 0U. */ - if ((p_info->unsignedp - ? (unsigned HOST_WIDE_INT) new_const > - (unsigned HOST_WIDE_INT) INTVAL (cmp1) - : new_const > INTVAL (cmp1)) - != (p_info->const_add > 0)) - { - /* This test is always true, but if INVERT is true then - the result of the test needs to be inverted so 0 should - be returned instead. */ - emit_move_insn (result, invert ? const0_rtx : const_true_rtx); - return result; - } - else - cmp1 = GEN_INT (new_const); - } - } - - else if (p_info->reverse_regs) - { - rtx temp = cmp0; - cmp0 = cmp1; - cmp1 = temp; - } - - if (test == ITEST_NE && GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0) - reg = cmp0; - else - { - reg = (invert || eqne_p) ? gen_reg_rtx (mode) : result; - 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); - if (p_invert != NULL) - *p_invert = 0; - invert = 0; - } - - else if (test == ITEST_EQ) - { - reg2 = invert ? gen_reg_rtx (mode) : result; - convert_move (reg2, gen_rtx_LTU (mode, reg, const1_rtx), 0); - reg = reg2; - } - - if (invert) - { - rtx one; - - one = const1_rtx; - convert_move (result, gen_rtx_XOR (mode, reg, one), 0); - } - - return result; -} - -/* Emit the common code for doing conditional branches. - operand[0] is the label to jump to. - The comparison operands are saved away by cmp{si,di,sf,df}. */ - -void -gen_conditional_branch (rtx operands[], enum rtx_code test_code) -{ - enum cmp_type type = branch_type; - rtx cmp0 = branch_cmp[0]; - rtx cmp1 = branch_cmp[1]; - enum machine_mode mode; - rtx reg; - int invert; - rtx label1, label2; - - switch (type) - { - case CMP_SI: - case CMP_DI: - mode = type == CMP_SI ? SImode : DImode; - invert = 0; - reg = gen_int_relational (test_code, NULL_RTX, cmp0, cmp1, &invert); - - if (reg) - { - cmp0 = reg; - cmp1 = const0_rtx; - test_code = NE; - } - else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0) - /* We don't want to build a comparison against a nonzero - constant. */ - cmp1 = force_reg (mode, cmp1); - - break; - - case CMP_SF: - case CMP_DF: - reg = gen_reg_rtx (CCmode); - - /* For cmp0 != cmp1, build cmp0 == cmp1, and test for result == 0. */ - emit_insn (gen_rtx_SET (VOIDmode, reg, - gen_rtx_fmt_ee (test_code == NE ? EQ : test_code, - CCmode, cmp0, cmp1))); - - test_code = test_code == NE ? EQ : NE; - mode = CCmode; - cmp0 = reg; - cmp1 = const0_rtx; - invert = 0; - break; - - default: - 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; - - if (invert) - { - label2 = label1; - label1 = pc_rtx; - } - - emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, - gen_rtx_IF_THEN_ELSE (VOIDmode, - gen_rtx_fmt_ee (test_code, - mode, - cmp0, cmp1), - label1, label2))); -} - -/* Initialize CUM for a function FNTYPE. */ - -void -init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, - rtx libname ATTRIBUTE_UNUSED) -{ - static CUMULATIVE_ARGS zero_cum; - tree param; - tree next_param; - - if (TARGET_DEBUG_D_MODE) - { - fprintf (stderr, - "\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)]); - } - } - - *cum = zero_cum; - - /* Determine if this function has variable arguments. This is - indicated by the last argument being 'void_type_mode' if there - are no variable arguments. The standard IQ2000 calling sequence - passes all arguments in the general purpose registers in this case. */ - - for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0; - param != 0; param = next_param) - { - next_param = TREE_CHAIN (param); - if (next_param == 0 && TREE_VALUE (param) != void_type_node) - cum->gp_reg_found = 1; - } -} - -/* Advance the argument of type TYPE and mode MODE to the next argument - position in CUM. */ - -void -function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, - int named) -{ - if (TARGET_DEBUG_D_MODE) - { - fprintf (stderr, - "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, "%p", (void *) type); - fprintf (stderr, ", %d )\n\n", named); - } - - cum->arg_number++; - switch (mode) - { - case VOIDmode: - break; - - default: - 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) - / UNITS_PER_WORD); - break; - - case BLKmode: - cum->gp_reg_found = 1; - cum->arg_words += ((int_size_in_bytes (type) + UNITS_PER_WORD - 1) - / UNITS_PER_WORD); - break; - - case SFmode: - cum->arg_words ++; - if (! cum->gp_reg_found && cum->arg_number <= 2) - cum->fp_code += 1 << ((cum->arg_number - 1) * 2); - break; - - case DFmode: - cum->arg_words += 2; - if (! cum->gp_reg_found && cum->arg_number <= 2) - cum->fp_code += 2 << ((cum->arg_number - 1) * 2); - break; - - case DImode: - cum->gp_reg_found = 1; - cum->arg_words += 2; - break; - - case QImode: - case HImode: - case SImode: - cum->gp_reg_found = 1; - cum->arg_words ++; - break; - } -} - -/* 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 (CUMULATIVE_ARGS *cum, enum machine_mode mode, const_tree type, - int named) -{ - rtx ret; - int regbase = -1; - int bias = 0; - unsigned int *arg_words = &cum->arg_words; - int struct_p = (type != 0 - && (TREE_CODE (type) == RECORD_TYPE - || TREE_CODE (type) == UNION_TYPE - || TREE_CODE (type) == QUAL_UNION_TYPE)); - - if (TARGET_DEBUG_D_MODE) - { - fprintf (stderr, - "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, "%p", (const void *) type); - fprintf (stderr, ", %d ) = ", named); - } - - - cum->last_arg_fp = 0; - switch (mode) - { - case SFmode: - regbase = GP_ARG_FIRST; - break; - - case DFmode: - cum->arg_words += cum->arg_words & 1; - - regbase = GP_ARG_FIRST; - break; - - default: - gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT - || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT); - - /* Drops through. */ - case BLKmode: - if (type != NULL_TREE && TYPE_ALIGN (type) > (unsigned) BITS_PER_WORD) - cum->arg_words += (cum->arg_words & 1); - regbase = GP_ARG_FIRST; - break; - - case VOIDmode: - case QImode: - case HImode: - case SImode: - regbase = GP_ARG_FIRST; - break; - - case DImode: - cum->arg_words += (cum->arg_words & 1); - regbase = GP_ARG_FIRST; - } - - if (*arg_words >= (unsigned) MAX_ARGS_IN_REGISTERS) - { - if (TARGET_DEBUG_D_MODE) - fprintf (stderr, "<stack>%s\n", struct_p ? ", [struct]" : ""); - - ret = 0; - } - else - { - gcc_assert (regbase != -1); - - if (! type || TREE_CODE (type) != RECORD_TYPE - || ! named || ! TYPE_SIZE_UNIT (type) - || ! host_integerp (TYPE_SIZE_UNIT (type), 1)) - ret = gen_rtx_REG (mode, regbase + *arg_words + bias); - else - { - tree field; - - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) - if (TREE_CODE (field) == FIELD_DECL - && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE - && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD - && host_integerp (bit_position (field), 0) - && int_bit_position (field) % BITS_PER_WORD == 0) - break; - - /* If the whole struct fits a DFmode register, - we don't need the PARALLEL. */ - if (! field || mode == DFmode) - ret = gen_rtx_REG (mode, regbase + *arg_words + bias); - else - { - unsigned int chunks; - HOST_WIDE_INT bitpos; - unsigned int regno; - unsigned int i; - - /* ??? 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 - use the actual mode here. */ - ret = gen_rtx_PARALLEL (mode, rtvec_alloc (chunks)); - - bitpos = 0; - regno = regbase + *arg_words + bias; - field = TYPE_FIELDS (type); - for (i = 0; i < chunks; i++) - { - rtx reg; - - for (; field; field = TREE_CHAIN (field)) - if (TREE_CODE (field) == FIELD_DECL - && int_bit_position (field) >= bitpos) - break; - - if (field - && int_bit_position (field) == bitpos - && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE - && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD) - reg = gen_rtx_REG (DFmode, regno++); - else - reg = gen_rtx_REG (word_mode, regno); - - XVECEXP (ret, 0, i) - = gen_rtx_EXPR_LIST (VOIDmode, reg, - GEN_INT (bitpos / BITS_PER_UNIT)); - - bitpos += 64; - regno++; - } - } - } - - if (TARGET_DEBUG_D_MODE) - fprintf (stderr, "%s%s\n", reg_names[regbase + *arg_words + bias], - struct_p ? ", [struct]" : ""); - } - - /* We will be called with a mode of VOIDmode after the last argument - has been seen. Whatever we return will be passed to the call - insn. If we need any shifts for small structures, return them in - a PARALLEL. */ - if (mode == VOIDmode) - { - if (cum->num_adjusts > 0) - ret = gen_rtx_PARALLEL ((enum machine_mode) cum->fp_code, - gen_rtvec_v (cum->num_adjusts, cum->adjust)); - } - - return ret; -} - -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 - 1) - { - if (TARGET_DEBUG_D_MODE) - fprintf (stderr, "iq2000_arg_partial_bytes=%d\n", UNITS_PER_WORD); - return UNITS_PER_WORD; - } - - return 0; -} - -/* Implement va_start. */ - -static void -iq2000_va_start (tree valist, rtx nextarg) -{ - int int_arg_words; - /* Find out how many non-float named formals. */ - int gpr_save_area_size; - /* Note UNITS_PER_WORD is 4 bytes. */ - int_arg_words = crtl->args.info.arg_words; - - if (int_arg_words < 8 ) - /* 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); - std_expand_builtin_va_start (valist, nextarg); -} - -/* Allocate a chunk of memory for per-function machine-dependent data. */ - -static struct machine_function * -iq2000_init_machine_status (void) -{ - struct machine_function *f; - - f = GGC_CNEW (struct machine_function); - - return f; -} - -/* Implement TARGET_HANDLE_OPTION. */ - -static bool -iq2000_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED) -{ - switch (code) - { - 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; - - case OPT_march_: - /* This option has no effect at the moment. */ - return (strcmp (arg, "default") == 0 - || strcmp (arg, "DEFAULT") == 0 - || strcmp (arg, "iq2000") == 0); - - default: - return true; - } -} - -/* Detect any conflicts in the switches. */ - -void -override_options (void) -{ - target_flags &= ~MASK_GPOPT; - - iq2000_isa = IQ2000_ISA_DEFAULT; - - /* Identify the processor type. */ - - iq2000_print_operand_punct['?'] = 1; - iq2000_print_operand_punct['#'] = 1; - iq2000_print_operand_punct['&'] = 1; - iq2000_print_operand_punct['!'] = 1; - iq2000_print_operand_punct['*'] = 1; - iq2000_print_operand_punct['@'] = 1; - iq2000_print_operand_punct['.'] = 1; - iq2000_print_operand_punct['('] = 1; - iq2000_print_operand_punct[')'] = 1; - iq2000_print_operand_punct['['] = 1; - iq2000_print_operand_punct[']'] = 1; - iq2000_print_operand_punct['<'] = 1; - iq2000_print_operand_punct['>'] = 1; - iq2000_print_operand_punct['{'] = 1; - iq2000_print_operand_punct['}'] = 1; - iq2000_print_operand_punct['^'] = 1; - iq2000_print_operand_punct['$'] = 1; - iq2000_print_operand_punct['+'] = 1; - iq2000_print_operand_punct['~'] = 1; - - /* Save GPR registers in word_mode sized hunks. word_mode hasn't been - initialized yet, so we can't use that here. */ - gpr_mode = SImode; - - /* Function to allocate machine-dependent function status. */ - init_machine_status = iq2000_init_machine_status; -} - -/* The arg pointer (which is eliminated) points to the virtual frame pointer, - while the frame pointer (which may be eliminated) points to the stack - pointer after the initial adjustments. */ - -HOST_WIDE_INT -iq2000_debugger_offset (rtx addr, HOST_WIDE_INT offset) -{ - rtx offset2 = const0_rtx; - 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->initialized) - ? compute_frame_size (get_frame_size ()) - : cfun->machine->total_size; - - offset = offset - frame_size; - } - - return offset; -} - -/* If defined, a C statement to be executed just prior to the output of - assembler code for INSN, to modify the extracted operands so they will be - output differently. - - Here the argument OPVEC is the vector containing the operands extracted - from INSN, and NOPERANDS is the number of elements of the vector which - contain meaningful data for this insn. The contents of this vector are - what will be used to convert the insn template into assembler code, so you - can change the assembler output by changing the contents of the vector. - - We use it to check if the current insn needs a nop in front of it because - of load delays, and also to update the delay slot statistics. */ - -void -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? */ - 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)) - || (iq2000_load_reg3 != 0 && reg_mentioned_p (iq2000_load_reg3, pattern)) - || (iq2000_load_reg4 != 0 - && reg_mentioned_p (iq2000_load_reg4, pattern))) - fputs ("\tnop\n", asm_out_file); - - else - dslots_load_filled ++; - - while (--dslots_number_nops > 0) - fputs ("\tnop\n", asm_out_file); - - iq2000_load_reg = 0; - iq2000_load_reg2 = 0; - iq2000_load_reg3 = 0; - iq2000_load_reg4 = 0; - } - - 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 ++; -} - -/* Return the bytes needed to compute the frame pointer from the current - stack pointer where SIZE is the # of var. bytes allocated. - - IQ2000 stack frames look like: - - Before call After call - +-----------------------+ +-----------------------+ - high | | | | - mem. | | | | - | caller's temps. | | caller's temps. | - | | | | - +-----------------------+ +-----------------------+ - | | | | - | arguments on stack. | | arguments on stack. | - | | | | - +-----------------------+ +-----------------------+ - | 4 words to save | | 4 words to save | - | arguments passed | | arguments passed | - | in registers, even | | in registers, even | - SP->| if not passed. | VFP->| if not passed. | - +-----------------------+ +-----------------------+ - | | - | fp register save | - | | - +-----------------------+ - | | - | gp register save | - | | - +-----------------------+ - | | - | local variables | - | | - +-----------------------+ - | | - | alloca allocations | - | | - +-----------------------+ - | | - | GP save for V.4 abi | - | | - +-----------------------+ - | | - | arguments on stack | - | | - +-----------------------+ - | 4 words to save | - | arguments passed | - | in registers, even | - low SP->| if not passed. | - memory +-----------------------+ */ - -HOST_WIDE_INT -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. */ - - gp_reg_size = 0; - fp_reg_size = 0; - mask = 0; - extra_size = IQ2000_STACK_ALIGN ((0)); - var_size = IQ2000_STACK_ALIGN (size); - args_size = IQ2000_STACK_ALIGN (crtl->outgoing_args_size); - - /* If a function dynamically allocates the stack and - has 0 for STACK_DYNAMIC_OFFSET then allocate some stack space. */ - if (args_size == 0 && cfun->calls_alloca) - args_size = 4 * UNITS_PER_WORD; - - total_size = var_size + args_size + extra_size; - - /* Calculate space needed for gp registers. */ - for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) - { - if (MUST_SAVE_REGISTER (regno)) - { - gp_reg_size += GET_MODE_SIZE (gpr_mode); - mask |= 1L << (regno - GP_REG_FIRST); - } - } - - /* We need to restore these for the handler. */ - if (crtl->calls_eh_return) - { - unsigned int i; - - for (i = 0; ; ++i) - { - regno = EH_RETURN_DATA_REGNO (i); - if (regno == (int) INVALID_REGNUM) - break; - gp_reg_size += GET_MODE_SIZE (gpr_mode); - mask |= 1L << (regno - GP_REG_FIRST); - } - } - - fp_inc = 2; - fp_bits = 3; - gp_reg_rounded = IQ2000_STACK_ALIGN (gp_reg_size); - total_size += gp_reg_rounded + IQ2000_STACK_ALIGN (fp_reg_size); - - /* The gp reg is caller saved, so there is no need for leaf routines - (total_size == extra_size) to save the gp reg. */ - if (total_size == extra_size - && ! profile_flag) - total_size = extra_size = 0; - - total_size += IQ2000_STACK_ALIGN (crtl->args.pretend_args_size); - - /* Save other computed information. */ - 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) - { - unsigned long offset; - - offset = (args_size + extra_size + var_size - + gp_reg_size - GET_MODE_SIZE (gpr_mode)); - - cfun->machine->gp_sp_offset = offset; - cfun->machine->gp_save_offset = offset - total_size; - } - else - { - cfun->machine->gp_sp_offset = 0; - cfun->machine->gp_save_offset = 0; - } - - cfun->machine->fp_sp_offset = 0; - cfun->machine->fp_save_offset = 0; - - /* Ok, we're done. */ - return total_size; -} - -/* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame - pointer, argument pointer, or return address pointer. TO is either - the stack pointer or hard frame pointer. */ - -int -iq2000_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED) -{ - int offset; - - compute_frame_size (get_frame_size ()); - if ((from) == FRAME_POINTER_REGNUM) - (offset) = 0; - else if ((from) == ARG_POINTER_REGNUM) - (offset) = (cfun->machine->total_size); - else if ((from) == RETURN_ADDRESS_POINTER_REGNUM) - { - 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; -} - -/* Common code to emit the insns (or to write the instructions to a file) - to save/restore registers. - Other parts of the code assume that IQ2000_TEMP1_REGNUM (aka large_reg) - is not modified within save_restore_insns. */ - -#define BITSET_P(VALUE,BIT) (((VALUE) & (1L << (BIT))) != 0) - -/* Emit instructions to load the value (SP + OFFSET) into IQ2000_TEMP2_REGNUM - and return an rtl expression for the register. Write the assembly - instructions directly to FILE if it is not null, otherwise emit them as - rtl. - - This function is a subroutine of save_restore_insns. It is used when - OFFSET is too large to add in a single instruction. */ - -static rtx -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); - - emit_move_insn (reg, offset_rtx); - emit_insn (gen_addsi3 (reg, reg, stack_pointer_rtx)); - return reg; -} - -/* Make INSN frame related and note that it performs the frame-related - operation DWARF_PATTERN. */ - -static void -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, - dwarf_pattern, - REG_NOTES (insn)); -} - -/* Emit a move instruction that stores REG in MEM. Make the instruction - frame related and note that it stores REG at (SP + OFFSET). */ - -static void -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); - - iq2000_annotate_frame_insn (emit_move_insn (mem, reg), - 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 (int store_p) -{ - 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; - - gcc_assert (!frame_pointer_needed - || BITSET_P (mask, HARD_FRAME_POINTER_REGNUM - GP_REG_FIRST)); - - if (mask == 0) - { - base_reg_rtx = 0, base_offset = 0; - return; - } - - /* Save registers starting from high to low. The debuggers prefer at least - the return register be stored at func+4, and also it allows us not to - need a nop in the epilog if at least one register is reloaded in - addition to return address. */ - - /* Save GP registers if needed. */ - /* Pick which pointer to use as a base register. For small frames, just - use the stack pointer. Otherwise, use a temporary register. Save 2 - cycles if the save area is near the end of a large frame, by reusing - the constant created in the prologue/epilogue to adjust the stack - frame. */ - - gp_offset = cfun->machine->gp_sp_offset; - end_offset - = 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", - (long) gp_offset, (long) end_offset); - - else if (gp_offset < 32768) - base_reg_rtx = stack_pointer_rtx, base_offset = 0; - else - { - 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); - base_reg_rtx = iq2000_add_large_offset_to_sp (base_offset); - } - - for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--) - { - if (BITSET_P (mask, regno - GP_REG_FIRST)) - { - rtx reg_rtx; - rtx mem_rtx - = gen_rtx_MEM (gpr_mode, - gen_rtx_PLUS (Pmode, base_reg_rtx, - GEN_INT (gp_offset - base_offset))); - - reg_rtx = gen_rtx_REG (gpr_mode, regno); - - if (store_p) - iq2000_emit_frame_related_store (mem_rtx, reg_rtx, gp_offset); - else - { - emit_move_insn (reg_rtx, mem_rtx); - } - gp_offset -= GET_MODE_SIZE (gpr_mode); - } - } -} - -/* Expand the prologue into a bunch of separate insns. */ - -void -iq2000_expand_prologue (void) -{ - int regno; - HOST_WIDE_INT tsize; - int last_arg_is_vararg_marker = 0; - tree fndecl = current_function_decl; - tree fntype = TREE_TYPE (fndecl); - tree fnargs = DECL_ARGUMENTS (fndecl); - rtx next_arg_reg; - int i; - tree next_arg; - tree cur_arg; - CUMULATIVE_ARGS args_so_far; - 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), fndecl) - && !cfun->returns_pcc_struct - && 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); - - DECL_ARG_TYPE (function_result_decl) = type; - TREE_CHAIN (function_result_decl) = fnargs; - fnargs = function_result_decl; - } - - /* For arguments passed in registers, find the register number - of the first argument in the variable part of the argument list, - otherwise GP_ARG_LAST+1. Note also if the last argument is - the varargs special argument, and treat it as part of the - variable arguments. - - This is only needed if store_args_on_stack is true. */ - 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) - { - tree passed_type = DECL_ARG_TYPE (cur_arg); - enum machine_mode passed_mode = TYPE_MODE (passed_type); - rtx entry_parm; - - if (TREE_ADDRESSABLE (passed_type)) - { - passed_type = build_pointer_type (passed_type); - passed_mode = Pmode; - } - - entry_parm = FUNCTION_ARG (args_so_far, passed_mode, passed_type, 1); - - FUNCTION_ARG_ADVANCE (args_so_far, passed_mode, passed_type, 1); - next_arg = TREE_CHAIN (cur_arg); - - if (entry_parm && store_args_on_stack) - { - if (next_arg == 0 - && DECL_NAME (cur_arg) - && ((0 == strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg)), - "__builtin_va_alist")) - || (0 == strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg)), - "va_alist")))) - { - last_arg_is_vararg_marker = 1; - break; - } - else - { - int words; - - gcc_assert (GET_CODE (entry_parm) == REG); - - /* 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 - words = (GET_MODE_SIZE (GET_MODE (entry_parm)) + 3) / 4; - - regno = REGNO (entry_parm) + words - 1; - } - } - else - { - regno = GP_ARG_LAST+1; - break; - } - } - - /* In order to pass small structures by value in registers we need to - shift the value into the high part of the register. - 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) - { - rtvec adjust = XVEC (next_arg_reg, 0); - int num = GET_NUM_ELEM (adjust); - - for (i = 0; i < num; i++) - { - rtx insn, pattern; - - pattern = RTVEC_ELT (adjust, i); - if (GET_CODE (pattern) != SET - || GET_CODE (SET_SRC (pattern)) != ASHIFT) - abort_with_insn (pattern, "Insn is not a shift"); - PUT_CODE (SET_SRC (pattern), ASHIFTRT); - - insn = emit_insn (pattern); - } - } - - tsize = compute_frame_size (get_frame_size ()); - - /* If this function is a varargs function, store any registers that - would normally hold arguments ($4 - $7) on the stack. */ - if (store_args_on_stack - && ((TYPE_ARG_TYPES (fntype) != 0 - && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) - != void_type_node)) - || last_arg_is_vararg_marker)) - { - int offset = (regno - GP_ARG_FIRST) * UNITS_PER_WORD; - rtx ptr = stack_pointer_rtx; - - 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)); - - offset += GET_MODE_SIZE (gpr_mode); - } - } - - if (tsize > 0) - { - rtx tsize_rtx = GEN_INT (tsize); - rtx adjustment_rtx, insn, dwarf_pattern; - - if (tsize > 32767) - { - adjustment_rtx = gen_rtx_REG (Pmode, IQ2000_TEMP1_REGNUM); - emit_move_insn (adjustment_rtx, tsize_rtx); - } - else - adjustment_rtx = tsize_rtx; - - insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, - adjustment_rtx)); - - dwarf_pattern = gen_rtx_SET (Pmode, stack_pointer_rtx, - plus_constant (stack_pointer_rtx, -tsize)); - - iq2000_annotate_frame_insn (insn, dwarf_pattern); - - save_restore_insns (1); - - if (frame_pointer_needed) - { - rtx insn = 0; - - insn = emit_insn (gen_movsi (hard_frame_pointer_rtx, - stack_pointer_rtx)); - - if (insn) - RTX_FRAME_RELATED_P (insn) = 1; - } - } - - emit_insn (gen_blockage ()); -} - -/* Expand the epilogue into a bunch of separate insns. */ - -void -iq2000_expand_epilogue (void) -{ - 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_jump_insn (gen_return ()); - return; - } - - if (tsize > 32767) - { - tmp_rtx = gen_rtx_REG (Pmode, IQ2000_TEMP1_REGNUM); - emit_move_insn (tmp_rtx, tsize_rtx); - tsize_rtx = tmp_rtx; - } - - if (tsize > 0) - { - if (frame_pointer_needed) - { - emit_insn (gen_blockage ()); - - emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx)); - } - - save_restore_insns (0); - - if (crtl->calls_eh_return) - { - rtx eh_ofs = EH_RETURN_STACKADJ_RTX; - emit_insn (gen_addsi3 (eh_ofs, eh_ofs, tsize_rtx)); - tsize_rtx = eh_ofs; - } - - emit_insn (gen_blockage ()); - - if (tsize != 0 || crtl->calls_eh_return) - { - emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, - tsize_rtx)); - } - } - - if (crtl->calls_eh_return) - { - /* Perform the additional bump for __throw. */ - emit_move_insn (gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM), - stack_pointer_rtx); - emit_use (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, - GP_REG_FIRST + 31))); -} - -void -iq2000_expand_eh_return (rtx address) -{ - HOST_WIDE_INT gp_offset = cfun->machine->gp_sp_offset; - rtx scratch; - - scratch = plus_constant (stack_pointer_rtx, gp_offset); - emit_move_insn (gen_rtx_MEM (GET_MODE (address), scratch), address); -} - -/* Return nonzero if this function is known to have a null epilogue. - This allows the optimizer to omit jumps to jumps if no stack - was created. */ - -int -iq2000_can_use_return_insn (void) -{ - if (! reload_completed) - return 0; - - if (df_regs_ever_live_p (31) || profile_flag) - return 0; - - if (cfun->machine->initialized) - return cfun->machine->total_size == 0; - - return compute_frame_size (get_frame_size ()) == 0; -} - -/* Returns nonzero if X contains a SYMBOL_REF. */ - -static int -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 (UNARY_P (x)) - return symbolic_expression_p (XEXP (x, 0)); - - if (ARITHMETIC_P (x)) - return (symbolic_expression_p (XEXP (x, 0)) - || symbolic_expression_p (XEXP (x, 1))); - - return 0; -} - -/* Choose the section to use for the constant rtx expression X that has - mode MODE. */ - -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. */ - return mergeable_constant_section (mode, align, 0); -} - -/* Choose the section to use for DECL. RELOC is true if its value contains - any relocatable expression. - - Some of the logic used here needs to be replicated in - ENCODE_SECTION_INFO in iq2000.h so that references to these symbols - are done correctly. */ - -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) - return readonly_data_section; - else - 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) - return readonly_data_section; - else - return data_section; - } -} -/* Return register to use for a function return value with VALTYPE for function - FUNC. */ - -rtx -iq2000_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED) -{ - int reg = GP_RETURN; - enum machine_mode mode = TYPE_MODE (valtype); - int unsignedp = TYPE_UNSIGNED (valtype); - - /* 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); -} - -/* Return true when an argument must be passed by reference. */ - -static bool -iq2000_pass_by_reference (CUMULATIVE_ARGS *cum, enum machine_mode mode, - const_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 && 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; - } - - if (type == NULL_TREE || mode == DImode || mode == DFmode) - return 0; - - size = int_size_in_bytes (type); - return size == -1 || size > UNITS_PER_WORD; -} - -/* Return the length of INSN. LENGTH is the initial length computed by - attributes in the machine-description file. */ - -int -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. */ - if (simplejump_p (insn) - || ( (GET_CODE (insn) == JUMP_INSN - || GET_CODE (insn) == CALL_INSN))) - length += 4; - - return length; -} - -/* Output assembly instructions to perform a conditional branch. - - 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 - nonzero the comparison takes two operands; OPERANDS[3] will be the - second operand. - - 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 (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]); - /* 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. */ - const char *op1 = "%z2"; - /* A string to use in the assembly output to represent the second - operand. Use the hard-wired zero register if there's no second - operand. */ - const char *op2 = (two_operands_p ? ",%z3" : ",%."); - /* The operand-printing string for the comparison. */ - const char *comp = (float_p ? "%F0" : "%C0"); - /* 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 - in the delay slot if the branch is not taken. */ - iq2000_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - - if (!two_operands_p) - { - /* To compute whether than A > B, for example, we normally - 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 nonzero. Thus, we change the CODE here to - reflect the simpler comparison operation. */ - switch (code) - { - case GTU: - code = NE; - break; - - case LEU: - code = EQ; - break; - - case GEU: - /* A condition which will always be true. */ - code = EQ; - op1 = "%."; - break; - - case LTU: - /* A condition which will always be false. */ - code = NE; - op1 = "%."; - break; - - default: - /* Not a special case. */ - break; - } - } - - /* Relative comparisons are always done against zero. But - equality comparisons are done between two operands, and therefore - do not require a `z' in the assembly language output. */ - need_z_p = (!float_p && code != EQ && code != NE); - /* For comparisons against zero, the zero is not provided - explicitly. */ - if (need_z_p) - op2 = ""; - - /* Begin by terminating the buffer. That way we can always use - strcat to add to it. */ - buffer[0] = '\0'; - - switch (length) - { - case 4: - case 8: - /* Just a simple conditional branch. */ - if (float_p) - sprintf (buffer, "b%s%%?\t%%Z2%%1", - inverted_p ? inverted_comp : comp); - else - sprintf (buffer, "b%s%s%%?\t%s%s,%%1", - inverted_p ? inverted_comp : comp, - need_z_p ? "z" : "", - op1, - op2); - return buffer; - - case 12: - case 16: - { - /* Generate a reversed conditional branch around ` j' - instruction: - - .set noreorder - .set nomacro - bc l - nop - j target - .set macro - .set reorder - l: - - Because we have to jump four bytes *past* the following - instruction if this branch was annulled, we can't just use - a label, as in the picture above; there's no way to put the - label after the next instruction, as the assembler does not - accept `.L+4' as the target of a branch. (We can't just - wait until the next instruction is output; it might be a - macro and take up more than four bytes. Once again, we see - why we want to eliminate macros.) - - If the branch is annulled, we jump four more bytes that we - would otherwise; that way we skip the annulled instruction - in the delay slot. */ - - const char *target - = ((iq2000_branch_likely || length == 16) ? ".+16" : ".+12"); - char *c; - - c = strchr (buffer, '\0'); - /* Generate the reversed comparison. This takes four - bytes. */ - if (float_p) - sprintf (c, "b%s\t%%Z2%s", - inverted_p ? comp : inverted_comp, - target); - else - sprintf (c, "b%s%s\t%s%s,%s", - inverted_p ? comp : inverted_comp, - need_z_p ? "z" : "", - op1, - op2, - target); - strcat (c, "\n\tnop\n\tj\t%1"); - if (length == 16) - /* The delay slot was unfilled. Since we're inside - .noreorder, the assembler will not fill in the NOP for - us, so we must do it ourselves. */ - strcat (buffer, "\n\tnop"); - return buffer; - } - - default: - gcc_unreachable (); - } - - /* NOTREACHED */ - return 0; -} - -#define def_builtin(NAME, TYPE, CODE) \ - add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \ - NULL, NULL_TREE) - -static void -iq2000_init_builtins (void) -{ - tree endlink = void_list_node; - tree void_ftype, void_ftype_int, void_ftype_int_int; - tree void_ftype_int_int_int; - tree int_ftype_int, int_ftype_int_int, int_ftype_int_int_int; - tree int_ftype_int_int_int_int; - - /* func () */ - void_ftype - = build_function_type (void_type_node, - tree_cons (NULL_TREE, void_type_node, endlink)); - - /* func (int) */ - void_ftype_int - = build_function_type (void_type_node, - tree_cons (NULL_TREE, integer_type_node, endlink)); - - /* void func (int, int) */ - void_ftype_int_int - = build_function_type (void_type_node, - tree_cons (NULL_TREE, integer_type_node, - tree_cons (NULL_TREE, integer_type_node, - endlink))); - - /* int func (int) */ - int_ftype_int - = build_function_type (integer_type_node, - tree_cons (NULL_TREE, integer_type_node, endlink)); - - /* int func (int, int) */ - int_ftype_int_int - = build_function_type (integer_type_node, - tree_cons (NULL_TREE, integer_type_node, - tree_cons (NULL_TREE, integer_type_node, - endlink))); - - /* void func (int, int, int) */ -void_ftype_int_int_int - = build_function_type - (void_type_node, - tree_cons (NULL_TREE, integer_type_node, - tree_cons (NULL_TREE, integer_type_node, - tree_cons (NULL_TREE, - integer_type_node, - endlink)))); - - /* int func (int, int, int, int) */ - int_ftype_int_int_int_int - = build_function_type - (integer_type_node, - tree_cons (NULL_TREE, integer_type_node, - tree_cons (NULL_TREE, integer_type_node, - tree_cons (NULL_TREE, - integer_type_node, - tree_cons (NULL_TREE, - integer_type_node, - endlink))))); - - /* int func (int, int, int) */ - int_ftype_int_int_int - = build_function_type - (integer_type_node, - tree_cons (NULL_TREE, integer_type_node, - tree_cons (NULL_TREE, integer_type_node, - tree_cons (NULL_TREE, - integer_type_node, - endlink)))); - - /* int func (int, int, int, int) */ - int_ftype_int_int_int_int - = build_function_type - (integer_type_node, - tree_cons (NULL_TREE, integer_type_node, - tree_cons (NULL_TREE, integer_type_node, - tree_cons (NULL_TREE, - integer_type_node, - tree_cons (NULL_TREE, - integer_type_node, - endlink))))); - - def_builtin ("__builtin_ado16", int_ftype_int_int, IQ2000_BUILTIN_ADO16); - def_builtin ("__builtin_ram", int_ftype_int_int_int_int, IQ2000_BUILTIN_RAM); - def_builtin ("__builtin_chkhdr", void_ftype_int_int, IQ2000_BUILTIN_CHKHDR); - def_builtin ("__builtin_pkrl", void_ftype_int_int, IQ2000_BUILTIN_PKRL); - def_builtin ("__builtin_cfc0", int_ftype_int, IQ2000_BUILTIN_CFC0); - def_builtin ("__builtin_cfc1", int_ftype_int, IQ2000_BUILTIN_CFC1); - def_builtin ("__builtin_cfc2", int_ftype_int, IQ2000_BUILTIN_CFC2); - def_builtin ("__builtin_cfc3", int_ftype_int, IQ2000_BUILTIN_CFC3); - def_builtin ("__builtin_ctc0", void_ftype_int_int, IQ2000_BUILTIN_CTC0); - def_builtin ("__builtin_ctc1", void_ftype_int_int, IQ2000_BUILTIN_CTC1); - def_builtin ("__builtin_ctc2", void_ftype_int_int, IQ2000_BUILTIN_CTC2); - def_builtin ("__builtin_ctc3", void_ftype_int_int, IQ2000_BUILTIN_CTC3); - def_builtin ("__builtin_mfc0", int_ftype_int, IQ2000_BUILTIN_MFC0); - def_builtin ("__builtin_mfc1", int_ftype_int, IQ2000_BUILTIN_MFC1); - def_builtin ("__builtin_mfc2", int_ftype_int, IQ2000_BUILTIN_MFC2); - def_builtin ("__builtin_mfc3", int_ftype_int, IQ2000_BUILTIN_MFC3); - def_builtin ("__builtin_mtc0", void_ftype_int_int, IQ2000_BUILTIN_MTC0); - def_builtin ("__builtin_mtc1", void_ftype_int_int, IQ2000_BUILTIN_MTC1); - def_builtin ("__builtin_mtc2", void_ftype_int_int, IQ2000_BUILTIN_MTC2); - def_builtin ("__builtin_mtc3", void_ftype_int_int, IQ2000_BUILTIN_MTC3); - def_builtin ("__builtin_lur", void_ftype_int_int, IQ2000_BUILTIN_LUR); - def_builtin ("__builtin_rb", void_ftype_int_int, IQ2000_BUILTIN_RB); - def_builtin ("__builtin_rx", void_ftype_int_int, IQ2000_BUILTIN_RX); - def_builtin ("__builtin_srrd", void_ftype_int, IQ2000_BUILTIN_SRRD); - def_builtin ("__builtin_srwr", void_ftype_int_int, IQ2000_BUILTIN_SRWR); - def_builtin ("__builtin_wb", void_ftype_int_int, IQ2000_BUILTIN_WB); - def_builtin ("__builtin_wx", void_ftype_int_int, IQ2000_BUILTIN_WX); - def_builtin ("__builtin_luc32l", void_ftype_int_int, IQ2000_BUILTIN_LUC32L); - def_builtin ("__builtin_luc64", void_ftype_int_int, IQ2000_BUILTIN_LUC64); - def_builtin ("__builtin_luc64l", void_ftype_int_int, IQ2000_BUILTIN_LUC64L); - def_builtin ("__builtin_luk", void_ftype_int_int, IQ2000_BUILTIN_LUK); - def_builtin ("__builtin_lulck", void_ftype_int, IQ2000_BUILTIN_LULCK); - def_builtin ("__builtin_lum32", void_ftype_int_int, IQ2000_BUILTIN_LUM32); - def_builtin ("__builtin_lum32l", void_ftype_int_int, IQ2000_BUILTIN_LUM32L); - def_builtin ("__builtin_lum64", void_ftype_int_int, IQ2000_BUILTIN_LUM64); - def_builtin ("__builtin_lum64l", void_ftype_int_int, IQ2000_BUILTIN_LUM64L); - def_builtin ("__builtin_lurl", void_ftype_int_int, IQ2000_BUILTIN_LURL); - def_builtin ("__builtin_mrgb", int_ftype_int_int_int, IQ2000_BUILTIN_MRGB); - def_builtin ("__builtin_srrdl", void_ftype_int, IQ2000_BUILTIN_SRRDL); - def_builtin ("__builtin_srulck", void_ftype_int, IQ2000_BUILTIN_SRULCK); - def_builtin ("__builtin_srwru", void_ftype_int_int, IQ2000_BUILTIN_SRWRU); - def_builtin ("__builtin_trapqfl", void_ftype, IQ2000_BUILTIN_TRAPQFL); - def_builtin ("__builtin_trapqne", void_ftype, IQ2000_BUILTIN_TRAPQNE); - def_builtin ("__builtin_traprel", void_ftype_int, IQ2000_BUILTIN_TRAPREL); - def_builtin ("__builtin_wbu", void_ftype_int_int_int, IQ2000_BUILTIN_WBU); - def_builtin ("__builtin_syscall", void_ftype, IQ2000_BUILTIN_SYSCALL); -} - -/* Builtin for ICODE having ARGCOUNT args in EXP where each arg - has an rtx CODE. */ - -static rtx -expand_one_builtin (enum insn_code icode, rtx target, tree exp, - enum rtx_code *code, int argcount) -{ - rtx pat; - tree arg [5]; - rtx op [5]; - enum machine_mode mode [5]; - int i; - - mode[0] = insn_data[icode].operand[0].mode; - for (i = 0; i < argcount; i++) - { - 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 %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]); - } - - if (insn_data[icode].operand[0].constraint[0] == '=') - { - if (target == 0 - || GET_MODE (target) != mode[0] - || ! (*insn_data[icode].operand[0].predicate) (target, mode[0])) - target = gen_reg_rtx (mode[0]); - } - else - target = 0; - - switch (argcount) - { - case 0: - pat = GEN_FCN (icode) (target); - case 1: - if (target) - pat = GEN_FCN (icode) (target, op[0]); - else - pat = GEN_FCN (icode) (op[0]); - break; - case 2: - if (target) - pat = GEN_FCN (icode) (target, op[0], op[1]); - else - pat = GEN_FCN (icode) (op[0], op[1]); - break; - case 3: - if (target) - pat = GEN_FCN (icode) (target, op[0], op[1], op[2]); - else - pat = GEN_FCN (icode) (op[0], op[1], op[2]); - break; - case 4: - if (target) - pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]); - else - pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]); - break; - default: - gcc_unreachable (); - } - - if (! pat) - return 0; - emit_insn (pat); - return target; -} - -/* Expand an expression EXP that calls a built-in function, - with result going to TARGET if that's convenient - (and in mode MODE if that's convenient). - SUBTARGET may be used as the target for computing one of EXP's operands. - IGNORE is nonzero if the value is to be ignored. */ - -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 (CALL_EXPR_FN (exp), 0); - int fcode = DECL_FUNCTION_CODE (fndecl); - enum rtx_code code [5]; - - code[0] = REG; - code[1] = REG; - code[2] = REG; - code[3] = REG; - code[4] = REG; - switch (fcode) - { - default: - break; - - case IQ2000_BUILTIN_ADO16: - 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, exp, code, 4); - - case IQ2000_BUILTIN_CHKHDR: - return expand_one_builtin (CODE_FOR_chkhdr, target, exp, code, 2); - - case IQ2000_BUILTIN_PKRL: - 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, exp, code, 1); - - case IQ2000_BUILTIN_CFC1: - code[0] = CONST_INT; - 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, exp, code, 1); - - case IQ2000_BUILTIN_CFC3: - code[0] = CONST_INT; - 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, exp, code, 2); - - case IQ2000_BUILTIN_CTC1: - code[1] = CONST_INT; - 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, exp, code, 2); - - case IQ2000_BUILTIN_CTC3: - code[1] = CONST_INT; - 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, exp, code, 1); - - case IQ2000_BUILTIN_MFC1: - code[0] = CONST_INT; - 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, exp, code, 1); - - case IQ2000_BUILTIN_MFC3: - code[0] = CONST_INT; - 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, exp, code, 2); - - case IQ2000_BUILTIN_MTC1: - code[1] = CONST_INT; - 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, exp, code, 2); - - case IQ2000_BUILTIN_MTC3: - code[1] = CONST_INT; - return expand_one_builtin (CODE_FOR_mtc3, target, exp, code, 2); - - case IQ2000_BUILTIN_LUR: - return expand_one_builtin (CODE_FOR_lur, target, exp, code, 2); - - case IQ2000_BUILTIN_RB: - return expand_one_builtin (CODE_FOR_rb, target, exp, code, 2); - - case IQ2000_BUILTIN_RX: - return expand_one_builtin (CODE_FOR_rx, target, exp, code, 2); - - case IQ2000_BUILTIN_SRRD: - return expand_one_builtin (CODE_FOR_srrd, target, exp, code, 1); - - case IQ2000_BUILTIN_SRWR: - return expand_one_builtin (CODE_FOR_srwr, target, exp, code, 2); - - case IQ2000_BUILTIN_WB: - return expand_one_builtin (CODE_FOR_wb, target, exp, code, 2); - - case IQ2000_BUILTIN_WX: - return expand_one_builtin (CODE_FOR_wx, target, exp, code, 2); - - case IQ2000_BUILTIN_LUC32L: - return expand_one_builtin (CODE_FOR_luc32l, target, exp, code, 2); - - case IQ2000_BUILTIN_LUC64: - return expand_one_builtin (CODE_FOR_luc64, target, exp, code, 2); - - case IQ2000_BUILTIN_LUC64L: - return expand_one_builtin (CODE_FOR_luc64l, target, exp, code, 2); - - case IQ2000_BUILTIN_LUK: - return expand_one_builtin (CODE_FOR_luk, target, exp, code, 2); - - case IQ2000_BUILTIN_LULCK: - return expand_one_builtin (CODE_FOR_lulck, target, exp, code, 1); - - case IQ2000_BUILTIN_LUM32: - return expand_one_builtin (CODE_FOR_lum32, target, exp, code, 2); - - case IQ2000_BUILTIN_LUM32L: - return expand_one_builtin (CODE_FOR_lum32l, target, exp, code, 2); - - case IQ2000_BUILTIN_LUM64: - return expand_one_builtin (CODE_FOR_lum64, target, exp, code, 2); - - case IQ2000_BUILTIN_LUM64L: - return expand_one_builtin (CODE_FOR_lum64l, target, exp, code, 2); - - case IQ2000_BUILTIN_LURL: - 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, exp, code, 3); - - case IQ2000_BUILTIN_SRRDL: - return expand_one_builtin (CODE_FOR_srrdl, target, exp, code, 1); - - case IQ2000_BUILTIN_SRULCK: - return expand_one_builtin (CODE_FOR_srulck, target, exp, code, 1); - - case IQ2000_BUILTIN_SRWRU: - return expand_one_builtin (CODE_FOR_srwru, target, exp, code, 2); - - case IQ2000_BUILTIN_TRAPQFL: - return expand_one_builtin (CODE_FOR_trapqfl, target, exp, code, 0); - - case IQ2000_BUILTIN_TRAPQNE: - return expand_one_builtin (CODE_FOR_trapqne, target, exp, code, 0); - - case IQ2000_BUILTIN_TRAPREL: - return expand_one_builtin (CODE_FOR_traprel, target, exp, code, 1); - - case IQ2000_BUILTIN_WBU: - return expand_one_builtin (CODE_FOR_wbu, target, exp, code, 3); - - case IQ2000_BUILTIN_SYSCALL: - return expand_one_builtin (CODE_FOR_syscall, target, exp, code, 0); - } - - return NULL_RTX; -} - -/* Worker function for TARGET_RETURN_IN_MEMORY. */ - -static bool -iq2000_return_in_memory (const_tree type, const_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)) - { - int iq2000_save_gp_regs - = 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); - - if (iq2000_save_gp_regs < 0) - iq2000_save_gp_regs = 0; - if (iq2000_save_fp_regs < 0) - iq2000_save_fp_regs = 0; - - *pretend_size = ((iq2000_save_gp_regs * UNITS_PER_WORD) - + (iq2000_save_fp_regs * UNITS_PER_FPREG)); - - if (! (no_rtl)) - { - if (cum->arg_words < MAX_ARGS_IN_REGISTERS - iq2000_off) - { - rtx ptr, mem; - ptr = plus_constant (virtual_incoming_args_rtx, - - (iq2000_save_gp_regs - * UNITS_PER_WORD)); - mem = gen_rtx_MEM (BLKmode, ptr); - move_block_from_reg - (cum->arg_words + GP_ARG_FIRST + iq2000_off, - mem, - iq2000_save_gp_regs); - } - } - } -} - -/* 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. */ - -void -print_operand_address (FILE * file, rtx addr) -{ - if (!addr) - error ("PRINT_OPERAND_ADDRESS, null pointer"); - - else - switch (GET_CODE (addr)) - { - case REG: - if (REGNO (addr) == ARG_POINTER_REGNUM) - abort_with_insn (addr, "Arg pointer not eliminated."); - - fprintf (file, "0(%s)", reg_names [REGNO (addr)]); - break; - - case LO_SUM: - { - rtx arg0 = XEXP (addr, 0); - rtx arg1 = XEXP (addr, 1); - - if (GET_CODE (arg0) != REG) - abort_with_insn (addr, - "PRINT_OPERAND_ADDRESS, LO_SUM with #1 not REG."); - - fprintf (file, "%%lo("); - print_operand_address (file, arg1); - fprintf (file, ")(%s)", reg_names [REGNO (arg0)]); - } - break; - - case PLUS: - { - rtx reg = 0; - rtx offset = 0; - rtx arg0 = XEXP (addr, 0); - rtx arg1 = XEXP (addr, 1); - - if (GET_CODE (arg0) == REG) - { - reg = arg0; - offset = arg1; - if (GET_CODE (offset) == REG) - abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, 2 regs"); - } - - else if (GET_CODE (arg1) == REG) - reg = arg1, offset = arg0; - else if (CONSTANT_P (arg0) && CONSTANT_P (arg1)) - { - output_addr_const (file, addr); - break; - } - else - abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, no regs"); - - if (! CONSTANT_P (offset)) - abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, invalid insn #2"); - - if (REGNO (reg) == ARG_POINTER_REGNUM) - abort_with_insn (addr, "Arg pointer not eliminated."); - - output_addr_const (file, offset); - fprintf (file, "(%s)", reg_names [REGNO (reg)]); - } - break; - - case LABEL_REF: - case SYMBOL_REF: - case CONST_INT: - case CONST: - output_addr_const (file, addr); - if (GET_CODE (addr) == CONST_INT) - fprintf (file, "(%s)", reg_names [0]); - break; - - default: - abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, invalid insn #1"); - break; - } -} - -/* A C compound statement to output to stdio stream FILE the - assembler syntax for an instruction operand OP. - - 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. LETTER - comes from the `%' specification that was used to request - printing of the operand. If the specification was just `%DIGIT' - then LETTER is 0; if the specification was `%LTR DIGIT' then LETTER - is the ASCII code for LTR. - - 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 LETTER. - - The IQ2000 specific codes are: - - 'X' X is CONST_INT, prints upper 16 bits in hexadecimal format = "0x%04x", - 'x' X is CONST_INT, prints lower 16 bits in hexadecimal format = "0x%04x", - 'd' output integer constant in decimal, - 'z' if the operand is 0, use $0 instead of normal operand. - 'D' print second part of double-word register or memory operand. - 'L' print low-order register of double-word register operand. - 'M' print high-order register of double-word register operand. - 'C' print part of opcode for a branch condition. - 'F' print part of opcode for a floating-point branch condition. - 'N' print part of opcode for a branch condition, inverted. - 'W' print part of opcode for a floating-point branch condition, inverted. - 'A' Print part of opcode for a bit test condition. - 'P' Print label for a bit test. - 'p' Print log for a bit test. - 'B' print 'z' for EQ, 'n' for NE - 'b' print 'n' for EQ, 'z' for NE - 'T' print 'f' for EQ, 't' for NE - 't' print 't' for EQ, 'f' for NE - 'Z' print register and a comma, but print nothing for $fcc0 - '?' Print 'l' if we are to use a branch likely instead of normal branch. - '@' Print the name of the assembler temporary register (at or $1). - '.' Print the name of the register with a hard-wired zero (zero or $0). - '$' Print the name of the stack pointer register (sp or $29). - '+' Print the name of the gp register (gp or $28). */ - -void -print_operand (FILE *file, rtx op, int letter) -{ - enum rtx_code code; - - if (PRINT_OPERAND_PUNCT_VALID_P (letter)) - { - switch (letter) - { - case '?': - if (iq2000_branch_likely) - putc ('l', file); - break; - - case '@': - fputs (reg_names [GP_REG_FIRST + 1], file); - break; - - case '.': - fputs (reg_names [GP_REG_FIRST + 0], file); - break; - - case '$': - fputs (reg_names[STACK_POINTER_REGNUM], file); - break; - - case '+': - fputs (reg_names[GP_REG_FIRST + 28], file); - break; - - default: - error ("PRINT_OPERAND: Unknown punctuation '%c'", letter); - break; - } - - return; - } - - if (! op) - { - error ("PRINT_OPERAND null pointer"); - return; - } - - code = GET_CODE (op); - - if (code == SIGN_EXTEND) - op = XEXP (op, 0), code = GET_CODE (op); - - if (letter == 'C') - switch (code) - { - case EQ: fputs ("eq", file); break; - case NE: fputs ("ne", file); break; - case GT: fputs ("gt", file); break; - case GE: fputs ("ge", file); break; - case LT: fputs ("lt", file); break; - case LE: fputs ("le", file); break; - case GTU: fputs ("ne", file); break; - case GEU: fputs ("geu", file); break; - case LTU: fputs ("ltu", file); break; - case LEU: fputs ("eq", file); break; - default: - abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%C"); - } - - else if (letter == 'N') - switch (code) - { - case EQ: fputs ("ne", file); break; - case NE: fputs ("eq", file); break; - case GT: fputs ("le", file); break; - case GE: fputs ("lt", file); break; - case LT: fputs ("ge", file); break; - case LE: fputs ("gt", file); break; - case GTU: fputs ("leu", file); break; - case GEU: fputs ("ltu", file); break; - case LTU: fputs ("geu", file); break; - case LEU: fputs ("gtu", file); break; - default: - abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%N"); - } - - else if (letter == 'F') - switch (code) - { - case EQ: fputs ("c1f", file); break; - case NE: fputs ("c1t", file); break; - default: - abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%F"); - } - - else if (letter == 'W') - switch (code) - { - case EQ: fputs ("c1t", file); break; - case NE: fputs ("c1f", file); break; - default: - abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%W"); - } - - else if (letter == 'A') - fputs (code == LABEL_REF ? "i" : "in", file); - - else if (letter == 'P') - { - if (code == LABEL_REF) - output_addr_const (file, op); - else if (code != PC) - output_operand_lossage ("invalid %%P operand"); - } - - else if (letter == 'p') - { - int value; - if (code != CONST_INT - || (value = exact_log2 (INTVAL (op))) < 0) - output_operand_lossage ("invalid %%p value"); - fprintf (file, "%d", value); - } - - else if (letter == 'Z') - { - gcc_unreachable (); - } - - else if (code == REG || code == SUBREG) - { - int regnum; - - if (code == REG) - regnum = REGNO (op); - else - regnum = true_regnum (op); - - if ((letter == 'M' && ! WORDS_BIG_ENDIAN) - || (letter == 'L' && WORDS_BIG_ENDIAN) - || letter == 'D') - regnum++; - - fprintf (file, "%s", reg_names[regnum]); - } - - else if (code == MEM) - { - if (letter == 'D') - output_address (plus_constant (XEXP (op, 0), 4)); - else - output_address (XEXP (op, 0)); - } - - else if (code == CONST_DOUBLE - && GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT) - { - char s[60]; - - real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (op), sizeof (s), 0, 1); - fputs (s, file); - } - - else if (letter == 'x' && GET_CODE (op) == CONST_INT) - fprintf (file, HOST_WIDE_INT_PRINT_HEX, 0xffff & INTVAL(op)); - - else if (letter == 'X' && GET_CODE(op) == CONST_INT) - fprintf (file, HOST_WIDE_INT_PRINT_HEX, 0xffff & (INTVAL (op) >> 16)); - - else if (letter == 'd' && GET_CODE(op) == CONST_INT) - fprintf (file, HOST_WIDE_INT_PRINT_DEC, (INTVAL(op))); - - else if (letter == 'z' && GET_CODE (op) == CONST_INT && INTVAL (op) == 0) - fputs (reg_names[GP_REG_FIRST], file); - - else if (letter == 'd' || letter == 'x' || letter == 'X') - output_operand_lossage ("invalid use of %%d, %%x, or %%X"); - - else if (letter == 'B') - fputs (code == EQ ? "z" : "n", file); - else if (letter == 'b') - fputs (code == EQ ? "n" : "z", file); - else if (letter == 'T') - fputs (code == EQ ? "f" : "t", file); - else if (letter == 't') - fputs (code == EQ ? "t" : "f", file); - - else if (code == CONST && GET_CODE (XEXP (op, 0)) == REG) - { - print_operand (file, XEXP (op, 0), letter); - } - - else - output_addr_const (file, op); -} - -static bool -iq2000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int * total, - bool speed ATTRIBUTE_UNUSED) -{ - 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" diff --git a/gcc-4.4.3/gcc/config/iq2000/iq2000.h b/gcc-4.4.3/gcc/config/iq2000/iq2000.h deleted file mode 100644 index f6c7ec5ed..000000000 --- a/gcc-4.4.3/gcc/config/iq2000/iq2000.h +++ /dev/null @@ -1,1135 +0,0 @@ -/* Definitions of target machine for GNU compiler. - Vitesse IQ2000 processors - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 - Free Software Foundation, Inc. - - This file is part of GCC. - - 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 3, or (at your - option) any later version. - - 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 GCC; see the file COPYING3. If not see - <http://www.gnu.org/licenses/>. */ - -/* Driver configuration. */ - -#undef SWITCH_TAKES_ARG -#define SWITCH_TAKES_ARG(CHAR) \ - (DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G') - -/* The svr4.h LIB_SPEC with -leval and --*group tacked on */ -#undef LIB_SPEC -#define LIB_SPEC "%{!shared:%{!symbolic:--start-group -lc -leval -lgcc --end-group}}" - -#undef STARTFILE_SPEC -#undef ENDFILE_SPEC - - -/* Run-time target specifications. */ - -#define TARGET_CPU_CPP_BUILTINS() \ - do \ - { \ - builtin_define ("__iq2000__"); \ - builtin_assert ("cpu=iq2000"); \ - builtin_assert ("machine=iq2000"); \ - } \ - while (0) - -/* Macros used in the machine description to test the flags. */ - -#define TARGET_STATS 0 - -#define TARGET_DEBUG_MODE 0 -#define TARGET_DEBUG_A_MODE 0 -#define TARGET_DEBUG_B_MODE 0 -#define TARGET_DEBUG_C_MODE 0 -#define TARGET_DEBUG_D_MODE 0 - -#ifndef IQ2000_ISA_DEFAULT -#define IQ2000_ISA_DEFAULT 1 -#endif - -#define IQ2000_VERSION "[1.0]" - -#ifndef MACHINE_TYPE -#define MACHINE_TYPE "IQ2000" -#endif - -#ifndef TARGET_VERSION_INTERNAL -#define TARGET_VERSION_INTERNAL(STREAM) \ - fprintf (STREAM, " %s %s", IQ2000_VERSION, MACHINE_TYPE) -#endif - -#ifndef TARGET_VERSION -#define TARGET_VERSION TARGET_VERSION_INTERNAL (stderr) -#endif - -#define OVERRIDE_OPTIONS override_options () - -#define CAN_DEBUG_WITHOUT_FP - -/* Storage Layout. */ - -#define BITS_BIG_ENDIAN 0 -#define BYTES_BIG_ENDIAN 1 -#define WORDS_BIG_ENDIAN 1 -#define LIBGCC2_WORDS_BIG_ENDIAN 1 -#define BITS_PER_WORD 32 -#define MAX_BITS_PER_WORD 64 -#define UNITS_PER_WORD 4 -#define MIN_UNITS_PER_WORD 4 -#define POINTER_SIZE 32 - -/* Define this macro if it is advisable to hold scalars in registers - in a wider mode than that declared by the program. In such cases, - the value is constrained to be within the bounds of the declared - type, but kept valid in the wider mode. The signedness of the - extension may differ from that of the type. - - We promote any value smaller than SImode up to SImode. */ - -#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \ - if (GET_MODE_CLASS (MODE) == MODE_INT \ - && GET_MODE_SIZE (MODE) < 4) \ - (MODE) = SImode; - -#define PARM_BOUNDARY 32 - -#define STACK_BOUNDARY 64 - -#define FUNCTION_BOUNDARY 32 - -#define BIGGEST_ALIGNMENT 64 - -#undef DATA_ALIGNMENT -#define DATA_ALIGNMENT(TYPE, ALIGN) \ - ((((ALIGN) < BITS_PER_WORD) \ - && (TREE_CODE (TYPE) == ARRAY_TYPE \ - || TREE_CODE (TYPE) == UNION_TYPE \ - || TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN)) - -#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ - ((TREE_CODE (EXP) == STRING_CST || TREE_CODE (EXP) == CONSTRUCTOR) \ - && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) - -#define EMPTY_FIELD_BOUNDARY 32 - -#define STRUCTURE_SIZE_BOUNDARY 8 - -#define STRICT_ALIGNMENT 1 - -#define PCC_BITFIELD_TYPE_MATTERS 1 - - -/* Layout of Source Language Data Types. */ - -#define INT_TYPE_SIZE 32 -#define SHORT_TYPE_SIZE 16 -#define LONG_TYPE_SIZE 32 -#define LONG_LONG_TYPE_SIZE 64 -#define CHAR_TYPE_SIZE BITS_PER_UNIT -#define FLOAT_TYPE_SIZE 32 -#define DOUBLE_TYPE_SIZE 64 -#define LONG_DOUBLE_TYPE_SIZE 64 -#define DEFAULT_SIGNED_CHAR 1 - - -/* Register Basics. */ - -/* On the IQ2000, we have 32 integer registers. */ -#define FIRST_PSEUDO_REGISTER 33 - -#define FIXED_REGISTERS \ -{ \ - 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1 \ -} - -#define CALL_USED_REGISTERS \ -{ \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1 \ -} - - -/* Order of allocation of registers. */ - -#define REG_ALLOC_ORDER \ -{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, \ - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 \ -} - - -/* How Values Fit in Registers. */ - -#define HARD_REGNO_NREGS(REGNO, MODE) \ - ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -#define HARD_REGNO_MODE_OK(REGNO, MODE) \ - ((REGNO_REG_CLASS (REGNO) == GR_REGS) \ - ? ((REGNO) & 1) == 0 || GET_MODE_SIZE (MODE) <= 4 \ - : ((REGNO) & 1) == 0 || GET_MODE_SIZE (MODE) == 4) - -#define MODES_TIEABLE_P(MODE1, MODE2) \ - ((GET_MODE_CLASS (MODE1) == MODE_FLOAT || \ - GET_MODE_CLASS (MODE1) == MODE_COMPLEX_FLOAT) \ - == (GET_MODE_CLASS (MODE2) == MODE_FLOAT || \ - GET_MODE_CLASS (MODE2) == MODE_COMPLEX_FLOAT)) - -#define AVOID_CCMODE_COPIES - - -/* Register Classes. */ - -enum reg_class -{ - NO_REGS, /* No registers in set. */ - GR_REGS, /* Integer registers. */ - ALL_REGS, /* All registers. */ - LIM_REG_CLASSES /* Max value + 1. */ -}; - -#define GENERAL_REGS GR_REGS - -#define N_REG_CLASSES (int) LIM_REG_CLASSES - -#define IRA_COVER_CLASSES \ -{ \ - GR_REGS, LIM_REG_CLASSES \ -} - -#define REG_CLASS_NAMES \ -{ \ - "NO_REGS", \ - "GR_REGS", \ - "ALL_REGS" \ -} - -#define REG_CLASS_CONTENTS \ -{ \ - { 0x00000000, 0x00000000 }, /* No registers, */ \ - { 0xffffffff, 0x00000000 }, /* Integer registers. */ \ - { 0xffffffff, 0x00000001 } /* All registers. */ \ -} - -#define REGNO_REG_CLASS(REGNO) \ -((REGNO) <= GP_REG_LAST + 1 ? GR_REGS : NO_REGS) - -#define BASE_REG_CLASS (GR_REGS) - -#define INDEX_REG_CLASS NO_REGS - -#define REG_CLASS_FROM_LETTER(C) \ - ((C) == 'd' ? GR_REGS : \ - (C) == 'b' ? ALL_REGS : \ - (C) == 'y' ? GR_REGS : \ - NO_REGS) - -#define REGNO_OK_FOR_INDEX_P(regno) 0 - -#define PREFERRED_RELOAD_CLASS(X,CLASS) \ - ((CLASS) != ALL_REGS \ - ? (CLASS) \ - : ((GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ - || GET_MODE_CLASS (GET_MODE (X)) == MODE_COMPLEX_FLOAT) \ - ? (GR_REGS) \ - : ((GET_MODE_CLASS (GET_MODE (X)) == MODE_INT \ - || GET_MODE (X) == VOIDmode) \ - ? (GR_REGS) \ - : (CLASS)))) - -#define SMALL_REGISTER_CLASSES 0 - -#define CLASS_MAX_NREGS(CLASS, MODE) \ - ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* For IQ2000: - - `I' is used for the range of constants an arithmetic insn can - actually contain (16-bits signed integers). - - `J' is used for the range which is just zero (i.e., $r0). - - `K' is used for the range of constants a logical insn can actually - contain (16-bit zero-extended integers). - - `L' is used for the range of constants that be loaded with lui - (i.e., the bottom 16 bits are zero). - - `M' is used for the range of constants that take two words to load - (i.e., not matched by `I', `K', and `L'). - - `N' is used for constants 0xffffnnnn or 0xnnnnffff - - `O' is a 5-bit zero-extended integer. */ - -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'I' ? ((unsigned HOST_WIDE_INT) ((VALUE) + 0x8000) < 0x10000) \ - : (C) == 'J' ? ((VALUE) == 0) \ - : (C) == 'K' ? ((unsigned HOST_WIDE_INT) (VALUE) < 0x10000) \ - : (C) == 'L' ? (((VALUE) & 0x0000ffff) == 0 \ - && (((VALUE) & ~2147483647) == 0 \ - || ((VALUE) & ~2147483647) == ~2147483647)) \ - : (C) == 'M' ? ((((VALUE) & ~0x0000ffff) != 0) \ - && (((VALUE) & ~0x0000ffff) != ~0x0000ffff) \ - && (((VALUE) & 0x0000ffff) != 0 \ - || (((VALUE) & ~2147483647) != 0 \ - && ((VALUE) & ~2147483647) != ~2147483647))) \ - : (C) == 'N' ? ((((VALUE) & 0xffff) == 0xffff) \ - || (((VALUE) & 0xffff0000) == 0xffff0000)) \ - : (C) == 'O' ? ((unsigned HOST_WIDE_INT) ((VALUE) + 0x20) < 0x40) \ - : 0) - -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'G' \ - && (VALUE) == CONST0_RTX (GET_MODE (VALUE))) - -/* `R' is for memory references which take 1 word for the instruction. */ - -#define EXTRA_CONSTRAINT(OP,CODE) \ - (((CODE) == 'R') ? simple_memory_operand (OP, GET_MODE (OP)) \ - : FALSE) - - -/* Basic Stack Layout. */ - -#define STACK_GROWS_DOWNWARD - -#define FRAME_GROWS_DOWNWARD 0 - -#define STARTING_FRAME_OFFSET \ - (crtl->outgoing_args_size) - -/* Use the default value zero. */ -/* #define STACK_POINTER_OFFSET 0 */ - -#define FIRST_PARM_OFFSET(FNDECL) 0 - -/* The return address for the current frame is in r31 if this is a leaf - function. Otherwise, it is on the stack. It is at a variable offset - from sp/fp/ap, so we define a fake hard register rap which is a - pointer to the return address on the stack. This always gets eliminated - during reload to be either the frame pointer or the stack pointer plus - an offset. */ - -#define RETURN_ADDR_RTX(count, frame) \ - (((count) == 0) \ - ? (leaf_function_p () \ - ? gen_rtx_REG (Pmode, GP_REG_FIRST + 31) \ - : gen_rtx_MEM (Pmode, gen_rtx_REG (Pmode, \ - RETURN_ADDRESS_POINTER_REGNUM))) \ - : (rtx) 0) - -/* Before the prologue, RA lives in r31. */ -#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (VOIDmode, GP_REG_FIRST + 31) - - -/* Register That Address the Stack Frame. */ - -#define STACK_POINTER_REGNUM (GP_REG_FIRST + 29) -#define FRAME_POINTER_REGNUM (GP_REG_FIRST + 1) -#define HARD_FRAME_POINTER_REGNUM (GP_REG_FIRST + 27) -#define ARG_POINTER_REGNUM GP_REG_FIRST -#define RETURN_ADDRESS_POINTER_REGNUM RAP_REG_NUM -#define STATIC_CHAIN_REGNUM (GP_REG_FIRST + 2) - - -/* Eliminating the Frame Pointer and the Arg Pointer. */ - -#define FRAME_POINTER_REQUIRED 0 - -#define ELIMINABLE_REGS \ -{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ - { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - { RETURN_ADDRESS_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ - { RETURN_ADDRESS_POINTER_REGNUM, GP_REG_FIRST + 31}, \ - { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}} - - -/* We can always eliminate to the frame pointer. We can eliminate to the - stack pointer unless a frame pointer is needed. */ - -#define CAN_ELIMINATE(FROM, TO) \ - (((FROM) == RETURN_ADDRESS_POINTER_REGNUM && (! leaf_function_p () \ - || (TO == GP_REG_FIRST + 31 && leaf_function_p))) \ - || ((FROM) != RETURN_ADDRESS_POINTER_REGNUM \ - && ((TO) == HARD_FRAME_POINTER_REGNUM \ - || ((TO) == STACK_POINTER_REGNUM && ! frame_pointer_needed)))) - -#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ - (OFFSET) = iq2000_initial_elimination_offset ((FROM), (TO)) - -/* Passing Function Arguments on the Stack. */ - -/* #define PUSH_ROUNDING(BYTES) 0 */ - -#define ACCUMULATE_OUTGOING_ARGS 1 - -#define REG_PARM_STACK_SPACE(FNDECL) 0 - -#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) 1 - -#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 - - -/* Function Arguments in Registers. */ - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - function_arg (& CUM, MODE, TYPE, NAMED) - -#define MAX_ARGS_IN_REGISTERS 8 - -typedef struct iq2000_args -{ - int gp_reg_found; /* Whether a gp register was found yet. */ - unsigned int arg_number; /* Argument number. */ - unsigned int arg_words; /* # total words the arguments take. */ - unsigned int fp_arg_words; /* # words for FP args (IQ2000_EABI only). */ - int last_arg_fp; /* Nonzero if last arg was FP (EABI only). */ - int fp_code; /* Mode of FP arguments. */ - unsigned int num_adjusts; /* Number of adjustments made. */ - /* Adjustments made to args pass in regs. */ - struct rtx_def * adjust[MAX_ARGS_IN_REGISTERS * 2]; -} CUMULATIVE_ARGS; - -/* Initialize a variable CUM of type CUMULATIVE_ARGS - for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is 0. */ -#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \ - init_cumulative_args (& CUM, FNTYPE, LIBNAME) \ - -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - function_arg_advance (& CUM, MODE, TYPE, NAMED) - -#define FUNCTION_ARG_PADDING(MODE, TYPE) \ - (! BYTES_BIG_ENDIAN \ - ? upward \ - : (((MODE) == BLKmode \ - ? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \ - && int_size_in_bytes (TYPE) < (PARM_BOUNDARY / BITS_PER_UNIT))\ - : (GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY \ - && (GET_MODE_CLASS (MODE) == MODE_INT))) \ - ? downward : upward)) - -#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \ - (((TYPE) != 0) \ - ? ((TYPE_ALIGN(TYPE) <= PARM_BOUNDARY) \ - ? PARM_BOUNDARY \ - : TYPE_ALIGN(TYPE)) \ - : ((GET_MODE_ALIGNMENT(MODE) <= PARM_BOUNDARY) \ - ? PARM_BOUNDARY \ - : GET_MODE_ALIGNMENT(MODE))) - -#define FUNCTION_ARG_REGNO_P(N) \ - (((N) >= GP_ARG_FIRST && (N) <= GP_ARG_LAST)) - - -/* How Scalar Function Values are Returned. */ - -#define FUNCTION_VALUE(VALTYPE, FUNC) iq2000_function_value (VALTYPE, FUNC) - -#define LIBCALL_VALUE(MODE) \ - gen_rtx_REG (((GET_MODE_CLASS (MODE) != MODE_INT \ - || GET_MODE_SIZE (MODE) >= 4) \ - ? (MODE) \ - : SImode), \ - GP_RETURN) - -/* On the IQ2000, R2 and R3 are the only register thus used. */ - -#define FUNCTION_VALUE_REGNO_P(N) ((N) == GP_RETURN) - - -/* How Large Values are Returned. */ - -#define DEFAULT_PCC_STRUCT_RETURN 0 - -/* Function Entry and Exit. */ - -#define EXIT_IGNORE_STACK 1 - - -/* Generating Code for Profiling. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) \ -{ \ - fprintf (FILE, "\t.set\tnoreorder\n"); \ - fprintf (FILE, "\t.set\tnoat\n"); \ - fprintf (FILE, "\tmove\t%s,%s\t\t# save current return address\n", \ - reg_names[GP_REG_FIRST + 1], reg_names[GP_REG_FIRST + 31]); \ - fprintf (FILE, "\tjal\t_mcount\n"); \ - fprintf (FILE, \ - "\t%s\t%s,%s,%d\t\t# _mcount pops 2 words from stack\n", \ - "subu", \ - reg_names[STACK_POINTER_REGNUM], \ - reg_names[STACK_POINTER_REGNUM], \ - Pmode == DImode ? 16 : 8); \ - fprintf (FILE, "\t.set\treorder\n"); \ - fprintf (FILE, "\t.set\tat\n"); \ -} - - -/* Trampolines for Nested Functions. */ - -/* A C statement to output, on the stream FILE, assembler code for a - block of data that contains the constant parts of a trampoline. - This code should not include a label--the label is taken care of - automatically. */ - -#define TRAMPOLINE_TEMPLATE(STREAM) \ -{ \ - fprintf (STREAM, "\t.word\t0x03e00821\t\t# move $1,$31\n"); \ - fprintf (STREAM, "\t.word\t0x04110001\t\t# bgezal $0,.+8\n"); \ - fprintf (STREAM, "\t.word\t0x00000000\t\t# nop\n"); \ - if (Pmode == DImode) \ - { \ - fprintf (STREAM, "\t.word\t0xdfe30014\t\t# ld $3,20($31)\n"); \ - fprintf (STREAM, "\t.word\t0xdfe2001c\t\t# ld $2,28($31)\n"); \ - } \ - else \ - { \ - fprintf (STREAM, "\t.word\t0x8fe30014\t\t# lw $3,20($31)\n"); \ - fprintf (STREAM, "\t.word\t0x8fe20018\t\t# lw $2,24($31)\n"); \ - } \ - fprintf (STREAM, "\t.word\t0x0060c821\t\t# move $25,$3 (abicalls)\n"); \ - fprintf (STREAM, "\t.word\t0x00600008\t\t# jr $3\n"); \ - fprintf (STREAM, "\t.word\t0x0020f821\t\t# move $31,$1\n"); \ - fprintf (STREAM, "\t.word\t0x00000000\t\t# <function address>\n"); \ - fprintf (STREAM, "\t.word\t0x00000000\t\t# <static chain value>\n"); \ -} - -#define TRAMPOLINE_SIZE (40) - -#define TRAMPOLINE_ALIGNMENT 32 - -#define INITIALIZE_TRAMPOLINE(ADDR, FUNC, CHAIN) \ -{ \ - rtx addr = ADDR; \ - emit_move_insn (gen_rtx_MEM (SImode, plus_constant (addr, 32)), FUNC); \ - emit_move_insn (gen_rtx_MEM (SImode, plus_constant (addr, 36)), CHAIN);\ -} - - -/* Addressing Modes. */ - -#define CONSTANT_ADDRESS_P(X) \ - ( (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ - || GET_CODE (X) == CONST_INT || GET_CODE (X) == HIGH \ - || (GET_CODE (X) == CONST))) - -#define MAX_REGS_PER_ADDRESS 1 - -#ifdef REG_OK_STRICT -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ - { \ - if (iq2000_legitimate_address_p (MODE, X, 1)) \ - goto ADDR; \ - } -#else -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ - { \ - if (iq2000_legitimate_address_p (MODE, X, 0)) \ - goto ADDR; \ - } -#endif - -#define REG_OK_FOR_INDEX_P(X) 0 - - -/* For the IQ2000, transform: - - memory(X + <large int>) - into: - Y = <large int> & ~0x7fff; - Z = X + Y - memory (Z + (<large int> & 0x7fff)); -*/ - -#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ -{ \ - rtx xinsn = (X); \ - \ - if (TARGET_DEBUG_B_MODE) \ - { \ - GO_PRINTF ("\n========== LEGITIMIZE_ADDRESS\n"); \ - GO_DEBUG_RTX (xinsn); \ - } \ - \ - if (iq2000_check_split (X, MODE)) \ - { \ - X = gen_rtx_LO_SUM (Pmode, \ - copy_to_mode_reg (Pmode, \ - gen_rtx_HIGH (Pmode, X)), \ - X); \ - goto WIN; \ - } \ - \ - if (GET_CODE (xinsn) == PLUS) \ - { \ - rtx xplus0 = XEXP (xinsn, 0); \ - rtx xplus1 = XEXP (xinsn, 1); \ - enum rtx_code code0 = GET_CODE (xplus0); \ - enum rtx_code code1 = GET_CODE (xplus1); \ - \ - if (code0 != REG && code1 == REG) \ - { \ - xplus0 = XEXP (xinsn, 1); \ - xplus1 = XEXP (xinsn, 0); \ - code0 = GET_CODE (xplus0); \ - code1 = GET_CODE (xplus1); \ - } \ - \ - if (code0 == REG && REG_MODE_OK_FOR_BASE_P (xplus0, MODE) \ - && code1 == CONST_INT && !SMALL_INT (xplus1)) \ - { \ - rtx int_reg = gen_reg_rtx (Pmode); \ - rtx ptr_reg = gen_reg_rtx (Pmode); \ - \ - emit_move_insn (int_reg, \ - GEN_INT (INTVAL (xplus1) & ~ 0x7fff)); \ - \ - emit_insn (gen_rtx_SET (VOIDmode, \ - ptr_reg, \ - gen_rtx_PLUS (Pmode, xplus0, int_reg))); \ - \ - X = plus_constant (ptr_reg, INTVAL (xplus1) & 0x7fff); \ - goto WIN; \ - } \ - } \ - \ - if (TARGET_DEBUG_B_MODE) \ - GO_PRINTF ("LEGITIMIZE_ADDRESS could not fix.\n"); \ -} - -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) {} - -#define LEGITIMATE_CONSTANT_P(X) (1) - - -/* Describing Relative Costs of Operations. */ - -#define REGISTER_MOVE_COST(MODE, FROM, TO) 2 - -#define MEMORY_MOVE_COST(MODE,CLASS,TO_P) \ - (TO_P ? 2 : 16) - -#define BRANCH_COST(speed_p, predictable_p) 2 - -#define SLOW_BYTE_ACCESS 1 - -#define NO_FUNCTION_CSE 1 - -#define ADJUST_COST(INSN,LINK,DEP_INSN,COST) \ - if (REG_NOTE_KIND (LINK) != 0) \ - (COST) = 0; /* Anti or output dependence. */ - - -/* Dividing the output into sections. */ - -#define TEXT_SECTION_ASM_OP "\t.text" /* Instructions. */ - -#define DATA_SECTION_ASM_OP "\t.data" /* Large data. */ - - -/* The Overall Framework of an Assembler File. */ - -#define ASM_COMMENT_START " #" - -#define ASM_APP_ON "#APP\n" - -#define ASM_APP_OFF "#NO_APP\n" - - -/* Output and Generation of Labels. */ - -#undef ASM_GENERATE_INTERNAL_LABEL -#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ - sprintf ((LABEL), "*%s%s%ld", (LOCAL_LABEL_PREFIX), (PREFIX), (long) (NUM)) - -#define GLOBAL_ASM_OP "\t.globl\t" - - -/* Output of Assembler Instructions. */ - -#define REGISTER_NAMES \ -{ \ - "%0", "%1", "%2", "%3", "%4", "%5", "%6", "%7", \ - "%8", "%9", "%10", "%11", "%12", "%13", "%14", "%15", \ - "%16", "%17", "%18", "%19", "%20", "%21", "%22", "%23", \ - "%24", "%25", "%26", "%27", "%28", "%29", "%30", "%31", "%rap" \ -}; - -#define ADDITIONAL_REGISTER_NAMES \ -{ \ - { "%0", 0 + GP_REG_FIRST }, \ - { "%1", 1 + GP_REG_FIRST }, \ - { "%2", 2 + GP_REG_FIRST }, \ - { "%3", 3 + GP_REG_FIRST }, \ - { "%4", 4 + GP_REG_FIRST }, \ - { "%5", 5 + GP_REG_FIRST }, \ - { "%6", 6 + GP_REG_FIRST }, \ - { "%7", 7 + GP_REG_FIRST }, \ - { "%8", 8 + GP_REG_FIRST }, \ - { "%9", 9 + GP_REG_FIRST }, \ - { "%10", 10 + GP_REG_FIRST }, \ - { "%11", 11 + GP_REG_FIRST }, \ - { "%12", 12 + GP_REG_FIRST }, \ - { "%13", 13 + GP_REG_FIRST }, \ - { "%14", 14 + GP_REG_FIRST }, \ - { "%15", 15 + GP_REG_FIRST }, \ - { "%16", 16 + GP_REG_FIRST }, \ - { "%17", 17 + GP_REG_FIRST }, \ - { "%18", 18 + GP_REG_FIRST }, \ - { "%19", 19 + GP_REG_FIRST }, \ - { "%20", 20 + GP_REG_FIRST }, \ - { "%21", 21 + GP_REG_FIRST }, \ - { "%22", 22 + GP_REG_FIRST }, \ - { "%23", 23 + GP_REG_FIRST }, \ - { "%24", 24 + GP_REG_FIRST }, \ - { "%25", 25 + GP_REG_FIRST }, \ - { "%26", 26 + GP_REG_FIRST }, \ - { "%27", 27 + GP_REG_FIRST }, \ - { "%28", 28 + GP_REG_FIRST }, \ - { "%29", 29 + GP_REG_FIRST }, \ - { "%30", 27 + GP_REG_FIRST }, \ - { "%31", 31 + GP_REG_FIRST }, \ - { "%rap", 32 + GP_REG_FIRST }, \ -} - -/* Check if the current insn needs a nop in front of it - because of load delays, and also update the delay slot statistics. */ - -#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \ - final_prescan_insn (INSN, OPVEC, NOPERANDS) - -/* See iq2000.c for the IQ2000 specific codes. */ -#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE) - -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) iq2000_print_operand_punct[CODE] - -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR) - -#define DBR_OUTPUT_SEQEND(STREAM) \ -do \ - { \ - fputs ("\n", STREAM); \ - } \ -while (0) - -#define LOCAL_LABEL_PREFIX "$" - -#define USER_LABEL_PREFIX "" - - -/* Output of dispatch tables. */ - -#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \ - do \ - { \ - fprintf (STREAM, "\t%s\t%sL%d\n", \ - Pmode == DImode ? ".dword" : ".word", \ - LOCAL_LABEL_PREFIX, VALUE); \ - } \ - while (0) - -#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \ - fprintf (STREAM, "\t%s\t%sL%d\n", \ - Pmode == DImode ? ".dword" : ".word", \ - LOCAL_LABEL_PREFIX, \ - VALUE) - - -/* Assembler Commands for Alignment. */ - -#undef ASM_OUTPUT_SKIP -#define ASM_OUTPUT_SKIP(STREAM,SIZE) \ - fprintf (STREAM, "\t.space\t" HOST_WIDE_INT_PRINT_UNSIGNED "\n", \ - (unsigned HOST_WIDE_INT)(SIZE)) - -#define ASM_OUTPUT_ALIGN(STREAM,LOG) \ - if ((LOG) != 0) \ - fprintf (STREAM, "\t.balign %d\n", 1<<(LOG)) - - -/* Macros Affecting all Debug Formats. */ - -#define DEBUGGER_AUTO_OFFSET(X) \ - iq2000_debugger_offset (X, (HOST_WIDE_INT) 0) - -#define DEBUGGER_ARG_OFFSET(OFFSET, X) \ - iq2000_debugger_offset (X, (HOST_WIDE_INT) OFFSET) - -#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG - -#define DWARF2_DEBUGGING_INFO 1 - - -/* Miscellaneous Parameters. */ - -#define CASE_VECTOR_MODE SImode - -#define WORD_REGISTER_OPERATIONS - -#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND - -#define MOVE_MAX 4 - -#define MAX_MOVE_MAX 8 - -#define SHIFT_COUNT_TRUNCATED 1 - -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -#define STORE_FLAG_VALUE 1 - -#define Pmode SImode - -#define FUNCTION_MODE SImode - -/* Standard GCC variables that we reference. */ - -extern char call_used_regs[]; - -/* IQ2000 external variables defined in iq2000.c. */ - -/* Comparison type. */ -enum cmp_type -{ - CMP_SI, /* Compare four byte integers. */ - CMP_DI, /* Compare eight byte integers. */ - CMP_SF, /* Compare single precision floats. */ - CMP_DF, /* Compare double precision floats. */ - CMP_MAX /* Max comparison type. */ -}; - -/* Types of delay slot. */ -enum delay_type -{ - DELAY_NONE, /* No delay slot. */ - DELAY_LOAD, /* Load from memory delay. */ - DELAY_FCMP /* Delay after doing c.<xx>.{d,s}. */ -}; - -/* Which processor to schedule for. */ - -enum processor_type -{ - PROCESSOR_DEFAULT, - PROCESSOR_IQ2000, - PROCESSOR_IQ10 -}; - -/* Recast the cpu class to be the cpu attribute. */ -#define iq2000_cpu_attr ((enum attr_cpu) iq2000_tune) - -#define BITMASK_UPPER16 ((unsigned long) 0xffff << 16) /* 0xffff0000 */ -#define BITMASK_LOWER16 ((unsigned long) 0xffff) /* 0x0000ffff */ - - -#define GENERATE_BRANCHLIKELY (ISA_HAS_BRANCHLIKELY) - -/* Macros to decide whether certain features are available or not, - depending on the instruction set architecture level. */ - -#define BRANCH_LIKELY_P() GENERATE_BRANCHLIKELY - -/* ISA has branch likely instructions. */ -#define ISA_HAS_BRANCHLIKELY (iq2000_isa == 1) - - -#undef ASM_SPEC - - -/* The mapping from gcc register number to DWARF 2 CFA column number. */ -#define DWARF_FRAME_REGNUM(REG) (REG) - -/* The DWARF 2 CFA column which tracks the return address. */ -#define DWARF_FRAME_RETURN_COLUMN (GP_REG_FIRST + 31) - -/* Describe how we implement __builtin_eh_return. */ -#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + GP_ARG_FIRST : INVALID_REGNUM) - -/* The EH_RETURN_STACKADJ_RTX macro returns RTL which describes the - location used to store the amount to adjust the stack. This is - usually a register that is available from end of the function's body - to the end of the epilogue. Thus, this cannot be a register used as a - temporary by the epilogue. - - This must be an integer register. */ -#define EH_RETURN_STACKADJ_REGNO 3 -#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, EH_RETURN_STACKADJ_REGNO) - -/* The EH_RETURN_HANDLER_RTX macro returns RTL which describes the - location used to store the address the processor should jump to - catch exception. This is usually a registers that is available from - end of the function's body to the end of the epilogue. Thus, this - cannot be a register used as a temporary by the epilogue. - - This must be an address register. */ -#define EH_RETURN_HANDLER_REGNO 26 -#define EH_RETURN_HANDLER_RTX \ - gen_rtx_REG (Pmode, EH_RETURN_HANDLER_REGNO) - -/* Offsets recorded in opcodes are a multiple of this alignment factor. */ -#define DWARF_CIE_DATA_ALIGNMENT 4 - -/* For IQ2000, width of a floating point register. */ -#define UNITS_PER_FPREG 4 - -/* Force right-alignment for small varargs in 32 bit little_endian mode */ - -#define PAD_VARARGS_DOWN !BYTES_BIG_ENDIAN - -/* Internal macros to classify a register number as to whether it's a - general purpose register, a floating point register, a - multiply/divide register, or a status register. */ - -#define GP_REG_FIRST 0 -#define GP_REG_LAST 31 -#define GP_REG_NUM (GP_REG_LAST - GP_REG_FIRST + 1) - -#define RAP_REG_NUM 32 -#define AT_REGNUM (GP_REG_FIRST + 1) - -#define GP_REG_P(REGNO) \ - ((unsigned int) ((int) (REGNO) - GP_REG_FIRST) < GP_REG_NUM) - -/* IQ2000 registers used in prologue/epilogue code when the stack frame - is larger than 32K bytes. These registers must come from the - scratch register set, and not used for passing and returning - arguments and any other information used in the calling sequence. */ - -#define IQ2000_TEMP1_REGNUM (GP_REG_FIRST + 12) -#define IQ2000_TEMP2_REGNUM (GP_REG_FIRST + 13) - -/* This macro is used later on in the file. */ -#define GR_REG_CLASS_P(CLASS) \ - ((CLASS) == GR_REGS) - -#define SMALL_INT(X) ((unsigned HOST_WIDE_INT) (INTVAL (X) + 0x8000) < 0x10000) -#define SMALL_INT_UNSIGNED(X) ((unsigned HOST_WIDE_INT) (INTVAL (X)) < 0x10000) - -/* Certain machines have the property that some registers cannot be - copied to some other registers without using memory. Define this - macro on those machines to be a C expression that is nonzero if - objects of mode MODE in registers of CLASS1 can only be copied to - registers of class CLASS2 by storing a register of CLASS1 into - memory and loading that memory location into a register of CLASS2. - - Do not define this macro if its value would always be zero. */ - -/* Return the maximum number of consecutive registers - needed to represent mode MODE in a register of class CLASS. */ - -#define CLASS_UNITS(mode, size) \ - ((GET_MODE_SIZE (mode) + (size) - 1) / (size)) - -/* If defined, gives a class of registers that cannot be used as the - operand of a SUBREG that changes the mode of the object illegally. */ - -#define CLASS_CANNOT_CHANGE_MODE 0 - -/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE. */ - -#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \ - (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)) - -/* Make sure 4 words are always allocated on the stack. */ - -#ifndef STACK_ARGS_ADJUST -#define STACK_ARGS_ADJUST(SIZE) \ - { \ - if (SIZE.constant < 4 * UNITS_PER_WORD) \ - SIZE.constant = 4 * UNITS_PER_WORD; \ - } -#endif - - -/* Symbolic macros for the registers used to return integer and floating - point values. */ - -#define GP_RETURN (GP_REG_FIRST + 2) - -/* Symbolic macros for the first/last argument registers. */ - -#define GP_ARG_FIRST (GP_REG_FIRST + 4) -#define GP_ARG_LAST (GP_REG_FIRST + 11) - -#define MAX_ARGS_IN_REGISTERS 8 - - -/* Tell prologue and epilogue if register REGNO should be saved / restored. */ - -#define MUST_SAVE_REGISTER(regno) \ - ((df_regs_ever_live_p (regno) && !call_used_regs[regno]) \ - || (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) \ - || (regno == (GP_REG_FIRST + 31) && df_regs_ever_live_p (GP_REG_FIRST + 31))) - -/* ALIGN FRAMES on double word boundaries */ -#ifndef IQ2000_STACK_ALIGN -#define IQ2000_STACK_ALIGN(LOC) (((LOC) + 7) & ~7) -#endif - - -/* These assume that REGNO is a hard or pseudo reg number. - They give nonzero only if REGNO is a hard reg of the suitable class - or a pseudo reg currently allocated to a suitable hard reg. - These definitions are NOT overridden anywhere. */ - -#define BASE_REG_P(regno, mode) \ - (GP_REG_P (regno)) - -#define GP_REG_OR_PSEUDO_STRICT_P(regno, mode) \ - BASE_REG_P((regno < FIRST_PSEUDO_REGISTER) ? regno : reg_renumber[regno], \ - (mode)) - -#define GP_REG_OR_PSEUDO_NONSTRICT_P(regno, mode) \ - (((regno) >= FIRST_PSEUDO_REGISTER) || (BASE_REG_P ((regno), (mode)))) - -#define REGNO_MODE_OK_FOR_BASE_P(regno, mode) \ - GP_REG_OR_PSEUDO_STRICT_P ((regno), (mode)) - -/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx - and check its validity for a certain class. - We have two alternate definitions for each of them. - The usual definition accepts all pseudo regs; the other rejects them all. - The symbol REG_OK_STRICT causes the latter definition to be used. - - Most source files want to accept pseudo regs in the hope that - they will get allocated to the class that the insn wants them to be in. - Some source files that are used after register allocation - need to be strict. */ - -#ifndef REG_OK_STRICT -#define REG_MODE_OK_FOR_BASE_P(X, MODE) \ - iq2000_reg_mode_ok_for_base_p (X, MODE, 0) -#else -#define REG_MODE_OK_FOR_BASE_P(X, MODE) \ - iq2000_reg_mode_ok_for_base_p (X, MODE, 1) -#endif - -#if 1 -#define GO_PRINTF(x) fprintf (stderr, (x)) -#define GO_PRINTF2(x,y) fprintf (stderr, (x), (y)) -#define GO_DEBUG_RTX(x) debug_rtx (x) - -#else -#define GO_PRINTF(x) -#define GO_PRINTF2(x,y) -#define GO_DEBUG_RTX(x) -#endif - -/* If defined, modifies the length assigned to instruction INSN as a - function of the context in which it is used. LENGTH is an lvalue - that contains the initially computed length of the insn and should - be updated with the correct length of the insn. */ -#define ADJUST_INSN_LENGTH(INSN, LENGTH) \ - ((LENGTH) = iq2000_adjust_insn_length ((INSN), (LENGTH))) - - - - -/* How to tell the debugger about changes of source files. */ - -#ifndef SET_FILE_NUMBER -#define SET_FILE_NUMBER() ++ num_source_filenames -#endif - -/* This is how to output a note the debugger telling it the line number - to which the following sequence of instructions corresponds. */ - -#ifndef LABEL_AFTER_LOC -#define LABEL_AFTER_LOC(STREAM) -#endif - - -/* Default to -G 8 */ -#ifndef IQ2000_DEFAULT_GVALUE -#define IQ2000_DEFAULT_GVALUE 8 -#endif - -#define SDATA_SECTION_ASM_OP "\t.sdata" /* Small data. */ - - -/* List of all IQ2000 punctuation characters used by print_operand. */ -extern char iq2000_print_operand_punct[256]; - -/* The target cpu for optimization and scheduling. */ -extern enum processor_type iq2000_tune; - -/* Which instruction set architecture to use. */ -extern int iq2000_isa; - -/* Cached operands, and operator to compare for use in set/branch/trap - on condition codes. */ -extern rtx branch_cmp[2]; - -/* What type of branch to use. */ -extern enum cmp_type branch_type; - -enum iq2000_builtins -{ - IQ2000_BUILTIN_ADO16, - IQ2000_BUILTIN_CFC0, - IQ2000_BUILTIN_CFC1, - IQ2000_BUILTIN_CFC2, - IQ2000_BUILTIN_CFC3, - IQ2000_BUILTIN_CHKHDR, - IQ2000_BUILTIN_CTC0, - IQ2000_BUILTIN_CTC1, - IQ2000_BUILTIN_CTC2, - IQ2000_BUILTIN_CTC3, - IQ2000_BUILTIN_LU, - IQ2000_BUILTIN_LUC32L, - IQ2000_BUILTIN_LUC64, - IQ2000_BUILTIN_LUC64L, - IQ2000_BUILTIN_LUK, - IQ2000_BUILTIN_LULCK, - IQ2000_BUILTIN_LUM32, - IQ2000_BUILTIN_LUM32L, - IQ2000_BUILTIN_LUM64, - IQ2000_BUILTIN_LUM64L, - IQ2000_BUILTIN_LUR, - IQ2000_BUILTIN_LURL, - IQ2000_BUILTIN_MFC0, - IQ2000_BUILTIN_MFC1, - IQ2000_BUILTIN_MFC2, - IQ2000_BUILTIN_MFC3, - IQ2000_BUILTIN_MRGB, - IQ2000_BUILTIN_MTC0, - IQ2000_BUILTIN_MTC1, - IQ2000_BUILTIN_MTC2, - IQ2000_BUILTIN_MTC3, - IQ2000_BUILTIN_PKRL, - IQ2000_BUILTIN_RAM, - IQ2000_BUILTIN_RB, - IQ2000_BUILTIN_RX, - IQ2000_BUILTIN_SRRD, - IQ2000_BUILTIN_SRRDL, - IQ2000_BUILTIN_SRULC, - IQ2000_BUILTIN_SRULCK, - IQ2000_BUILTIN_SRWR, - IQ2000_BUILTIN_SRWRU, - IQ2000_BUILTIN_TRAPQF, - IQ2000_BUILTIN_TRAPQFL, - IQ2000_BUILTIN_TRAPQN, - IQ2000_BUILTIN_TRAPQNE, - IQ2000_BUILTIN_TRAPRE, - IQ2000_BUILTIN_TRAPREL, - IQ2000_BUILTIN_WB, - IQ2000_BUILTIN_WBR, - IQ2000_BUILTIN_WBU, - IQ2000_BUILTIN_WX, - IQ2000_BUILTIN_SYSCALL -}; diff --git a/gcc-4.4.3/gcc/config/iq2000/iq2000.md b/gcc-4.4.3/gcc/config/iq2000/iq2000.md deleted file mode 100644 index 225147cfc..000000000 --- a/gcc-4.4.3/gcc/config/iq2000/iq2000.md +++ /dev/null @@ -1,2550 +0,0 @@ -;; iq2000.md Machine Description for Vitesse IQ2000 processors -;; Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc. - -;; This file is part of GCC. - -;; 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 3, or (at your option) -;; any later version. - -;; 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 GCC; see the file COPYING3. If not see -;; <http://www.gnu.org/licenses/>. - -(define_constants - [(UNSPEC_ADO16 0) - (UNSPEC_RAM 1) - (UNSPEC_CHKHDR 2) - (UNSPEC_PKRL 3) - (UNSPEC_CFC0 4) - (UNSPEC_CFC1 5) - (UNSPEC_CFC2 6) - (UNSPEC_CFC3 7) - (UNSPEC_CTC0 8) - (UNSPEC_CTC1 9) - (UNSPEC_CTC2 10) - (UNSPEC_CTC3 11) - (UNSPEC_MFC0 12) - (UNSPEC_MFC1 13) - (UNSPEC_MFC2 14) - (UNSPEC_MFC3 15) - (UNSPEC_MTC0 16) - (UNSPEC_MTC1 17) - (UNSPEC_MTC2 18) - (UNSPEC_MTC3 19) - (UNSPEC_LUR 20) - (UNSPEC_RB 21) - (UNSPEC_RX 22) - (UNSPEC_SRRD 23) - (UNSPEC_SRWR 24) - (UNSPEC_WB 25) - (UNSPEC_WX 26) - (UNSPEC_LUC32 49) - (UNSPEC_LUC32L 27) - (UNSPEC_LUC64 28) - (UNSPEC_LUC64L 29) - (UNSPEC_LUK 30) - (UNSPEC_LULCK 31) - (UNSPEC_LUM32 32) - (UNSPEC_LUM32L 33) - (UNSPEC_LUM64 34) - (UNSPEC_LUM64L 35) - (UNSPEC_LURL 36) - (UNSPEC_MRGB 37) - (UNSPEC_SRRDL 38) - (UNSPEC_SRULCK 39) - (UNSPEC_SRWRU 40) - (UNSPEC_TRAPQFL 41) - (UNSPEC_TRAPQNE 42) - (UNSPEC_TRAPREL 43) - (UNSPEC_WBU 44) - (UNSPEC_SYSCALL 45)] -) -;; UNSPEC values used in iq2000.md -;; Number USE -;; 0 movsi_ul -;; 1 movsi_us, get_fnaddr -;; 3 eh_set_return -;; 20 builtin_setjmp_setup -;; -;; UNSPEC_VOLATILE values -;; 0 blockage -;; 2 loadgp -;; 3 builtin_longjmp -;; 4 exception_receiver -;; 10 consttable_qi -;; 11 consttable_hi -;; 12 consttable_si -;; 13 consttable_di -;; 14 consttable_sf -;; 15 consttable_df -;; 16 align_2 -;; 17 align_4 -;; 18 align_8 - - -;; .................... -;; -;; Attributes -;; -;; .................... - -;; Classification of each insn. -;; branch conditional branch -;; jump unconditional jump -;; call unconditional call -;; load load instruction(s) -;; store store instruction(s) -;; move data movement within same register set -;; xfer transfer to/from coprocessor -;; arith integer arithmetic instruction -;; darith double precision integer arithmetic instructions -;; imul integer multiply -;; idiv integer divide -;; icmp integer compare -;; fadd floating point add/subtract -;; fmul floating point multiply -;; fmadd floating point multiply-add -;; fdiv floating point divide -;; fabs floating point absolute value -;; fneg floating point negation -;; fcmp floating point compare -;; fcvt floating point convert -;; fsqrt floating point square root -;; multi multiword sequence (or user asm statements) -;; nop no operation - -(define_attr "type" - "unknown,branch,jump,call,load,store,move,xfer,arith,darith,imul,idiv,icmp,fadd,fmul,fmadd,fdiv,fabs,fneg,fcmp,fcvt,fsqrt,multi,nop" - (const_string "unknown")) - -;; Main data type used by the insn -(define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF,FPSW" (const_string "unknown")) - -;; Length (in # of bytes). A conditional branch is allowed only to a -;; location within a signed 18-bit offset of the delay slot. If that -;; provides too small a range, we use the `j' instruction. This -;; instruction takes a 28-bit value, but that value is not an offset. -;; Instead, it's bitwise-ored with the high-order four bits of the -;; instruction in the delay slot, which means it cannot be used to -;; cross a 256MB boundary. We could fall back back on the jr, -;; instruction which allows full access to the entire address space, -;; but we do not do so at present. - -(define_attr "length" "" - (cond [(eq_attr "type" "branch") - (cond [(lt (abs (minus (match_dup 1) (plus (pc) (const_int 4)))) - (const_int 131072)) - (const_int 4)] - (const_int 12))] - (const_int 4))) - -(define_attr "cpu" - "default,iq2000" - (const (symbol_ref "iq2000_cpu_attr"))) - -;; Does the instruction have a mandatory delay slot? has_dslot -;; Can the instruction be in a delay slot? ok_in_dslot -;; Can the instruction not be in a delay slot? not_in_dslot -(define_attr "dslot" "has_dslot,ok_in_dslot,not_in_dslot" - (if_then_else (eq_attr "type" "branch,jump,call,xfer,fcmp") - (const_string "has_dslot") - (const_string "ok_in_dslot"))) - -;; Attribute defining whether or not we can use the branch-likely instructions - -(define_attr "branch_likely" "no,yes" - (const - (if_then_else (ne (symbol_ref "GENERATE_BRANCHLIKELY") (const_int 0)) - (const_string "yes") - (const_string "no")))) - - -;; Describe a user's asm statement. -(define_asm_attributes - [(set_attr "type" "multi")]) - - - -;; ......................... -;; -;; Delay slots, can't describe load/fcmp/xfer delay slots here -;; -;; ......................... - -(define_delay (eq_attr "type" "jump") - [(and (eq_attr "dslot" "ok_in_dslot") (eq_attr "length" "4")) - (nil) - (nil)]) - -(define_delay (eq_attr "type" "branch") - [(and (eq_attr "dslot" "ok_in_dslot") (eq_attr "length" "4")) - (nil) - (and (eq_attr "branch_likely" "yes") (and (eq_attr "dslot" "ok_in_dslot") (eq_attr "length" "4")))]) - -(define_delay (eq_attr "type" "call") - [(and (eq_attr "dslot" "ok_in_dslot") (eq_attr "length" "4")) - (nil) - (nil)]) - -(include "predicates.md") - - -;; ......................... -;; -;; Pipeline model -;; -;; ......................... - -(define_automaton "iq2000") -(define_cpu_unit "core,memory" "iq2000") - -(define_insn_reservation "nonmemory" 1 - (eq_attr "type" "!load,move,store,xfer") - "core") - -(define_insn_reservation "iq2000_load_move" 3 - (and (eq_attr "type" "load,move") - (eq_attr "cpu" "iq2000")) - "memory") - -(define_insn_reservation "other_load_move" 1 - (and (eq_attr "type" "load,move") - (eq_attr "cpu" "!iq2000")) - "memory") - -(define_insn_reservation "store" 1 - (eq_attr "type" "store") - "memory") - -(define_insn_reservation "xfer" 2 - (eq_attr "type" "xfer") - "memory") - -;; -;; .................... -;; -;; CONDITIONAL TRAPS -;; -;; .................... -;; - -(define_insn "trap" - [(trap_if (const_int 1) (const_int 0))] - "" - "* -{ - return \"break\"; -}") - -;; -;; .................... -;; -;; ADDITION -;; -;; .................... -;; - -(define_expand "addsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (plus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "") - -(define_insn "addsi3_internal" - [(set (match_operand:SI 0 "register_operand" "=d,=d") - (plus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ,dJ") - (match_operand:SI 2 "arith_operand" "d,I")))] - "" - "@ - addu\\t%0,%z1,%2 - addiu\\t%0,%z1,%2" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -;; -;; .................... -;; -;; SUBTRACTION -;; -;; .................... -;; - -(define_expand "subsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (minus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "") - -(define_insn "subsi3_internal" - [(set (match_operand:SI 0 "register_operand" "=d,=d") - (minus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ,dJ") - (match_operand:SI 2 "arith_operand" "d,I")))] - "" - "@ - subu\\t%0,%z1,%2 - addiu\\t%0,%z1,%n2" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -;; -;; .................... -;; -;; NEGATION and ONE'S COMPLEMENT -;; -;; .................... - -(define_insn "negsi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (neg:SI (match_operand:SI 1 "register_operand" "d")))] - "" - "* -{ - operands[2] = const0_rtx; - return \"subu\\t%0,%z2,%1\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (not:SI (match_operand:SI 1 "register_operand" "d")))] - "" - "* -{ - operands[2] = const0_rtx; - return \"nor\\t%0,%z2,%1\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -;; -;; .................... -;; -;; LOGICAL -;; -;; .................... -;; - -(define_expand "andsi3" - [(set (match_operand:SI 0 "register_operand" "=d,d,d") - (and:SI (match_operand:SI 1 "uns_arith_operand" "%d,d,d") - (match_operand:SI 2 "nonmemory_operand" "d,K,N")))] - "" - "") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,d,d") - (and:SI (match_operand:SI 1 "uns_arith_operand" "%d,d,d") - (match_operand:SI 2 "nonmemory_operand" "d,K,N")))] - "" - "* -{ - if (which_alternative == 0) - return \"and\\t%0,%1,%2\"; - else if (which_alternative == 1) - return \"andi\\t%0,%1,%x2\"; - else if (which_alternative == 2) - { - if ((INTVAL (operands[2]) & 0xffff) == 0xffff) - { - operands[2] = GEN_INT (INTVAL (operands[2]) >> 16); - return \"andoui\\t%0,%1,%x2\"; - } - else - { - operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff); - return \"andoi\\t%0,%1,%x2\"; - } - } -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -(define_expand "iorsi3" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (ior:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") - (match_operand:SI 2 "uns_arith_operand" "d,K")))] - "" - "") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (ior:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") - (match_operand:SI 2 "uns_arith_operand" "d,K")))] - "" - "@ - or\\t%0,%1,%2 - ori\\t%0,%1,%x2" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -(define_expand "xorsi3" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (xor:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") - (match_operand:SI 2 "uns_arith_operand" "d,K")))] - "" - "") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (xor:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") - (match_operand:SI 2 "uns_arith_operand" "d,K")))] - "" - "@ - xor\\t%0,%1,%2 - xori\\t%0,%1,%x2" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -(define_insn "*norsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (and:SI (not:SI (match_operand:SI 1 "register_operand" "d")) - (not:SI (match_operand:SI 2 "register_operand" "d"))))] - "" - "nor\\t%0,%z1,%z2" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -;; -;; .................... -;; -;; ZERO EXTENSION -;; -;; .................... - -;; Extension insns. -;; Those for integer source operand are ordered widest source type first. - -(define_expand "zero_extendhisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] - "" - "") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,d,d") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,R,m")))] - "" - "* -{ - if (which_alternative == 0) - return \"andi\\t%0,%1,0xffff\"; - else - return iq2000_move_1word (operands, insn, TRUE); -}" - [(set_attr "type" "arith,load,load") - (set_attr "mode" "SI") - (set_attr "length" "4,4,8")]) - -(define_expand "zero_extendqihi2" - [(set (match_operand:HI 0 "register_operand" "") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] - "" - "") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=d,d,d") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))] - "" - "* -{ - if (which_alternative == 0) - return \"andi\\t%0,%1,0x00ff\"; - else - return iq2000_move_1word (operands, insn, TRUE); -}" - [(set_attr "type" "arith,load,load") - (set_attr "mode" "HI") - (set_attr "length" "4,4,8")]) - -(define_expand "zero_extendqisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] - "" - "") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,d,d") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))] - "" - "* -{ - if (which_alternative == 0) - return \"andi\\t%0,%1,0x00ff\"; - else - return iq2000_move_1word (operands, insn, TRUE); -}" - [(set_attr "type" "arith,load,load") - (set_attr "mode" "SI") - (set_attr "length" "4,4,8")]) - -;; -;; .................... -;; -;; SIGN EXTENSION -;; -;; .................... - -;; Extension insns. -;; Those for integer source operand are ordered widest source type first. - -;; These patterns originally accepted general_operands, however, slightly -;; better code is generated by only accepting register_operands, and then -;; letting combine generate the lh and lb insns. - -(define_expand "extendhisi2" - [(set (match_operand:SI 0 "register_operand" "") - (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (optimize && GET_CODE (operands[1]) == MEM) - operands[1] = force_not_mem (operands[1]); - - if (GET_CODE (operands[1]) != MEM) - { - rtx op1 = gen_lowpart (SImode, operands[1]); - rtx temp = gen_reg_rtx (SImode); - rtx shift = GEN_INT (16); - - emit_insn (gen_ashlsi3 (temp, op1, shift)); - emit_insn (gen_ashrsi3 (operands[0], temp, shift)); - DONE; - } -}") - -(define_insn "extendhisi2_internal" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (sign_extend:SI (match_operand:HI 1 "memory_operand" "R,m")))] - "" - "* return iq2000_move_1word (operands, insn, FALSE);" - [(set_attr "type" "load") - (set_attr "mode" "SI") - (set_attr "length" "4,8")]) - -(define_expand "extendqihi2" - [(set (match_operand:HI 0 "register_operand" "") - (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (optimize && GET_CODE (operands[1]) == MEM) - operands[1] = force_not_mem (operands[1]); - - if (GET_CODE (operands[1]) != MEM) - { - rtx op0 = gen_lowpart (SImode, operands[0]); - rtx op1 = gen_lowpart (SImode, operands[1]); - rtx temp = gen_reg_rtx (SImode); - rtx shift = GEN_INT (24); - - emit_insn (gen_ashlsi3 (temp, op1, shift)); - emit_insn (gen_ashrsi3 (op0, temp, shift)); - DONE; - } -}") - -(define_insn "extendqihi2_internal" - [(set (match_operand:HI 0 "register_operand" "=d,d") - (sign_extend:HI (match_operand:QI 1 "memory_operand" "R,m")))] - "" - "* return iq2000_move_1word (operands, insn, FALSE);" - [(set_attr "type" "load") - (set_attr "mode" "SI") - (set_attr "length" "4,8")]) - - -(define_expand "extendqisi2" - [(set (match_operand:SI 0 "register_operand" "") - (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (optimize && GET_CODE (operands[1]) == MEM) - operands[1] = force_not_mem (operands[1]); - - if (GET_CODE (operands[1]) != MEM) - { - rtx op1 = gen_lowpart (SImode, operands[1]); - rtx temp = gen_reg_rtx (SImode); - rtx shift = GEN_INT (24); - - emit_insn (gen_ashlsi3 (temp, op1, shift)); - emit_insn (gen_ashrsi3 (operands[0], temp, shift)); - DONE; - } -}") - -(define_insn "extendqisi2_insn" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (sign_extend:SI (match_operand:QI 1 "memory_operand" "R,m")))] - "" - "* return iq2000_move_1word (operands, insn, FALSE);" - [(set_attr "type" "load") - (set_attr "mode" "SI") - (set_attr "length" "4,8")]) - -;; -;; ........................ -;; -;; BIT FIELD EXTRACTION -;; -;; ........................ - -(define_insn "extzv" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extract:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "const_int_operand" "O") - (match_operand:SI 3 "const_int_operand" "O")))] - "" - "* -{ - int value[4]; - value[2] = INTVAL (operands[2]); - value[3] = INTVAL (operands[3]); - operands[2] = GEN_INT ((value[3])); - operands[3] = GEN_INT ((32 - value[2])); - return \"ram\\t%0,%1,%2,%3,0x0\"; -}" - [(set_attr "type" "arith")]) - -;; -;; .................... -;; -;; DATA MOVEMENT -;; -;; .................... - -/* Take care of constants that don't fit in single instruction */ -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "(reload_in_progress || reload_completed) - && large_int (operands[1], SImode)" - - [(set (match_dup 0 ) - (high:SI (match_dup 1))) - (set (match_dup 0 ) - (lo_sum:SI (match_dup 0) - (match_dup 1)))] -) - -;; ??? iq2000_move_1word has support for HIGH, so this pattern may be -;; unnecessary. - -(define_insn "high" - [(set (match_operand:SI 0 "register_operand" "=r") - (high:SI (match_operand:SI 1 "immediate_operand" "")))] - "" - "lui\\t%0,%%hi(%1) # high" - [(set_attr "type" "move")]) - -(define_insn "low" - [(set (match_operand:SI 0 "register_operand" "=r") - (lo_sum:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "immediate_operand" "")))] - "" - "addiu\\t%0,%1,%%lo(%2) # low" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -;; 32-bit Integer moves - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "large_int" ""))] - "reload_in_progress | reload_completed" - [(set (match_dup 0) - (match_dup 2)) - (set (match_dup 0) - (ior:SI (match_dup 0) - (match_dup 3)))] - " -{ - operands[2] = GEN_INT (trunc_int_for_mode (INTVAL (operands[1]) - & BITMASK_UPPER16, - SImode)); - operands[3] = GEN_INT (INTVAL (operands[1]) & BITMASK_LOWER16); -}") - -;; Unlike most other insns, the move insns can't be split with -;; different predicates, because register spilling and other parts of -;; the compiler, have memoized the insn number already. - -(define_expand "movsi" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "" - " -{ - if (iq2000_check_split (operands[1], SImode)) - { - enum machine_mode mode = GET_MODE (operands[0]); - rtx tem = ((reload_in_progress | reload_completed) - ? operands[0] : gen_reg_rtx (mode)); - - emit_insn (gen_rtx_SET (VOIDmode, tem, - gen_rtx_HIGH (mode, operands[1]))); - - operands[1] = gen_rtx_LO_SUM (mode, tem, operands[1]); - } - - if ((reload_in_progress | reload_completed) == 0 - && !register_operand (operands[0], SImode) - && !register_operand (operands[1], SImode) - && (GET_CODE (operands[1]) != CONST_INT - || INTVAL (operands[1]) != 0)) - { - rtx temp = force_reg (SImode, operands[1]); - emit_move_insn (operands[0], temp); - DONE; - } - - /* Take care of constants that don't fit in single instruction */ - if ((reload_in_progress || reload_completed) - && CONSTANT_P (operands[1]) - && GET_CODE (operands[1]) != HIGH - && GET_CODE (operands[1]) != LO_SUM - && ! SMALL_INT_UNSIGNED (operands[1])) - { - rtx tem = ((reload_in_progress | reload_completed) - ? operands[0] : gen_reg_rtx (SImode)); - - emit_insn (gen_rtx_SET (VOIDmode, tem, - gen_rtx_HIGH (SImode, operands[1]))); - operands[1] = gen_rtx_LO_SUM (SImode, tem, operands[1]); - } -}") - -;; The difference between these two is whether or not ints are allowed -;; in FP registers (off by default, use -mdebugh to enable). - -(define_insn "movsi_internal2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*z,*x,*d,*x,*d") - (match_operand:SI 1 "move_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*z,*d,J,*x,*d,*a"))] - "(register_operand (operands[0], SImode) - || register_operand (operands[1], SImode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" - "* return iq2000_move_1word (operands, insn, FALSE);" - [(set_attr "type" "move,load,arith,arith,load,load,store,store,xfer,xfer,move,move,move,move") - (set_attr "mode" "SI") - (set_attr "length" "4,8,4,8,4,8,4,8,4,4,4,4,4,4")]) - -;; 16-bit Integer moves - -;; Unlike most other insns, the move insns can't be split with -;; different predicates, because register spilling and other parts of -;; the compiler, have memoized the insn number already. -;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined - -(define_expand "movhi" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ - if ((reload_in_progress | reload_completed) == 0 - && !register_operand (operands[0], HImode) - && !register_operand (operands[1], HImode) - && ((GET_CODE (operands[1]) != CONST_INT - || INTVAL (operands[1]) != 0))) - { - rtx temp = force_reg (HImode, operands[1]); - emit_move_insn (operands[0], temp); - DONE; - } -}") - -;; The difference between these two is whether or not ints are allowed -;; in FP registers (off by default, use -mdebugh to enable). - -(define_insn "movhi_internal2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*z,*x,*d") - (match_operand:HI 1 "general_operand" "d,IK,R,m,dJ,dJ,*z,*d,*d,*x"))] - "(register_operand (operands[0], HImode) - || register_operand (operands[1], HImode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" - "* return iq2000_move_1word (operands, insn, TRUE);" - [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,move,move") - (set_attr "mode" "HI") - (set_attr "length" "4,4,4,8,4,8,4,4,4,4")]) - -;; 8-bit Integer moves - -;; Unlike most other insns, the move insns can't be split with -;; different predicates, because register spilling and other parts of -;; the compiler, have memoized the insn number already. -;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined - -(define_expand "movqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ - if ((reload_in_progress | reload_completed) == 0 - && !register_operand (operands[0], QImode) - && !register_operand (operands[1], QImode) - && (GET_CODE (operands[1]) != CONST_INT - || INTVAL (operands[1]) != 0)) - { - rtx temp = force_reg (QImode, operands[1]); - emit_move_insn (operands[0], temp); - DONE; - } -}") - -;; The difference between these two is whether or not ints are allowed -;; in FP registers (off by default, use -mdebugh to enable). - -(define_insn "movqi_internal2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*z,*x,*d") - (match_operand:QI 1 "general_operand" "d,IK,R,m,dJ,dJ,*z,*d,*d,*x"))] - "(register_operand (operands[0], QImode) - || register_operand (operands[1], QImode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" - "* return iq2000_move_1word (operands, insn, TRUE);" - [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,move,move") - (set_attr "mode" "QI") - (set_attr "length" "4,4,4,8,4,8,4,4,4,4")]) - -;; 32-bit floating point moves - -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress - && !reload_completed - && GET_CODE (operands[0]) == MEM - && (GET_CODE (operands[1]) == MEM - || GET_CODE (operands[1]) == CONST_DOUBLE)) - operands[1] = copy_to_mode_reg (SFmode, operands[1]); - - /* Take care of reg <- SF constant */ - if ( const_double_operand (operands[1], GET_MODE (operands[1]) ) ) - { - emit_insn (gen_movsf_high (operands[0], operands[1])); - emit_insn (gen_movsf_lo_sum (operands[0], operands[0], operands[1])); - DONE; - } -}") - -(define_insn "movsf_lo_sum" - [(set (match_operand:SF 0 "register_operand" "=r") - (lo_sum:SF (match_operand:SF 1 "register_operand" "r") - (match_operand:SF 2 "const_double_operand" "")))] - "" - "* -{ - REAL_VALUE_TYPE r; - long i; - - REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]); - REAL_VALUE_TO_TARGET_SINGLE (r, i); - operands[2] = GEN_INT (i); - return \"addiu\\t%0,%1,%%lo(%2) # low\"; -}" - [(set_attr "length" "4") - (set_attr "type" "arith")]) - -(define_insn "movsf_high" - [(set (match_operand:SF 0 "register_operand" "=r") - (high:SF (match_operand:SF 1 "const_double_operand" "")))] - "" - "* -{ - REAL_VALUE_TYPE r; - long i; - - REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]); - REAL_VALUE_TO_TARGET_SINGLE (r, i); - operands[1] = GEN_INT (i); - return \"lui\\t%0,%%hi(%1) # high\"; -}" - [(set_attr "length" "4") - (set_attr "type" "arith")]) - -(define_insn "*movsf_internal" - [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m") - (match_operand:SF 1 "nonimmediate_operand" "r,m,r"))] - "!memory_operand (operands[0], SFmode) || !memory_operand (operands[1], SFmode)" - "* -{ - iq2000_fill_delay_slot (\"\", DELAY_LOAD, operands, insn); - if (which_alternative == 0) - return \"or\\t%0,%1,%1\"; - else if (which_alternative == 1) - return \"lw\\t%0,%1\"; - else if (which_alternative == 2) - return \"sw\\t%1,%0\"; -}" - [(set_attr "length" "4,4,4") - (set_attr "type" "arith,load,store")] -) - -;; -;; .................... -;; -;; SHIFTS -;; -;; .................... - -(define_expand "ashlsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (ashift:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "") - -(define_insn "ashlsi3_internal1" - [(set (match_operand:SI 0 "register_operand" "=d") - (ashift:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); - return \"sll\\t%0,%1,%2\"; - } - else - return \"sllv\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -(define_expand "ashrsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "") - -(define_insn "ashrsi3_internal1" - [(set (match_operand:SI 0 "register_operand" "=d") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); - return \"sra\\t%0,%1,%2\"; - } - else - return \"srav\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -(define_expand "lshrsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "") - -(define_insn "lshrsi3_internal1" - [(set (match_operand:SI 0 "register_operand" "=d") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); - return \"srl\\t%0,%1,%2\"; - } - else - return \"srlv\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -;; Rotate Right -(define_insn "rotrsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (rotatert:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "uns_arith_operand" "O")))] - "" - "ram %0,%1,%2,0x0,0x0" - [(set_attr "type" "arith")]) - - -;; -;; .................... -;; -;; COMPARISONS -;; -;; .................... - -;; Flow here is rather complex: -;; -;; 1) The cmp{si,di,sf,df} routine is called. It deposits the -;; arguments into the branch_cmp array, and the type into -;; branch_type. No RTL is generated. -;; -;; 2) The appropriate branch define_expand is called, which then -;; creates the appropriate RTL for the comparison and branch. -;; Different CC modes are used, based on what type of branch is -;; done, so that we can constrain things appropriately. There -;; are assumptions in the rest of GCC that break if we fold the -;; operands into the branches for integer operations, and use cc0 -;; for floating point, so we use the fp status register instead. -;; If needed, an appropriate temporary is created to hold the -;; of the integer compare. - -(define_expand "cmpsi" - [(set (cc0) - (compare:CC (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "arith_operand" "")))] - "" - " -{ - if (operands[0]) /* avoid unused code message */ - { - branch_cmp[0] = operands[0]; - branch_cmp[1] = operands[1]; - branch_type = CMP_SI; - DONE; - } -}") - -(define_expand "tstsi" - [(set (cc0) - (match_operand:SI 0 "register_operand" ""))] - "" - " -{ - if (operands[0]) /* avoid unused code message */ - { - branch_cmp[0] = operands[0]; - branch_cmp[1] = const0_rtx; - branch_type = CMP_SI; - DONE; - } -}") - -;; -;; .................... -;; -;; CONDITIONAL BRANCHES -;; -;; .................... - -;; Conditional branches on comparisons with zero. - -(define_insn "branch_zero" - [(set (pc) - (if_then_else - (match_operator:SI 0 "cmp_op" - [(match_operand:SI 2 "register_operand" "d") - (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] - "" - "* -{ - return iq2000_output_conditional_branch (insn, - operands, - /*two_operands_p=*/0, - /*float_p=*/0, - /*inverted_p=*/0, - get_attr_length (insn)); -}" - [(set_attr "type" "branch") - (set_attr "mode" "none")]) - -(define_insn "branch_zero_inverted" - [(set (pc) - (if_then_else - (match_operator:SI 0 "cmp_op" - [(match_operand:SI 2 "register_operand" "d") - (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] - "" - "* -{ - return iq2000_output_conditional_branch (insn, - operands, - /*two_operands_p=*/0, - /*float_p=*/0, - /*inverted_p=*/1, - get_attr_length (insn)); -}" - [(set_attr "type" "branch") - (set_attr "mode" "none")]) - -;; Conditional branch on equality comparison. - -(define_insn "branch_equality" - [(set (pc) - (if_then_else - (match_operator:SI 0 "equality_op" - [(match_operand:SI 2 "register_operand" "d") - (match_operand:SI 3 "register_operand" "d")]) - (label_ref (match_operand 1 "" "")) - (pc)))] - "" - "* -{ - return iq2000_output_conditional_branch (insn, - operands, - /*two_operands_p=*/1, - /*float_p=*/0, - /*inverted_p=*/0, - get_attr_length (insn)); -}" - [(set_attr "type" "branch") - (set_attr "mode" "none")]) - -(define_insn "branch_equality_inverted" - [(set (pc) - (if_then_else - (match_operator:SI 0 "equality_op" - [(match_operand:SI 2 "register_operand" "d") - (match_operand:SI 3 "register_operand" "d")]) - (pc) - (label_ref (match_operand 1 "" ""))))] - "" - "* -{ - return iq2000_output_conditional_branch (insn, - operands, - /*two_operands_p=*/1, - /*float_p=*/0, - /*inverted_p=*/1, - get_attr_length (insn)); -}" - [(set_attr "type" "branch") - (set_attr "mode" "none")]) - -(define_expand "beq" - [(set (pc) - (if_then_else (eq:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, EQ); - DONE; - } -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, NE); - DONE; - } -}") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GT); - DONE; - } -}") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GE); - DONE; - } -}") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LT); - DONE; - } -}") - -(define_expand "ble" - [(set (pc) - (if_then_else (le:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LE); - DONE; - } -}") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GTU); - DONE; - } -}") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GEU); - DONE; - } -}") - - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LTU); - DONE; - } -}") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LEU); - DONE; - } -}") - -;; Recognize bbi and bbin instructions. These use two unusual template -;; patterns, %Ax and %Px. %Ax outputs an 'i' if operand `x' is a LABEL_REF -;; otherwise it outputs an 'in'. %Px does nothing if `x' is PC -;; and outputs the operand if `x' is a LABEL_REF. - -(define_insn "" - [(set (pc) - (if_then_else - (ne (sign_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand:SI 1 "arith_operand" "I")) - (const_int 0)) - (match_operand 2 "pc_or_label_operand" "") - (match_operand 3 "pc_or_label_operand" "")))] - "" - "bb%A2\\t%0(31-%1),%P2%P3" - [(set_attr "length" "4") - (set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (eq (sign_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand:SI 1 "arith_operand" "I")) - (const_int 0)) - (match_operand 2 "pc_or_label_operand" "") - (match_operand 3 "pc_or_label_operand" "")))] - "" - "bb%A3\\t%0(31-%1),%P2%P3" - [(set_attr "length" "4") - (set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand:SI 1 "arith_operand" "I")) - (const_int 0)) - (match_operand 2 "pc_or_label_operand" "") - (match_operand 3 "pc_or_label_operand" "")))] - "" - "bb%A2\\t%0(31-%1),%P2%P3" - [(set_attr "length" "4") - (set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand:SI 1 "arith_operand" "I")) - (const_int 0)) - (match_operand 2 "pc_or_label_operand" "") - (match_operand 3 "pc_or_label_operand" "")))] - "" - "bb%A3\\t%0(31-%1),%P2%P3" - [(set_attr "length" "4") - (set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (eq (and:SI (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "power_of_2_operand" "I")) - (const_int 0)) - (match_operand 2 "pc_or_label_operand" "") - (match_operand 3 "pc_or_label_operand" "")))] - "" - "bb%A3\\t%0(%p1),%P2%P3" - [(set_attr "length" "4") - (set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (ne (and:SI (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "power_of_2_operand" "I")) - (const_int 0)) - (match_operand 2 "pc_or_label_operand" "") - (match_operand 3 "pc_or_label_operand" "")))] - "" - "bb%A2\\t%0(%p1),%P2%P3" - [(set_attr "length" "4") - (set_attr "type" "branch")]) - -;; -;; .................... -;; -;; SETTING A REGISTER FROM A COMPARISON -;; -;; .................... - -(define_expand "seq" - [(set (match_operand:SI 0 "register_operand" "=d") - (eq:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (EQ, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - - -(define_insn "seq_si_zero" - [(set (match_operand:SI 0 "register_operand" "=d") - (eq:SI (match_operand:SI 1 "register_operand" "d") - (const_int 0)))] - "" - "sltiu\\t%0,%1,1" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -(define_expand "sne" - [(set (match_operand:SI 0 "register_operand" "=d") - (ne:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (NE, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - -(define_insn "sne_si_zero" - [(set (match_operand:SI 0 "register_operand" "=d") - (ne:SI (match_operand:SI 1 "register_operand" "d") - (const_int 0)))] - "" - "sltu\\t%0,%.,%1" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -(define_expand "sgt" - [(set (match_operand:SI 0 "register_operand" "=d") - (gt:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (GT, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - -(define_insn "sgt_si" - [(set (match_operand:SI 0 "register_operand" "=d,=d") - (gt:SI (match_operand:SI 1 "register_operand" "d,d") - (match_operand:SI 2 "reg_or_0_operand" "d,J")))] - "" - "@ - slt\\t%0,%z2,%1 - slt\\t%0,%z2,%1" - [(set_attr "type" "arith,arith") - (set_attr "mode" "SI,SI")]) - -(define_expand "sge" - [(set (match_operand:SI 0 "register_operand" "=d") - (ge:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (GE, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - -(define_expand "slt" - [(set (match_operand:SI 0 "register_operand" "=d") - (lt:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (LT, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - -(define_insn "slt_si" - [(set (match_operand:SI 0 "register_operand" "=d,=d") - (lt:SI (match_operand:SI 1 "register_operand" "d,d") - (match_operand:SI 2 "arith_operand" "d,I")))] - "" - "@ - slt\\t%0,%1,%2 - slti\\t%0,%1,%2" - [(set_attr "type" "arith,arith") - (set_attr "mode" "SI,SI")]) - -(define_expand "sle" - [(set (match_operand:SI 0 "register_operand" "=d") - (le:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (LE, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - -(define_insn "sle_si_const" - [(set (match_operand:SI 0 "register_operand" "=d") - (le:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "small_int" "I")))] - "INTVAL (operands[2]) < 32767" - "* -{ - operands[2] = GEN_INT (INTVAL (operands[2])+1); - return \"slti\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -(define_expand "sgtu" - [(set (match_operand:SI 0 "register_operand" "=d") - (gtu:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (GTU, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - -(define_insn "sgtu_si" - [(set (match_operand:SI 0 "register_operand" "=d") - (gtu:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "reg_or_0_operand" "dJ")))] - "" - "sltu\\t%0,%z2,%1" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=t") - (gtu:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d")))] - "" - "sltu\\t%2,%1" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -(define_expand "sgeu" - [(set (match_operand:SI 0 "register_operand" "=d") - (geu:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (GEU, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - -(define_expand "sltu" - [(set (match_operand:SI 0 "register_operand" "=d") - (ltu:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (LTU, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - -(define_insn "sltu_si" - [(set (match_operand:SI 0 "register_operand" "=d,=d") - (ltu:SI (match_operand:SI 1 "register_operand" "d,d") - (match_operand:SI 2 "arith_operand" "d,I")))] - "" - "@ - sltu\\t%0,%1,%2 - sltiu\\t%0,%1,%2" - [(set_attr "type" "arith,arith") - (set_attr "mode" "SI,SI")]) - -(define_expand "sleu" - [(set (match_operand:SI 0 "register_operand" "=d") - (leu:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (LEU, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - -(define_insn "sleu_si_const" - [(set (match_operand:SI 0 "register_operand" "=d") - (leu:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "small_int" "I")))] - "INTVAL (operands[2]) < 32767" - "* -{ - operands[2] = GEN_INT (INTVAL (operands[2]) + 1); - return \"sltiu\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - - -;; -;; .................... -;; -;; UNCONDITIONAL BRANCHES -;; -;; .................... - -;; Unconditional branches. - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "* -{ - if (GET_CODE (operands[0]) == REG) - return \"j\\t%0\"; - return \"j\\t%l0\"; - /* return \"b\\t%l0\";*/ -}" - [(set_attr "type" "jump") - (set_attr "mode" "none")]) - -(define_expand "indirect_jump" - [(set (pc) (match_operand 0 "register_operand" "d"))] - "" - " -{ - rtx dest; - - if (operands[0]) /* eliminate unused code warnings */ - { - dest = operands[0]; - if (GET_CODE (dest) != REG || GET_MODE (dest) != Pmode) - operands[0] = copy_to_mode_reg (Pmode, dest); - - if (!(Pmode == DImode)) - emit_jump_insn (gen_indirect_jump_internal1 (operands[0])); - else - emit_jump_insn (gen_indirect_jump_internal2 (operands[0])); - - DONE; - } -}") - -(define_insn "indirect_jump_internal1" - [(set (pc) (match_operand:SI 0 "register_operand" "d"))] - "!(Pmode == DImode)" - "j\\t%0" - [(set_attr "type" "jump") - (set_attr "mode" "none")]) - -(define_expand "tablejump" - [(set (pc) - (match_operand 0 "register_operand" "d")) - (use (label_ref (match_operand 1 "" "")))] - "" - " -{ - if (operands[0]) /* eliminate unused code warnings */ - { - gcc_assert (GET_MODE (operands[0]) == Pmode); - - if (!(Pmode == DImode)) - emit_jump_insn (gen_tablejump_internal1 (operands[0], operands[1])); - else - emit_jump_insn (gen_tablejump_internal2 (operands[0], operands[1])); - - DONE; - } -}") - -(define_insn "tablejump_internal1" - [(set (pc) - (match_operand:SI 0 "register_operand" "d")) - (use (label_ref (match_operand 1 "" "")))] - "!(Pmode == DImode)" - "j\\t%0" - [(set_attr "type" "jump") - (set_attr "mode" "none")]) - -(define_expand "tablejump_internal3" - [(parallel [(set (pc) - (plus:SI (match_operand:SI 0 "register_operand" "d") - (label_ref:SI (match_operand 1 "" "")))) - (use (label_ref:SI (match_dup 1)))])] - "" - "") - -;;; Make sure that this only matches the insn before ADDR_DIFF_VEC. Otherwise -;;; it is not valid. ??? With the USE, the condition tests may not be required -;;; any longer. - -;;; ??? The length depends on the ABI. It is two for o32, and one for n32. -;;; We just use the conservative number here. - -(define_insn "" - [(set (pc) - (plus:SI (match_operand:SI 0 "register_operand" "d") - (label_ref:SI (match_operand 1 "" "")))) - (use (label_ref:SI (match_dup 1)))] - "!(Pmode == DImode) && next_active_insn (insn) != 0 - && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC - && PREV_INSN (next_active_insn (insn)) == operands[1]" - "* -{ - return \"j\\t%0\"; -}" - [(set_attr "type" "jump") - (set_attr "mode" "none") - (set_attr "length" "8")]) - -;; -;; .................... -;; -;; Function prologue/epilogue -;; -;; .................... -;; - -(define_expand "prologue" - [(const_int 1)] - "" - " -{ - if (iq2000_isa >= 0) /* avoid unused code warnings */ - { - iq2000_expand_prologue (); - DONE; - } -}") - -;; Block any insns from being moved before this point, since the -;; profiling call to mcount can use various registers that aren't -;; saved or used to pass arguments. - -(define_insn "blockage" - [(unspec_volatile [(const_int 0)] 0)] - "" - "" - [(set_attr "type" "unknown") - (set_attr "mode" "none") - (set_attr "length" "0")]) - -(define_expand "epilogue" - [(const_int 2)] - "" - " -{ - if (iq2000_isa >= 0) /* avoid unused code warnings */ - { - iq2000_expand_epilogue (); - DONE; - } -}") - -;; Trivial return. Make it look like a normal return insn as that -;; allows jump optimizations to work better . -(define_insn "return" - [(return)] - "iq2000_can_use_return_insn ()" - "j\\t%%31" - [(set_attr "type" "jump") - (set_attr "mode" "none")]) - -;; Normal return. - -(define_insn "return_internal" - [(use (match_operand 0 "pmode_register_operand" "")) - (return)] - "" - "* -{ - return \"j\\t%0\"; -}" - [(set_attr "type" "jump") - (set_attr "mode" "none")]) - -(define_insn "eh_return_internal" - [(const_int 4) - (return) - (use (reg:SI 26)) - (use (reg:SI 31))] - "" - "j\\t%%26" - [(set_attr "type" "jump") - (set_attr "mode" "none")]) - -(define_expand "eh_return" - [(use (match_operand:SI 0 "register_operand" "r"))] - "" - " -{ - iq2000_expand_eh_return (operands[0]); - DONE; -}") - - -;; -;; .................... -;; -;; FUNCTION CALLS -;; -;; .................... - -;; calls.c now passes a third argument, make saber happy - -(define_expand "call" - [(parallel [(call (match_operand 0 "memory_operand" "m") - (match_operand 1 "" "i")) - (clobber (reg:SI 31)) - (use (match_operand 2 "" "")) ;; next_arg_reg - (use (match_operand 3 "" ""))])] ;; struct_value_size_rtx - "" - " -{ - rtx addr; - - if (operands[0]) /* eliminate unused code warnings */ - { - addr = XEXP (operands[0], 0); - if ((GET_CODE (addr) != REG && (!CONSTANT_ADDRESS_P (addr))) - || ! call_insn_operand (addr, VOIDmode)) - XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, addr); - - /* In order to pass small structures by value in registers - compatibly with the IQ2000 compiler, we need to shift the value - into the high part of the register. 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. */ - - if (operands[2] != (rtx)0 && GET_CODE (operands[2]) == PARALLEL) - { - rtvec adjust = XVEC (operands[2], 0); - int num = GET_NUM_ELEM (adjust); - int i; - - for (i = 0; i < num; i++) - emit_insn (RTVEC_ELT (adjust, i)); - } - - emit_call_insn (gen_call_internal0 (operands[0], operands[1], - gen_rtx_REG (SImode, - GP_REG_FIRST + 31))); - DONE; - } -}") - -(define_expand "call_internal0" - [(parallel [(call (match_operand 0 "" "") - (match_operand 1 "" "")) - (clobber (match_operand:SI 2 "" ""))])] - "" - "") - -(define_insn "call_internal1" - [(call (mem (match_operand 0 "call_insn_operand" "ri")) - (match_operand 1 "" "i")) - (clobber (match_operand:SI 2 "register_operand" "=d"))] - "" - "* -{ - register rtx target = operands[0]; - - if (GET_CODE (target) == CONST_INT) - return \"li\\t%@,%0\\n\\tjalr\\t%2,%@\"; - else if (CONSTANT_ADDRESS_P (target)) - return \"jal\\t%0\"; - else - return \"jalr\\t%2,%0\"; -}" - [(set_attr "type" "call") - (set_attr "mode" "none")]) - -;; calls.c now passes a fourth argument, make saber happy - -(define_expand "call_value" - [(parallel [(set (match_operand 0 "register_operand" "=df") - (call (match_operand 1 "memory_operand" "m") - (match_operand 2 "" "i"))) - (clobber (reg:SI 31)) - (use (match_operand 3 "" ""))])] ;; next_arg_reg - "" - " -{ - rtx addr; - - if (operands[0]) /* eliminate unused code warning */ - { - addr = XEXP (operands[1], 0); - if ((GET_CODE (addr) != REG && (!CONSTANT_ADDRESS_P (addr))) - || ! call_insn_operand (addr, VOIDmode)) - XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, addr); - - /* In order to pass small structures by value in registers - compatibly with the IQ2000 compiler, we need to shift the value - into the high part of the register. 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. */ - - if (operands[3] != (rtx)0 && GET_CODE (operands[3]) == PARALLEL) - { - rtvec adjust = XVEC (operands[3], 0); - int num = GET_NUM_ELEM (adjust); - int i; - - for (i = 0; i < num; i++) - emit_insn (RTVEC_ELT (adjust, i)); - } - - if (GET_CODE (operands[0]) == PARALLEL && XVECLEN (operands[0], 0) > 1) - { - emit_call_insn (gen_call_value_multiple_internal0 - (XEXP (XVECEXP (operands[0], 0, 0), 0), - operands[1], operands[2], - XEXP (XVECEXP (operands[0], 0, 1), 0), - gen_rtx_REG (SImode, GP_REG_FIRST + 31))); - DONE; - } - - /* We have a call returning a DImode structure in an FP reg. - Strip off the now unnecessary PARALLEL. */ - if (GET_CODE (operands[0]) == PARALLEL) - operands[0] = XEXP (XVECEXP (operands[0], 0, 0), 0); - - emit_call_insn (gen_call_value_internal0 (operands[0], operands[1], operands[2], - gen_rtx_REG (SImode, - GP_REG_FIRST + 31))); - - DONE; - } -}") - -(define_expand "call_value_internal0" - [(parallel [(set (match_operand 0 "" "") - (call (match_operand 1 "" "") - (match_operand 2 "" ""))) - (clobber (match_operand:SI 3 "" ""))])] - "" - "") - -(define_insn "call_value_internal1" - [(set (match_operand 0 "register_operand" "=df") - (call (mem (match_operand 1 "call_insn_operand" "ri")) - (match_operand 2 "" "i"))) - (clobber (match_operand:SI 3 "register_operand" "=d"))] - "" - "* -{ - register rtx target = operands[1]; - - if (GET_CODE (target) == CONST_INT) - return \"li\\t%@,%1\\n\\tjalr\\t%3,%@\"; - else if (CONSTANT_ADDRESS_P (target)) - return \"jal\\t%1\"; - else - return \"jalr\\t%3,%1\"; -}" - [(set_attr "type" "call") - (set_attr "mode" "none")]) - -(define_expand "call_value_multiple_internal0" - [(parallel [(set (match_operand 0 "" "") - (call (match_operand 1 "" "") - (match_operand 2 "" ""))) - (set (match_operand 3 "" "") - (call (match_dup 1) - (match_dup 2))) - (clobber (match_operand:SI 4 "" ""))])] - "" - "") - -;; ??? May eventually need all 6 versions of the call patterns with multiple -;; return values. - -(define_insn "call_value_multiple_internal1" - [(set (match_operand 0 "register_operand" "=df") - (call (mem (match_operand 1 "call_insn_operand" "ri")) - (match_operand 2 "" "i"))) - (set (match_operand 3 "register_operand" "=df") - (call (mem (match_dup 1)) - (match_dup 2))) - (clobber (match_operand:SI 4 "register_operand" "=d"))] - "" - "* -{ - register rtx target = operands[1]; - - if (GET_CODE (target) == CONST_INT) - return \"li\\t%@,%1\\n\\tjalr\\t%4,%@\"; - else if (CONSTANT_ADDRESS_P (target)) - return \"jal\\t%1\"; - else - return \"jalr\\t%4,%1\"; -}" - [(set_attr "type" "call") - (set_attr "mode" "none")]) - -;; Call subroutine returning any type. - -(define_expand "untyped_call" - [(parallel [(call (match_operand 0 "" "") - (const_int 0)) - (match_operand 1 "" "") - (match_operand 2 "" "")])] - "" - " -{ - if (operands[0]) /* silence statement not reached warnings */ - { - int i; - - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); - - for (i = 0; i < XVECLEN (operands[2], 0); i++) - { - rtx set = XVECEXP (operands[2], 0, i); - emit_move_insn (SET_DEST (set), SET_SRC (set)); - } - - emit_insn (gen_blockage ()); - DONE; - } -}") - -;; -;; .................... -;; -;; MISC. -;; -;; .................... -;; - -(define_insn "nop" - [(const_int 0)] - "" - "nop" - [(set_attr "type" "nop") - (set_attr "mode" "none")]) - - -;; For the rare case where we need to load an address into a register -;; that cannot be recognized by the normal movsi/addsi instructions. -;; I have no idea how many insns this can actually generate. It should -;; be rare, so over-estimating as 10 instructions should not have any -;; real performance impact. -(define_insn "leasi" - [(set (match_operand:SI 0 "register_operand" "=d") - (match_operand:SI 1 "address_operand" "p"))] - "Pmode == SImode" - "* -{ - rtx xoperands [3]; - - xoperands[0] = operands[0]; - xoperands[1] = XEXP (operands[1], 0); - xoperands[2] = XEXP (operands[1], 1); - output_asm_insn (\"addiu\\t%0,%1,%2\", xoperands); - return \"\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "40")]) - -(define_insn "ado16" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "register_operand" "r")] - UNSPEC_ADO16))] - "" - "ado16\\t%0, %1, %2" -) - -(define_insn "ram" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "const_int_operand" "I") - (match_operand:SI 3 "const_int_operand" "I") - (match_operand:SI 4 "const_int_operand" "I")] - UNSPEC_RAM))] - "" - "ram\\t%0, %1, %2, %3, %4" -) - -(define_insn "chkhdr" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "=r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_CHKHDR)] - "" - "* return iq2000_fill_delay_slot (\"chkhdr\\t%0, %1\", DELAY_LOAD, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "pkrl" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_PKRL)] - "" - "* return iq2000_fill_delay_slot (\"pkrl\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "cfc0" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "I")] - UNSPEC_CFC0))] - "" - "* return iq2000_fill_delay_slot (\"cfc0\\t%0, %%%1\", DELAY_LOAD, operands, insn);" - [(set_attr "dslot" "ok_in_dslot")] -) - -(define_insn "cfc1" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "I")] - UNSPEC_CFC1))] - "" - "* return iq2000_fill_delay_slot (\"cfc1\\t%0, %%%1\", DELAY_LOAD, operands, insn);" - [(set_attr "dslot" "ok_in_dslot")] -) - -(define_insn "cfc2" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "I")] - UNSPEC_CFC2))] - "" - "* return iq2000_fill_delay_slot (\"cfc2\\t%0, %%%1\", DELAY_LOAD, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "cfc3" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "I")] - UNSPEC_CFC3))] - "" - "* return iq2000_fill_delay_slot (\"cfc3\\t%0, %%%1\", DELAY_LOAD, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "ctc0" - [(unspec_volatile:SI [(match_operand:SI 0 "reg_or_0_operand" "rJ") - (match_operand:SI 1 "const_int_operand" "I")] - UNSPEC_CTC0)] - "" - "* return iq2000_fill_delay_slot (\"ctc0\\t%z0, %%%1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "ok_in_dslot")] -) - -(define_insn "ctc1" - [(unspec_volatile:SI [(match_operand:SI 0 "reg_or_0_operand" "rJ") - (match_operand:SI 1 "const_int_operand" "I")] - UNSPEC_CTC1)] - "" - "* return iq2000_fill_delay_slot (\"ctc1\\t%z0, %%%1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "ok_in_dslot")] -) - -(define_insn "ctc2" - [(unspec_volatile:SI [(match_operand:SI 0 "reg_or_0_operand" "rJ") - (match_operand:SI 1 "const_int_operand" "I")] - UNSPEC_CTC2)] - "" - "* return iq2000_fill_delay_slot (\"ctc2\\t%z0, %%%1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "ok_in_dslot")] -) - -(define_insn "ctc3" - [(unspec_volatile:SI [(match_operand:SI 0 "reg_or_0_operand" "rJ") - (match_operand:SI 1 "const_int_operand" "I")] - UNSPEC_CTC3)] - "" - "* return iq2000_fill_delay_slot (\"ctc3\\t%z0, %%%1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "ok_in_dslot")] -) - -(define_insn "mfc0" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "I")] - UNSPEC_MFC0))] - "" - "* return iq2000_fill_delay_slot (\"mfc0\\t%0, %%%1\", DELAY_LOAD, operands, insn);" - [(set_attr "dslot" "ok_in_dslot")] -) - -(define_insn "mfc1" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "I")] - UNSPEC_MFC1))] - "" - "* return iq2000_fill_delay_slot (\"mfc1\\t%0, %%%1\", DELAY_LOAD, operands, insn);" - [(set_attr "dslot" "ok_in_dslot")] -) - -(define_insn "mfc2" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "I")] - UNSPEC_MFC2))] - "" - "* return iq2000_fill_delay_slot (\"mfc2\\t%0, %%%1\", DELAY_LOAD, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "mfc3" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "I")] - UNSPEC_MFC3))] - "" - "* return iq2000_fill_delay_slot (\"mfc3\\t%0, %%%1\", DELAY_LOAD, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "mtc0" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "const_int_operand" "I")] - UNSPEC_MTC0)] - "" - "* return iq2000_fill_delay_slot (\"mtc0\\t%0, %%%1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "ok_in_dslot")] -) - -(define_insn "mtc1" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "const_int_operand" "I")] - UNSPEC_MTC1)] - "" - "* return iq2000_fill_delay_slot (\"mtc1\\t%0, %%%1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "ok_in_dslot")] -) - -(define_insn "mtc2" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "const_int_operand" "I")] - UNSPEC_MTC2)] - "" - "* return iq2000_fill_delay_slot (\"mtc2\\t%0, %%%1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "ok_in_dslot")] -) - -(define_insn "mtc3" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "const_int_operand" "I")] - UNSPEC_MTC3)] - "" - "* return iq2000_fill_delay_slot (\"mtc3\\t%0, %%%1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "ok_in_dslot")] -) - -(define_insn "lur" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_LUR)] - "" - "* return iq2000_fill_delay_slot (\"lur\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "rb" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_RB)] - "" - "* return iq2000_fill_delay_slot (\"rb\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "rx" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_RX)] - "" - "* return iq2000_fill_delay_slot (\"rx\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "srrd" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] - UNSPEC_SRRD)] - "" - "* return iq2000_fill_delay_slot (\"srrd\\t%0\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "srwr" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_SRWR)] - "" - "* return iq2000_fill_delay_slot (\"srwr\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "wb" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_WB)] - "" - "* return iq2000_fill_delay_slot (\"wb\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "wx" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_WX)] - "" - "* return iq2000_fill_delay_slot (\"wx\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "luc32" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_LUC32)] - "" - "* return iq2000_fill_delay_slot (\"luc32\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "luc32l" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_LUC32L)] - "" - "* return iq2000_fill_delay_slot (\"luc32l\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "luc64" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_LUC64)] - "" - "* return iq2000_fill_delay_slot (\"luc64\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "luc64l" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_LUC64L)] - "" - "* return iq2000_fill_delay_slot (\"luc64l\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "luk" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_LUK)] - "" - "* return iq2000_fill_delay_slot (\"luk\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "ok_in_dslot")] -) - -(define_insn "lulck" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] - UNSPEC_LULCK)] - "" - "* return iq2000_fill_delay_slot (\"lulck\\t%0\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "lum32" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_LUM32)] - "" - "* return iq2000_fill_delay_slot (\"lum32\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "lum32l" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_LUM32L)] - "" - "* return iq2000_fill_delay_slot (\"lum32l\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "lum64" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_LUM64)] - "" - "* return iq2000_fill_delay_slot (\"lum64\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "lum64l" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_LUM64L)] - "" - "* return iq2000_fill_delay_slot (\"lum64l\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "lurl" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_LURL)] - "" - "* return iq2000_fill_delay_slot (\"lurl\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "mrgb" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "register_operand" "r") - (match_operand:SI 3 "const_int_operand" "I")] - UNSPEC_MRGB))] - "" - "* return iq2000_fill_delay_slot (\"mrgb\\t%0, %1, %2, %3\", DELAY_LOAD, operands, insn);" - [(set_attr "dslot" "ok_in_dslot")] -) - -(define_insn "srrdl" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] - UNSPEC_SRRDL)] - "" - "* return iq2000_fill_delay_slot (\"srrdl\\t%0\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "srulck" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] - UNSPEC_SRULCK)] - "" - "* return iq2000_fill_delay_slot (\"srulck\\t%0\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "srwru" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_SRWRU)] - "" - "* return iq2000_fill_delay_slot (\"srwru\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "trapqfl" - [(unspec_volatile:SI [(const_int 1)] UNSPEC_TRAPQFL)] - "" - "* return iq2000_fill_delay_slot (\"trapqfl\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "trapqne" - [(unspec_volatile:SI [(const_int 2)] UNSPEC_TRAPQNE)] - "" - "* return iq2000_fill_delay_slot (\"trapqne\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "traprel" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] - UNSPEC_TRAPREL)] - "" - "* return iq2000_fill_delay_slot (\"traprel %0\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "wbu" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_WBU)] - "" - "* return iq2000_fill_delay_slot (\"wbu\\t%0, %1\", DELAY_NONE, operands, insn);" - [(set_attr "dslot" "not_in_dslot")] -) - -(define_insn "syscall" - [(unspec_volatile:SI [(const_int 2)] UNSPEC_SYSCALL)] - "" - "syscall" - [(set_attr "dslot" "not_in_dslot")] -) diff --git a/gcc-4.4.3/gcc/config/iq2000/iq2000.opt b/gcc-4.4.3/gcc/config/iq2000/iq2000.opt deleted file mode 100644 index 7ca61424f..000000000 --- a/gcc-4.4.3/gcc/config/iq2000/iq2000.opt +++ /dev/null @@ -1,44 +0,0 @@ -; Options for the Vitesse IQ2000 port of the compiler. - -; Copyright (C) 2005, 2007 Free Software Foundation, Inc. -; -; This file is part of GCC. -; -; 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 3, or (at your option) any later -; version. -; -; 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 GCC; see the file COPYING3. If not see -; <http://www.gnu.org/licenses/>. - -march= -Target RejectNegative Joined -Specify CPU for code generation purposes - -mcpu= -Target RejectNegative Joined -Specify CPU for scheduling purposes - -membedded-data -Target Mask(EMBEDDED_DATA) -Use ROM instead of RAM - -mgpopt -Target Mask(GPOPT) -Use GP relative sdata/sbss sections - -; Not used by the compiler proper. -mno-crt0 -Target RejectNegative -No default crt0.o - -muninit-const-in-rodata -Target Mask(UNINIT_CONST_IN_RODATA) -Put uninitialized constants in ROM (needs -membedded-data) diff --git a/gcc-4.4.3/gcc/config/iq2000/lib2extra-funcs.c b/gcc-4.4.3/gcc/config/iq2000/lib2extra-funcs.c deleted file mode 100644 index e092babdd..000000000 --- a/gcc-4.4.3/gcc/config/iq2000/lib2extra-funcs.c +++ /dev/null @@ -1,17 +0,0 @@ -typedef unsigned int USItype __attribute__ ((mode (SI))); - -USItype -__mulsi3 (USItype a, USItype b) -{ - USItype c = 0; - - while (a != 0) - { - if (a & 1) - c += b; - a >>= 1; - b <<= 1; - } - - return c; -} diff --git a/gcc-4.4.3/gcc/config/iq2000/predicates.md b/gcc-4.4.3/gcc/config/iq2000/predicates.md deleted file mode 100644 index 53471e455..000000000 --- a/gcc-4.4.3/gcc/config/iq2000/predicates.md +++ /dev/null @@ -1,232 +0,0 @@ -;; Predicate definitions for Vitesse IQ2000. -;; Copyright (C) 2005, 2007 Free Software Foundation, Inc. -;; -;; This file is part of GCC. -;; -;; 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 3, or (at your option) -;; any later version. -;; -;; 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 GCC; see the file COPYING3. If not see -;; <http://www.gnu.org/licenses/>. - -;; Return 1 if OP can be used as an operand where a register or 16-bit -;; unsigned integer is needed. - -(define_predicate "uns_arith_operand" - (match_code "reg,const_int,subreg") -{ - 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. - -(define_predicate "arith_operand" - (match_code "reg,const_int,subreg") -{ - 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. - -(define_predicate "small_int" - (match_code "const_int") -{ - 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. - -(define_predicate "large_int" - (match_code "const_int") -{ - 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. - -(define_predicate "reg_or_0_operand" - (match_code "reg,const_int,const_double,subreg") -{ - 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 (i.e., register + small offset). - -(define_predicate "simple_memory_operand" - (match_code "mem,subreg") -{ - 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. - -(define_predicate "equality_op" - (match_code "eq,ne") -{ - 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). - -(define_predicate "cmp_op" - (match_code "eq,ne,gt,ge,gtu,geu,lt,le,ltu,leu") -{ - if (mode != GET_MODE (op)) - return 0; - - return COMPARISON_P (op); -}) - -;; Return nonzero if the operand is either the PC or a label_ref. - -(define_special_predicate "pc_or_label_operand" - (match_code "pc,label_ref") -{ - 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. - -(define_predicate "call_insn_operand" - (match_code "const_int,const,symbol_ref,reg") -{ - 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. - -(define_predicate "move_operand" - (match_code "const_int,const_double,const,symbol_ref,label_ref,subreg,reg,mem") -{ - /* 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. - -(define_predicate "power_of_2_operand" - (match_code "const_int") -{ - int intval; - - if (GET_CODE (op) != CONST_INT) - return 0; - else - intval = INTVAL (op); - - return ((intval & ((unsigned)(intval) - 1)) == 0); -}) diff --git a/gcc-4.4.3/gcc/config/iq2000/t-iq2000 b/gcc-4.4.3/gcc/config/iq2000/t-iq2000 deleted file mode 100644 index 23dc9558e..000000000 --- a/gcc-4.4.3/gcc/config/iq2000/t-iq2000 +++ /dev/null @@ -1,36 +0,0 @@ -# Suppress building libgcc1.a, since the MIPS compiler port is complete -# and does not need anything from libgcc1.a. -LIBGCC1 = -CROSS_LIBGCC1 = - -# We must build libgcc2.a with -G 0, in case the user wants to link -# without the $gp register. -TARGET_LIBGCC2_CFLAGS = -G 0 - -LIB2FUNCS_EXTRA = $(srcdir)/config/udivmod.c $(srcdir)/config/divmod.c $(srcdir)/config/udivmodsi4.c $(srcdir)/config/iq2000/lib2extra-funcs.c - -# We want fine grained libraries, so use the new code to build the -# floating point emulation libraries. -FPBIT = fp-bit.c -DPBIT = dp-bit.c - -fp-bit.c: $(srcdir)/config/fp-bit.c - echo '#define FLOAT' > fp-bit.c - cat $(srcdir)/config/fp-bit.c >> fp-bit.c - -dp-bit.c: $(srcdir)/config/fp-bit.c - cat $(srcdir)/config/fp-bit.c > dp-bit.c - -# Enable the following if multilibs are needed. -# See gcc/genmultilib, gcc/gcc.texi and gcc/tm.texi for a -# description of the options and their values. -# -# MULTILIB_OPTIONS = -# MULTILIB_DIRNAMES = -# MULTILIB_MATCHES = -# MULTILIB_EXCEPTIONS = -# MULTILIB_EXTRA_OPTS = -# -# LIBGCC = stmp-multilib -# INSTALL_LIBGCC = install-multilib - |