--- gcc/config/sparc/sparc.h 2018/04/24 18:10:25 1.1 +++ gcc/config/sparc/sparc.h 2018/04/24 18:15:14 1.1.1.2 @@ -34,7 +34,8 @@ the Free Software Foundation, 675 Mass A #define ASM_SPEC " %| %{fpic:-k} %{fPIC:-k}" /* Define macros to distinguish architectures. */ -#define CPP_SPEC "%{msparclite:-D__sparclite__} %{mv8:-D__sparc_v8__}" +#define CPP_SPEC "%{msparclite:-D__sparclite__} %{mf930:-D__sparclite__} \ +%{mf934:-D__sparclite__} %{mv8:-D__sparc_v8__}" /* Prevent error on `-sun4' and `-target sun4' options. */ /* This used to translate -dalign to -malign, but that is no good @@ -42,17 +43,6 @@ the Free Software Foundation, 675 Mass A #define CC1_SPEC "%{sun4:} %{target:}" -#if 0 -/* ??? This fails because REAL_VALUE_TYPE is `double' making it impossible to - represent and output `long double' constants. This causes problems during - a bootstrap with enquire/float.h, and hence must be disabled for now. - To fix, we need to implement code for TFmode just like the existing XFmode - support in real.[ch]. */ -/* Sparc ABI says that long double is 4 words. */ - -#define LONG_DOUBLE_TYPE_SIZE 128 -#endif - #define PTRDIFF_TYPE "int" /* In 2.4 it should work to delete this. #define SIZE_TYPE "int" */ @@ -74,8 +64,14 @@ the Free Software Foundation, 675 Mass A the frame pointer (because the return address will get smashed). */ #define OVERRIDE_OPTIONS \ - do { if (profile_flag || profile_block_flag) \ - flag_omit_frame_pointer = 0, flag_pic = 0; } while (0) +{ \ + if (profile_flag || profile_block_flag) \ + flag_omit_frame_pointer = 0, flag_pic = 0; \ + SUBTARGET_OVERRIDE_OPTIONS \ + } + +/* This is meant to be redefined in the host dependent files */ +#define SUBTARGET_OVERRIDE_OPTIONS /* These compiler options take an argument. We ignore -target for now. */ @@ -90,7 +86,9 @@ the Free Software Foundation, 675 Mass A because gcc does "gvarargs.h" instead of , and thus gets the wrong varargs file when it is compiled with a different version of gcc. */ -#define CPP_PREDEFINES "-Dsparc -Dsun -Dunix -D__GCC_NEW_VARARGS__" +#define CPP_PREDEFINES \ + "-Dsparc -Dsun -Dunix -D__GCC_NEW_VARARGS__ \ + -Asystem(unix) -Asystem(bsd) -Acpu(sparc) -Amachine(sparc)" /* Print subsidiary information on the compiler version in use. */ @@ -119,7 +117,9 @@ extern int target_flags; /* Nonzero means that we should generate code for a v8 sparc. */ #define TARGET_V8 (target_flags & 64) -/* Nonzero means that we should generate code for a sparclite. */ +/* Nonzero means that we should generate code for a sparclite. + This enables the sparclite specific instructions, but does not affect + whether FPU instructions are emitted. */ #define TARGET_SPARCLITE (target_flags & 128) /* Nonzero means that we should generate code using a flat register window @@ -144,6 +144,11 @@ extern int target_flags; where VALUE is the bits to set or minus the bits to clear. An empty string NAME is used to identify the default VALUE. */ +/* The Fujitsu MB86930 is the original sparclite chip, with no fpu. + The Fujitsu MB86934 is the recent sparclite chip, with an fup. + We use -mf930 and -mf934 options to choose which. + ??? These should perhaps be -mcpu= options. */ + #define TARGET_SWITCHES \ { {"fpu", 1}, \ {"no-fpu", -1}, \ @@ -156,19 +161,36 @@ extern int target_flags; {"v8", 64}, \ {"no-v8", -64}, \ {"sparclite", 128}, \ - {"sparclite", -1}, \ {"no-sparclite", -128}, \ - {"no-sparclite", 1}, \ /* {"frw", 256}, */ \ /* {"no-frw", -256}, */ \ /* {"frw-compat", 256+512}, */ \ /* {"no-frw-compat", -(256+512)}, */ \ + {"f930", 128}, \ + {"f930", -1}, \ + {"f934", 128}, \ + SUBTARGET_SWITCHES \ { "", TARGET_DEFAULT}} #define TARGET_DEFAULT 3 + +/* This is meant to be redefined in the host dependent files */ +#define SUBTARGET_SWITCHES /* target machine storage layout */ +#if 0 +/* ??? This does not work in SunOS 4.x, so it is not enabled here. + Instead, it is enabled in sol2.h, because it does work under Solaris. */ +/* Define for support of TFmode long double and REAL_ARITHMETIC. + Sparc ABI says that long double is 4 words. */ +#define LONG_DOUBLE_TYPE_SIZE 128 +#endif + +/* Define for cross-compilation to a sparc target with no TFmode from a host + with a different float format (e.g. VAX). */ +#define REAL_ARITHMETIC + /* Define this if most significant bit is lowest numbered in instructions that operate on numbered bit-fields. */ #define BITS_BIG_ENDIAN 1 @@ -427,9 +449,9 @@ extern int leaf_function; /* Base register for access to arguments of the function. */ #define ARG_POINTER_REGNUM 30 -/* Register in which static-chain is passed to a function. */ -/* ??? */ -#define STATIC_CHAIN_REGNUM 1 +/* Register in which static-chain is passed to a function. This must + not be a register used by the prologue. */ +#define STATIC_CHAIN_REGNUM 2 /* Register which holds offset table for position-independent data references. */ @@ -512,7 +534,7 @@ enum reg_class { NO_REGS, GENERAL_REGS, normally. We put %f0/%f1 last among the float registers, so as to make it more - likely that a pseduo-register which dies in the float return register + likely that a pseudo-register which dies in the float return register will get allocated to the float return register, thus saving a move instruction at the end of the function. */ #define REG_ALLOC_ORDER \ @@ -589,8 +611,7 @@ extern char leaf_reg_backmap[]; Here VALUE is the CONST_DOUBLE rtx itself. */ #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'G' ? CONST_DOUBLE_HIGH (VALUE) == 0 \ - && CONST_DOUBLE_LOW (VALUE) == 0 \ + ((C) == 'G' ? fp_zero_operand (VALUE) \ : (C) == 'H' ? arith_double_operand (VALUE, DImode) \ : 0) @@ -619,8 +640,7 @@ extern char leaf_reg_backmap[]; a paradoxical subreg in a float/fix conversion insn. */ #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN) \ - (flag_pic && pic_address_needs_scratch (IN) ? GENERAL_REGS \ - : ((CLASS) == FP_REGS && ((MODE) == HImode || (MODE) == QImode)\ + (((CLASS) == FP_REGS && ((MODE) == HImode || (MODE) == QImode)\ && (GET_CODE (IN) == MEM \ || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG) \ && true_regnum (IN) == -1))) ? GENERAL_REGS : NO_REGS) @@ -639,7 +659,8 @@ extern char leaf_reg_backmap[]; /* Return the stack location to use for secondary memory needed reloads. */ #define SECONDARY_MEMORY_NEEDED_RTX(MODE) \ - gen_rtx (MEM, MODE, gen_rtx (PLUS, Pmode, frame_pointer_rtx, GEN_INT (-8))) + gen_rtx (MEM, MODE, gen_rtx (PLUS, Pmode, frame_pointer_rtx, \ + GEN_INT (STARTING_FRAME_OFFSET))) /* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. */ @@ -667,7 +688,8 @@ extern char leaf_reg_backmap[]; If FRAME_GROWS_DOWNWARD, this is the offset to the END of the first local allocated. Otherwise, it is the offset to the BEGINNING of the first local allocated. */ -#define STARTING_FRAME_OFFSET (-8) +/* This is 16 to allow space for one TFmode floating point value. */ +#define STARTING_FRAME_OFFSET (-16) /* If we generate an insn to push BYTES bytes, this says how many the stack pointer really advances by. @@ -752,6 +774,11 @@ extern char leaf_reg_backmap[]; #define FUNCTION_VALUE_REGNO_P(N) ((N) == 8 || (N) == 32) +/* Define the size of space to allocate for the return value of an + untyped_call. */ + +#define APPLY_RESULT_SIZE 16 + /* 1 if N is a possible register number for function argument passing. On SPARC, these are the "output" registers. */ @@ -879,10 +906,6 @@ do { \ ASM_OUTPUT_LABEL (FILE, NAME); \ } while (0) -/* Two views of the size of the current frame. */ -extern int actual_fsize; -extern int apparent_fsize; - /* This macro generates the assembly code for function entry. FILE is a stdio stream to output the code to. SIZE is an int: how many units of temporary storage to allocate. @@ -971,22 +994,22 @@ extern union tree_node *current_function #define ELIGIBLE_FOR_EPILOGUE_DELAY(trial, slots_filled) \ (TARGET_FRW ? sparc_frw_eligible_for_epilogue_delay (trial, slots_filled) \ : eligible_for_epilogue_delay (trial, slots_filled)) - + /* Output assembler code for a block containing the constant parts of a trampoline, leaving space for the variable parts. */ /* On the sparc, the trampoline contains five instructions: - sethi #TOP_OF_FUNCTION,%g2 - or #BOTTOM_OF_FUNCTION,%g2,%g2 - sethi #TOP_OF_STATIC,%g1 - jmp g2 - or #BOTTOM_OF_STATIC,%g1,%g1 */ + sethi #TOP_OF_FUNCTION,%g1 + or #BOTTOM_OF_FUNCTION,%g1,%g1 + sethi #TOP_OF_STATIC,%g2 + jmp g1 + or #BOTTOM_OF_STATIC,%g2,%g2 */ #define TRAMPOLINE_TEMPLATE(FILE) \ { \ ASM_OUTPUT_INT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x00000000)); \ ASM_OUTPUT_INT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x00000000)); \ ASM_OUTPUT_INT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x00000000)); \ - ASM_OUTPUT_INT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x81C08000)); \ + ASM_OUTPUT_INT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x81C04000)); \ ASM_OUTPUT_INT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x00000000)); \ } @@ -1001,7 +1024,10 @@ extern union tree_node *current_function This takes 16 insns: 2 shifts & 2 ands (to split up addresses), 4 sethi (to load in opcodes), 4 iors (to merge address and opcodes), and 4 writes (to store insns). This is a bit excessive. Perhaps a different - mechanism would be better here. */ + mechanism would be better here. + + Emit 3 FLUSH instructions (UNSPEC_VOLATILE 2) to synchonize the data + and instruction caches. */ #define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ { \ @@ -1020,20 +1046,29 @@ extern union tree_node *current_function rtx g2_ori = gen_rtx (HIGH, SImode, \ gen_rtx (CONST_INT, VOIDmode, 0x8410A000)); \ rtx tem = gen_reg_rtx (SImode); \ - emit_move_insn (tem, g2_sethi); \ + emit_move_insn (tem, g1_sethi); \ emit_insn (gen_iorsi3 (high_fn, high_fn, tem)); \ emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 0)), high_fn);\ - emit_move_insn (tem, g2_ori); \ + emit_move_insn (tem, g1_ori); \ emit_insn (gen_iorsi3 (low_fn, low_fn, tem)); \ emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 4)), low_fn);\ - emit_move_insn (tem, g1_sethi); \ + emit_move_insn (tem, g2_sethi); \ emit_insn (gen_iorsi3 (high_cxt, high_cxt, tem)); \ emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 8)), high_cxt);\ - emit_move_insn (tem, g1_ori); \ + emit_move_insn (tem, g2_ori); \ emit_insn (gen_iorsi3 (low_cxt, low_cxt, tem)); \ emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 16)), low_cxt);\ + emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode, \ + gen_rtvec (1, plus_constant (TRAMP, 0)), \ + 2)); \ + emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode, \ + gen_rtvec (1, plus_constant (TRAMP, 8)), \ + 2)); \ + emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode, \ + gen_rtvec (1, plus_constant (TRAMP, 16)), \ + 2)); \ } - + /* Generate necessary RTL for __builtin_saveregs(). ARGLIST is the argument list; see expr.c. */ extern struct rtx_def *sparc_builtin_saveregs (); @@ -1105,12 +1140,20 @@ extern struct rtx_def *sparc_builtin_sav #define MAX_REGS_PER_ADDRESS 2 -/* Recognize any constant value that is a valid address. */ +/* Recognize any constant value that is a valid address. + When PIC, we do not accept an address that would require a scratch reg + to load into a register. */ #define CONSTANT_ADDRESS_P(X) \ (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ - || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \ - || GET_CODE (X) == HIGH) + || GET_CODE (X) == CONST_INT || GET_CODE (X) == HIGH \ + || (GET_CODE (X) == CONST \ + && ! (flag_pic && pic_address_needs_scratch (X)))) + +/* Define this, so that when PIC, reload won't try to reload invalid + addresses which require two reload registers. */ + +#define LEGITIMATE_PIC_OPERAND_P(X) (! pic_address_needs_scratch (X)) /* Nonzero if the constant value X is a legitimate general operand. Anything can be made to work except floating point constants. */ @@ -1157,8 +1200,6 @@ extern struct rtx_def *sparc_builtin_sav && ! symbolic_memory_operand (OP, VOIDmode)) \ || (reload_in_progress && GET_CODE (OP) == REG \ && REGNO (OP) >= FIRST_PSEUDO_REGISTER)) \ - : (C) == 'S' \ - ? (CONSTANT_P (OP) || memory_address_p (Pmode, OP)) \ : (C) == 'T' \ ? (mem_aligned_8 (OP)) \ : (C) == 'U' \ @@ -1178,14 +1219,13 @@ extern struct rtx_def *sparc_builtin_sav ? (REGNO (OP) >= FIRST_PSEUDO_REGISTER \ && reg_renumber[REGNO (OP)] < 0) \ : GET_CODE (OP) == MEM) \ - : (C) == 'S' \ - ? (CONSTANT_P (OP) \ - || (GET_CODE (OP) == REG && reg_renumber[REGNO (OP)] > 0) \ - || strict_memory_address_p (Pmode, OP)) \ : (C) == 'T' \ - ? mem_aligned_8 (OP) && strict_memory_address_p (Pmode, OP) \ + ? mem_aligned_8 (OP) && strict_memory_address_p (Pmode, XEXP (OP, 0)) \ : (C) == 'U' \ - ? register_ok_for_ldd (OP) : 0) + ? (GET_CODE (OP) == REG \ + && (REGNO (OP) < FIRST_PSEUDO_REGISTER \ + || reg_renumber[REGNO (OP)] > 0) \ + && register_ok_for_ldd (OP)) : 0) #endif /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression @@ -1227,7 +1267,9 @@ extern struct rtx_def *sparc_builtin_sav else if (flag_pic == 1 \ && GET_CODE (op1) != REG \ && GET_CODE (op1) != LO_SUM \ - && GET_CODE (op1) != MEM) \ + && GET_CODE (op1) != MEM \ + && (GET_CODE (op1) != CONST_INT \ + || SMALL_INT (op1))) \ goto ADDR; \ } \ else if (RTX_OK_FOR_BASE_P (op0)) \ @@ -1286,7 +1328,7 @@ extern struct rtx_def *legitimize_pic_ad force_operand (XEXP (X, 1), NULL_RTX)); \ if (sparc_x != (X) && memory_address_p (MODE, X)) \ goto WIN; \ - if (flag_pic) (X) = legitimize_pic_address (X, MODE, 0, 0); \ + if (flag_pic) (X) = legitimize_pic_address (X, MODE, 0); \ else if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 1))) \ (X) = gen_rtx (PLUS, Pmode, XEXP (X, 0), \ copy_to_mode_reg (Pmode, XEXP (X, 1))); \ @@ -1338,9 +1380,15 @@ extern struct rtx_def *legitimize_pic_ad gen_rtx (MEM, SImode, gen_rtx (SYMBOL_REF, Pmode, "errno")) #endif /* 0 */ -/* Define if normal loads of shorter-than-word items from memory clears - the rest of the bigs in the register. */ -#define BYTE_LOADS_ZERO_EXTEND +/* Define if operations between registers always perform the operation + on the full register even if a narrower mode is specified. */ +#define WORD_REGISTER_OPERATIONS + +/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD + will either zero-extend or sign-extend. The value of this macro should + be the code that says which one of the two operations is implicitly + done, NIL if none. */ +#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND /* Nonzero if access to memory by bytes is slow and undesirable. For RISC chips, it means that access to memory by bytes is no @@ -1356,10 +1404,9 @@ extern struct rtx_def *legitimize_pic_ad /* When a prototype says `char' or `short', really pass an `int'. */ #define PROMOTE_PROTOTYPES -/* Define if shifts truncate the shift count - which implies one can omit a sign-extension or zero-extension - of a shift count. */ -#define SHIFT_COUNT_TRUNCATED +/* Define this to be nonzero if shift instructions ignore all but the low-order + few bits. */ +#define SHIFT_COUNT_TRUNCATED 1 /* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits is done just by pretending it is already truncated. */ @@ -1392,12 +1439,13 @@ extern struct rtx_def *legitimize_pic_ad /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, return the mode to be used for the comparison. For floating-point, CCFP[E]mode is used. CC_NOOVmode should be used when the first operand is a - PLUS, MINUS, or NEG. CCmode should be used when no special processing is - needed. */ + PLUS, MINUS, NEG, or ASHIFT. CCmode should be used when no special + processing is needed. */ #define SELECT_CC_MODE(OP,X,Y) \ (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ - ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode) \ - : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS || GET_CODE (X) == NEG) \ + ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode) \ + : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \ + || GET_CODE (X) == NEG || GET_CODE (X) == ASHIFT) \ ? CC_NOOVmode : CCmode)) /* A function address in a call instruction @@ -1601,39 +1649,22 @@ extern struct rtx_def *legitimize_pic_ad /* This is how to output an assembler line defining a `double' constant. */ -/* Assemblers (both gas 1.35 and as in 4.0.3) - seem to treat -0.0 as if it were 0.0. - They reject 99e9999, but accept inf. */ #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ { \ - if (REAL_VALUE_ISINF (VALUE) \ - || REAL_VALUE_ISNAN (VALUE) \ - || REAL_VALUE_MINUS_ZERO (VALUE)) \ - { \ - long t[2]; \ - REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \ - fprintf (FILE, "\t%s\t0x%lx\n\t%s\t0x%lx\n", \ - ASM_LONG, t[0], ASM_LONG, t[1]); \ - } \ - else \ - fprintf (FILE, "\t.double 0r%.17g\n", VALUE); \ + long t[2]; \ + REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \ + fprintf (FILE, "\t%s\t0x%lx\n\t%s\t0x%lx\n", \ + ASM_LONG, t[0], ASM_LONG, t[1]); \ } /* This is how to output an assembler line defining a `float' constant. */ #define ASM_OUTPUT_FLOAT(FILE,VALUE) \ { \ - if (REAL_VALUE_ISINF (VALUE) \ - || REAL_VALUE_ISNAN (VALUE) \ - || REAL_VALUE_MINUS_ZERO (VALUE)) \ - { \ - long t; \ - REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ - fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t); \ - } \ - else \ - fprintf (FILE, "\t.single 0r%.9g\n", VALUE); \ - } + long t; \ + REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ + fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t); \ + } \ /* This is how to output an assembler line defining a `long double' constant. */