From 5c3ea8054637ec397cdc68b22f3c06ce7920a205 Mon Sep 17 00:00:00 2001 From: Jim Wilson Date: Thu, 18 Jan 1996 14:40:12 -0800 Subject: [PATCH] (CPP_SPEC, CONDITIONAL_REGISTER_USAGE, TARGET_SWITCHES, OVERRIDE_OPTIONS, FIRST_PSEUDO_REGISTER, FIXED_REGISTERS, CALL_USED_REGISTERS, HARD_REGNO_MODE_OK, enum reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS, REG_ALLOC_ORDER, CONST_DOUBLE_OK_FOR_LETTER_P, NPARM_REGS, FUNCTION_VALUE, LIBCALL_VALUE, FUNCTION_VALUE_REGNO_P, FUNCTION_ARG_REGNO_P, CUMULATIVE_ARGS, ROUND_REG, INIT_CUMULATIVE_ARGS, FUNCTION_ARG_ADVANCE, FUNCTION_ARG, FUNCTION_ARG_PARTIAL_NREGS, LEGITIMATE_CONSTANT_P, MODE_DISP_OK_4, REGISTER_MOVE_COST, REGISTER_NAMES, DBX_REGISTER_NUMBER, enum processor_type): Add SH3E support. (SH3E_BIT, TARGET_SH3E, FPUL_REG, FIRST_FP_REG, LAST_FP_REG, FIRST_FP_PARM_REG, FIRST_FP_RET_REG, BASE_RETURN_VALUE_REG, BASE_ARG_REG, enum sh_arg_class, struct sh_args, GET_SH_ARG_CLASS, PASS_IN_REG_P, sh_builtin_saveregs, EXPAND_BUILTIN_SAVEREGS, DOUBLE_TYPE_SIZE): New. (TARGET_SWITCHES): Delete broken -m3l option. From-SVN: r11067 --- gcc/config/sh/sh.h | 225 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 177 insertions(+), 48 deletions(-) diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index 6c346711a5f..0a41c2984f4 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -34,7 +34,7 @@ Boston, MA 02111-1307, USA. */ #define SDB_DELIM ";" -#define CPP_SPEC "%{ml:-D__LITTLE_ENDIAN__}" +#define CPP_SPEC "%{ml:-D__LITTLE_ENDIAN__} %{m3e:-D__SH3E__}" #define CPP_PREDEFINES "-D__sh__ -Acpu(sh) -Amachine(sh)" @@ -46,6 +46,12 @@ Boston, MA 02111-1307, USA. */ /* #define CAN_DEBUG_WITHOUT_FP */ #define CONDITIONAL_REGISTER_USAGE \ + if (! TARGET_SH3E) \ + { \ + int regno; \ + for (regno = FIRST_FP_REG; regno <= LAST_FP_REG; regno++) \ + fixed_regs[regno] = call_used_regs[regno] = 1; \ + } \ /* Hitachi saves and restores mac registers on call. */ \ if (TARGET_HITACHI) \ { \ @@ -65,6 +71,7 @@ extern int target_flags; #define SH1_BIT (1<<8) #define SH2_BIT (1<<9) #define SH3_BIT (1<<10) +#define SH3E_BIT (1<<11) #define SPACE_BIT (1<<13) #define BIGTABLE_BIT (1<<14) #define RELAX_BIT (1<<15) @@ -92,6 +99,9 @@ extern int target_flags; /* Nonzero if we should generate code using type 3 insns. */ #define TARGET_SH3 (target_flags & SH3_BIT) +/* Nonzero if we should generate code using type 3E insns. */ +#define TARGET_SH3E (target_flags & SH3E_BIT) + /* Nonzero if we should generate smaller code rather than faster code. */ #define TARGET_SMALLCODE (target_flags & SPACE_BIT) @@ -120,7 +130,7 @@ extern int target_flags; {"1", SH1_BIT}, \ {"2", SH2_BIT}, \ {"3", SH3_BIT|SH2_BIT}, \ - {"3l", SH3_BIT|SH2_BIT|LITTLE_ENDIAN_BIT}, \ + {"3e", SH3E_BIT|SH3_BIT|SH2_BIT}, \ {"b", -LITTLE_ENDIAN_BIT}, \ {"bigtable", BIGTABLE_BIT}, \ {"dalign", DALIGN_BIT}, \ @@ -144,6 +154,8 @@ do { \ sh_cpu = CPU_SH2; \ if (TARGET_SH3) \ sh_cpu = CPU_SH3; \ + if (TARGET_SH3E) \ + sh_cpu = CPU_SH3E; \ \ /* Never run scheduling before reload, since that can \ break global alloc, and generates slower code anyway due \ @@ -252,7 +264,12 @@ do { \ pr subroutine return address t t bit mach multiply/accumulate result, high part - macl multiply/accumulate result, low part. */ + macl multiply/accumulate result, low part. + fpul fp/int communication register + fr0 fp arg return + fr1..fr3 scratch floating point registers + fr4..fr11 fp args in + fr12..fr15 call saved floating point registers */ /* Number of actual hardware registers. The hardware registers are assigned numbers for the compiler @@ -267,8 +284,12 @@ do { \ #define MACH_REG 20 #define MACL_REG 21 #define SPECIAL_REG(REGNO) ((REGNO) >= 18 && (REGNO) <= 21) +#define FPUL_REG 22 +/* Number 23 is unused. Reserved for future expansion. */ +#define FIRST_FP_REG 24 +#define LAST_FP_REG 39 -#define FIRST_PSEUDO_REGISTER 22 +#define FIRST_PSEUDO_REGISTER 40 /* 1 for registers that have pervasive standard uses and are not available for the register allocator. @@ -282,7 +303,12 @@ do { \ 0, 0, 0, 0, \ 0, 0, 0, 1, \ 1, 1, 1, 1, \ - 1, 1} + 1, 1, 1, 1, \ + 0, 0, 0, 0, \ + 0, 0, 0, 0, \ + 0, 0, 0, 0, \ + 0, 0, 0, 0 \ +} /* 1 for registers not available across function calls. These must include the FIXED_REGISTERS and also any @@ -292,12 +318,17 @@ do { \ Aside from that, you can include as many other registers as you like. */ #define CALL_USED_REGISTERS \ - { 1, 1, 1, 1, \ - 1, 1, 1, 1, \ - 0, 0, 0, 0, \ - 0, 0, 0, 1, \ - 1, 0, 1, 1, \ - 1, 1} + { 1, 1, 1, 1, \ + 1, 1, 1, 1, \ + 0, 0, 0, 0, \ + 0, 0, 0, 1, \ + 1, 0, 1, 1, \ + 1, 1, 1, 1, \ + 1, 1, 1, 1, \ + 1, 1, 1, 1, \ + 1, 1, 1, 1, \ + 0, 0, 0, 0 \ +} /* Return number of consecutive hard regs needed starting at reg REGNO to hold something of mode MODE. @@ -315,6 +346,8 @@ do { \ #define HARD_REGNO_MODE_OK(REGNO, MODE) \ (SPECIAL_REG (REGNO) ? (MODE) == SImode \ + : (REGNO) == FPUL_REG ? (MODE) == SImode || (MODE) == SFmode \ + : (REGNO) >= FIRST_FP_REG && (REGNO) <= LAST_FP_REG ? (MODE) == SFmode \ : (REGNO) == PR_REG ? 0 \ : 1) @@ -427,6 +460,9 @@ enum reg_class T_REGS, MAC_REGS, GENERAL_REGS, + FPUL_REGS, + FP0_REGS, + FP_REGS, ALL_REGS, LIM_REG_CLASSES }; @@ -442,6 +478,9 @@ enum reg_class "T_REGS", \ "MAC_REGS", \ "GENERAL_REGS", \ + "FPUL_REGS", \ + "FP0_REGS", \ + "FP_REGS", \ "ALL_REGS", \ } @@ -449,15 +488,18 @@ enum reg_class This is an initializer for a vector of HARD_REG_SET of length N_REG_CLASSES. */ -#define REG_CLASS_CONTENTS \ -{ \ - 0x000000, /* NO_REGS */ \ - 0x000001, /* R0_REGS */ \ - 0x020000, /* PR_REGS */ \ - 0x040000, /* T_REGS */ \ - 0x300000, /* MAC_REGS */ \ - 0x01FFFF, /* GENERAL_REGS */ \ - 0x37FFFF /* ALL_REGS */ \ +#define REG_CLASS_CONTENTS \ +{ \ + { 0x00000000, 0x00000000 }, /* NO_REGS */ \ + { 0x00000001, 0x00000000 }, /* R0_REGS */ \ + { 0x00020000, 0x00000000 }, /* PR_REGS */ \ + { 0x00040000, 0x00000000 }, /* T_REGS */ \ + { 0x00300000, 0x00000000 }, /* MAC_REGS */ \ + { 0x0001FFFF, 0x00000000 }, /* GENERAL_REGS */ \ + { 0x00400000, 0x00000000 }, /* FPUL_REGS */ \ + { 0x01000000, 0x00000000 }, /* FP0_REGS */ \ + { 0xFF000000, 0x000000FF }, /* FP_REGS */ \ + { 0xFF7FFFFF, 0x000000FF }, /* ALL_REGS */ \ } /* The same information, inverted: @@ -476,7 +518,9 @@ extern int regno_reg_class[]; /* The order in which register should be allocated. */ #define REG_ALLOC_ORDER \ - { 1,2,3,7,6,5,4,0,8,9,10,11,12,13,14,15,16,17,18,19,20,21 } + { 1,2,3,7,6,5,4,0,8,9,10,11,12,13,14, \ + 24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39, \ + 22,15,16,17,18,19,20,21,23 } /* The class value for index registers, and the one for base regs. */ #define INDEX_REG_CLASS R0_REGS @@ -518,6 +562,12 @@ extern enum reg_class reg_class_from_letter[]; #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0 +#undef CONST_DOUBLE_OK_FOR_LETTER_P +#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ +((C) == 'G' ? fp_zero_operand (VALUE) \ + : (C) == 'H' ? fp_one_operand (VALUE) \ + : 0) + /* Given an rtx X being reloaded into a reg required to be in class CLASS, return the class of reg to actually use. In general this is just CLASS; but on some machines @@ -535,11 +585,17 @@ extern enum reg_class reg_class_from_letter[]; /* Stack layout; function entry, exit and calling. */ /* Define the number of registers that can hold parameters. - These three macros are used only in other macro definitions below. */ -#define NPARM_REGS 4 + These macros are used only in other macro definitions below. */ + +#define NPARM_REGS(MODE) \ + ((TARGET_SH3E && ((MODE) == SFmode)) ? 8 : 4) + #define FIRST_PARM_REG 4 #define FIRST_RET_REG 0 +#define FIRST_FP_PARM_REG (FIRST_FP_REG + 4) +#define FIRST_FP_RET_REG FIRST_FP_REG + /* Define this if pushing a word on the stack makes the stack pointer a smaller address. */ #define STACK_GROWS_DOWNWARD @@ -572,26 +628,39 @@ extern enum reg_class reg_class_from_letter[]; on the stack. */ #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 +/* Some subroutine macros specific to this machine. */ + +#define BASE_RETURN_VALUE_REG(MODE) \ + ((TARGET_SH3E && ((MODE) == SFmode)) \ + ? FIRST_FP_RET_REG \ + : FIRST_RET_REG) + +#define BASE_ARG_REG(MODE) \ + ((TARGET_SH3E && ((MODE) == SFmode)) \ + ? FIRST_FP_PARM_REG \ + : FIRST_PARM_REG) + /* Define how to find the value returned by a function. VALTYPE is the data type of the value (as a tree). If the precise function being called is known, FUNC is its FUNCTION_DECL; otherwise, FUNC is 0. */ #define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx (REG, TYPE_MODE (VALTYPE), FIRST_RET_REG) - + LIBCALL_VALUE (TYPE_MODE (VALTYPE)) + /* Define how to find the value returned by a library function assuming the value has mode MODE. */ -#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, FIRST_RET_REG) +#define LIBCALL_VALUE(MODE) \ + gen_rtx (REG, MODE, BASE_RETURN_VALUE_REG (MODE)); -/* 1 if N is a possible register number for a function value. - On the SH, only r0 can return results. */ -#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == FIRST_RET_REG) +/* 1 if N is a possible register number for a function value. */ +#define FUNCTION_VALUE_REGNO_P(REGNO) \ + ((REGNO) == FIRST_RET_REG || (REGNO) == FIRST_FP_RET_REG) /* 1 if N is a possible register number for function argument passing. */ - #define FUNCTION_ARG_REGNO_P(REGNO) \ - ((REGNO) >= FIRST_PARM_REG && (REGNO) < (NPARM_REGS + FIRST_PARM_REG)) + (((REGNO) >= FIRST_PARM_REG && (REGNO) < (FIRST_PARM_REG + 4)) \ + || ((REGNO >= FIRST_FP_PARM_REG && (REGNO) < (FIRST_FP_PARM_REG + 8)))) /* Define a data type for recording info about an argument list during the scan of that argument list. This data type should @@ -604,7 +673,15 @@ extern enum reg_class reg_class_from_letter[]; if any, which holds the structure-value-address). Thus NARGREGS or more means all following args should go on the stack. */ -#define CUMULATIVE_ARGS int +enum sh_arg_class { SH_ARG_INT = 0, SH_ARG_FLOAT = 1 }; +struct sh_args { + int arg_count[2]; +}; + +#define CUMULATIVE_ARGS struct sh_args + +#define GET_SH_ARG_CLASS(MODE) \ + ((TARGET_SH3E && ((MODE) == SFmode)) ? SH_ARG_FLOAT : SH_ARG_INT) #define ROUND_ADVANCE(SIZE) \ ((SIZE + UNITS_PER_WORD - 1) / UNITS_PER_WORD) @@ -615,10 +692,12 @@ extern enum reg_class reg_class_from_letter[]; The SH doesn't care about double alignment, so we only round doubles to even regs when asked to explicitly. */ -#define ROUND_REG(X, MODE) \ - ((TARGET_ALIGN_DOUBLE \ - && GET_MODE_UNIT_SIZE ((MODE)) > UNITS_PER_WORD) \ - ? ((X) + ((X) & 1)) : (X)) +#define ROUND_REG(CUM, MODE) \ + ((TARGET_ALIGN_DOUBLE \ + && GET_MODE_UNIT_SIZE ((MODE)) > UNITS_PER_WORD) \ + ? ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)] \ + + ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)] & 1)) \ + : (CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)]) /* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE. @@ -628,7 +707,10 @@ extern enum reg_class reg_class_from_letter[]; the same reg. */ #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME) \ - ((CUM) = 0) + do { \ + (CUM).arg_count[(int) SH_ARG_INT] = 0; \ + (CUM).arg_count[(int) SH_ARG_FLOAT] = 0; \ + } while (0) /* Update the data in CUM to advance over an argument of mode MODE and data type TYPE. @@ -636,11 +718,20 @@ extern enum reg_class reg_class_from_letter[]; available.) */ #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - ((CUM) = (ROUND_REG ((CUM), (MODE)) \ + ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)] = \ + (ROUND_REG ((CUM), (MODE)) \ + ((MODE) != BLKmode \ ? ROUND_ADVANCE (GET_MODE_SIZE (MODE)) \ : ROUND_ADVANCE (int_size_in_bytes (TYPE))))) +/* Return boolean indicating arg of mode MODE will be passed in a reg. + This macro is only used in this file. */ + +#define PASS_IN_REG_P(CUM, MODE, TYPE) \ + (ROUND_REG ((CUM), (MODE)) < NPARM_REGS (MODE) \ + && ((TYPE)==0 || ! TREE_ADDRESSABLE((tree)(TYPE))) \ + && ((TYPE)==0 || (MODE) != BLKmode)) + /* Define where to put the arguments to a function. Value is zero to push the argument on the stack, or a hard register in which to store the argument. @@ -660,9 +751,11 @@ extern enum reg_class reg_class_from_letter[]; its data type forbids. */ #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - sh_function_arg (CUM, MODE, TYPE, NAMED) - -extern struct rtx_def *sh_function_arg(); + ((PASS_IN_REG_P ((CUM), (MODE), (TYPE)) \ + && (NAMED || TARGET_SH3E)) \ + ? gen_rtx (REG, (MODE), \ + (BASE_ARG_REG (MODE) + ROUND_REG ((CUM), (MODE)))) \ + : 0) /* For an arg passed partly in registers and partly in memory, this is the number of registers used. @@ -671,7 +764,15 @@ extern struct rtx_def *sh_function_arg(); We sometimes split args. */ #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ - sh_function_arg_partial_nregs (CUM, MODE, TYPE, NAMED) + ((PASS_IN_REG_P ((CUM), (MODE), (TYPE)) \ + && (NAMED || TARGET_SH3E) \ + && (ROUND_REG ((CUM), (MODE)) \ + + (MODE != BLKmode \ + ? ROUND_ADVANCE (GET_MODE_SIZE (MODE)) \ + : ROUND_ADVANCE (int_size_in_bytes (TYPE))) \ + - NPARM_REGS (MODE) > 0)) \ + ? NPARM_REGS (MODE) - ROUND_REG ((CUM), (MODE)) \ + : 0) extern int current_function_anonymous_args; @@ -744,6 +845,11 @@ extern int current_function_anonymous_args; (FNADDR)); \ } +/* Generate necessary RTL for __builtin_saveregs(). + ARGLIST is the argument list; see expr.c. */ +extern struct rtx_def *sh_builtin_saveregs (); +#define EXPAND_BUILTIN_SAVEREGS(ARGLIST) sh_builtin_saveregs (ARGLIST) + /* Addressing modes, and classification of registers for them. */ #define HAVE_POST_INCREMENT 1 /*#define HAVE_PRE_INCREMENT 1*/ @@ -778,7 +884,10 @@ extern int current_function_anonymous_args; constant pool table code to fix loads of CONST_DOUBLEs. If that doesn't work well, then we can at least handle simple CONST_DOUBLEs here such as 0.0. */ -#define LEGITIMATE_CONSTANT_P(X) (GET_CODE(X) != CONST_DOUBLE) + +#define LEGITIMATE_CONSTANT_P(X) \ + (GET_CODE (X) != CONST_DOUBLE \ + || (TARGET_SH3E && (fp_zero_operand (X) || fp_one_operand (X)))) /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx and check its validity for a certain class. @@ -840,7 +949,9 @@ extern int current_function_anonymous_args; The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS. */ -#define MODE_DISP_OK_4(X,MODE) ((GET_MODE_SIZE(MODE)==4) && ((unsigned)INTVAL(X)<64) && (!(INTVAL(X) &3))) +#define MODE_DISP_OK_4(X,MODE) \ +(GET_MODE_SIZE (MODE) == 4 && (unsigned) INTVAL (X) < 64 \ + && ! (INTVAL (X) & 3) && ! (TARGET_SH3E && MODE == SFmode)) #define MODE_DISP_OK_8(X,MODE) ((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60) && (!(INTVAL(X) &3))) #define BASE_REGISTER_RTX_P(X) \ @@ -868,6 +979,11 @@ extern int current_function_anonymous_args; REG++ --REG */ +/* ??? The SH3e does not have the REG+disp addressing mode when loading values + into the FRx registers. We implement this by setting the maximum offset + to zero when the value is SFmode. This also restricts loading of SFmode + values into the integer registers, but that can't be helped. */ + /* The SH allows a displacement in a QI or HI amode, but only when the other operand is R0. GCC doesn't handle this very well, so we forgo all of that. @@ -945,6 +1061,10 @@ extern int current_function_anonymous_args; /* This is the kind of divide that is easiest to do in the general case. */ #define EASY_DIV_EXPR TRUNC_DIV_EXPR +/* Since the SH3e has only `float' support, it is desirable to make all + floating point types equivalent to `float'. */ +#define DOUBLE_TYPE_SIZE (TARGET_SH3E ? 32 : 64) + /* 'char' is signed by default. */ #define DEFAULT_SIGNED_CHAR 1 @@ -1094,7 +1214,10 @@ extern int current_function_anonymous_args; from it. */ #define REGISTER_MOVE_COST(SRCCLASS, DSTCLASS) \ - (((DSTCLASS == T_REGS) || (DSTCLASS == PR_REG)) ? 10 : 1) + (((DSTCLASS == T_REGS) || (DSTCLASS == PR_REG)) ? 10 \ + : ((DSTCLASS == FP_REGS && SRCCLASS == GENERAL_REGS) \ + || (DSTCLASS == GENERAL_REGS && SRCCLASS == FP_REGS)) ? 4 \ + : 1) /* ??? Perhaps make MEMORY_MOVE_COST depend on compiler option? This would be so that people would slow memory systems could generate @@ -1197,11 +1320,16 @@ dtors_section() \ { \ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \ - "ap", "pr", "t", "gbr", "mach","macl" \ + "ap", "pr", "t", "gbr", "mach","macl", "fpul", "X", \ + "fr0","fr1","fr2", "fr3", "fr4", "fr5", "fr6", "fr7", \ + "fr8","fr9","fr10","fr11","fr12","fr13","fr14","fr15",\ } /* DBX register number for a given compiler register number. */ -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) +/* GDB has FPUL at 23 and FP0 at 25, so we must add one to all FP registers + to match gdb. */ +#define DBX_REGISTER_NUMBER(REGNO) \ + (((REGNO) >= 22 && (REGNO) <= 39) ? ((REGNO) + 1) : (REGNO)) /* Output a label definition. */ #define ASM_OUTPUT_LABEL(FILE,NAME) \ @@ -1363,7 +1491,8 @@ enum processor_type { PROCESSOR_SH0, PROCESSOR_SH1, PROCESSOR_SH2, - PROCESSOR_SH3 + PROCESSOR_SH3, + PROCESSOR_SH3E }; #define sh_cpu_attr ((enum attr_cpu)sh_cpu)