--- gcc/config/mips/mips.h 2018/04/24 18:10:25 1.1 +++ gcc/config/mips/mips.h 2018/04/24 18:21:55 1.1.1.3 @@ -1,7 +1,9 @@ /* Definitions of target machine for GNU compiler. MIPS version. Contributed by A. Lichnewsky, lich@inria.inria.fr Changed by Michael Meissner, meissner@osf.org - Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + 64 bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and + Brendan Eich, brendan@microunity.com. + Copyright (C) 1989, 90, 91, 92, 93, 1994 Free Software Foundation, Inc. This file is part of GNU CC. @@ -44,7 +46,8 @@ extern char *version_string; /* comparison type */ enum cmp_type { - CMP_SI, /* compare integers */ + 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 */ @@ -67,12 +70,23 @@ enum processor_type { PROCESSOR_DEFAULT, PROCESSOR_R3000, PROCESSOR_R6000, - PROCESSOR_R4000 + PROCESSOR_R4000, + PROCESSOR_R4600 }; /* Recast the cpu class to be the cpu attribute. */ #define mips_cpu_attr ((enum attr_cpu)mips_cpu) +/* Whether to emit abicalls code sequences or not. */ + +enum mips_abicalls_type { + MIPS_ABICALLS_NO, + MIPS_ABICALLS_YES +}; + +/* Recast the abicalls class to be the abicalls attribute. */ +#define mips_abicalls_attr ((enum attr_abicalls)mips_abicalls) + /* Which type of block move to do (whether or not the last store is split out so it can fill a branch delay slot). */ @@ -101,10 +115,10 @@ extern int set_noat; /* # of nested .s extern int set_volatile; /* # of nested .set volatile's */ extern int mips_branch_likely; /* emit 'l' after br (branch likely) */ extern int mips_dbx_regno[]; /* Map register # to debug register # */ -extern char mips_rtx_classify[]; /* classify an RTX code */ extern struct rtx_def *branch_cmp[2]; /* operands for compare */ extern enum cmp_type branch_type; /* what type of branch to use */ extern enum processor_type mips_cpu; /* which cpu are we scheduling for */ +extern enum mips_abicalls_type mips_abicalls;/* for svr4 abi pic calls */ extern int mips_isa; /* architectural level */ extern char *mips_cpu_string; /* for -mcpu= */ extern char *mips_isa_string; /* for -mips{1,2,3} */ @@ -118,6 +132,7 @@ extern struct rtx_def *mips_load_reg; /* extern struct rtx_def *mips_load_reg2; /* 2nd reg to check for load delay */ extern struct rtx_def *mips_load_reg3; /* 3rd reg to check for load delay */ extern struct rtx_def *mips_load_reg4; /* 4th reg to check for load delay */ +extern struct rtx_def *embedded_pic_fnaddr_rtx; /* function address */ /* Functions within mips.c that we reference. */ @@ -125,14 +140,11 @@ extern void abort_with_insn (); extern int arith32_operand (); extern int arith_operand (); extern int cmp_op (); -extern int cmp2_op (); extern long compute_frame_size (); extern int epilogue_reg_mentioned_p (); extern void expand_block_move (); extern int equality_op (); -extern int fcmp_op (); extern void final_prescan_insn (); -extern int fpsw_register_operand (); extern struct rtx_def * function_arg (); extern void function_arg_advance (); extern int function_arg_partial_nregs (); @@ -142,7 +154,6 @@ extern void gen_conditional_branch (); extern struct rtx_def * gen_int_relational (); extern void init_cumulative_args (); extern int large_int (); -extern int md_register_operand (); extern int mips_address_cost (); extern void mips_asm_file_end (); extern void mips_asm_file_start (); @@ -173,7 +184,8 @@ extern int simple_memory_operand (); extern int small_int (); extern void trace(); extern int uns_arith_operand (); -extern int uns_cmp_op (); +extern struct rtx_def * embedded_pic_offset (); +extern void mips_finalize_pic (); /* Recognition functions that return if a condition is true. */ extern int address_operand (); @@ -206,7 +218,6 @@ extern char *permalloc (); extern int reg_mentioned_p (); /* Functions in the standard library that we reference. */ -extern void abort (); extern int atoi (); extern char *getenv (); extern char *mktemp (); @@ -233,8 +244,8 @@ extern char *mktemp (); /* Bits for real switches */ #define MASK_INT64 0x00000001 /* ints are 64 bits */ -#define MASK_LONG64 0x00000002 /* longs are 64 bits */ -#define MASK_LLONG128 0x00000004 /* long longs are 128 bits */ +#define MASK_LONG64 0x00000002 /* longs and pointers are 64 bits */ +#define MASK_UNUSED 0x00000004 #define MASK_GPOPT 0x00000008 /* Optimize for global pointer */ #define MASK_GAS 0x00000010 /* Gas used instead of MIPS as */ #define MASK_NAME_REGS 0x00000020 /* Use MIPS s/w reg name convention */ @@ -245,13 +256,13 @@ extern char *mktemp (); #define MASK_ABICALLS 0x00000400 /* emit .abicalls/.cprestore/.cpload */ #define MASK_HALF_PIC 0x00000800 /* Emit OSF-style pic refs to externs*/ #define MASK_LONG_CALLS 0x00001000 /* Always call through a register */ -#define MASK_UNUSED1 0x00002000 -#define MASK_UNUSED2 0x00004000 -#define MASK_UNUSED3 0x00008000 +#define MASK_64BIT 0x00002000 /* Use 64 bit GP registers and insns */ +#define MASK_EMBEDDED_PIC 0x00004000 /* Generate embedded PIC code */ +#define MASK_EMBEDDED_DATA 0x00008000 /* Reduce RAM usage, not fast code */ #define MASK_UNUSED4 0x00010000 -#define MASK_UNUSED5 0x00020000 -#define MASK_UNUSED6 0x00040000 -#define MASK_UNUSED7 0x00080000 +#define MASK_UNUSED3 0x00020000 +#define MASK_UNUSED2 0x00040000 +#define MASK_UNUSED1 0x00080000 /* Dummy switches used only in spec's*/ #define MASK_MIPS_TFILE 0x00000000 /* flag for mips-tfile usage */ @@ -272,8 +283,8 @@ extern char *mktemp (); /* r4000 64 bit sizes */ #define TARGET_INT64 (target_flags & MASK_INT64) #define TARGET_LONG64 (target_flags & MASK_LONG64) -#define TARGET_LLONG128 (target_flags & MASK_LLONG128) #define TARGET_FLOAT64 (target_flags & MASK_FLOAT64) +#define TARGET_64BIT (target_flags & MASK_64BIT) /* Mips vs. GNU assembler */ #define TARGET_GAS (target_flags & MASK_GAS) @@ -318,6 +329,15 @@ extern char *mktemp (); /* always call through a register */ #define TARGET_LONG_CALLS (target_flags & MASK_LONG_CALLS) + /* generate embedded PIC code; + requires gas. */ +#define TARGET_EMBEDDED_PIC (target_flags & MASK_EMBEDDED_PIC) + + /* for embedded systems, optimize for + reduced RAM space instead of for + fastest code. */ +#define TARGET_EMBEDDED_DATA (target_flags & MASK_EMBEDDED_DATA) + /* Macro to define tables used to set the flags. This is a list in braces of pairs in braces, each pair being { "NAME", VALUE } @@ -328,7 +348,6 @@ extern char *mktemp (); { \ {"int64", MASK_INT64 | MASK_LONG64}, \ {"long64", MASK_LONG64}, \ - {"longlong128", MASK_INT64 | MASK_LONG64 | MASK_LLONG128}, \ {"mips-as", -MASK_GAS}, \ {"gas", MASK_GAS}, \ {"rnames", MASK_NAME_REGS}, \ @@ -347,12 +366,18 @@ extern char *mktemp (); {"hard-float", -MASK_SOFT_FLOAT}, \ {"fp64", MASK_FLOAT64}, \ {"fp32", -MASK_FLOAT64}, \ + {"gp64", MASK_64BIT}, \ + {"gp32", -MASK_64BIT}, \ {"abicalls", MASK_ABICALLS}, \ {"no-abicalls", -MASK_ABICALLS}, \ {"half-pic", MASK_HALF_PIC}, \ {"no-half-pic", -MASK_HALF_PIC}, \ {"long-calls", MASK_LONG_CALLS}, \ {"no-long-calls", -MASK_LONG_CALLS}, \ + {"embedded-pic", MASK_EMBEDDED_PIC}, \ + {"no-embedded-pic", -MASK_EMBEDDED_PIC}, \ + {"embedded-data", MASK_EMBEDDED_DATA}, \ + {"no-embedded-data", -MASK_EMBEDDED_DATA}, \ {"debug", MASK_DEBUG}, \ {"debuga", MASK_DEBUG_A}, \ {"debugb", MASK_DEBUG_B}, \ @@ -404,9 +429,20 @@ extern char *mktemp (); depending on the instruction set architecture level. */ #define BRANCH_LIKELY_P() (mips_isa >= 2) -#define HAVE_64BIT_P() (mips_isa >= 3) #define HAVE_SQRT_P() (mips_isa >= 2) +/* CC1_SPEC causes -mips3 to set -mfp64 and -mgp64; -mips1 or -mips2 + sets -mfp32 and -mgp32. This can be overridden by an explicit + -mfp32, -mfp64, -mgp32 or -mgp64. -mfp64 sets MASK_FLOAT64 in + target_flags, and -mgp64 sets MASK_64BIT. + + Setting MASK_64BIT in target_flags will cause gcc to assume that + registers are 64 bits wide. int, long and void * will be 32 bit; + this may be changed with -mint64 or -mlong64. + + The gen* programs link code that refers to MASK_64BIT. They don't + actually use the information in target_flags; they just refer to + it. */ /* Switch Recognition by gcc.c. Add -G xx support */ @@ -467,28 +503,9 @@ do \ } \ while (0) - -/* Some machines may desire to change what optimizations are - performed for various optimization levels. This macro, if - defined, is executed once just after the optimization level is - determined and before the remainder of the command options have - been parsed. Values set in this macro are used as the default - values for the other command line options. - - LEVEL is the optimization level specified; 2 if -O2 is - specified, 1 if -O is specified, and 0 if neither is specified. */ - -#define OPTIMIZATION_OPTIONS(LEVEL) \ -{ \ - if (LEVEL) \ - { \ - flag_omit_frame_pointer = TRUE; \ - flag_schedule_insns_after_reload = TRUE; \ - target_flags &= MASK_GPOPT; \ - } \ -} +/* Show we can debug even without a frame pointer. */ +#define CAN_DEBUG_WITHOUT_FP - /* Complain about missing specs and predefines that should be defined in each of the target tm files to override the defaults. This is mostly a place- holder until I can get each of the files updated [mm]. */ @@ -505,14 +522,6 @@ while (0) #error "Define CPP_PREDEFINES in the appropriate tm.h file" #endif -#ifndef CPP_SPEC - #error "Define CPP_SPEC in the appropriate tm.h file" -#endif - -#ifndef LINK_SPEC - #error "Define LINK_SPEC in the appropriate tm.h file" -#endif - #ifndef LIB_SPEC #error "Define LIB_SPEC in the appropriate tm.h file" #endif @@ -536,29 +545,53 @@ while (0) #ifndef CPP_PREDEFINES #define CPP_PREDEFINES "-Dmips -Dunix -Dhost_mips -DMIPSEB -DR3000 -DSYSTYPE_BSD43 \ --D_mips -D_unix -D_host_mips -D_MIPSEB -D_R3000 -D_SYSTYPE_BSD43" +-D_mips -D_unix -D_host_mips -D_MIPSEB -D_R3000 -D_SYSTYPE_BSD43 \ +-Asystem(unix) -Asystem(bsd) -Acpu(mips) -Amachine(mips)" #endif /* Extra switches sometimes passed to the assembler. */ #ifndef ASM_SPEC +#if ((TARGET_CPU_DEFAULT | TARGET_DEFAULT) & MASK_GAS) != 0 +/* GAS */ +#define ASM_SPEC "\ +%{mmips-as: \ + %{!.s:-nocpp} %{.s: %{cpp} %{nocpp}} \ + %{pipe: %e-pipe is not supported.} \ + %{K}} \ +%{!mmips-as: \ + %{mcpu=*}} \ +%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{v} \ +%{noasmopt:-O0} \ +%{!noasmopt:%{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3}} \ +%{g} %{g0} %{g1} %{g2} %{g3} \ +%{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3} \ +%{gstabs:-g} %{gstabs0:-g0} %{gstabs1:-g1} %{gstabs2:-g2} %{gstabs3:-g3} \ +%{gstabs+:-g} %{gstabs+0:-g0} %{gstabs+1:-g1} %{gstabs+2:-g2} %{gstabs+3:-g3} \ +%{gcoff:-g} %{gcoff0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3} \ +%{membedded-pic}" + +#else +/* not GAS */ #define ASM_SPEC "\ %{!mgas: \ - %{!mrnames: %{!.s:-nocpp} %{.s: %{cpp} %{nocpp}}} \ + %{!.s:-nocpp} %{.s: %{cpp} %{nocpp}} \ %{pipe: %e-pipe is not supported.} \ - %{EB} %{!EB:-EB} \ - %{EL: %e-EL not supported} \ - %{mips1} %{mips2} %{mips3} \ - %{noasmopt:-O0} \ - %{!noasmopt:%{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3}} \ - %{g} %{g0} %{g1} %{g2} %{g3} %{v} %{K} \ - %{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3} \ - %{gstabs:-g} %{gstabs0:-g0} %{gstabs1:-g1} %{gstabs2:-g2} %{gstabs3:-g3} \ - %{gstabs+:-g} %{gstabs+0:-g0} %{gstabs+1:-g1} %{gstabs+2:-g2} %{gstabs+3:-g3} \ - %{gcoff:-g} %{gstabs0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3}} \ -%{G*}" + %{K}} \ +%{mgas: \ + %{mcpu=*}} \ +%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{v} \ +%{noasmopt:-O0} \ +%{!noasmopt:%{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3}} \ +%{g} %{g0} %{g1} %{g2} %{g3} \ +%{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3} \ +%{gstabs:-g} %{gstabs0:-g0} %{gstabs1:-g1} %{gstabs2:-g2} %{gstabs3:-g3} \ +%{gstabs+:-g} %{gstabs+0:-g0} %{gstabs+1:-g1} %{gstabs+2:-g2} %{gstabs+3:-g3} \ +%{gcoff:-g} %{gcoff0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3} \ +%{membedded-pic}" -#endif /* ASM_SPEC */ +#endif +#endif /* ASM_SPEC */ /* Specify to run a post-processor, mips-tfile after the assembler has run to stuff the mips debug information into the object file. @@ -568,8 +601,8 @@ while (0) -mmips-tfile. */ #ifndef ASM_FINAL_SPEC -#if ((TARGET_CPU_DEFAULT | TARGET_DEFAULT) & MASK_GAS) != 0 || defined (CROSS_COMPILE) - /* GAS */ +#if ((TARGET_CPU_DEFAULT | TARGET_DEFAULT) & MASK_GAS) != 0 +/* GAS */ #define ASM_FINAL_SPEC "\ %{mmips-as: %{!mno-mips-tfile: \ \n mips-tfile %{v*: -v} \ @@ -578,7 +611,8 @@ while (0) %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %U.o} \ %{.s:%i} %{!.s:%g.s}}}" -#else /* not GAS, clean up after MIPS assembler */ +#else +/* not GAS */ #define ASM_FINAL_SPEC "\ %{!mgas: %{!mno-mips-tfile: \ \n mips-tfile %{v*: -v} \ @@ -587,7 +621,7 @@ while (0) %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %U.o} \ %{.s:%i} %{!.s:%g.s}}}" -#endif /* GAS */ +#endif #endif /* ASM_FINAL_SPEC */ /* Redefinition of libraries used. Mips doesn't support normal @@ -599,23 +633,21 @@ while (0) #endif /* Extra switches sometimes passed to the linker. */ +/* ??? The bestGnum will never be passed to the linker, because the gcc driver + will interpret it as a -b option. */ #ifndef LINK_SPEC #define LINK_SPEC "\ -%{G*} \ -%{!mgas: \ - %{pipe: %e-pipe is not supported.} \ - %{EB} %{!EB:-EB} \ - %{EL: %e-EL not supported} \ - %{mips1} %{mips2} %{mips3} \ - %{bestGnum} %{shared} %{non_shared}}" -#endif /* LINK_SPEC defined */ +%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} \ +%{bestGnum} %{shared} %{non_shared}" +#endif /* LINK_SPEC defined */ /* Specs for the compiler proper */ #ifndef CC1_SPEC #define CC1_SPEC "\ %{gline:%{!g:%{!g0:%{!g1:%{!g2: -g1}}}}} \ +%{mips1:-mfp32 -mgp32}%{mips2:-mfp32 -mgp32}%{mips3:-mfp64 -mgp64} \ %{G*} \ %{pic-none: -mno-half-pic} \ %{pic-lib: -mhalf-pic} \ @@ -633,7 +665,11 @@ while (0) %{.C: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \ %{.m: -D__LANGUAGE_OBJECTIVE_C -D_LANGUAGE_OBJECTIVE_C} \ %{.S: -D__LANGUAGE_ASSEMBLY -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \ -%{!.S: -D__LANGUAGE_C -D_LANGUAGE_C %{!ansi:-DLANGUAGE_C}}" +%{.s: -D__LANGUAGE_ASSEMBLY -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \ +%{!.S:%{!.s: -D__LANGUAGE_C -D_LANGUAGE_C %{!ansi:-DLANGUAGE_C}}} \ +%{mlong64:-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int} \ +%{!mlong64:-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int} \ +%{mips3:-U__mips -D__mips=3}" #endif /* If defined, this macro is an additional prefix to try after @@ -906,15 +942,28 @@ do { \ Note that this is not necessarily the width of data type `int'; if using 16-bit ints on a 68000, this would still be 32. But on a machine with 16-bit registers, this would be 16. */ -#define BITS_PER_WORD 32 +#define BITS_PER_WORD (TARGET_64BIT ? 64 : 32) +#define MAX_BITS_PER_WORD 64 /* Width of a word, in units (bytes). */ -#define UNITS_PER_WORD 4 +#define UNITS_PER_WORD (TARGET_64BIT ? 8 : 4) +#define MAX_UNITS_PER_WORD 8 + +/* For MIPS, width of a floating point register. */ +#define UNITS_PER_FPREG (TARGET_FLOAT64 ? 8 : 4) /* A C expression for the size in bits of the type `int' on the target machine. If you don't define this, the default is one word. */ -#define INT_TYPE_SIZE 32 +#define INT_TYPE_SIZE (TARGET_INT64 ? 64 : 32) +#define MAX_INT_TYPE_SIZE 64 + +/* Tell the preprocessor the maximum size of wchar_t. */ +#ifndef MAX_WCHAR_TYPE_SIZE +#ifndef WCHAR_TYPE_SIZE +#define MAX_WCHAR_TYPE_SIZE MAX_INT_TYPE_SIZE +#endif +#endif /* A C expression for the size in bits of the type `short' on the target machine. If you don't define this, the default is half a @@ -925,7 +974,8 @@ do { \ /* A C expression for the size in bits of the type `long' on the target machine. If you don't define this, the default is one word. */ -#define LONG_TYPE_SIZE 32 +#define LONG_TYPE_SIZE (TARGET_LONG64 ? 64 : 32) +#define MAX_LONG_TYPE_SIZE 64 /* A C expression for the size in bits of the type `long long' on the target machine. If you don't define this, the default is two @@ -955,19 +1005,19 @@ do { \ /* Width in bits of a pointer. See also the macro `Pmode' defined below. */ -#define POINTER_SIZE 32 +#define POINTER_SIZE (TARGET_LONG64 ? 64 : 32) /* Allocation boundary (in *bits*) for storing pointers in memory. */ -#define POINTER_BOUNDARY 32 +#define POINTER_BOUNDARY (TARGET_LONG64 ? 64 : 32) /* Allocation boundary (in *bits*) for storing arguments in argument list. */ -#define PARM_BOUNDARY 32 +#define PARM_BOUNDARY (TARGET_64BIT ? 64 : 32) /* Allocation boundary (in *bits*) for the code of a function. */ #define FUNCTION_BOUNDARY 32 /* Alignment of field after `int : 0' in a structure. */ -#define EMPTY_FIELD_BOUNDARY 32 +#define EMPTY_FIELD_BOUNDARY (TARGET_LONG64 ? 64 : 32) /* Every structure's size must be a multiple of this. */ /* 8 is observed right on a DECstation and on riscos 4.02. */ @@ -1049,12 +1099,15 @@ do { \ #define PROMOTE_PROTOTYPES -/* Define this macro if an instruction to load a value narrower - than a word from memory into a register also zero-extends the - value to the whole 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 /* Standard register usage. */ @@ -1153,14 +1206,13 @@ do { \ #define HARD_REGNO_NREGS(REGNO, MODE) \ (! FP_REG_P (REGNO) \ ? ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) \ - : (((GET_MODE_SIZE (MODE) + (2*UNITS_PER_WORD) - 1) / (2*UNITS_PER_WORD)) \ - << (TARGET_FLOAT64 == 0))) + : (((GET_MODE_SIZE (MODE) + 7) / 8) << (TARGET_FLOAT64 == 0))) /* Value is 1 if hard register REGNO can hold a value of machine-mode - MODE. Require that DImode and DFmode be in even registers. For - DImode, this makes some of the insns easier to write, since you - don't have to worry about a DImode value in registers 3 & 4, - producing a result in 4 & 5. + MODE. In 32 bit mode, require that DImode and DFmode be in even + registers. For DImode, this makes some of the insns easier to + write, since you don't have to worry about a DImode value in + registers 3 & 4, producing a result in 4 & 5. To make the code simpler HARD_REGNO_MODE_OK now just references an array built in override_options. Because machmodes.h is not yet @@ -1214,7 +1266,7 @@ extern char mips_hard_regno_mode_ok[][FI `STRUCT_VALUE' as an expression returning an RTX for the place where the address is passed. If it returns 0, the address is passed as an "invisible" first argument. */ -#define STRUCT_VALUE ((rtx)0) +#define STRUCT_VALUE 0 /* Mips registers used in prologue/epilogue code when the stack frame is larger than 32K bytes. These registers must come from the @@ -1243,6 +1295,9 @@ extern char mips_hard_regno_mode_ok[][FI files to allocate such a register (if necessary). */ #define PIC_OFFSET_TABLE_REGNUM (GP_REG_FIRST + 28) +#define PIC_FUNCTION_ADDR_REGNUM (GP_REG_FIRST + 25) + +#define FINALIZE_PIC mips_finalize_pic () /* Define the classes of registers for register constraints in the machine description. Also define ranges of constants. @@ -1342,7 +1397,7 @@ extern enum reg_class mips_regno_to_clas factor or added to another register (as well as added to a displacement). */ -#define INDEX_REG_CLASS GR_REGS +#define INDEX_REG_CLASS NO_REGS /* REGISTER AND CONSTANT CLASSES */ @@ -1398,10 +1453,14 @@ extern enum reg_class mips_char_to_class ((C) == 'I' ? ((unsigned) ((VALUE) + 0x8000) < 0x10000) \ : (C) == 'J' ? ((VALUE) == 0) \ : (C) == 'K' ? ((unsigned) (VALUE) < 0x10000) \ - : (C) == 'L' ? (((VALUE) & 0xffff0000) == (VALUE)) \ + : (C) == 'L' ? (((VALUE) & 0x0000ffff) == 0 \ + && (((VALUE) & ~2147483647) == 0 \ + || ((VALUE) & ~2147483647) == ~2147483647)) \ : (C) == 'M' ? ((((VALUE) & ~0x0000ffff) != 0) \ && (((VALUE) & ~0x0000ffff) != ~0x0000ffff) \ - && ((VALUE) & 0x0000ffff) != 0) \ + && (((VALUE) & 0x0000ffff) != 0 \ + || (((VALUE) & ~2147483647) != 0 \ + && ((VALUE) & ~2147483647) != ~2147483647))) \ : (C) == 'N' ? (((VALUE) & ~0x0000ffff) == ~0x0000ffff) \ : (C) == 'O' ? (exact_log2 (VALUE) >= 0) \ : (C) == 'P' ? ((VALUE) != 0 && (((VALUE) & ~0x0000ffff) == 0)) \ @@ -1416,8 +1475,7 @@ extern enum reg_class mips_char_to_class #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ ((C) == 'G' \ - && CONST_DOUBLE_HIGH (VALUE) == 0 \ - && CONST_DOUBLE_LOW (VALUE) == 0) + && (VALUE) == CONST0_RTX (GET_MODE (VALUE))) /* Letters in the range `Q' through `U' may be defined in a machine-dependent fashion to stand for arbitrary operand types. @@ -1443,12 +1501,15 @@ extern enum reg_class mips_char_to_class in some cases it is preferable to use a more restrictive class. */ #define PREFERRED_RELOAD_CLASS(X,CLASS) \ - ((GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ - || GET_MODE_CLASS (GET_MODE (X)) == MODE_COMPLEX_FLOAT) \ - ? (TARGET_SOFT_FLOAT ? GR_REGS : FP_REGS) \ - : ((GET_MODE (X) == VOIDmode) \ - ? GR_REGS \ - : CLASS)) + ((CLASS) != ALL_REGS \ + ? (CLASS) \ + : ((GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ + || GET_MODE_CLASS (GET_MODE (X)) == MODE_COMPLEX_FLOAT) \ + ? (TARGET_SOFT_FLOAT ? GR_REGS : FP_REGS) \ + : ((GET_MODE_CLASS (GET_MODE (X)) == MODE_INT \ + || GET_MODE (X) == VOIDmode) \ + ? GR_REGS \ + : (CLASS)))) /* Certain machines have the property that some registers cannot be copied to some other registers without using memory. Define this @@ -1460,23 +1521,26 @@ extern enum reg_class mips_char_to_class Do not define this macro if its value would always be zero. */ #define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \ - (!TARGET_DEBUG_H_MODE \ - && GET_MODE_CLASS (MODE) == MODE_INT \ - && ((CLASS1 == FP_REGS && CLASS2 == GR_REGS) \ - || (CLASS1 == GR_REGS && CLASS2 == FP_REGS))) + ((!TARGET_DEBUG_H_MODE \ + && GET_MODE_CLASS (MODE) == MODE_INT \ + && ((CLASS1 == FP_REGS && CLASS2 == GR_REGS) \ + || (CLASS1 == GR_REGS && CLASS2 == FP_REGS))) \ + || (TARGET_FLOAT64 && !TARGET_64BIT && (MODE) == DFmode \ + && ((CLASS1 == GR_REGS && CLASS2 == FP_REGS) \ + || (CLASS2 == GR_REGS && CLASS1 == FP_REGS)))) /* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. */ -#define CLASS_UNITS(mode, num) \ - ((GET_MODE_SIZE (mode) + ((num) * UNITS_PER_WORD) - 1) / ((num) * UNITS_PER_WORD)) +#define CLASS_UNITS(mode, size) \ + ((GET_MODE_SIZE (mode) + (size) - 1) / (size)) #define CLASS_MAX_NREGS(CLASS, MODE) \ - (((CLASS) == FP_REGS && TARGET_FLOAT64) \ - ? CLASS_UNITS (MODE, 2) \ - : (((CLASS) == FP_REGS) \ - ? (2*CLASS_UNITS (MODE, 1)) \ - : CLASS_UNITS (MODE, 1))) + ((CLASS) == FP_REGS \ + ? (TARGET_FLOAT64 \ + ? CLASS_UNITS (MODE, 8) \ + : 2 * CLASS_UNITS (MODE, 8)) \ + : CLASS_UNITS (MODE, UNITS_PER_WORD)) /* If defined, this is a C expression whose value should be nonzero if the insn INSN has the effect of mysteriously @@ -1508,7 +1572,9 @@ extern enum reg_class mips_char_to_class 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 current_function_outgoing_args_size +#define STARTING_FRAME_OFFSET \ + (current_function_outgoing_args_size \ + + (TARGET_ABICALLS ? MIPS_STACK_ALIGN (UNITS_PER_WORD) : 0)) /* Offset from the stack pointer register to an item dynamically allocated on the stack, e.g., by `alloca'. @@ -1650,7 +1716,7 @@ extern struct mips_frame_info current_fr the first argument's address. On the MIPS, we must skip the first argument position if we are - returning a structure or a union, to account for it's address being + returning a structure or a union, to account for its address being passed in $4. However, at the current time, this produces a compiler that can't bootstrap, so comment it out for now. */ @@ -1687,13 +1753,13 @@ extern struct mips_frame_info current_fr /* Align stack frames on 64 bits (Double Word ). */ #define STACK_BOUNDARY 64 -/* Make sure 16 bytes are always allocated on the stack. */ +/* Make sure 4 words are always allocated on the stack. */ #ifndef STACK_ARGS_ADJUST #define STACK_ARGS_ADJUST(SIZE) \ { \ - if (SIZE.constant < 16) \ - SIZE.constant = 16; \ + if (SIZE.constant < 4 * UNITS_PER_WORD) \ + SIZE.constant = 4 * UNITS_PER_WORD; \ } #endif @@ -1810,7 +1876,10 @@ typedef struct mips_args { int arg_words; /* # total words the arguments take */ int num_adjusts; /* number of adjustments made */ /* Adjustments made to args pass in regs. */ - struct rtx_def *adjust[MAX_ARGS_IN_REGISTERS]; + /* ??? The size is doubled to work around a + bug in the code that sets the adjustments + in function_arg. */ + struct rtx_def *adjust[MAX_ARGS_IN_REGISTERS*2]; } CUMULATIVE_ARGS; /* Initialize a variable CUM of type CUMULATIVE_ARGS @@ -1921,9 +1990,12 @@ typedef struct mips_args { 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, "\tsubu\t%s,%s,8\t\t# _mcount pops 2 words from stack\n", \ + fprintf (FILE, \ + "\t%s\t%s,%s,%d\t\t# _mcount pops 2 words from stack\n", \ + TARGET_64BIT ? "dsubu" : "subu", \ reg_names[STACK_POINTER_REGNUM], \ - reg_names[STACK_POINTER_REGNUM]); \ + reg_names[STACK_POINTER_REGNUM], \ + TARGET_LONG64 ? 16 : 8); \ fprintf (FILE, "\t.set\treorder\n"); \ fprintf (FILE, "\t.set\tat\n"); \ } @@ -1952,25 +2024,39 @@ typedef struct mips_args { 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"); \ - fprintf (STREAM, "\t.word\t0x8fe30010\t\t# lw $3,16($31)\n"); \ - fprintf (STREAM, "\t.word\t0x8fe20014\t\t# lw $2,20($31)\n"); \ + if (TARGET_LONG64) \ + { \ + 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# \n"); \ - fprintf (STREAM, "\t.word\t0x00000000\t\t# \n"); \ + if (TARGET_LONG64) \ + { \ + fprintf (STREAM, "\t.dword\t0x00000000\t\t# \n"); \ + fprintf (STREAM, "\t.dword\t0x00000000\t\t# \n"); \ + } \ + else \ + { \ + fprintf (STREAM, "\t.word\t0x00000000\t\t# \n"); \ + fprintf (STREAM, "\t.word\t0x00000000\t\t# \n"); \ + } \ } /* A C expression for the size in bytes of the trampoline, as an integer. */ -#define TRAMPOLINE_SIZE (9*4) - -/* Alignment required for trampolines, in bits. +#define TRAMPOLINE_SIZE (32 + (TARGET_LONG64 ? 16 : 8)) - If you don't define this macro, the value of `BIGGEST_ALIGNMENT' - is used for aligning trampolines. */ +/* Alignment required for trampolines, in bits. */ -/* #define TRAMPOLINE_ALIGNMENT 32 */ +#define TRAMPOLINE_ALIGNMENT (TARGET_LONG64 ? 64 : 32) /* A C statement to initialize the variable parts of a trampoline. ADDR is an RTX for the address of the trampoline; FNADDR is an @@ -1978,45 +2064,28 @@ typedef struct mips_args { RTX for the static chain value that should be passed to the function when it is called. */ -#ifndef INITIALIZE_TRAMPOLINE #define INITIALIZE_TRAMPOLINE(ADDR, FUNC, CHAIN) \ { \ rtx addr = ADDR; \ - emit_move_insn (gen_rtx (MEM, SImode, plus_constant (addr, 28)), FUNC); \ - emit_move_insn (gen_rtx (MEM, SImode, plus_constant (addr, 32)), CHAIN); \ + if (TARGET_LONG64) \ + { \ + emit_move_insn (gen_rtx (MEM, DImode, plus_constant (addr, 32)), FUNC); \ + emit_move_insn (gen_rtx (MEM, DImode, plus_constant (addr, 40)), CHAIN);\ + } \ + else \ + { \ + emit_move_insn (gen_rtx (MEM, SImode, plus_constant (addr, 32)), FUNC); \ + emit_move_insn (gen_rtx (MEM, SImode, plus_constant (addr, 36)), CHAIN);\ + } \ \ - /* Attempt to make stack executable */ \ - emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"), \ - 0, VOIDmode, 1, addr, Pmode); \ -} -#endif /* INITIALIZE_TRAMPOLINE */ - - -/* Attempt to turn on access permissions for the stack. */ - -#ifndef TRANSFER_FROM_TRAMPOLINE -#define TRANSFER_FROM_TRAMPOLINE \ - \ -void \ -__enable_execute_stack (addr) \ - char *addr; \ -{ \ - int size = getpagesize (); \ - int mask = ~(size-1); \ - char *page = (char *) (((int) addr) & mask); \ - char *end = (char *) ((((int) (addr + TRAMPOLINE_SIZE)) & mask) + size); \ - \ - /* 7 is PROT_READ | PROT_WRITE | PROT_EXEC */ \ - if (mprotect (page, end - page, 7) < 0) \ - perror ("mprotect of trampoline code"); \ - \ -/* \ - if (cacheflush (addr, TRAMPOLINE_SIZE, 1) < 0) \ - perror ("cacheflush of trampoline code"); \ - */ \ + /* Flush the instruction cache. */ \ + /* ??? Are the modes right? Maybe they should depend on -mint64/-mlong64? */\ + /* ??? Should check the return value for errors. */ \ + emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "cacheflush"), \ + 0, VOIDmode, 3, addr, Pmode, \ + GEN_INT (TRAMPOLINE_SIZE), SImode, \ + GEN_INT (1), SImode); \ } -#endif /* TRANSFER_FROM_TRAMPOLINE */ - /* Addressing modes, and classification of registers for them. */ @@ -2037,7 +2106,7 @@ __enable_execute_stack (addr) \ #define GP_REG_OR_PSEUDO_NONSTRICT_P(regno) \ (((regno) >= FIRST_PSEUDO_REGISTER) || (GP_REG_P (regno))) -#define REGNO_OK_FOR_INDEX_P(regno) GP_REG_OR_PSEUDO_STRICT_P (regno) +#define REGNO_OK_FOR_INDEX_P(regno) 0 #define REGNO_OK_FOR_BASE_P(regno) GP_REG_OR_PSEUDO_STRICT_P (regno) /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx @@ -2054,13 +2123,13 @@ __enable_execute_stack (addr) \ #ifndef REG_OK_STRICT #define REG_OK_STRICT_P 0 -#define REG_OK_FOR_INDEX_P(X) GP_REG_OR_PSEUDO_NONSTRICT_P (REGNO (X)) +#define REG_OK_FOR_INDEX_P(X) 0 #define REG_OK_FOR_BASE_P(X) GP_REG_OR_PSEUDO_NONSTRICT_P (REGNO (X)) #else #define REG_OK_STRICT_P 1 -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) +#define REG_OK_FOR_INDEX_P(X) 0 #define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) #endif @@ -2165,14 +2234,10 @@ __enable_execute_stack (addr) \ \ if (code0 == REG && REG_OK_FOR_BASE_P (xplus0)) \ { \ - if (code1 == CONST_INT) \ - { \ - register unsigned adj_offset = INTVAL (xplus1) + 0x8000; \ - \ - if ((adj_offset <= 0xffff) \ - && (adj_offset + GET_MODE_SIZE (MODE) - 1 <= 0xffff)) \ - goto ADDR; \ - } \ + if (code1 == CONST_INT \ + && INTVAL (xplus1) >= -32768 \ + && INTVAL (xplus1) + GET_MODE_SIZE (MODE) - 1 <= 32767) \ + goto ADDR; \ \ /* For some code sequences, you actually get better code by \ pretending that the MIPS supports an address mode of a \ @@ -2186,9 +2251,15 @@ __enable_execute_stack (addr) \ MIPS assembler does not have syntax to generate the \ appropriate relocation. */ \ \ - else if (!TARGET_DEBUG_A_MODE \ - && code0 == REG \ - && CONSTANT_ADDRESS_P (xplus1)) \ + /* Also accept CONST_INT addresses here, so no else. */ \ + /* Reject combining an embedded PIC text segment reference \ + with a register. That requires an additional \ + instruction. */ \ + if (!TARGET_DEBUG_A_MODE \ + && CONSTANT_ADDRESS_P (xplus1) \ + && (!TARGET_EMBEDDED_PIC \ + || code1 != CONST \ + || GET_CODE (XEXP (xplus1, 0)) != MINUS)) \ goto ADDR; \ } \ } \ @@ -2201,11 +2272,23 @@ __enable_execute_stack (addr) \ /* A C expression that is 1 if the RTX X is a constant which is a valid address. This is defined to be the same as `CONSTANT_P (X)', but rejecting CONST_DOUBLE. */ +/* When pic, we must reject addresses of the form symbol+large int. + This is because an instruction `sw $4,s+70000' needs to be converted + by the assembler to `lw $at,s($gp);sw $4,70000($at)'. Normally the + assembler would use $at as a temp to load in the large offset. In this + case $at is already in use. We convert such problem addresses to + `la $5,s;sw $4,70000($5)' via LEGITIMIZE_ADDRESS. */ #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) && (!HALF_PIC_P () || !HALF_PIC_ADDRESS_P (X))) + || GET_CODE (X) == CONST_INT || GET_CODE (X) == HIGH \ + || (GET_CODE (X) == CONST \ + && ! (flag_pic && pic_address_needs_scratch (X)))) \ + && (!HALF_PIC_P () || !HALF_PIC_ADDRESS_P (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. It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. @@ -2251,7 +2334,11 @@ __enable_execute_stack (addr) \ Z = X + Y memory (Z + ( & 0x7fff)); - This is for CSE to find several similar references, and only use one Z. */ + This is for CSE to find several similar references, and only use one Z. + + When PIC, convert addresses of the form memory (symbol+large int) to + memory (reg+large int). */ + #define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ { \ @@ -2297,6 +2384,16 @@ __enable_execute_stack (addr) \ } \ } \ \ + if (flag_pic && pic_address_needs_scratch (xinsn)) \ + { \ + rtx ptr_reg = gen_reg_rtx (Pmode); \ + \ + emit_move_insn (ptr_reg, XEXP (XEXP (xinsn, 0), 0)); \ + \ + X = gen_rtx (PLUS, Pmode, ptr_reg, XEXP (XEXP (xinsn, 0), 1)); \ + goto WIN; \ + } \ + \ if (TARGET_DEBUG_B_MODE) \ GO_PRINTF ("LEGITIMIZE_ADDRESS could not fix.\n"); \ } @@ -2345,8 +2442,20 @@ __enable_execute_stack (addr) \ #define ENCODE_SECTION_INFO(DECL) \ do \ { \ - if (optimize && mips_section_threshold > 0 && TARGET_GP_OPT \ - && TREE_CODE (DECL) == VAR_DECL) \ + if (TARGET_EMBEDDED_PIC) \ + { \ + if (TREE_CODE (DECL) == VAR_DECL) \ + SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; \ + else if (TREE_CODE (DECL) == FUNCTION_DECL) \ + SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 0; \ + else if (TREE_CODE (DECL) == STRING_CST \ + && ! flag_writable_strings) \ + SYMBOL_REF_FLAG (XEXP (TREE_CST_RTL (DECL), 0)) = 0; \ + else \ + SYMBOL_REF_FLAG (XEXP (TREE_CST_RTL (DECL), 0)) = 1; \ + } \ + \ + else if (TARGET_GP_OPT && TREE_CODE (DECL) == VAR_DECL) \ { \ int size = int_size_in_bytes (TREE_TYPE (DECL)); \ \ @@ -2362,7 +2471,7 @@ while (0) /* Specify the machine mode that this machine uses for the index in the tablejump instruction. */ -#define CASE_VECTOR_MODE SImode +#define CASE_VECTOR_MODE (TARGET_LONG64 ? DImode : SImode) /* Define this if the tablejump instruction expects the table to contain offsets from the address of the table. @@ -2382,7 +2491,8 @@ while (0) /* Max number of bytes we can move from memory to memory in one reasonably fast instruction. */ -#define MOVE_MAX 4 +#define MOVE_MAX (TARGET_64BIT ? 8 : 4) +#define MAX_MOVE_MAX 8 /* Define this macro as a C expression which is nonzero if accessing less than a word of memory (i.e. a `char' or a @@ -2402,17 +2512,20 @@ while (0) /* Define this if zero-extension is slow (more than one real instruction). */ #define SLOW_ZERO_EXTEND -/* Define if shifts truncate the shift count - which implies one can omit a sign-extension or zero-extension - of a shift count. - - Only 5 bits are used in SLLV and SRLV */ - -#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. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 +/* In 64 bit mode, 32 bit instructions require that register values be properly + sign-extended to 64 bits. As a result, a truncate is not a no-op if it + converts a value >32 bits to a value <32 bits. */ +/* ??? This results in inefficient code for 64 bit to 32 conversions. + Something needs to be done about this. Perhaps not use any 32 bit + instructions? Perhaps use PROMOTE_MODE? */ +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) \ + (TARGET_64BIT ? ((INPREC) <= 32 || (OUTPREC) > 32) : 1) /* Define this macro to control use of the character `$' in identifier names. The value should be 0, 1, or 2. 0 means `$' @@ -2428,13 +2541,14 @@ while (0) /* Specify the machine mode that pointers have. After generation of rtl, the compiler makes no further distinction between pointers and any other objects of this machine mode. */ -#define Pmode SImode + +#define Pmode (TARGET_LONG64 ? DImode : SImode) /* A function address in a call instruction is a word address (for indexing purposes) so give the MEM rtx a words's mode. */ -#define FUNCTION_MODE SImode +#define FUNCTION_MODE (TARGET_LONG64 ? DImode : SImode) /* Define TARGET_MEM_FUNCTIONS if we want to use calls to memcpy and memset, instead of the BSD functions bcopy and bzero. */ @@ -2461,7 +2575,7 @@ while (0) /* Always return 0, since we don't have different sized \ instructions, hence different costs according to Richard \ Kenner */ \ - return COSTS_N_INSNS (0); \ + return 0; \ \ case LABEL_REF: \ return COSTS_N_INSNS (2); \ @@ -2469,7 +2583,7 @@ while (0) case CONST: \ { \ rtx offset = const0_rtx; \ - rtx symref = eliminate_constant_term (X, &offset); \ + rtx symref = eliminate_constant_term (XEXP (X, 0), &offset); \ \ if (GET_CODE (symref) == LABEL_REF) \ return COSTS_N_INSNS (2); \ @@ -2519,34 +2633,21 @@ while (0) return COSTS_N_INSNS (6); \ \ case NOT: \ - return COSTS_N_INSNS ((GET_MODE (X) == DImode) ? 2 : 1); \ + return COSTS_N_INSNS ((GET_MODE (X) == DImode && !TARGET_64BIT) ? 2 : 1); \ \ case AND: \ case IOR: \ case XOR: \ - if (GET_MODE (X) == DImode) \ + if (GET_MODE (X) == DImode && !TARGET_64BIT) \ return COSTS_N_INSNS (2); \ \ - if (GET_CODE (XEXP (X, 1)) == CONST_INT) \ - { \ - rtx number = XEXP (X, 1); \ - if (SMALL_INT_UNSIGNED (number)) \ - return COSTS_N_INSNS (1); \ - \ - else if (SMALL_INT (number)) \ - return COSTS_N_INSNS (2); \ - \ - return COSTS_N_INSNS (3); \ - } \ - \ return COSTS_N_INSNS (1); \ \ case ASHIFT: \ case ASHIFTRT: \ - case LSHIFT: \ case LSHIFTRT: \ - if (GET_MODE (X) == DImode) \ - return COSTS_N_INSNS ((GET_CODE (XEXP (X, 1)) == CONST_INT) ? 12 : 4); \ + if (GET_MODE (X) == DImode && !TARGET_64BIT) \ + return COSTS_N_INSNS ((GET_CODE (XEXP (X, 1)) == CONST_INT) ? 4 : 12); \ \ return COSTS_N_INSNS (1); \ \ @@ -2564,27 +2665,53 @@ while (0) { \ enum machine_mode xmode = GET_MODE (X); \ if (xmode == SFmode || xmode == DFmode) \ - return COSTS_N_INSNS (2); \ + { \ + if (mips_cpu == PROCESSOR_R3000) \ + return COSTS_N_INSNS (2); \ + else if (mips_cpu == PROCESSOR_R6000) \ + return COSTS_N_INSNS (3); \ + else \ + return COSTS_N_INSNS (6); \ + } \ \ - if (xmode == DImode) \ + if (xmode == DImode && !TARGET_64BIT) \ return COSTS_N_INSNS (4); \ \ return COSTS_N_INSNS (1); \ } \ \ case NEG: \ - return COSTS_N_INSNS ((GET_MODE (X) == DImode) ? 4 : 1); \ + return COSTS_N_INSNS ((GET_MODE (X) == DImode && !TARGET_64BIT) ? 4 : 1); \ \ case MULT: \ { \ enum machine_mode xmode = GET_MODE (X); \ if (xmode == SFmode) \ - return COSTS_N_INSNS (4); \ + { \ + if (mips_cpu == PROCESSOR_R3000) \ + return COSTS_N_INSNS (4); \ + else if (mips_cpu == PROCESSOR_R6000) \ + return COSTS_N_INSNS (5); \ + else \ + return COSTS_N_INSNS (7); \ + } \ \ if (xmode == DFmode) \ - return COSTS_N_INSNS (5); \ + { \ + if (mips_cpu == PROCESSOR_R3000) \ + return COSTS_N_INSNS (5); \ + else if (mips_cpu == PROCESSOR_R6000) \ + return COSTS_N_INSNS (6); \ + else \ + return COSTS_N_INSNS (8); \ + } \ \ - return COSTS_N_INSNS (12); \ + if (mips_cpu == PROCESSOR_R3000) \ + return COSTS_N_INSNS (12); \ + else if (mips_cpu == PROCESSOR_R6000) \ + return COSTS_N_INSNS (17); \ + else \ + return COSTS_N_INSNS (10); \ } \ \ case DIV: \ @@ -2592,16 +2719,35 @@ while (0) { \ enum machine_mode xmode = GET_MODE (X); \ if (xmode == SFmode) \ - return COSTS_N_INSNS (12); \ + { \ + if (mips_cpu == PROCESSOR_R3000) \ + return COSTS_N_INSNS (12); \ + else if (mips_cpu == PROCESSOR_R6000) \ + return COSTS_N_INSNS (15); \ + else \ + return COSTS_N_INSNS (23); \ + } \ \ if (xmode == DFmode) \ - return COSTS_N_INSNS (19); \ + { \ + if (mips_cpu == PROCESSOR_R3000) \ + return COSTS_N_INSNS (19); \ + else if (mips_cpu == PROCESSOR_R6000) \ + return COSTS_N_INSNS (16); \ + else \ + return COSTS_N_INSNS (36); \ + } \ } \ /* fall through */ \ \ case UDIV: \ case UMOD: \ - return COSTS_N_INSNS (35); + if (mips_cpu == PROCESSOR_R3000) \ + return COSTS_N_INSNS (35); \ + else if (mips_cpu == PROCESSOR_R6000) \ + return COSTS_N_INSNS (38); \ + else \ + return COSTS_N_INSNS (69); /* An expression giving the cost of an addressing mode that contains ADDRESS. If not defined, the cost is computed from the @@ -2664,7 +2810,15 @@ while (0) met. You should do this if the `movM' pattern's constraints do not allow such copying. */ -#define REGISTER_MOVE_COST(FROM, TO) 4 /* force reload to use constraints */ +#define REGISTER_MOVE_COST(FROM, TO) \ + ((FROM) == GR_REGS && (TO) == GR_REGS ? 2 \ + : (FROM) == FP_REGS && (TO) == FP_REGS ? 2 \ + : (FROM) == GR_REGS && (TO) == FP_REGS ? 4 \ + : (FROM) == FP_REGS && (TO) == GR_REGS ? 4 \ + : 6) + +#define MEMORY_MOVE_COST(MODE) \ + ((mips_cpu == PROCESSOR_R4000 || mips_cpu == PROCESSOR_R6000) ? 6 : 4) /* A C expression for the cost of a branch instruction. A value of 1 is the default; other values are interpreted relative to that. */ @@ -2672,22 +2826,15 @@ while (0) #define BRANCH_COST \ ((mips_cpu == PROCESSOR_R4000 || mips_cpu == PROCESSOR_R6000) ? 2 : 1) - -/* Used in by the peephole code. */ -#define classify_op(op,mode) (mips_rtx_classify[ (int)GET_CODE (op) ]) -#define additive_op(op,mode) ((classify_op (op,mode) & CLASS_ADD_OP) != 0) -#define divmod_op(op,mode) ((classify_op (op,mode) & CLASS_DIVMOD_OP) != 0) -#define unsigned_op(op,mode) ((classify_op (op,mode) & CLASS_UNSIGNED_OP) != 0) - -#define CLASS_ADD_OP 0x01 /* operator is PLUS/MINUS */ -#define CLASS_DIVMOD_OP 0x02 /* operator is {,U}{DIV,MOD} */ -#define CLASS_UNSIGNED_OP 0x04 /* operator is U{DIV,MOD} */ -#define CLASS_CMP_OP 0x08 /* operator is comparison */ -#define CLASS_EQUALITY_OP 0x10 /* operator is == or != */ -#define CLASS_FCMP_OP 0x08 /* operator is fp. compare */ - -#define CLASS_UNS_CMP_OP (CLASS_UNSIGNED_OP | CLASS_CMP_OP) - +/* A C statement (sans semicolon) to update the integer variable COST + based on the relationship between INSN that is dependent on + DEP_INSN through the dependence LINK. The default is to make no + adjustment to COST. On the MIPS, ignore the cost of anti- and + output-dependencies. */ + +#define ADJUST_COST(INSN,LINK,DEP_INSN,COST) \ + if (REG_NOTE_KIND (LINK) != 0) \ + (COST) = 0; /* Anti or output dependence. */ /* Optionally define this if you have added predicates to `MACHINE.c'. This macro is called within an initializer of an @@ -2717,16 +2864,13 @@ while (0) {"reg_or_0_operand", { REG, CONST_INT, SUBREG }}, \ {"small_int", { CONST_INT }}, \ {"large_int", { CONST_INT }}, \ - {"md_register_operand", { REG }}, \ {"mips_const_double_ok", { CONST_DOUBLE }}, \ {"simple_memory_operand", { MEM, SUBREG }}, \ {"equality_op", { EQ, NE }}, \ {"cmp_op", { EQ, NE, GT, GE, GTU, GEU, LT, LE, \ LTU, LEU }}, \ - {"cmp2_op", { EQ, NE, GT, GE, GTU, GEU, LT, LE, \ - LTU, LEU }}, \ - {"fcmp_op", { EQ, NE, GT, GE, LT, LE }}, \ - {"uns_cmp_op", { GTU, GEU, LTU, LEU }}, + {"pc_or_label_operand", { PC, LABEL_REF }}, \ + {"call_insn_operand", { MEM }}, \ /* If defined, a C statement to be executed just prior to the @@ -2752,23 +2896,6 @@ while (0) Here we define machine-dependent flags and fields in cc_status (see `conditions.h'). */ -/* A C compound statement to set the components of `cc_status' - appropriately for an insn INSN whose body is EXP. It is this - macro's responsibility to recognize insns that set the condition - code as a byproduct of other activity as well as those that - explicitly set `(cc0)'. - - This macro is not used on machines that do not use `cc0'. */ - -#define NOTICE_UPDATE_CC(EXP, INSN) \ -do \ - { \ - enum attr_type type = get_attr_type (INSN); \ - if (type == TYPE_ICMP || type == TYPE_FCMP) \ - CC_STATUS_INIT; \ - } \ -while (0) - /* A list of names to be used for additional modes for condition code values in registers. These names are added to `enum machine_mode' and all have class `MODE_CC'. By convention, they should start @@ -3104,7 +3231,7 @@ while (0) #define ASM_OUTPUT_SOURCE_LINE(STREAM, LINE) \ mips_output_lineno (STREAM, LINE) -/* The MIPS implementation uses some labels for it's own purposed. The +/* The MIPS implementation uses some labels for it's own purpose. The following lists what labels are created, and are all formed by the pattern $L[a-z].*. The machine independent portion of GCC creates labels matching: $L[A-Z][0-9]+ and $L[0-9]+. @@ -3163,13 +3290,13 @@ while (0) /* This says how to define a global common symbol. */ #define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \ - mips_declare_object (STREAM, NAME, "\n\t.comm\t", ",%u\n", (ROUNDED)) + mips_declare_object (STREAM, NAME, "\n\t.comm\t", ",%u\n", (SIZE)) /* This says how to define a local common symbol (ie, not visible to linker). */ #define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED) \ - mips_declare_object (STREAM, NAME, "\n\t.lcomm\t", ",%u\n", (ROUNDED)) + mips_declare_object (STREAM, NAME, "\n\t.lcomm\t", ",%u\n", (SIZE)) /* This says how to output an external. It would be possible not to @@ -3241,7 +3368,24 @@ do { \ fprintf (STREAM, "\n"); \ } while (0) -/* Likewise for `char' and `short' constants. */ +/* Likewise for 64 bit, `char' and `short' constants. */ + +#define ASM_OUTPUT_DOUBLE_INT(STREAM,VALUE) \ +do { \ + if (TARGET_64BIT) \ + { \ + fprintf (STREAM, "\t.dword\t"); \ + output_addr_const (STREAM, (VALUE)); \ + fprintf (STREAM, "\n"); \ + } \ + else \ + { \ + assemble_integer (operand_subword ((VALUE), 0, 0, DImode), \ + UNITS_PER_WORD, 1); \ + assemble_integer (operand_subword ((VALUE), 1, 0, DImode), \ + UNITS_PER_WORD, 1); \ + } \ +} while (0) #define ASM_OUTPUT_SHORT(STREAM,VALUE) \ { \ @@ -3265,26 +3409,38 @@ do { \ /* This is how to output an element of a case-vector that is absolute. */ #define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \ - fprintf (STREAM, "\t.word\t$L%d\n", VALUE) + fprintf (STREAM, "\t%s\t$L%d\n", \ + TARGET_LONG64 ? ".dword" : ".word", \ + VALUE) /* This is how to output an element of a case-vector that is relative. - (We do not use such vectors, - but we must define this macro anyway.) */ + This is used for pc-relative code (e.g. when TARGET_ABICALLS or + TARGET_EMBEDDED_PIC). */ #define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, VALUE, REL) \ - fprintf (STREAM, "\t.word\t$L%d-$L%d\n", VALUE, REL) - -/* This is how to emit the initial label for switch statements. We - need to put the switch labels somewhere else from the text section, - because the MIPS assembler gets real confused about line numbers if - .word's appear in the text section. */ +do { \ + if (TARGET_EMBEDDED_PIC) \ + fprintf (STREAM, "\t%s\t$L%d-$LS%d\n", \ + TARGET_LONG64 ? ".dword" : ".word", \ + VALUE, REL); \ + else \ + fprintf (STREAM, "\t%s\t$L%d\n", \ + TARGET_LONG64 ? ".gpdword" : ".gpword", \ + VALUE); \ +} while (0) -#define ASM_OUTPUT_CASE_LABEL(STREAM, PREFIX, NUM, JUMPTABLE) \ -{ \ - rdata_section (); \ - ASM_OUTPUT_ALIGN (STREAM, 2); \ - ASM_OUTPUT_INTERNAL_LABEL (STREAM, PREFIX, NUM); \ -} +/* When generating embedded PIC code we want to put the jump table in + the .text section. In all other cases, we want to put the jump + table in the .rdata section. Unfortunately, we can't use + JUMP_TABLES_IN_TEXT_SECTION, because it is not conditional. + Instead, we use ASM_OUTPUT_CASE_LABEL to switch back to the .text + section if appropriate. */ +#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, INSN) \ +do { \ + if (TARGET_EMBEDDED_PIC) \ + text_section (); \ + ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); \ +} while (0) /* This is how to output an assembler line that says to advance the location counter @@ -3302,7 +3458,6 @@ do { \ #define ASM_OUTPUT_SKIP(STREAM,SIZE) \ fprintf (STREAM, "\t.space\t%u\n", (SIZE)) - /* This is how to output a string. */ #define ASM_OUTPUT_ASCII(STREAM, STRING, LEN) \ do { \ @@ -3400,7 +3555,7 @@ do { \ /* What other sections we support other than the normal .data/.text. */ -#define EXTRA_SECTIONS in_sdata, in_rdata, in_last_p1 +#define EXTRA_SECTIONS in_sdata, in_rdata /* Define the additional functions to select our additional sections. */ @@ -3436,41 +3591,9 @@ rdata_section () \ /* Given a decl node or constant node, choose the section to output it in and select that section. */ -#define SELECT_RTX_SECTION(MODE,RTX) \ -{ \ - if ((GET_MODE_SIZE(MODE) / BITS_PER_UNIT) <= mips_section_threshold \ - && mips_section_threshold > 0) \ - sdata_section (); \ - else \ - rdata_section (); \ -} \ +#define SELECT_RTX_SECTION(MODE,RTX) mips_select_rtx_section (MODE, RTX) -#define SELECT_SECTION(DECL, RELOC) \ -{ \ - if (int_size_in_bytes (TREE_TYPE (DECL)) <= mips_section_threshold \ - && mips_section_threshold > 0) \ - sdata_section (); \ - \ - else if (RELOC) \ - data_section (); \ - \ - else if (TREE_CODE (DECL) == STRING_CST) \ - { \ - if (flag_writable_strings) \ - data_section (); \ - else \ - rdata_section (); \ - } \ - \ - else if (TREE_CODE (DECL) != VAR_DECL) \ - rdata_section (); \ - \ - else if (!TREE_READONLY (DECL)) \ - data_section (); \ - \ - else \ - rdata_section (); \ -} +#define SELECT_SECTION(DECL, RELOC) mips_select_section (DECL, RELOC) /* Store in OUTPUT a string (made with alloca) containing @@ -3484,9 +3607,11 @@ rdata_section () \ #define ASM_OUTPUT_REG_PUSH(STREAM,REGNO) \ do \ { \ - fprintf (STREAM, "\tsubu\t%s,%s,8\n\tsw\t%s,0(%s)\n", \ + fprintf (STREAM, "\t%s\t%s,%s,8\n\t%s\t%s,0(%s)\n", \ + TARGET_64BIT ? "dsubu" : "subu", \ reg_names[STACK_POINTER_REGNUM], \ reg_names[STACK_POINTER_REGNUM], \ + TARGET_64BIT ? "sd" : "sw", \ reg_names[REGNO], \ reg_names[STACK_POINTER_REGNUM]); \ } \ @@ -3500,9 +3625,11 @@ do \ \ dslots_load_total++; \ dslots_load_filled++; \ - fprintf (STREAM, "\tlw\t%s,0(%s)\n\taddu\t%s,%s,8\n", \ + fprintf (STREAM, "\t%s\t%s,0(%s)\n\t%s\t%s,%s,8\n", \ + TARGET_64BIT ? "ld" : "lw", \ reg_names[REGNO], \ reg_names[STACK_POINTER_REGNUM], \ + TARGET_64BIT ? "daddu" : "addu", \ reg_names[STACK_POINTER_REGNUM], \ reg_names[STACK_POINTER_REGNUM]); \ \ @@ -3539,10 +3666,11 @@ while (0) /* Default definitions for size_t and ptrdiff_t. */ #ifndef SIZE_TYPE -#define SIZE_TYPE "unsigned int" +#define NO_BUILTIN_SIZE_TYPE +#define SIZE_TYPE (TARGET_LONG64 ? "long unsigned int" : "unsigned int") #endif #ifndef PTRDIFF_TYPE -#define PTRDIFF_TYPE "int" +#define NO_BUILTIN_PTRDIFF_TYPE +#define PTRDIFF_TYPE (TARGET_LONG64 ? "long int" : "int") #endif -