--- gcc/config/mips/mips.h 2018/04/24 18:21:55 1.1.1.3 +++ gcc/config/mips/mips.h 2018/04/24 18:29:30 1.1.1.4 @@ -3,7 +3,7 @@ Changed by Michael Meissner, meissner@osf.org 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. + Copyright (C) 1989, 90, 91, 92, 93, 94, 1995 Free Software Foundation, Inc. This file is part of GNU CC. @@ -19,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; @@ -71,7 +66,9 @@ enum processor_type { PROCESSOR_R3000, PROCESSOR_R6000, PROCESSOR_R4000, - PROCESSOR_R4600 + PROCESSOR_R4600, + PROCESSOR_R4650, + PROCESSOR_R8000 }; /* Recast the cpu class to be the cpu attribute. */ @@ -98,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. */ @@ -121,7 +118,7 @@ extern enum processor_type mips_cpu; /* 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 */ @@ -185,7 +182,6 @@ extern int small_int (); extern void trace(); extern int uns_arith_operand (); 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 (); @@ -259,9 +255,9 @@ extern char *mktemp (); #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_UNUSED3 0x00020000 -#define MASK_UNUSED2 0x00040000 +#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*/ @@ -338,6 +334,14 @@ extern char *mktemp (); 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 } @@ -378,6 +382,13 @@ extern char *mktemp (); {"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}, \ @@ -389,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 */ @@ -402,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. @@ -431,8 +460,8 @@ extern char *mktemp (); #define BRANCH_LIKELY_P() (mips_isa >= 2) #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 +/* 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. @@ -500,9 +529,13 @@ 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 + /* Show we can debug even without a frame pointer. */ #define CAN_DEBUG_WITHOUT_FP @@ -560,8 +593,8 @@ while (0) %{pipe: %e-pipe is not supported.} \ %{K}} \ %{!mmips-as: \ - %{mcpu=*}} \ -%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{v} \ + %{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} \ @@ -579,8 +612,8 @@ while (0) %{pipe: %e-pipe is not supported.} \ %{K}} \ %{mgas: \ - %{mcpu=*}} \ -%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{v} \ + %{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} \ @@ -638,7 +671,7 @@ while (0) #ifndef LINK_SPEC #define LINK_SPEC "\ -%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} \ +%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{mips4} \ %{bestGnum} %{shared} %{non_shared}" #endif /* LINK_SPEC defined */ @@ -647,8 +680,13 @@ while (0) #ifndef CC1_SPEC #define CC1_SPEC "\ %{gline:%{!g:%{!g0:%{!g1:%{!g2: -g1}}}}} \ -%{mips1:-mfp32 -mgp32}%{mips2:-mfp32 -mgp32}%{mips3:-mfp64 -mgp64} \ -%{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} \ @@ -669,7 +707,11 @@ while (0) %{!.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}" +%{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 @@ -722,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 @@ -839,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++; \ @@ -851,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++; \ @@ -861,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) @@ -900,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 */ @@ -947,7 +1000,7 @@ do { \ /* Width of a word, in units (bytes). */ #define UNITS_PER_WORD (TARGET_64BIT ? 8 : 4) -#define MAX_UNITS_PER_WORD 8 +#define MIN_UNITS_PER_WORD 4 /* For MIPS, width of a floating point register. */ #define UNITS_PER_FPREG (TARGET_FLOAT64 ? 8 : 4) @@ -1117,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. @@ -1133,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 \ } @@ -1150,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 @@ -1172,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) @@ -1189,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 @@ -1206,7 +1255,7 @@ 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) + 7) / 8) << (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. In 32 bit mode, require that DImode and DFmode be in even @@ -1272,10 +1321,11 @@ extern char mips_hard_regno_mode_ok[][FI 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. */ @@ -1297,7 +1347,10 @@ extern char mips_hard_regno_mode_ok[][FI #define PIC_FUNCTION_ADDR_REGNUM (GP_REG_FIRST + 25) -#define FINALIZE_PIC mips_finalize_pic () +/* 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. @@ -1326,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 */ @@ -1347,6 +1401,7 @@ enum reg_class "FP_REGS", \ "HI_REG", \ "LO_REG", \ + "HILO_REG", \ "MD_REGS", \ "ST_REGS", \ "ALL_REGS" \ @@ -1370,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 */ \ } @@ -1412,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[]; @@ -1446,13 +1504,13 @@ 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) == 'K' ? ((unsigned HOST_WIDE_INT) (VALUE) < 0x10000) \ : (C) == 'L' ? (((VALUE) & 0x0000ffff) == 0 \ && (((VALUE) & ~2147483647) == 0 \ || ((VALUE) & ~2147483647) == ~2147483647)) \ @@ -1529,6 +1587,18 @@ extern enum reg_class mips_char_to_class && ((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. */ @@ -1558,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 @@ -1683,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. */ @@ -1741,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. @@ -1769,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. @@ -1788,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 @@ -1811,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). @@ -2255,7 +2336,10 @@ typedef struct mips_args { /* 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 \ @@ -2278,11 +2362,13 @@ typedef struct mips_args { 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) == HIGH \ || (GET_CODE (X) == CONST \ - && ! (flag_pic && pic_address_needs_scratch (X)))) \ + && ! (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 @@ -2297,9 +2383,11 @@ typedef struct mips_args { 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 @@ -2350,6 +2438,24 @@ typedef struct mips_args { 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); \ @@ -2384,16 +2490,6 @@ typedef struct mips_args { } \ } \ \ - 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"); \ } @@ -2602,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 @@ -2619,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: \ { \ @@ -2815,14 +2916,22 @@ while (0) : (FROM) == FP_REGS && (TO) == FP_REGS ? 2 \ : (FROM) == GR_REGS && (TO) == FP_REGS ? 4 \ : (FROM) == FP_REGS && (TO) == GR_REGS ? 4 \ - : 6) + : (((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) @@ -3024,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. @@ -3038,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 @@ -3220,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. */ @@ -3322,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 @@ -3345,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. */ @@ -3409,8 +3539,9 @@ 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%s\t$L%d\n", \ + 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. @@ -3420,12 +3551,17 @@ do { \ #define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, VALUE, REL) \ do { \ if (TARGET_EMBEDDED_PIC) \ - fprintf (STREAM, "\t%s\t$L%d-$LS%d\n", \ + fprintf (STREAM, "\t%s\t%sL%d-%sLS%d\n", \ TARGET_LONG64 ? ".dword" : ".word", \ - VALUE, REL); \ - else \ - fprintf (STREAM, "\t%s\t$L%d\n", \ + 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) @@ -3552,6 +3688,7 @@ 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. */