--- gcc/config/mips/mips.h 2018/04/24 18:10:25 1.1 +++ gcc/config/mips/mips.h 2018/04/24 18:29:30 1.1.1.4 @@ -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, 94, 1995 Free Software Foundation, Inc. This file is part of GNU CC. @@ -17,15 +19,10 @@ 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. */ -/* Make Saber happier on obstack.[ch]. */ -#if defined(__mips__) || defined(mips) -#define __PTR_TO_INT(P) ((int)(P)) -#define __INT_TO_PTR(P) ((char *)(P)) -#endif - /* Standard GCC variables that we reference. */ extern char *asm_file_name; @@ -44,7 +41,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 +65,25 @@ enum processor_type { PROCESSOR_DEFAULT, PROCESSOR_R3000, PROCESSOR_R6000, - PROCESSOR_R4000 + PROCESSOR_R4000, + PROCESSOR_R4600, + PROCESSOR_R4650, + PROCESSOR_R8000 }; /* 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). */ @@ -84,13 +95,13 @@ enum block_move_type { extern char mips_reg_names[][8]; /* register names (a0 vs. $4). */ extern char mips_print_operand_punct[]; /* print_operand punctuation chars */ -extern char *current_function_name; /* current function being compiled */ extern char *current_function_file; /* filename current function is in */ extern int num_source_filenames; /* current .file # */ extern int inside_function; /* != 0 if inside of a function */ extern int ignore_line_number; /* != 0 if we are to ignore next .loc */ extern int file_in_function_warning; /* warning given about .file in func */ extern int sdb_label_count; /* block start/end next label # */ +extern int sdb_begin_function_line; /* Starting Line of current function */ extern int mips_section_threshold; /* # bytes of data/sdata cutoff */ extern int g_switch_value; /* value of the -G xx switch */ extern int g_switch_set; /* whether -G xx was passed. */ @@ -101,13 +112,13 @@ 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} */ +extern char *mips_isa_string; /* for -mips{1,2,3,4} */ extern int dslots_load_total; /* total # load related delay slots */ extern int dslots_load_filled; /* # filled load delay slots */ extern int dslots_jump_total; /* total # jump related delay slots */ @@ -118,6 +129,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 +137,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 +151,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 +181,7 @@ 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 (); /* Recognition functions that return if a condition is true. */ extern int address_operand (); @@ -206,7 +214,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 +240,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 +252,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_UNUSED4 0x00010000 -#define MASK_UNUSED5 0x00020000 -#define MASK_UNUSED6 0x00040000 -#define MASK_UNUSED7 0x00080000 +#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_BIG_ENDIAN 0x00010000 /* Generate big endian code */ +#define MASK_SINGLE_FLOAT 0x00020000 /* Only single precision FPU. */ +#define MASK_MAD 0x00040000 /* Generate mad/madu as on 4650. */ +#define MASK_UNUSED1 0x00080000 /* Dummy switches used only in spec's*/ #define MASK_MIPS_TFILE 0x00000000 /* flag for mips-tfile usage */ @@ -272,8 +279,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 +325,23 @@ 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) + + /* generate big endian code. */ +#define TARGET_BIG_ENDIAN (target_flags & MASK_BIG_ENDIAN) + +#define TARGET_SINGLE_FLOAT (target_flags & MASK_SINGLE_FLOAT) +#define TARGET_DOUBLE_FLOAT (! TARGET_SINGLE_FLOAT) + +#define TARGET_MAD (target_flags & MASK_MAD) + /* 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 +352,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 +370,25 @@ 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}, \ + {"eb", MASK_BIG_ENDIAN}, \ + {"el", -MASK_BIG_ENDIAN}, \ + {"single-float", MASK_SINGLE_FLOAT}, \ + {"double-float", -MASK_SINGLE_FLOAT}, \ + {"mad", MASK_MAD}, \ + {"no-mad", -MASK_MAD}, \ + {"4650", MASK_MAD | MASK_SINGLE_FLOAT}, \ {"debug", MASK_DEBUG}, \ {"debuga", MASK_DEBUG_A}, \ {"debugb", MASK_DEBUG_B}, \ @@ -364,7 +400,9 @@ extern char *mktemp (); {"debugh", MASK_DEBUG_H}, \ {"debugi", MASK_DEBUG_I}, \ {"debugj", MASK_DEBUG_J}, \ - {"", TARGET_DEFAULT | TARGET_CPU_DEFAULT} \ + {"", (TARGET_DEFAULT \ + | TARGET_CPU_DEFAULT \ + | TARGET_ENDIAN_DEFAULT)} \ } /* Default target_flags if no switches are specified */ @@ -377,6 +415,22 @@ extern char *mktemp (); #define TARGET_CPU_DEFAULT 0 #endif +#ifndef TARGET_ENDIAN_DEFAULT +#ifndef DECSTATION +#define TARGET_ENDIAN_DEFAULT MASK_BIG_ENDIAN +#else +#define TARGET_ENDIAN_DEFAULT 0 +#endif +#endif + +#ifndef MULTILIB_DEFAULTS +#if TARGET_ENDIAN_DEFAULT == 0 +#define MULTILIB_DEFAULTS { "EL", "mips1" } +#else +#define MULTILIB_DEFAULTS { "EB", "mips1" } +#endif +#endif + /* This macro is similar to `TARGET_SWITCHES' but defines names of command options that have values. Its definition is an initializer with a subgrouping for each command option. @@ -404,9 +458,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 and -mips4 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 */ @@ -464,31 +529,16 @@ do \ for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) \ fixed_regs[regno] = call_used_regs[regno] = 1; \ } \ + SUBTARGET_CONDITIONAL_REGISTER_USAGE \ } \ while (0) +/* This is meant to be redefined in the host dependent files */ +#define SUBTARGET_CONDITIONAL_REGISTER_USAGE -/* 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 +555,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 +578,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=*} %{m4650} %{mmad:-m4650}} \ +%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{mips4} %{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=*} %{m4650} %{mmad:-m4650}} \ +%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{mips4} %{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 +634,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 +644,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 +654,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,24 +666,27 @@ 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} %{mips4} \ +%{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}}}}} \ -%{G*} \ +%{mips1:-mfp32 -mgp32}%{mips2:-mfp32 -mgp32}\ +%{mips3:%{!msingle-float:%{!m4650:-mfp64}} -mgp64} \ +%{mips4:%{!msingle-float:%{!m4650:-mfp64}} -mgp64} \ +%{mfp64:%{msingle-float:%emay not use both -mfp64 and -msingle-float}} \ +%{mfp64:%{m4650:%emay not use both -mfp64 and -m4650}} \ +%{m4650:-mcpu=r4650} \ +%{G*} %{EB:-meb} %{EL:-mel} %{EB:%{EL:%emay not use both -EB and -EL}} \ %{pic-none: -mno-half-pic} \ %{pic-lib: -mhalf-pic} \ %{pic-extern: -mhalf-pic} \ @@ -633,7 +703,15 @@ 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 -D__mips64} \ +%{mips4:-U__mips -D__mips=4 -D__mips64} \ +%{mgp32:-U__mips64} %{mgp64:-D__mips64} \ +%{EB:-UMIPSEL -U_MIPSEL -U__MIPSEL -U__MIPSEL__ -D_MIPSEB -D__MIPSEB -D__MIPSEB__ %{!ansi:-DMIPSEB}} \ +%{EL:-UMIPSEB -U_MIPSEB -U__MIPSEB -U__MIPSEB__ -D_MIPSEL -D__MIPSEL -D__MIPSEL__ %{!ansi:-DMIPSEL}}" #endif /* If defined, this macro is an additional prefix to try after @@ -686,6 +764,21 @@ while (0) #define ASM_STABN_OP ((TARGET_GAS) ? ".stabn" : " #.stabn") #define ASM_STABD_OP ((TARGET_GAS) ? ".stabd" : " #.stabd") +/* Local compiler-generated symbols must have a prefix that the assembler + understands. By default, this is $, although some targets (e.g., + NetBSD-ELF) need to override this. */ + +#ifndef LOCAL_LABEL_PREFIX +#define LOCAL_LABEL_PREFIX "$" +#endif + +/* By default on the mips, external symbols do not have an underscore + prepended, but some targets (e.g., NetBSD) require this. */ + +#ifndef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "" +#endif + /* Forward references to tags are allowed. */ #define SDB_ALLOW_FORWARD_REFERENCES @@ -803,9 +896,11 @@ do { \ do { \ extern FILE *asm_out_text_file; \ fprintf (asm_out_text_file, \ - "$Lb%d:\n\t%s.begin\t$Lb%d\t%d\n", \ + "%sLb%d:\n\t%s.begin\t%sLb%d\t%d\n", \ + LOCAL_LABEL_PREFIX, \ sdb_label_count, \ (TARGET_GAS) ? "" : "#", \ + LOCAL_LABEL_PREFIX, \ sdb_label_count, \ (LINE)); \ sdb_label_count++; \ @@ -815,9 +910,11 @@ do { \ do { \ extern FILE *asm_out_text_file; \ fprintf (asm_out_text_file, \ - "$Le%d:\n\t%s.bend\t$Le%d\t%d\n", \ + "%sLe%d:\n\t%s.bend\t%sLe%d\t%d\n", \ + LOCAL_LABEL_PREFIX, \ sdb_label_count, \ (TARGET_GAS) ? "" : "#", \ + LOCAL_LABEL_PREFIX, \ sdb_label_count, \ (LINE)); \ sdb_label_count++; \ @@ -825,7 +922,11 @@ do { \ #define PUT_SDB_FUNCTION_START(LINE) -#define PUT_SDB_FUNCTION_END(LINE) +#define PUT_SDB_FUNCTION_END(LINE) \ +do { \ + extern FILE *asm_out_text_file; \ + ASM_OUTPUT_SOURCE_LINE (asm_out_text_file, LINE + sdb_begin_function_line); \ +} while (0) #define PUT_SDB_EPILOGUE_END(NAME) @@ -864,39 +965,27 @@ do { \ /* Target machine storage layout */ +/* Define in order to support both big and little endian float formats + in the same gcc binary. */ +#define REAL_ARITHMETIC + /* Define this if most significant bit is lowest numbered in instructions that operate on numbered bit-fields. */ #define BITS_BIG_ENDIAN 0 /* Define this if most significant byte of a word is the lowest numbered. */ -#ifndef BYTES_BIG_ENDIAN -#ifndef DECSTATION -#define BYTES_BIG_ENDIAN 1 -#else -#define BYTES_BIG_ENDIAN 0 -#endif -#endif +#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0) /* Define this if most significant word of a multiword number is the lowest. */ -#ifndef WORDS_BIG_ENDIAN -#ifndef DECSTATION -#define WORDS_BIG_ENDIAN 1 -#else -#define WORDS_BIG_ENDIAN 0 -#endif -#endif - -/* Define macros to easily access the most and least significant words - without a lot of #ifdef's. */ - -#if WORDS_BIG_ENDIAN -#define MOST_SIGNIFICANT_WORD 0 -#define LEAST_SIGNIFICANT_WORD 1 +#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0) +/* Define this to set the endianness to use in libgcc2.c, which can + not depend on target_flags. */ +#if !defined(MIPSEL) && !defined(__MIPSEL__) +#define LIBGCC2_WORDS_BIG_ENDIAN 1 #else -#define MOST_SIGNIFICANT_WORD 1 -#define LEAST_SIGNIFICANT_WORD 0 +#define LIBGCC2_WORDS_BIG_ENDIAN 0 #endif /* Number of bits in an addressable storage unit */ @@ -906,15 +995,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 MIN_UNITS_PER_WORD 4 + +/* 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 +1027,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 +1058,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 +1152,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. */ @@ -1064,10 +1170,13 @@ do { \ All registers that the compiler knows about must be given numbers, even those that are not normally considered general registers. - On the Mips, we have 32 integer registers, 32 floating point registers - and the special registers hi, lo, and fp status. */ + On the Mips, we have 32 integer registers, 32 floating point + registers and the special registers hi, lo, hilo, and fp status. + The hilo register is only used in 64 bit mode. It represents a 64 + bit value stored as two 32 bit values in the hi and lo registers; + this is the result of the mult instruction. */ -#define FIRST_PSEUDO_REGISTER 67 +#define FIRST_PSEUDO_REGISTER 68 /* 1 for registers that have pervasive standard uses and are not available for the register allocator. @@ -1080,7 +1189,7 @@ do { \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 1, 1, 1 \ + 0, 0, 0, 1 \ } @@ -1097,16 +1206,13 @@ do { \ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, \ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 1, 1, 1 \ + 1, 1, 1, 1 \ } /* Internal macros to classify a register number as to whether it's a general purpose register, a floating point register, a - multiply/divide register, or a status register. - - The macro FP_CALL_REG_P also allows registers $4 and $6 as floating - point registers to pass floating point as per MIPS spec. */ + multiply/divide register, or a status register. */ #define GP_REG_FIRST 0 #define GP_REG_LAST 31 @@ -1119,16 +1225,17 @@ do { \ #define FP_DBX_FIRST ((write_symbols == DBX_DEBUG) ? 38 : 32) #define MD_REG_FIRST 64 -#define MD_REG_LAST 65 +#define MD_REG_LAST 66 #define MD_REG_NUM (MD_REG_LAST - MD_REG_FIRST + 1) -#define ST_REG_FIRST 66 -#define ST_REG_LAST 66 +#define ST_REG_FIRST 67 +#define ST_REG_LAST 67 #define ST_REG_NUM (ST_REG_LAST - ST_REG_FIRST + 1) #define AT_REGNUM (GP_REG_FIRST + 1) #define HI_REGNUM (MD_REG_FIRST + 0) #define LO_REGNUM (MD_REG_FIRST + 1) +#define HILO_REGNUM (MD_REG_FIRST + 2) #define FPSW_REGNUM ST_REG_FIRST #define GP_REG_P(REGNO) ((unsigned) ((REGNO) - GP_REG_FIRST) < GP_REG_NUM) @@ -1136,11 +1243,6 @@ do { \ #define MD_REG_P(REGNO) ((unsigned) ((REGNO) - MD_REG_FIRST) < MD_REG_NUM) #define ST_REG_P(REGNO) ((REGNO) == ST_REG_FIRST) -#define FP_CALL_REG_P(REGNO) \ - (FP_REG_P (REGNO) \ - || (REGNO) == (4 + GP_REG_FIRST) \ - || (REGNO) == (6 + GP_REG_FIRST)) - /* Return number of consecutive hard regs needed starting at reg REGNO to hold something of mode MODE. This is ordinarily the length in words of a value of mode MODE @@ -1153,14 +1255,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) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG)) /* 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,16 +1315,17 @@ 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 scratch register set, and not used for passing and returning arguments and any other information used in the calling sequence - (such as pic). */ + (such as pic). Must start at 12, since t0/t3 are parameter passing + registers in the 64 bit ABI. */ -#define MIPS_TEMP1_REGNUM (GP_REG_FIRST + 8) -#define MIPS_TEMP2_REGNUM (GP_REG_FIRST + 9) +#define MIPS_TEMP1_REGNUM (GP_REG_FIRST + 12) +#define MIPS_TEMP2_REGNUM (GP_REG_FIRST + 13) /* Define this macro if it is as good or better to call a constant function address than to call an address kept in a register. */ @@ -1243,6 +1345,12 @@ 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) + +/* Initialize embedded_pic_fnaddr_rtx before RTL generation for + each function. We used to do this in FINALIZE_PIC, but FINALIZE_PIC + isn't always called for static inline functions. */ +#define INIT_EXPANDERS embedded_pic_fnaddr_rtx = NULL; /* Define the classes of registers for register constraints in the machine description. Also define ranges of constants. @@ -1271,6 +1379,7 @@ enum reg_class FP_REGS, /* floating point registers */ HI_REG, /* hi register */ LO_REG, /* lo register */ + HILO_REG, /* hilo register pair for 64 bit mode mult */ MD_REGS, /* multiply/divide registers (hi/lo) */ ST_REGS, /* status registers (fp status) */ ALL_REGS, /* all registers */ @@ -1292,6 +1401,7 @@ enum reg_class "FP_REGS", \ "HI_REG", \ "LO_REG", \ + "HILO_REG", \ "MD_REGS", \ "ST_REGS", \ "ALL_REGS" \ @@ -1315,9 +1425,10 @@ enum reg_class { 0x00000000, 0xffffffff, 0x00000000 }, /* floating registers*/ \ { 0x00000000, 0x00000000, 0x00000001 }, /* hi register */ \ { 0x00000000, 0x00000000, 0x00000002 }, /* lo register */ \ + { 0x00000000, 0x00000000, 0x00000004 }, /* hilo register */ \ { 0x00000000, 0x00000000, 0x00000003 }, /* mul/div registers */ \ - { 0x00000000, 0x00000000, 0x00000004 }, /* status registers */ \ - { 0xffffffff, 0xffffffff, 0x00000007 } /* all registers */ \ + { 0x00000000, 0x00000000, 0x00000008 }, /* status registers */ \ + { 0xffffffff, 0xffffffff, 0x0000000f } /* all registers */ \ } @@ -1342,7 +1453,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 */ @@ -1357,7 +1468,9 @@ extern enum reg_class mips_regno_to_clas 'h' Hi register 'l' Lo register 'x' Multiply/divide registers - 'z' FP Status register */ + 'a' HILO_REG + 'z' FP Status register + 'b' All registers */ extern enum reg_class mips_char_to_class[]; @@ -1391,17 +1504,21 @@ extern enum reg_class mips_char_to_class `P' is used for positive 16 bit constants. */ -#define SMALL_INT(X) ((unsigned) (INTVAL (X) + 0x8000) < 0x10000) -#define SMALL_INT_UNSIGNED(X) ((unsigned) (INTVAL (X)) < 0x10000) +#define SMALL_INT(X) ((unsigned HOST_WIDE_INT) (INTVAL (X) + 0x8000) < 0x10000) +#define SMALL_INT_UNSIGNED(X) ((unsigned HOST_WIDE_INT) (INTVAL (X)) < 0x10000) #define CONST_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'I' ? ((unsigned) ((VALUE) + 0x8000) < 0x10000) \ + ((C) == 'I' ? ((unsigned HOST_WIDE_INT) ((VALUE) + 0x8000) < 0x10000) \ : (C) == 'J' ? ((VALUE) == 0) \ - : (C) == 'K' ? ((unsigned) (VALUE) < 0x10000) \ - : (C) == 'L' ? (((VALUE) & 0xffff0000) == (VALUE)) \ + : (C) == 'K' ? ((unsigned HOST_WIDE_INT) (VALUE) < 0x10000) \ + : (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 +1533,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 +1559,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 +1579,38 @@ 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)))) + +/* The HI and LO registers can only be reloaded via the general + registers. */ + +#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \ + mips_secondary_reload_class (CLASS, MODE, X, 1) +#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \ + mips_secondary_reload_class (CLASS, MODE, X, 0) + +/* Not declared above, with the other functions, because enum + reg_class is not declared yet. */ +extern enum reg_class mips_secondary_reload_class (); /* 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 @@ -1494,6 +1628,10 @@ extern enum reg_class mips_char_to_class /* Stack layout; function entry, exit and calling. */ +/* Don't enable support for the 64 bit ABI calling convention. + Some embedded code depends on the old 64 bit calling convention. */ +#define ABI_64BIT 0 + /* Define this if pushing a word on the stack makes the stack pointer a smaller address. */ #define STACK_GROWS_DOWNWARD @@ -1508,7 +1646,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'. @@ -1617,15 +1757,17 @@ extern struct mips_frame_info current_fr { compute_frame_size (get_frame_size ()); \ if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ (OFFSET) = 0; \ - else if ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM) \ - (OFFSET) = current_frame_info.total_size; \ - else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ - (OFFSET) = current_frame_info.total_size; \ + else if ((FROM) == ARG_POINTER_REGNUM \ + && ((TO) == FRAME_POINTER_REGNUM \ + || (TO) == STACK_POINTER_REGNUM)) \ + (OFFSET) = (current_frame_info.total_size \ + - (ABI_64BIT && mips_isa >= 3 \ + ? current_function_pretend_args_size \ + : 0)); \ else \ abort (); \ } - /* If we generate an insn to push BYTES bytes, this says how many the stack pointer really advances by. On the vax, sp@- in a byte insn really pushes a word. */ @@ -1650,7 +1792,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. */ @@ -1675,7 +1817,8 @@ extern struct mips_frame_info current_fr in register. In case an argument list is of form GF used registers are a0 (a2,a3), but we should push over a1... */ -#define REG_PARM_STACK_SPACE(FNDECL) ((4*UNITS_PER_WORD) - FIRST_PARM_OFFSET (FNDECL)) +#define REG_PARM_STACK_SPACE(FNDECL) \ + ((MAX_ARGS_IN_REGISTERS*UNITS_PER_WORD) - FIRST_PARM_OFFSET (FNDECL)) /* Define this if it is the responsibility of the caller to allocate the area reserved for arguments passed in registers. @@ -1687,13 +1830,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 @@ -1703,6 +1846,8 @@ extern struct mips_frame_info current_fr if the function pops no arguments and the caller must therefore pop them all after the function returns. + FUNDECL is the declaration node of the function (as a tree). + FUNTYPE is a C variable whose value is a tree node that describes the function in question. Normally it is a node of type `FUNCTION_TYPE' that describes the data type of the function. @@ -1722,7 +1867,7 @@ extern struct mips_frame_info current_fr argument popping will always be the responsibility of the calling function. */ -#define RETURN_POPS_ARGS(FUNTYPE, SIZE) 0 +#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 /* Symbolic macros for the registers used to return integer and floating @@ -1745,9 +1890,11 @@ extern struct mips_frame_info current_fr #define LIBCALL_VALUE(MODE) \ gen_rtx (REG, MODE, \ - (GET_MODE_CLASS (MODE) == MODE_FLOAT) \ - ? FP_RETURN \ - : GP_RETURN) + ((GET_MODE_CLASS (MODE) == MODE_FLOAT \ + && (! TARGET_SINGLE_FLOAT \ + || GET_MODE_SIZE (MODE) <= 4)) \ + ? FP_RETURN \ + : GP_RETURN)) /* Define how to find the value returned by a function. VALTYPE is the data type of the value (as a tree). @@ -1810,7 +1957,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 +2071,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 +2105,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) +#define TRAMPOLINE_SIZE (32 + (TARGET_LONG64 ? 16 : 8)) -/* Alignment required for trampolines, in bits. +/* Alignment required for trampolines, in bits. */ - If you don't define this macro, the value of `BIGGEST_ALIGNMENT' - is used for aligning trampolines. */ - -/* #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 +2145,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); \ + /* 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 /* 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"); \ - */ \ -} -#endif /* TRANSFER_FROM_TRAMPOLINE */ - /* Addressing modes, and classification of registers for them. */ @@ -2037,7 +2187,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 +2204,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 +2315,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 +2332,18 @@ __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. */ \ + /* ??? Reject combining an address with a register for the MIPS \ + 64 bit ABI, because the SGI assembler can not handle this. */ \ + if (!TARGET_DEBUG_A_MODE \ + && ! ABI_64BIT \ + && CONSTANT_ADDRESS_P (xplus1) \ + && (!TARGET_EMBEDDED_PIC \ + || code1 != CONST \ + || GET_CODE (XEXP (xplus1, 0)) != MINUS)) \ goto ADDR; \ } \ } \ @@ -2201,11 +2356,25 @@ __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. */ +/* ??? SGI Irix 6 assembler fails for CONST address, so reject them. */ #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)) \ + && ! ABI_64BIT)) \ + && (!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. @@ -2214,9 +2383,11 @@ __enable_execute_stack (addr) \ to be generated at present. Also, the MIPS assembler does not grok li.d Infinity. */ +/* ??? SGI Irix 6 assembler fails for CONST address, so reject them. */ #define LEGITIMATE_CONSTANT_P(X) \ - (GET_CODE (X) != CONST_DOUBLE || mips_const_double_ok (X, GET_MODE (X))) - + ((GET_CODE (X) != CONST_DOUBLE \ + || mips_const_double_ok (X, GET_MODE (X))) \ + && ! (GET_CODE (X) == CONST && ABI_64BIT)) /* A C compound statement that attempts to replace X with a valid memory address for an operand of mode MODE. WIN will be a C @@ -2251,7 +2422,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) \ { \ @@ -2263,6 +2438,24 @@ __enable_execute_stack (addr) \ GO_DEBUG_RTX (xinsn); \ } \ \ + if (GET_CODE (xinsn) == CONST \ + && ((flag_pic && pic_address_needs_scratch (xinsn)) \ + /* ??? SGI's Irix 6 assembler can't handle CONST. */ \ + || ABI_64BIT)) \ + { \ + rtx ptr_reg = gen_reg_rtx (Pmode); \ + rtx constant = XEXP (XEXP (xinsn, 0), 1); \ + \ + emit_move_insn (ptr_reg, XEXP (XEXP (xinsn, 0), 0)); \ + \ + X = gen_rtx (PLUS, Pmode, ptr_reg, constant); \ + if (SMALL_INT (constant)) \ + goto WIN; \ + /* Otherwise we fall through so the code below will fix the \ + constant. */ \ + xinsn = X; \ + } \ + \ if (GET_CODE (xinsn) == PLUS) \ { \ register rtx xplus0 = XEXP (xinsn, 0); \ @@ -2345,8 +2538,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 +2567,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 +2587,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 +2608,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 +2637,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 +2671,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 +2679,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); \ @@ -2488,9 +2698,13 @@ while (0) return COSTS_N_INSNS (SYMBOL_REF_FLAG (X) ? 1 : 2); \ \ case CONST_DOUBLE: \ - return COSTS_N_INSNS ((CONST_DOUBLE_HIGH (X) == 0 \ - && CONST_DOUBLE_LOW (X)) ? 2 : 4); - + { \ + rtx high, low; \ + split_double (X, &high, &low); \ + return COSTS_N_INSNS ((high == CONST0_RTX (GET_MODE (high)) \ + || low == CONST0_RTX (GET_MODE (low))) \ + ? 2 : 4); \ + } /* Like `CONST_COSTS' but applies to nonconstant RTL expressions. This can be used, for example, to indicate how costly a multiply @@ -2505,6 +2719,7 @@ while (0) strength reduction, and also makes it easier to identify what the compiler is doing. */ +/* ??? Fix this to be right for the R8000. */ #define RTX_COSTS(X,CODE,OUTER_CODE) \ case MEM: \ { \ @@ -2519,34 +2734,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 +2766,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 +2820,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,30 +2911,39 @@ 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 \ + : (((FROM) == HI_REG || (FROM) == LO_REG \ + || (FROM) == MD_REGS || (FROM) == HILO_REG) \ + && (TO) == GR_REGS) ? 6 \ + : (((TO) == HI_REG || (TO) == LO_REG \ + || (TO) == MD_REGS || (FROM) == HILO_REG) \ + && (FROM) == GR_REGS) ? 6 \ + : 12) + +/* ??? Fix this to be right for the R8000. */ +#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. */ +/* ??? Fix this to be right for the R8000. */ #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 +2973,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 +3005,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 @@ -2897,6 +3133,7 @@ while (0) &mips_reg_names[64][0], \ &mips_reg_names[65][0], \ &mips_reg_names[66][0], \ + &mips_reg_names[67][0], \ } /* print-rtl.c can't use REGISTER_NAMES, since it depends on mips.c. @@ -2911,7 +3148,7 @@ while (0) "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", \ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", \ "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", \ - "hi", "lo", "$fcr31" \ + "hi", "lo", "accum","$fcr31" \ } /* If defined, a C initializer for an array of structures @@ -3093,6 +3330,16 @@ while (0) #define ASM_OUTPUT_SOURCE_FILENAME(STREAM, NAME) \ mips_output_filename (STREAM, NAME) +/* This is defined so that it can be overridden in iris6.h. */ +#define ASM_OUTPUT_FILENAME(STREAM, NUM_SOURCE_FILENAMES, NAME) \ +do \ + { \ + fprintf (STREAM, "\t.file\t%d ", NUM_SOURCE_FILENAMES); \ + output_quoted_string (STREAM, NAME); \ + fputs ("\n", STREAM); \ + } \ +while (0) + /* This is how to output a note the debugger telling it the line number to which the following sequence of instructions corresponds. Silicon graphics puts a label after each .loc. */ @@ -3104,7 +3351,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 +3410,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 @@ -3195,22 +3442,32 @@ while (0) { \ extern FILE *asm_out_text_file; \ if (TARGET_GP_OPT) \ - STREAM = asm_out_text_file; \ + { \ + STREAM = asm_out_text_file; \ + /* ??? text_section gets called too soon. If the previous \ + function is in a special section and we're not, we have \ + to switch back to the text section. We can't call \ + text_section again as gcc thinks we're already there. */ \ + /* ??? See varasm.c. There are other things that get output \ + too early, like alignment (before we've switched STREAM). */ \ + if (DECL_SECTION_NAME (DECL) == NULL_TREE) \ + fprintf (STREAM, "%s\n", TEXT_SECTION_ASM_OP); \ + } \ \ - current_function_name = NAME; \ HALF_PIC_DECLARE (NAME); \ } /* This is how to output a reference to a user-level label named NAME. `assemble_name' uses this. */ -#define ASM_OUTPUT_LABELREF(STREAM,NAME) fprintf (STREAM, "%s", NAME) +#define ASM_OUTPUT_LABELREF(STREAM,NAME) \ + fprintf (STREAM, "%s%s", USER_LABEL_PREFIX, NAME) /* This is how to output an internal numbered label where PREFIX is the class of label and NUM is the number within the class. */ #define ASM_OUTPUT_INTERNAL_LABEL(STREAM,PREFIX,NUM) \ - fprintf (STREAM, "$%s%d:\n", PREFIX, NUM) + fprintf (STREAM, "%s%s%d:\n", LOCAL_LABEL_PREFIX, PREFIX, NUM) /* This is how to store into the string LABEL the symbol_ref name of an internal numbered label where @@ -3218,7 +3475,7 @@ while (0) This is suitable for output with `assemble_name'. */ #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ - sprintf (LABEL, "*$%s%d", PREFIX, NUM) + sprintf (LABEL, "*%s%s%d", LOCAL_LABEL_PREFIX, PREFIX, NUM) /* This is how to output an assembler line defining a `double' constant. */ @@ -3241,7 +3498,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 +3539,44 @@ 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%sL%d\n", \ + TARGET_LONG64 ? ".dword" : ".word", \ + LOCAL_LABEL_PREFIX, \ + 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%sL%d-%sLS%d\n", \ + TARGET_LONG64 ? ".dword" : ".word", \ + LOCAL_LABEL_PREFIX, VALUE, LOCAL_LABEL_PREFIX, REL); \ + else if (! ABI_64BIT) \ + fprintf (STREAM, "\t%s\t%sL%d\n", \ + TARGET_LONG64 ? ".gpdword" : ".gpword", \ + LOCAL_LABEL_PREFIX, VALUE); \ + else \ + /* ??? Why does this one use . and not LOCAL_LABEL_PREFIX? */ \ + fprintf (STREAM, "\t%s\t.L%d\n", \ + TARGET_LONG64 ? ".dword" : ".word", \ + 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 +3594,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 { \ @@ -3397,10 +3688,11 @@ do { \ #define SDATA_SECTION_ASM_OP "\t.sdata" /* small data */ #define RDATA_SECTION_ASM_OP "\t.rdata" /* read-only data */ #define READONLY_DATA_SECTION rdata_section +#define SMALL_DATA_SECTION sdata_section /* 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 +3728,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 +3744,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 +3762,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 +3803,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 -