--- gcc/config/sparc/sparc.h 2018/04/24 18:21:34 1.1.1.3 +++ gcc/config/sparc/sparc.h 2018/04/24 18:34:36 1.1.1.5 @@ -1,5 +1,5 @@ /* Definitions of target machine for GNU compiler, for Sun SPARC. - Copyright (C) 1987, 1988, 1989, 1992, 1994 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 89, 92, 94, 1995 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com). 64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans, at Cygnus Support. @@ -18,7 +18,8 @@ GNU General Public License for more deta You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ /* Note that some other tm.h files include this one and then override many of the definitions that relate to assembler syntax. */ @@ -60,16 +61,18 @@ extern enum arch_type sparc_arch_type; -Asystem(unix) -Asystem(bsd) -Acpu(sparc) -Amachine(sparc)" #endif -#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} %{g:-lg}" +#define LIB_SPEC "%{!shared:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} %{g:-lg}}" /* Provide required defaults for linker -e and -d switches. */ #define LINK_SPEC \ - "%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{static:-Bstatic} %{assert*}" + "%{!shared:%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp} %{static:-Bstatic} \ + %{assert*} %{shared:-assert pure-text}" /* Special flags to the Sun-4 assembler when using pipe for input. */ -#define ASM_SPEC " %| %{!pg:%{!p:%{fpic:-k} %{fPIC:-k}}}" +#define ASM_SPEC \ + " %| %{R} %{!pg:%{!p:%{fpic:-k} %{fPIC:-k}}} %{keep-local-as-symbols:-L}" /* Define macros to distinguish architectures. */ @@ -129,11 +132,11 @@ void sparc_override_options (); } \ flag_omit_frame_pointer = 0; \ } \ - SUBTARGET_OVERRIDE_OPTIONS \ + SUBTARGET_OVERRIDE_OPTIONS; \ sparc_override_options (); \ } while (0) -/* This is meant to be redefined in the host dependent files */ +/* 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. */ @@ -368,7 +371,7 @@ extern int target_flags; /* Width of a word, in units (bytes). */ #define UNITS_PER_WORD (TARGET_V9 ? 8 : 4) -#define MAX_UNITS_PER_WORD 8 +#define MIN_UNITS_PER_WORD 4 /* Now define the sizes of the C data types. */ @@ -445,6 +448,15 @@ extern int target_flags; Put them in the data section. This macro is only used in this file. */ #define MAX_TEXT_ALIGN 32 +/* This forces all variables and constants to the data section when PIC. + This is because the SunOS 4 shared library scheme thinks everything in + text is a function, and patches the address to point to a loader stub. */ +/* This is defined to zero for every system which doesn't use the a.out object + file format. */ +#ifndef SUNOS4_SHARED_LIBRARIES +#define SUNOS4_SHARED_LIBRARIES 0 +#endif + /* This is defined differently for v9 in a cover file. */ #define SELECT_SECTION(T,RELOC) \ { \ @@ -455,20 +467,21 @@ extern int target_flags; && (DECL_INITIAL (T) == error_mark_node \ || TREE_CONSTANT (DECL_INITIAL (T))) \ && DECL_ALIGN (T) <= MAX_TEXT_ALIGN \ - && ! (flag_pic && (RELOC))) \ + && ! (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES))) \ text_section (); \ else \ data_section (); \ } \ else if (TREE_CODE (T) == CONSTRUCTOR) \ { \ - if (flag_pic != 0 && (RELOC) != 0) \ + if (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES)) \ data_section (); \ } \ - else if (*tree_code_type[(int) TREE_CODE (T)] == 'c') \ + else if (TREE_CODE_CLASS (TREE_CODE (T)) == 'c') \ { \ if ((TREE_CODE (T) == STRING_CST && flag_writable_strings) \ - || TYPE_ALIGN (TREE_TYPE (T)) > MAX_TEXT_ALIGN) \ + || TYPE_ALIGN (TREE_TYPE (T)) > MAX_TEXT_ALIGN \ + || (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES))) \ data_section (); \ else \ text_section (); \ @@ -481,7 +494,7 @@ extern int target_flags; #define SELECT_RTX_SECTION(MODE, X) \ { \ if (GET_MODE_BITSIZE (MODE) <= MAX_TEXT_ALIGN \ - && ! (flag_pic && symbolic_operand (X))) \ + && ! (flag_pic && (symbolic_operand (X) || SUNOS4_SHARED_LIBRARIES))) \ text_section (); \ else \ data_section (); \ @@ -608,18 +621,10 @@ do \ for (regno = 32; regno < FIRST_PSEUDO_REGISTER; regno++) \ fixed_regs[regno] = 1; \ } \ - if (! TARGET_APP_REGS) \ - { \ - fixed_regs[2] = 1; \ - fixed_regs[3] = 1; \ - fixed_regs[4] = 1; \ - } \ - else \ - { \ - fixed_regs[2] = 0; \ - fixed_regs[3] = 0; \ - fixed_regs[4] = TARGET_MEDANY != 0; \ - } \ + /* Don't unfix g2-g4 if they were fixed with -ffixed-. */ \ + fixed_regs[2] |= ! TARGET_APP_REGS; \ + fixed_regs[3] |= ! TARGET_APP_REGS; \ + fixed_regs[4] |= ! TARGET_APP_REGS || TARGET_MEDANY; \ if (TARGET_FLAT) \ { \ /* Let the compiler believe the frame pointer is still \ @@ -734,9 +739,8 @@ extern int sparc_mode_class[]; #define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM /* Register in which static-chain is passed to a function. This must - not be a register used by the prologue. - ??? v9: Since %g2 is reserved but %g5 is available, perhaps use %g5. */ -#define STATIC_CHAIN_REGNUM 2 + not be a register used by the prologue. */ +#define STATIC_CHAIN_REGNUM (TARGET_V9 ? 5 : 2) /* Register which holds offset table for position-independent data references. */ @@ -1086,7 +1090,7 @@ extern char leaf_reg_remap[]; if the frame size is zero. */ #define SECONDARY_MEMORY_NEEDED_RTX(MODE) \ (get_frame_size () == 0 \ - ? assign_stack_local (mode, GET_MODE_SIZE (mode), 0) \ + ? assign_stack_local (MODE, GET_MODE_SIZE (MODE), 0) \ : gen_rtx (MEM, MODE, gen_rtx (PLUS, Pmode, frame_pointer_rtx, \ GEN_INT (STARTING_FRAME_OFFSET)))) @@ -1095,11 +1099,11 @@ extern char leaf_reg_remap[]; For v8 we copy the default definition. */ #define SECONDARY_MEMORY_NEEDED_MODE(MODE) \ (TARGET_V9 \ - ? (GET_MODE_BITSIZE (mode) < 32 \ - ? mode_for_size (32, GET_MODE_CLASS (mode), 0) \ + ? (GET_MODE_BITSIZE (MODE) < 32 \ + ? mode_for_size (32, GET_MODE_CLASS (MODE), 0) \ : MODE) \ - : (GET_MODE_BITSIZE (mode) < BITS_PER_WORD \ - ? mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (mode), 0) \ + : (GET_MODE_BITSIZE (MODE) < BITS_PER_WORD \ + ? mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0) \ : MODE)) /* Return the maximum number of consecutive registers @@ -1166,11 +1170,12 @@ extern char leaf_reg_remap[]; /* Value is the number of bytes of arguments automatically popped when returning from a subroutine call. + FUNDECL is the declaration node of the function (as a tree), FUNTYPE is the data type of the function (as a tree), or for a library call it is an identifier node for the subroutine name. SIZE is the number of bytes of arguments passed on the stack. */ -#define RETURN_POPS_ARGS(FUNTYPE,SIZE) 0 +#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 /* Some subroutine macros specific to this machine. When !TARGET_FPU, put float return values in the general registers, @@ -1479,9 +1484,6 @@ extern struct rtx_def *gen_compare_reg ( /* This function handles all v9 scc insns */ extern int gen_v9_scc (); - -/* ??? This is a hack until conditional move support is complete. */ -#define HAVE_conditional_move (TARGET_V9) /* Generate the special assembly code needed to tell the assembler whatever it might need to know about the return value of a function. @@ -1606,24 +1608,50 @@ extern union tree_node *current_function /* 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: +/* On 32 bit sparcs, the trampoline contains five instructions: 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, 0x81C04000)); \ - ASM_OUTPUT_INT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x00000000)); \ -} + or #BOTTOM_OF_STATIC,%g2,%g2 + + On 64 bit sparcs, the trampoline contains 4 insns and two pseudo-immediate + constants (plus some padding): + rd %pc,%g1 + ldx[%g1+20],%g5 + ldx[%g1+28],%g1 + jmp %g1 + nop + nop + .xword context + .xword function */ + +#define TRAMPOLINE_TEMPLATE(FILE) \ +do { \ + if (TARGET_V9) \ + { \ + fprintf (FILE, "\trd %%pc,%%g1\n"); \ + fprintf (FILE, "\tldx [%%g1+24],%%g5\n"); \ + fprintf (FILE, "\tldx [%%g1+32],%%g1\n"); \ + fprintf (FILE, "\tjmp %%g1\n"); \ + fprintf (FILE, "\tnop\n"); \ + fprintf (FILE, "\tnop\n"); \ + /* -mmedlow shouldn't generate .xwords, so don't use them at all */ \ + fprintf (FILE, "\t.word 0,0,0,0\n"); \ + } \ + else \ + { \ + 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, 0x81C04000)); \ + ASM_OUTPUT_INT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x00000000)); \ + } \ +} while (0) /* Length in units of the trampoline for entering a nested function. */ -#define TRAMPOLINE_SIZE 20 +#define TRAMPOLINE_SIZE (TARGET_V9 ? 40 : 20) /* Emit RTL insns to initialize the variable parts of a trampoline. FNADDR is an RTX for the address of the function's pure code. @@ -1662,6 +1690,10 @@ extern struct rtx_def *sparc_builtin_sav save area. */ #define RETURN_ADDR_IN_PREVIOUS_FRAME +/* This is the offset of the return address to the true next instruction to be + executed for normal void functions. */ +#define NORMAL_RETURN_ADDR_OFFSET (8) + /* The current return address is in %i7. The return address of anything farther back is in the register window save area at [%fp+60]. */ /* ??? This ignores the fact that the actual return address is +8 for normal @@ -1669,8 +1701,8 @@ extern struct rtx_def *sparc_builtin_sav #define RETURN_ADDR_RTX(count, frame) \ ((count == -1) \ ? gen_rtx (REG, Pmode, 31) \ - : copy_to_reg (gen_rtx (MEM, Pmode, \ - memory_address (Pmode, plus_constant (frame, 15 * UNITS_PER_WORD))))) + : gen_rtx (MEM, Pmode, \ + memory_address (Pmode, plus_constant (frame, 15 * UNITS_PER_WORD)))) /* Addressing modes, and classification of registers for them. */ @@ -2079,6 +2111,7 @@ extern struct rtx_def *legitimize_pic_ad SPARC ABI. */ #define ADDTF3_LIBCALL "_Q_add" #define SUBTF3_LIBCALL "_Q_sub" +#define NEGTF2_LIBCALL "_Q_neg" #define MULTF3_LIBCALL "_Q_mul" #define DIVTF3_LIBCALL "_Q_div" #define FLOATSITF2_LIBCALL "_Q_itoq" @@ -2099,11 +2132,36 @@ extern struct rtx_def *legitimize_pic_ad with soft-float, the SFmode and DFmode sqrt instructions will be absent, and the compiler will notice and try to use the TFmode sqrt instruction for calls to the builtin function sqrt, but this fails. */ -#define INIT_TARGET_OPTABS \ - do { \ - INIT_SUBTARGET_OPTABS; \ - if (TARGET_FPU) \ - sqrt_optab->handlers[(int) TFmode].libfunc = gen_rtx (SYMBOL_REF, Pmode, "_Q_sqrt"); \ +#define INIT_TARGET_OPTABS \ + do { \ + add_optab->handlers[(int) TFmode].libfunc \ + = gen_rtx (SYMBOL_REF, Pmode, ADDTF3_LIBCALL); \ + sub_optab->handlers[(int) TFmode].libfunc \ + = gen_rtx (SYMBOL_REF, Pmode, SUBTF3_LIBCALL); \ + neg_optab->handlers[(int) TFmode].libfunc \ + = gen_rtx (SYMBOL_REF, Pmode, NEGTF2_LIBCALL); \ + smul_optab->handlers[(int) TFmode].libfunc \ + = gen_rtx (SYMBOL_REF, Pmode, MULTF3_LIBCALL); \ + flodiv_optab->handlers[(int) TFmode].libfunc \ + = gen_rtx (SYMBOL_REF, Pmode, DIVTF3_LIBCALL); \ + eqtf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, EQTF2_LIBCALL); \ + netf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, NETF2_LIBCALL); \ + gttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, GTTF2_LIBCALL); \ + getf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, GETF2_LIBCALL); \ + lttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, LTTF2_LIBCALL); \ + letf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, LETF2_LIBCALL); \ + trunctfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, TRUNCTFSF2_LIBCALL); \ + trunctfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, TRUNCTFDF2_LIBCALL); \ + extendsftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, EXTENDSFTF2_LIBCALL); \ + extenddftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, EXTENDDFTF2_LIBCALL); \ + floatsitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, FLOATSITF2_LIBCALL); \ + fixtfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, FIX_TRUNCTFSI2_LIBCALL); \ + fixunstfsi_libfunc \ + = gen_rtx (SYMBOL_REF, Pmode, FIXUNS_TRUNCTFSI2_LIBCALL); \ + if (TARGET_FPU) \ + sqrt_optab->handlers[(int) TFmode].libfunc \ + = gen_rtx (SYMBOL_REF, Pmode, "_Q_sqrt"); \ + INIT_SUBTARGET_OPTABS; \ } while (0) /* This is meant to be redefined in the host dependent files */ @@ -2156,7 +2214,7 @@ extern struct rtx_def *legitimize_pic_ad #define RTX_COSTS(X,CODE,OUTER_CODE) \ case MULT: \ - return (TARGET_V8 || TARGET_V9) ? COSTS_N_INSNS (5) : COSTS_N_INSNS (25); \ + return (TARGET_V8 || TARGET_SPARCLITE || TARGET_V9) ? COSTS_N_INSNS (5) : COSTS_N_INSNS (25); \ case DIV: \ case UDIV: \ case MOD: \ @@ -2491,7 +2549,8 @@ do { \ fprintf (FILE, "%+d", offset); \ else if (GET_CODE (index) == REG) \ fprintf (FILE, "+%s", reg_names[REGNO (index)]); \ - else if (GET_CODE (index) == SYMBOL_REF) \ + else if (GET_CODE (index) == SYMBOL_REF \ + || GET_CODE (index) == CONST) \ fputc ('+', FILE), output_addr_const (FILE, index); \ else abort (); \ } \