summaryrefslogtreecommitdiff
path: root/gcc/config/nds32/nds32.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/nds32/nds32.h')
-rw-r--r--gcc/config/nds32/nds32.h982
1 files changed, 982 insertions, 0 deletions
diff --git a/gcc/config/nds32/nds32.h b/gcc/config/nds32/nds32.h
new file mode 100644
index 00000000000..74f126cecc4
--- /dev/null
+++ b/gcc/config/nds32/nds32.h
@@ -0,0 +1,982 @@
+/* Definitions of target machine of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ 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/>. */
+
+
+/* ------------------------------------------------------------------------ */
+
+/* The following are auxiliary macros or structure declarations
+ that are used all over the nds32.c and nds32.h. */
+
+
+/* Computing the Length of an Insn. */
+#define ADJUST_INSN_LENGTH(INSN, LENGTH) \
+ (LENGTH = nds32_adjust_insn_length (INSN, LENGTH))
+
+/* Check instruction LS-37-FP-implied form.
+ Note: actually its immediate range is imm9u
+ since it is used for lwi37/swi37 instructions. */
+#define NDS32_LS_37_FP_P(rt, ra, imm) \
+ (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \
+ && REGNO (ra) == FP_REGNUM \
+ && satisfies_constraint_Iu09 (imm))
+
+/* Check instruction LS-37-SP-implied form.
+ Note: actually its immediate range is imm9u
+ since it is used for lwi37/swi37 instructions. */
+#define NDS32_LS_37_SP_P(rt, ra, imm) \
+ (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \
+ && REGNO (ra) == SP_REGNUM \
+ && satisfies_constraint_Iu09 (imm))
+
+
+/* Check load/store instruction form : Rt3, Ra3, imm3u. */
+#define NDS32_LS_333_P(rt, ra, imm, mode) nds32_ls_333_p (rt, ra, imm, mode)
+
+/* Check load/store instruction form : Rt4, Ra5, const_int_0.
+ Note: no need to check ra because Ra5 means it covers all registers. */
+#define NDS32_LS_450_P(rt, ra, imm) \
+ ((imm == const0_rtx) \
+ && (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \
+ || REGNO_REG_CLASS (REGNO (rt)) == MIDDLE_REGS))
+
+/* Check instruction RRI-333-form. */
+#define NDS32_RRI_333_P(rt, ra, imm) \
+ (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \
+ && REGNO_REG_CLASS (REGNO (ra)) == LOW_REGS \
+ && satisfies_constraint_Iu03 (imm))
+
+/* Check instruction RI-45-form. */
+#define NDS32_RI_45_P(rt, ra, imm) \
+ (REGNO (rt) == REGNO (ra) \
+ && (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \
+ || REGNO_REG_CLASS (REGNO (rt)) == MIDDLE_REGS) \
+ && satisfies_constraint_Iu05 (imm))
+
+
+/* Check instruction RR-33-form. */
+#define NDS32_RR_33_P(rt, ra) \
+ (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \
+ && REGNO_REG_CLASS (REGNO (ra)) == LOW_REGS)
+
+/* Check instruction RRR-333-form. */
+#define NDS32_RRR_333_P(rt, ra, rb) \
+ (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \
+ && REGNO_REG_CLASS (REGNO (ra)) == LOW_REGS \
+ && REGNO_REG_CLASS (REGNO (rb)) == LOW_REGS)
+
+/* Check instruction RR-45-form.
+ Note: no need to check rb because Rb5 means it covers all registers. */
+#define NDS32_RR_45_P(rt, ra, rb) \
+ (REGNO (rt) == REGNO (ra) \
+ && (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \
+ || REGNO_REG_CLASS (REGNO (rt)) == MIDDLE_REGS))
+
+/* Classifies address type to distinguish 16-bit/32-bit format. */
+enum nds32_16bit_address_type
+{
+ /* [reg]: 45 format address. */
+ ADDRESS_REG,
+ /* [lo_reg + imm3u]: 333 format address. */
+ ADDRESS_LO_REG_IMM3U,
+ /* post_inc [lo_reg + imm3u]: 333 format address. */
+ ADDRESS_POST_INC_LO_REG_IMM3U,
+ /* [$fp + imm7u]: fp imply address. */
+ ADDRESS_FP_IMM7U,
+ /* [$sp + imm7u]: sp imply address. */
+ ADDRESS_SP_IMM7U,
+ /* Other address format. */
+ ADDRESS_NOT_16BIT_FORMAT
+};
+
+
+/* ------------------------------------------------------------------------ */
+
+/* Define maximum numbers of registers for passing arguments. */
+#define NDS32_MAX_REGS_FOR_ARGS 6
+
+/* Define the register number for first argument. */
+#define NDS32_GPR_ARG_FIRST_REGNUM 0
+
+/* Define the register number for return value. */
+#define NDS32_GPR_RET_FIRST_REGNUM 0
+
+
+/* Define double word alignment bits. */
+#define NDS32_DOUBLE_WORD_ALIGNMENT 64
+
+/* Define alignment checking macros for convenience. */
+#define NDS32_HALF_WORD_ALIGN_P(value) (((value) & 0x01) == 0)
+#define NDS32_SINGLE_WORD_ALIGN_P(value) (((value) & 0x03) == 0)
+#define NDS32_DOUBLE_WORD_ALIGN_P(value) (((value) & 0x07) == 0)
+
+/* Round X up to the nearest double word. */
+#define NDS32_ROUND_UP_DOUBLE_WORD(value) (((value) + 7) & ~7)
+
+
+/* This macro is used to calculate the numbers of registers for
+ containing 'size' bytes of the argument.
+ The size of a register is a word in nds32 target.
+ So we use UNITS_PER_WORD to do the calculation. */
+#define NDS32_NEED_N_REGS_FOR_ARG(mode, type) \
+ ((mode == BLKmode) \
+ ? ((int_size_in_bytes (type) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) \
+ : ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+/* This macro is used to return the register number for passing argument.
+ We need to obey the following rules:
+ 1. If it is required MORE THAN one register,
+ make sure the register number is a even value.
+ 2. If it is required ONLY one register,
+ the register number can be odd or even value. */
+#define NDS32_AVAILABLE_REGNUM_FOR_ARG(reg_offset, mode, type) \
+ ((NDS32_NEED_N_REGS_FOR_ARG (mode, type) > 1) \
+ ? (((reg_offset) + NDS32_GPR_ARG_FIRST_REGNUM + 1) & ~1) \
+ : ((reg_offset) + NDS32_GPR_ARG_FIRST_REGNUM))
+
+/* This macro is to check if there are still available registers
+ for passing argument. */
+#define NDS32_ARG_PASS_IN_REG_P(reg_offset, mode, type) \
+ (((reg_offset) < NDS32_MAX_REGS_FOR_ARGS) \
+ && ((reg_offset) + NDS32_NEED_N_REGS_FOR_ARG (mode, type) \
+ <= NDS32_MAX_REGS_FOR_ARGS))
+
+/* This macro is to check if the register is required to be saved on stack.
+ If call_used_regs[regno] == 0, regno is the callee-saved register.
+ If df_regs_ever_live_p(regno) == true, it is used in the current function.
+ As long as the register satisfies both criteria above,
+ it is required to be saved. */
+#define NDS32_REQUIRED_CALLEE_SAVED_P(regno) \
+ ((!call_used_regs[regno]) && (df_regs_ever_live_p (regno)))
+
+/* ------------------------------------------------------------------------ */
+
+/* A C structure for machine-specific, per-function data.
+ This is added to the cfun structure. */
+struct GTY(()) machine_function
+{
+ /* Number of bytes allocated on the stack for variadic args
+ if we want to push them into stack as pretend arguments by ourself. */
+ int va_args_size;
+ /* Number of bytes reserved on the stack for
+ local and temporary variables. */
+ int local_size;
+ /* Number of bytes allocated on the stack for outgoing arguments. */
+ int out_args_size;
+
+ /* Number of bytes on the stack for saving $fp. */
+ int fp_size;
+ /* Number of bytes on the stack for saving $gp. */
+ int gp_size;
+ /* Number of bytes on the stack for saving $lp. */
+ int lp_size;
+
+ /* Number of bytes on the stack for saving callee-saved registers. */
+ int callee_saved_regs_size;
+ /* The padding bytes in callee-saved area may be required. */
+ int callee_saved_area_padding_bytes;
+
+ /* The first required register that should be saved on stack
+ for va_args (one named argument + nameless arguments). */
+ int va_args_first_regno;
+ /* The last required register that should be saved on stack
+ for va_args (one named argument + nameless arguments). */
+ int va_args_last_regno;
+
+ /* The first required callee-saved register. */
+ int callee_saved_regs_first_regno;
+ /* The last required callee-saved register. */
+ int callee_saved_regs_last_regno;
+
+ /* Indicate that whether this function needs
+ prologue/epilogue code generation. */
+ int naked_p;
+ /* Indicate that whether this function
+ uses fp_as_gp optimization. */
+ int fp_as_gp_p;
+};
+
+/* A C structure that contains the arguments information. */
+typedef struct
+{
+ unsigned int reg_offset;
+} nds32_cumulative_args;
+
+/* ------------------------------------------------------------------------ */
+
+/* The following we define C-ISR related stuff.
+ In nds32 architecture, we have 73 vectors for interrupt/exception.
+ For each vector (except for vector 0, which is used for reset behavior),
+ we allow users to set its register saving scheme and interrupt level. */
+
+/* There are 73 vectors in nds32 architecture.
+ 0 for reset handler,
+ 1-8 for exception handler,
+ and 9-72 for interrupt handler.
+ We use an array, which is defined in nds32.c, to record
+ essential information for each vector. */
+#define NDS32_N_ISR_VECTORS 73
+
+/* Define possible isr category. */
+enum nds32_isr_category
+{
+ NDS32_ISR_NONE,
+ NDS32_ISR_INTERRUPT,
+ NDS32_ISR_EXCEPTION,
+ NDS32_ISR_RESET
+};
+
+/* Define isr register saving scheme. */
+enum nds32_isr_save_reg
+{
+ NDS32_SAVE_ALL,
+ NDS32_PARTIAL_SAVE
+};
+
+/* Define isr nested type. */
+enum nds32_isr_nested_type
+{
+ NDS32_NESTED,
+ NDS32_NOT_NESTED,
+ NDS32_NESTED_READY
+};
+
+/* Define structure to record isr information.
+ The isr vector array 'isr_vectors[]' with this structure
+ is defined in nds32.c. */
+struct nds32_isr_info
+{
+ /* The field to identify isr category.
+ It should be set to NDS32_ISR_NONE by default.
+ If user specifies a function as isr by using attribute,
+ this field will be set accordingly. */
+ enum nds32_isr_category category;
+
+ /* A string for the applied function name.
+ It should be set to empty string by default. */
+ char func_name[100];
+
+ /* The register saving scheme.
+ It should be set to NDS32_PARTIAL_SAVE by default
+ unless user specifies attribute to change it. */
+ enum nds32_isr_save_reg save_reg;
+
+ /* The nested type.
+ It should be set to NDS32_NOT_NESTED by default
+ unless user specifies attribute to change it. */
+ enum nds32_isr_nested_type nested_type;
+
+ /* Total vectors.
+ The total vectors = interrupt + exception numbers + reset.
+ It should be set to 0 by default.
+ This field is ONLY used in NDS32_ISR_RESET category. */
+ unsigned int total_n_vectors;
+
+ /* A string for nmi handler name.
+ It should be set to empty string by default.
+ This field is ONLY used in NDS32_ISR_RESET category. */
+ char nmi_name[100];
+
+ /* A string for warm handler name.
+ It should be set to empty string by default.
+ This field is ONLY used in NDS32_ISR_RESET category. */
+ char warm_name[100];
+};
+
+/* ------------------------------------------------------------------------ */
+
+/* Define code for all nds32 builtins. */
+enum nds32_builtins
+{
+ NDS32_BUILTIN_ISYNC,
+ NDS32_BUILTIN_ISB,
+ NDS32_BUILTIN_MFSR,
+ NDS32_BUILTIN_MFUSR,
+ NDS32_BUILTIN_MTSR,
+ NDS32_BUILTIN_MTUSR,
+ NDS32_BUILTIN_SETGIE_EN,
+ NDS32_BUILTIN_SETGIE_DIS
+};
+
+/* ------------------------------------------------------------------------ */
+
+#define TARGET_ISA_V2 (nds32_arch_option == ARCH_V2)
+#define TARGET_ISA_V3 (nds32_arch_option == ARCH_V3)
+#define TARGET_ISA_V3M (nds32_arch_option == ARCH_V3M)
+
+/* ------------------------------------------------------------------------ */
+
+/* Controlling the Compilation Driver. */
+
+#define OPTION_DEFAULT_SPECS \
+ {"arch", "%{!march=*:-march=%(VALUE)}" }
+
+#define CC1_SPEC \
+ ""
+
+#define ASM_SPEC \
+ " %{mbig-endian:-EB} %{mlittle-endian:-EL}"
+
+/* If user issues -mrelax, -mforce-fp-as-gp, or -mex9,
+ we need to pass '--relax' to linker.
+ Besides, for -mex9, we need to further pass '--mex9'. */
+#define LINK_SPEC \
+ " %{mbig-endian:-EB} %{mlittle-endian:-EL}" \
+ " %{mrelax|mforce-fp-as-gp|mex9:--relax}" \
+ " %{mex9:--mex9}"
+
+#define LIB_SPEC \
+ " -lc -lgloss"
+
+/* The option -mno-ctor-dtor can disable constructor/destructor feature
+ by applying different crt stuff. In the convention, crt0.o is the
+ startup file without constructor/destructor;
+ crt1.o, crti.o, crtbegin.o, crtend.o, and crtn.o are the
+ startup files with constructor/destructor.
+ Note that crt0.o, crt1.o, crti.o, and crtn.o are provided
+ by newlib/mculib/glibc/ublic, while crtbegin.o and crtend.o are
+ currently provided by GCC for nds32 target.
+
+ For nds32 target so far:
+ If -mno-ctor-dtor, we are going to link
+ "crt0.o [user objects]".
+ If general cases, we are going to link
+ "crt1.o crtbegin1.o [user objects] crtend1.o". */
+#define STARTFILE_SPEC \
+ " %{!mno-ctor-dtor:crt1.o%s;:crt0.o%s}" \
+ " %{!mno-ctor-dtor:crtbegin1.o%s}"
+#define ENDFILE_SPEC \
+ " %{!mno-ctor-dtor:crtend1.o%s}"
+
+/* The TARGET_BIG_ENDIAN_DEFAULT is defined if we configure gcc
+ with --target=nds32be-* setting.
+ Check gcc/config.gcc for more information.
+ In addition, currently we only have elf toolchain,
+ where mgp-direct is always the default. */
+#ifdef TARGET_BIG_ENDIAN_DEFAULT
+#define MULTILIB_DEFAULTS { "mbig-endian", "mgp-direct" }
+#else
+#define MULTILIB_DEFAULTS { "mlittle-endian", "mgp-direct" }
+#endif
+
+
+/* Run-time Target Specification. */
+
+#define TARGET_CPU_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__nds32__"); \
+ \
+ if (TARGET_ISA_V2) \
+ builtin_define ("__NDS32_ISA_V2__"); \
+ if (TARGET_ISA_V3) \
+ builtin_define ("__NDS32_ISA_V3__"); \
+ if (TARGET_ISA_V3M) \
+ builtin_define ("__NDS32_ISA_V3M__"); \
+ \
+ if (TARGET_BIG_ENDIAN) \
+ builtin_define ("__big_endian__"); \
+ if (TARGET_REDUCED_REGS) \
+ builtin_define ("__NDS32_REDUCED_REGS__"); \
+ if (TARGET_CMOV) \
+ builtin_define ("__NDS32_CMOV__"); \
+ if (TARGET_PERF_EXT) \
+ builtin_define ("__NDS32_PERF_EXT__"); \
+ if (TARGET_16_BIT) \
+ builtin_define ("__NDS32_16_BIT__"); \
+ if (TARGET_GP_DIRECT) \
+ builtin_define ("__NDS32_GP_DIRECT__"); \
+ \
+ builtin_assert ("cpu=nds32"); \
+ builtin_assert ("machine=nds32"); \
+ } while (0)
+
+
+/* Defining Data Structures for Per-function Information. */
+
+/* This macro is called once per function,
+ before generation of any RTL has begun. */
+#define INIT_EXPANDERS nds32_init_expanders ()
+
+
+/* Storage Layout. */
+
+#define BITS_BIG_ENDIAN 0
+
+#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN)
+
+#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN)
+
+#define UNITS_PER_WORD 4
+
+#define PROMOTE_MODE(m, unsignedp, type) \
+ if (GET_MODE_CLASS (m) == MODE_INT && GET_MODE_SIZE (m) < UNITS_PER_WORD) \
+ { \
+ (m) = SImode; \
+ }
+
+#define PARM_BOUNDARY 32
+
+#define STACK_BOUNDARY 64
+
+#define FUNCTION_BOUNDARY 32
+
+#define BIGGEST_ALIGNMENT 64
+
+#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 FLOAT_TYPE_SIZE 32
+#define DOUBLE_TYPE_SIZE 64
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+#define DEFAULT_SIGNED_CHAR 1
+
+#define SIZE_TYPE "long unsigned int"
+#define PTRDIFF_TYPE "long int"
+#define WCHAR_TYPE "short unsigned int"
+#define WCHAR_TYPE_SIZE 16
+
+
+/* Register Usage. */
+
+/* Number of actual hardware registers.
+ The hardware registers are assigned numbers for the compiler
+ from 0 to just below FIRST_PSEUDO_REGISTER.
+ All registers that the compiler knows about must be given numbers,
+ even those that are not normally considered general registers. */
+#define FIRST_PSEUDO_REGISTER 34
+
+/* An initializer that says which registers are used for fixed
+ purposes all throughout the compiled code and are therefore
+ not available for general allocation.
+
+ $r28 : $fp
+ $r29 : $gp
+ $r30 : $lp
+ $r31 : $sp
+
+ caller-save registers: $r0 ~ $r5, $r16 ~ $r23
+ callee-save registers: $r6 ~ $r10, $r11 ~ $r14
+
+ reserved for assembler : $r15
+ reserved for other use : $r24, $r25, $r26, $r27 */
+#define FIXED_REGISTERS \
+{ /* r0 r1 r2 r3 r4 r5 r6 r7 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ /* r8 r9 r10 r11 r12 r13 r14 r15 */ \
+ 0, 0, 0, 0, 0, 0, 0, 1, \
+ /* r16 r17 r18 r19 r20 r21 r22 r23 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ /* r24 r25 r26 r27 r28 r29 r30 r31 */ \
+ 1, 1, 1, 1, 0, 1, 0, 1, \
+ /* ARG_POINTER:32 */ \
+ 1, \
+ /* FRAME_POINTER:33 */ \
+ 1 \
+}
+
+/* Identifies the registers that are not available for
+ general allocation of values that must live across
+ function calls -- so they are caller-save registers.
+
+ 0 : callee-save registers
+ 1 : caller-save registers */
+#define CALL_USED_REGISTERS \
+{ /* r0 r1 r2 r3 r4 r5 r6 r7 */ \
+ 1, 1, 1, 1, 1, 1, 0, 0, \
+ /* r8 r9 r10 r11 r12 r13 r14 r15 */ \
+ 0, 0, 0, 0, 0, 0, 0, 1, \
+ /* r16 r17 r18 r19 r20 r21 r22 r23 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* r24 r25 r26 r27 r28 r29 r30 r31 */ \
+ 1, 1, 1, 1, 0, 1, 0, 1, \
+ /* ARG_POINTER:32 */ \
+ 1, \
+ /* FRAME_POINTER:33 */ \
+ 1 \
+}
+
+/* In nds32 target, we have three levels of registers:
+ LOW_COST_REGS : $r0 ~ $r7
+ MIDDLE_COST_REGS : $r8 ~ $r11, $r16 ~ $r19
+ HIGH_COST_REGS : $r12 ~ $r14, $r20 ~ $r31 */
+#define REG_ALLOC_ORDER \
+{ \
+ 0, 1, 2, 3, 4, 5, 6, 7, \
+ 8, 9, 10, 11, 16, 17, 18, 19, \
+ 12, 13, 14, 15, 20, 21, 22, 23, \
+ 24, 25, 26, 27, 28, 29, 30, 31, \
+ 32, \
+ 33 \
+}
+
+/* Tell IRA to use the order we define rather than messing it up with its
+ own cost calculations. */
+#define HONOR_REG_ALLOC_ORDER
+
+/* The number of consecutive hard regs needed starting at
+ reg "regno" for holding a value of mode "mode". */
+#define HARD_REGNO_NREGS(regno, mode) nds32_hard_regno_nregs (regno, mode)
+
+/* Value is 1 if hard register "regno" can hold a value
+ of machine-mode "mode". */
+#define HARD_REGNO_MODE_OK(regno, mode) nds32_hard_regno_mode_ok (regno, mode)
+
+/* A C expression that is nonzero if a value of mode1
+ is accessible in mode2 without copying.
+ Define this macro to return nonzero in as many cases as possible
+ since doing so will allow GCC to perform better register allocation.
+ We can use general registers to tie QI/HI/SI modes together. */
+#define MODES_TIEABLE_P(mode1, mode2) \
+ (GET_MODE_CLASS (mode1) == MODE_INT \
+ && GET_MODE_CLASS (mode2) == MODE_INT \
+ && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD \
+ && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD)
+
+
+/* Register Classes. */
+
+/* In nds32 target, we have three levels of registers:
+ Low cost regsiters : $r0 ~ $r7
+ Middle cost registers : $r8 ~ $r11, $r16 ~ $r19
+ High cost registers : $r12 ~ $r14, $r20 ~ $r31
+
+ In practice, we have MIDDLE_REGS cover LOW_REGS register class contents
+ so that it provides more chance to use low cost registers. */
+enum reg_class
+{
+ NO_REGS,
+ R15_TA_REG,
+ STACK_REG,
+ LOW_REGS,
+ MIDDLE_REGS,
+ HIGH_REGS,
+ GENERAL_REGS,
+ FRAME_REGS,
+ ALL_REGS,
+ LIM_REG_CLASSES
+};
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+#define REG_CLASS_NAMES \
+{ \
+ "NO_REGS", \
+ "R15_TA_REG", \
+ "STACK_REG", \
+ "LOW_REGS", \
+ "MIDDLE_REGS", \
+ "HIGH_REGS", \
+ "GENERAL_REGS", \
+ "FRAME_REGS", \
+ "ALL_REGS" \
+}
+
+#define REG_CLASS_CONTENTS \
+{ \
+ {0x00000000, 0x00000000}, /* NO_REGS : */ \
+ {0x00008000, 0x00000000}, /* R15_TA_REG : 15 */ \
+ {0x80000000, 0x00000000}, /* STACK_REG : 31 */ \
+ {0x000000ff, 0x00000000}, /* LOW_REGS : 0-7 */ \
+ {0x000f0fff, 0x00000000}, /* MIDDLE_REGS : 0-11, 16-19 */ \
+ {0xfff07000, 0x00000000}, /* HIGH_REGS : 12-14, 20-31 */ \
+ {0xffffffff, 0x00000000}, /* GENERAL_REGS: 0-31 */ \
+ {0x00000000, 0x00000003}, /* FRAME_REGS : 32, 33 */ \
+ {0xffffffff, 0x00000003} /* ALL_REGS : 0-31, 32, 33 */ \
+}
+
+#define REGNO_REG_CLASS(regno) nds32_regno_reg_class (regno)
+
+#define BASE_REG_CLASS GENERAL_REGS
+#define INDEX_REG_CLASS GENERAL_REGS
+
+/* Return nonzero if it is suitable for use as a
+ base register in operand addresses.
+ So far, we return nonzero only if "num" is a hard reg
+ of the suitable class or a pseudo register which is
+ allocated to a suitable hard reg. */
+#define REGNO_OK_FOR_BASE_P(num) \
+ ((num) < 32 || (unsigned) reg_renumber[num] < 32)
+
+/* Return nonzero if it is suitable for use as a
+ index register in operand addresses.
+ So far, we return nonzero only if "num" is a hard reg
+ of the suitable class or a pseudo register which is
+ allocated to a suitable hard reg.
+ The difference between an index register and a base register is that
+ the index register may be scaled. */
+#define REGNO_OK_FOR_INDEX_P(num) \
+ ((num) < 32 || (unsigned) reg_renumber[num] < 32)
+
+
+/* Obsolete Macros for Defining Constraints. */
+
+
+/* Stack Layout and Calling Conventions. */
+
+#define STACK_GROWS_DOWNWARD
+
+#define FRAME_GROWS_DOWNWARD 1
+
+#define STARTING_FRAME_OFFSET 0
+
+#define STACK_POINTER_OFFSET 0
+
+#define FIRST_PARM_OFFSET(fundecl) 0
+
+#define RETURN_ADDR_RTX(count, frameaddr) \
+ nds32_return_addr_rtx (count, frameaddr)
+
+/* A C expression whose value is RTL representing the location
+ of the incoming return address at the beginning of any function
+ before the prologue.
+ If this RTL is REG, you should also define
+ DWARF_FRAME_RETURN_COLUMN to DWARF_FRAME_REGNUM (REGNO). */
+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, LP_REGNUM)
+#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (LP_REGNUM)
+
+#define STACK_POINTER_REGNUM SP_REGNUM
+
+#define FRAME_POINTER_REGNUM 33
+
+#define HARD_FRAME_POINTER_REGNUM FP_REGNUM
+
+#define ARG_POINTER_REGNUM 32
+
+#define STATIC_CHAIN_REGNUM 16
+
+#define ELIMINABLE_REGS \
+{ { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }, \
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM } }
+
+#define INITIAL_ELIMINATION_OFFSET(from_reg, to_reg, offset_var) \
+ (offset_var) = nds32_initial_elimination_offset (from_reg, to_reg)
+
+#define ACCUMULATE_OUTGOING_ARGS 1
+
+#define OUTGOING_REG_PARM_STACK_SPACE(fntype) 1
+
+#define CUMULATIVE_ARGS nds32_cumulative_args
+
+#define INIT_CUMULATIVE_ARGS(cum, fntype, libname, fndecl, n_named_args) \
+ nds32_init_cumulative_args (&cum, fntype, libname, fndecl, n_named_args)
+
+/* The REGNO is an unsigned integer but NDS32_GPR_ARG_FIRST_REGNUM may be 0.
+ We better cast REGNO into signed integer so that we can avoid
+ 'comparison of unsigned expression >= 0 is always true' warning. */
+#define FUNCTION_ARG_REGNO_P(regno) \
+ (((int) regno - NDS32_GPR_ARG_FIRST_REGNUM >= 0) \
+ && ((int) regno - NDS32_GPR_ARG_FIRST_REGNUM < NDS32_MAX_REGS_FOR_ARGS))
+
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning
+ from a function, the stack pointer does not matter.
+ The value is tested only in functions that have frame pointers.
+ In nds32 target, the function epilogue recovers the
+ stack pointer from the frame. */
+#define EXIT_IGNORE_STACK 1
+
+#define FUNCTION_PROFILER(file, labelno) \
+ fprintf (file, "/* profiler %d */", (labelno))
+
+
+/* Implementing the Varargs Macros. */
+
+
+/* Trampolines for Nested Functions. */
+
+/* Giving A-function and B-function,
+ if B-function wants to call A-function's nested function,
+ we need to fill trampoline code into A-function's stack
+ so that B-function can execute the code in stack to indirectly
+ jump to (like 'trampoline' action) desired nested function.
+
+ The trampoline code for nds32 target must contains following parts:
+
+ 1. instructions (4 * 4 = 16 bytes):
+ get $pc first
+ load chain_value to static chain register via $pc
+ load nested function address to $r15 via $pc
+ jump to desired nested function via $r15
+ 2. data (4 * 2 = 8 bytes):
+ chain_value
+ nested function address
+
+ Please check nds32.c implementation for more information. */
+#define TRAMPOLINE_SIZE 24
+
+/* Because all instructions/data in trampoline template are 4-byte size,
+ we set trampoline alignment 8*4=32 bits. */
+#define TRAMPOLINE_ALIGNMENT 32
+
+
+/* Implicit Calls to Library Routines. */
+
+
+/* Addressing Modes. */
+
+/* We can use "LWI.bi Rt, [Ra], 4" to support post increment. */
+#define HAVE_POST_INCREMENT 1
+/* We can use "LWI.bi Rt, [Ra], -4" to support post decrement. */
+#define HAVE_POST_DECREMENT 1
+
+/* We have "LWI.bi Rt, [Ra], imm" instruction form. */
+#define HAVE_POST_MODIFY_DISP 1
+/* We have "LW.bi Rt, [Ra], Rb" instruction form. */
+#define HAVE_POST_MODIFY_REG 1
+
+#define CONSTANT_ADDRESS_P(x) (CONSTANT_P (x) && GET_CODE (x) != CONST_DOUBLE)
+
+#define MAX_REGS_PER_ADDRESS 2
+
+
+/* Anchored Addresses. */
+
+
+/* Condition Code Status. */
+
+
+/* Describing Relative Costs of Operations. */
+
+/* A C expression for the cost of a branch instruction.
+ A value of 1 is the default;
+ other values are interpreted relative to that. */
+#define BRANCH_COST(speed_p, predictable_p) ((speed_p) ? 2 : 0)
+
+#define SLOW_BYTE_ACCESS 1
+
+#define NO_FUNCTION_CSE
+
+
+/* Adjusting the Instruction Scheduler. */
+
+
+/* Dividing the Output into Sections (Texts, Data, . . . ). */
+
+#define TEXT_SECTION_ASM_OP "\t.text"
+#define DATA_SECTION_ASM_OP "\t.data"
+
+/* Currently, nds32 assembler does NOT handle '.bss' pseudo-op.
+ So we use '.section .bss' alternatively. */
+#define BSS_SECTION_ASM_OP "\t.section\t.bss"
+
+/* Define this macro to be an expression with a nonzero value if jump tables
+ (for tablejump insns) should be output in the text section,
+ along with the assembler instructions.
+ Otherwise, the readonly data section is used. */
+#define JUMP_TABLES_IN_TEXT_SECTION 1
+
+
+/* Position Independent Code. */
+
+
+/* Defining the Output Assembler Language. */
+
+#define ASM_COMMENT_START "!"
+
+#define ASM_APP_ON "! #APP"
+
+#define ASM_APP_OFF "! #NO_APP\n"
+
+#define ASM_OUTPUT_LABELREF(stream, name) \
+ asm_fprintf (stream, "%U%s", (*targetm.strip_name_encoding) (name))
+
+#define ASM_OUTPUT_SYMBOL_REF(stream, sym) \
+ assemble_name (stream, XSTR (sym, 0))
+
+#define ASM_OUTPUT_LABEL_REF(stream, buf) \
+ assemble_name (stream, buf)
+
+#define LOCAL_LABEL_PREFIX "."
+
+#define REGISTER_NAMES \
+{ \
+ "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7", \
+ "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$ta", \
+ "$r16", "$r17", "$r18", "$r19", "$r20", "$r21", "$r22", "$r23", \
+ "$r24", "$r25", "$r26", "$r27", "$fp", "$gp", "$lp", "$sp", \
+ "$AP", \
+ "$SFP" \
+}
+
+/* Output normal jump table entry. */
+#define ASM_OUTPUT_ADDR_VEC_ELT(stream, value) \
+ asm_fprintf (stream, "\t.word\t%LL%d\n", value)
+
+/* Output pc relative jump table entry. */
+#define ASM_OUTPUT_ADDR_DIFF_ELT(stream, body, value, rel) \
+ do \
+ { \
+ switch (GET_MODE (body)) \
+ { \
+ case QImode: \
+ asm_fprintf (stream, "\t.byte\t.L%d-.L%d\n", value, rel); \
+ break; \
+ case HImode: \
+ asm_fprintf (stream, "\t.short\t.L%d-.L%d\n", value, rel); \
+ break; \
+ case SImode: \
+ asm_fprintf (stream, "\t.word\t.L%d-.L%d\n", value, rel); \
+ break; \
+ default: \
+ gcc_unreachable(); \
+ } \
+ } while (0)
+
+/* We have to undef it first because elfos.h formerly define it
+ check gcc/config.gcc and gcc/config/elfos.h for more information. */
+#undef ASM_OUTPUT_CASE_LABEL
+#define ASM_OUTPUT_CASE_LABEL(stream, prefix, num, table) \
+ do \
+ { \
+ asm_fprintf (stream, "\t! Jump Table Begin\n"); \
+ (*targetm.asm_out.internal_label) (stream, prefix, num); \
+ } while (0)
+
+#define ASM_OUTPUT_CASE_END(stream, num, table) \
+ do \
+ { \
+ /* Because our jump table is in text section, \
+ we need to make sure 2-byte alignment after \
+ the jump table for instructions fetch. */ \
+ if (GET_MODE (PATTERN (table)) == QImode) \
+ ASM_OUTPUT_ALIGN (stream, 1); \
+ asm_fprintf (stream, "\t! Jump Table End\n"); \
+ } while (0)
+
+/* This macro is not documented yet.
+ But we do need it to make jump table vector aligned. */
+#define ADDR_VEC_ALIGN(JUMPTABLE) 2
+
+#define DWARF2_UNWIND_INFO 1
+
+#define JUMP_ALIGN(x) \
+ (align_jumps_log ? align_jumps_log : nds32_target_alignment (x))
+
+#define LOOP_ALIGN(x) \
+ (align_loops_log ? align_loops_log : nds32_target_alignment (x))
+
+#define LABEL_ALIGN(x) \
+ (align_labels_log ? align_labels_log : nds32_target_alignment (x))
+
+#define ASM_OUTPUT_ALIGN(stream, power) \
+ fprintf (stream, "\t.align\t%d\n", power)
+
+
+/* Controlling Debugging Information Format. */
+
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+#define DWARF2_DEBUGGING_INFO 1
+
+#define DWARF2_ASM_LINE_DEBUG_INFO 1
+
+
+/* Cross Compilation and Floating Point. */
+
+
+/* Mode Switching Instructions. */
+
+
+/* Defining target-specific uses of __attribute__. */
+
+
+/* Emulating TLS. */
+
+
+/* Defining coprocessor specifics for MIPS targets. */
+
+
+/* Parameters for Precompiled Header Validity Checking. */
+
+
+/* C++ ABI parameters. */
+
+
+/* Adding support for named address spaces. */
+
+
+/* Miscellaneous Parameters. */
+
+/* This is the machine mode that elements of a jump-table should have. */
+#define CASE_VECTOR_MODE Pmode
+
+/* Return the preferred mode for and addr_diff_vec when the mininum
+ and maximum offset are known. */
+#define CASE_VECTOR_SHORTEN_MODE(min_offset, max_offset, body) \
+ ((min_offset < 0 || max_offset >= 0x2000 ) ? SImode \
+ : (max_offset >= 100) ? HImode \
+ : QImode)
+
+/* Generate pc relative jump table when -fpic or -Os. */
+#define CASE_VECTOR_PC_RELATIVE (flag_pic || optimize_size)
+
+/* Define this macro if operations between registers with integral mode
+ smaller than a word are always performed on the entire register. */
+#define WORD_REGISTER_OPERATIONS
+
+/* A C expression indicating when insns that read memory in mem_mode,
+ an integral mode narrower than a word, set the bits outside of mem_mode
+ to be either the sign-extension or the zero-extension of the data read. */
+#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
+
+/* The maximum number of bytes that a single instruction can move quickly
+ between memory and registers or between two memory locations. */
+#define MOVE_MAX 4
+
+/* A C expression that is nonzero if on this machine the number of bits
+ actually used for the count of a shift operation is equal to the number
+ of bits needed to represent the size of the object being shifted. */
+#define SHIFT_COUNT_TRUNCATED 1
+
+/* A C expression which is nonzero if on this machine it is safe to "convert"
+ an integer of 'inprec' bits to one of 'outprec' bits by merely operating
+ on it as if it had only 'outprec' bits. */
+#define TRULY_NOOP_TRUNCATION(outprec, inprec) 1
+
+/* A C expression describing the value returned by a comparison operator with
+ an integral mode and stored by a store-flag instruction ('cstoremode4')
+ when the condition is true. */
+#define STORE_FLAG_VALUE 1
+
+/* An alias for the machine mode for pointers. */
+#define Pmode SImode
+
+/* An alias for the machine mode used for memory references to functions
+ being called, in call RTL expressions. */
+#define FUNCTION_MODE SImode
+
+/* ------------------------------------------------------------------------ */