diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h new file mode 100644 index 00000000000..ee9cc60ea0d --- /dev/null +++ b/gcc/config/mips/mips.h @@ -0,0 +1,3340 @@ +/* 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. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +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. */ + + +/* 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 int target_flags; +extern int optimize; +extern int may_call_alloca; +extern int current_function_calls_alloca; +extern int frame_pointer_needed; +extern int flag_omit_frame_pointer; + +/* MIPS external variables defined in mips.c. */ + +/* comparison type */ +enum cmp_type { + CMP_SI, /* compare integers */ + CMP_SF, /* compare single precision floats */ + CMP_DF, /* compare double precision floats */ + CMP_MAX /* max comparison type */ +}; + +/* types of delay slot */ +enum delay_type { + DELAY_NONE, /* no delay slot */ + DELAY_LOAD, /* load from memory delay */ + DELAY_HILO /* move from/to hi/lo registers */ +}; + +/* Which processor to schedule for. Since there is no difference between + a R2000 and R3000 in terms of the scheduler, we collapse them into + just an R3000. */ + +enum processor_type { + PROCESSOR_DEFAULT, + PROCESSOR_R3000, + PROCESSOR_R6000, + PROCESSOR_R4000 +}; + +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 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. */ +extern int sym_lineno; /* sgi next label # for each stmt */ +extern int set_noreorder; /* # of nested .set noreorder's */ +extern int set_nomacro; /* # of nested .set nomacro's */ +extern int set_noat; /* # of nested .set noat's */ +extern int set_volatile; /* # of nested .set volatile's */ +extern int flag_half_pic; /* whether or not we use half-pic */ +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 int mips_isa; /* architectural level */ +extern char *mips_cpu_string; /* for -mcpu= */ +extern char *mips_isa_string; /* for -mips{1,2,3} */ +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 */ +extern int dslots_jump_filled; /* # filled jump delay slots */ +extern int dslots_number_nops; /* # of nops needed by previous insn */ +extern int num_refs[3]; /* # 1/2/3 word references */ +extern struct rtx_def *mips_load_reg; /* register to check for load delay */ +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 */ + +/* Functions within mips.c that we reference. */ + +extern void abort_with_insn (); +extern int arith32_operand (); +extern int arith_operand (); +extern int call_memory_operand (); +extern int cmp_op (); +extern int cmp2_op (); +extern unsigned long compute_frame_size (); +extern void expand_block_move (); +extern int equality_op (); +extern int fcmp_op (); +extern struct rtx_def * function_arg (); +extern void function_arg_advance (); +extern int function_arg_partial_nregs (); +extern void function_epilogue (); +extern void function_prologue (); +extern void gen_conditional_branch (); +extern void half_pic_encode_section_info (); +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 (); +extern int mips_const_double_ok (); +extern int mips_constant_address_p (); +extern void mips_count_memory_refs (); +extern int mips_debugger_offset (); +extern int mips_epilogue_delay_slots (); +extern char *mips_fill_delay_slot (); +extern char *mips_move_1word (); +extern char *mips_move_2words (); +extern int mips_output_external (); +extern void mips_output_filename (); +extern void mips_output_lineno (); +extern void override_options (); +extern void print_operand_address (); +extern void print_operand (); +extern void print_options (); +extern int reg_or_0_operand (); +extern int simple_memory_operand (); +extern int small_int (); +extern void trace(); +extern int uns_arith_operand (); +extern int uns_cmp_op (); + +/* Functions in varasm.c that we reference. */ +extern void data_section (); +extern void rdata_section (); +extern void readonly_data_section (); +extern void sdata_section (); +extern void text_section (); + + +/* Switch Recognition by gcc.c. Add -G xx support */ + +#ifdef SWITCH_TAKES_ARG +#undef SWITCH_TAKES_ARG +#endif + +#define SWITCH_TAKES_ARG(CHAR) \ + ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \ + || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \ + || (CHAR) == 'I' || (CHAR) == 'm' \ + || (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'G') + +/* Sometimes certain combinations of command options do not make sense + on a particular target machine. You can define a macro + `OVERRIDE_OPTIONS' to take account of this. This macro, if + defined, is executed once just after all the command options have + been parsed. + + On the MIPS, it is used to handle -G. We also use it to set up all + of the tables referenced in the other macros. */ + +#define OVERRIDE_OPTIONS override_options () + +/* Zero or more C statements that may conditionally modify two + variables `fixed_regs' and `call_used_regs' (both of type `char + []') after they have been initialized from the two preceding + macros. + + This is necessary in case the fixed or call-clobbered registers + depend on target flags. + + You need not define this macro if it has no work to do. + + If the usage of an entire class of registers depends on the target + flags, you may indicate this to GCC by using this macro to modify + `fixed_regs' and `call_used_regs' to 1 for each of the registers in + the classes which should not be used by GCC. Also define the macro + `REG_CLASS_FROM_LETTER' to return `NO_REGS' if it is called with a + letter for a class that shouldn't be used. + + (However, if this class is not included in `GENERAL_REGS' and all + of the insn patterns whose constraints permit this class are + controlled by target switches, then GCC will automatically avoid + using these registers when the target switches are opposed to + them.) */ + +#define CONDITIONAL_REGISTER_USAGE \ +do \ + { \ + if (!TARGET_HARD_FLOAT) \ + { \ + int regno; \ + \ + for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) \ + fixed_regs[regno] = call_used_regs[regno] = 1; \ + } \ + } \ +while (0) + + +/* Some machines may desire to change what optimizations are + performed for various optimization levels. This macro, if + defined, is executed once just after the optimization level is + determined and before the remainder of the command options have + been parsed. Values set in this macro are used as the default + values for the other command line options. + + LEVEL is the optimization level specified; 2 if -O2 is + specified, 1 if -O is specified, and 0 if neither is specified. */ + +#define OPTIMIZATION_OPTIONS(LEVEL) \ +{ \ + if (LEVEL) \ + { \ + flag_omit_frame_pointer = TRUE; \ + flag_delayed_branch = TRUE; \ + flag_thread_jumps = TRUE; \ + flag_schedule_insns_after_reload = TRUE; \ + flag_caller_saves = TRUE; \ + } \ + \ + if (LEVEL >= 2) \ + { \ + flag_strength_reduce = TRUE; \ + flag_cse_follow_jumps = TRUE; \ + flag_expensive_optimizations = TRUE; \ + flag_rerun_cse_after_loop = TRUE; \ + flag_schedule_insns = TRUE; \ + } \ + \ + if (LEVEL >= 3) \ + { \ + flag_inline_functions = TRUE; \ + } \ +} + + + +/* 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]. */ + +#if defined(OSF_OS) \ + || defined(DECSTATION) \ + || defined(SGI_TARGET) \ + || defined(MIPS_NEWS) \ + || defined(MIPS_SYSV) \ + || defined(MIPS_BSD43) + +#ifndef CPP_PREDEFINES + #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 + +#ifndef STARTFILE_SPEC + #error "Define STARTFILE_SPEC in the appropriate tm.h file" +#endif + +#ifndef MACHINE_TYPE + #error "Define MACHINE_TYPE in the appropriate tm.h file" +#endif +#endif + + +/* Names to predefine in the preprocessor for this target machine. */ + +#ifndef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dmips -Dunix -Dhost_mips -DMIPSEB -DR3000" +#endif + +/* Extra switches sometimes passed to the assembler. */ + +#ifndef ASM_SPEC +#define ASM_SPEC "%{!mgas: \ + %{!mrnames: -nocpp} \ + %{pipe: %e-pipe is not supported.} \ + %{EB} %{!EB:-EB} \ + %{EL: %e-EL not supported} \ + %{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3} \ + %{g} %{g0} %{g1} %{g2} %{g3} %{v} %{K}} \ + %{G*}" + +#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. + This is needed because the $#!%^ MIPS assembler provides no way + of specifing such information in the assembly file. */ + +#ifndef ASM_FINAL_SPEC +#define ASM_FINAL_SPEC "%{!mgas: %{!mno-mips-tfile: \ + \n mips-tfile %{v*: -v} \ + %{K: -I %b.o~} \ + %{!K: %{save-temps: -I %b.o~}} \ + %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %b.o} \ + %{.s:%i} %{!.s:%g.s}}}" +#endif + +/* Redefinition of libraries used. Mips doesn't support normal + UNIX style profiling via calling _mcount. It does offer + profiling that samples the PC, so do what we can... */ + +#ifndef LIB_SPEC +#define LIB_SPEC "%{pg:-lprof1} %{p:-lprof1} -lc" +#endif + +/* Suppress libg.a from being linked in when debugging, since MIPS doesn't + supply one. */ + +#ifndef LIBG_SPEC +#define LIBG_SPEC "" +#endif + +/* Extra switches sometimes passed to the loader. */ + + +#ifndef LINK_SPEC +#define LINK_SPEC "%{G*} \ + %{!mgas: \ + %{pipe: %e-pipe is not supported.} \ + %{EB} %{!EB:-EB} \ + %{EL: %e-EL not supported} \ + %{bestGnum}}" +#endif /* LINK_SPEC defined */ + +/* Specs for the compiler proper */ + +#ifndef CC1_SPEC +#define CC1_SPEC "%{O*: %{!mno-gpOPT:%{!mno-gpopt: -mgpopt}}} \ + %{gline:%{!g:%{!g0:%{!g1:%{!g2: -g1}}}}} \ + %{G*} \ + %{pic-none: -mno-half-pic} \ + %{pic-lib: -mhalf-pic} \ + %{pic-extern: -mhalf-pic} \ + %{pic-calls: -mhalf-pic} \ + %{save-temps: }" +#endif + +#ifndef CC1PLUS_SPEC +#define CC1PLUS_SPEC "%{!fgnu-binutils: -fno-gnu-binutils}" +#endif + +/* Preprocessor specs */ + +#ifndef CPP_SPEC +#define CPP_SPEC "%{!ansi:-DSYSTYPE_BSD} -D__SYSTYPE_BSD__ \ + %{.S: -D__LANGUAGE_ASSEMBLY__ \ + -D_LANGUAGE_ASSEMBLY \ + %{!ansi:-DLANGUAGE_ASSEMBLY}} \ + %{.cc: -D__LANGUAGE_C_PLUS_PLUS__ \ + -D_LANGUAGE_C_PLUS_PLUS \ + %{!ansi:-DLANGUAGE_C_PLUS_PLUS}} \ + %{.cxx:-D__LANGUAGE_C_PLUS_PLUS__ \ + -D_LANGUAGE_C_PLUS_PLUS \ + %{!ansi:-DLANGUAGE_C_PLUS_PLUS}} \ + %{.C: -D__LANGUAGE_C_PLUS_PLUS__ \ + -D_LANGUAGE_C_PLUS_PLUS \ + %{!ansi:-DLANGUAGE_C_PLUS_PLUS}} \ + %{.m: -D__LANGUAGE_OBJECTIVE_C__ \ + -D_LANGUAGE_OBJECTIVE_C \ + %{!ansi:-DLANGUAGE_OBJECTIVE_C}} \ + %{!.S: -D__LANGUAGE_C__ \ + -D_LANGUAGE_C \ + %{!ansi:-DLANGUAGE_C}}" +#endif + +/* If defined, this macro is an additional prefix to try after + `STANDARD_EXEC_PREFIX'. */ + +#ifndef MD_EXEC_PREFIX +#define MD_EXEC_PREFIX "/usr/lib/cmplrs/cc" +#endif + + +/* Print subsidiary information on the compiler version in use. */ + +#define MIPS_VERSION "[AL 1.1, MM 11]" + +#ifndef MACHINE_TYPE +#define MACHINE_TYPE "BSD Mips" +#endif + +#ifndef TARGET_VERSION_INTERNAL +#define TARGET_VERSION_INTERNAL(STREAM) \ + fprintf (STREAM, " %s %s", MIPS_VERSION, MACHINE_TYPE) +#endif + +#ifndef TARGET_VERSION +#define TARGET_VERSION TARGET_VERSION_INTERNAL (stderr) +#endif + + +#define SDB_DEBUGGING_INFO /* generate info for mips-tfile */ +#define DBX_DEBUGGING_INFO /* generate stabs (OSF/rose) */ +#define MIPS_DEBUGGING_INFO /* MIPS specific debugging info */ + +#ifndef PREFERRED_DEBUGGING_TYPE /* assume SDB_DEBUGGING_INFO */ +#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG +#endif + +/* If we are passing smuggling stabs through the MIPS ECOFF object + format, put a comment in front of the .stab operation so + that the MIPS assembler does not choke. The mips-tfile program + will correctly put the stab into the object file. */ + +#define ASM_STABS_OP ((TARGET_GAS) ? ".stabs" : " #.stabs") +#define ASM_STABN_OP ((TARGET_GAS) ? ".stabn" : " #.stabn") +#define ASM_STABD_OP ((TARGET_GAS) ? ".stabd" : " #.stabd") + +/* Forward references to tags are allowed. */ +#define SDB_ALLOW_FORWARD_REFERENCES + +/* Unknown tags are also allowed. */ +#define SDB_ALLOW_UNKNOWN_REFERENCES + +/* On Sun 4, this limit is 2048. We use 1500 to be safe, + since the length can run past this up to a continuation point. */ +#define DBX_CONTIN_LENGTH 1500 + + +/* How to renumber registers for dbx and gdb. */ +#define DBX_REGISTER_NUMBER(REGNO) mips_dbx_regno[ (REGNO) ] + + +/* Overrides for the COFF debug format. */ +#define PUT_SDB_SCL(a) \ +do { \ + extern FILE *asm_out_text_file; \ + fprintf (asm_out_text_file, "\t.scl\t%d;", (a)); \ +} while (0) + +#define PUT_SDB_INT_VAL(a) \ +do { \ + extern FILE *asm_out_text_file; \ + fprintf (asm_out_text_file, "\t.val\t%d;", (a)); \ +} while (0) + +#define PUT_SDB_VAL(a) \ +do { \ + extern FILE *asm_out_text_file; \ + fputs ("\t.val\t", asm_out_text_file); \ + output_addr_const (asm_out_text_file, (a)); \ + fputc (';', asm_out_text_file); \ +} while (0) + +#define PUT_SDB_DEF(a) \ +do { \ + extern FILE *asm_out_text_file; \ + fprintf (asm_out_text_file, "\t#.def\t"); \ + ASM_OUTPUT_LABELREF (asm_out_text_file, a); \ + fputc (';', asm_out_text_file); \ +} while (0) + +#define PUT_SDB_PLAIN_DEF(a) \ +do { \ + extern FILE *asm_out_text_file; \ + fprintf (asm_out_text_file, "\t#.def\t.%s;", (a)); \ +} while (0) + +#define PUT_SDB_ENDEF \ +do { \ + extern FILE *asm_out_text_file; \ + fprintf (asm_out_text_file, "\t.endef\n"); \ +} while (0) + +#define PUT_SDB_TYPE(a) \ +do { \ + extern FILE *asm_out_text_file; \ + fprintf (asm_out_text_file, "\t.type\t0x%x;", (a)); \ +} while (0) + +#define PUT_SDB_SIZE(a) \ +do { \ + extern FILE *asm_out_text_file; \ + fprintf (asm_out_text_file, "\t.size\t%d;", (a)); \ +} while (0) + +#define PUT_SDB_DIM(a) \ +do { \ + extern FILE *asm_out_text_file; \ + fprintf (asm_out_text_file, "\t.dim\t%d;", (a)); \ +} while (0) + +#ifndef PUT_SDB_START_DIM +#define PUT_SDB_START_DIM \ +do { \ + extern FILE *asm_out_text_file; \ + fprintf (asm_out_text_file, "\t.dim\t"); \ +} while (0) +#endif + +#ifndef PUT_SDB_NEXT_DIM +#define PUT_SDB_NEXT_DIM(a) \ +do { \ + extern FILE *asm_out_text_file; \ + fprintf (asm_out_text_file, "%d,", a); \ +} while (0) +#endif + +#ifndef PUT_SDB_LAST_DIM +#define PUT_SDB_LAST_DIM(a) \ +do { \ + extern FILE *asm_out_text_file; \ + fprintf (asm_out_text_file, "%d;", a); \ +} while (0) +#endif + +#define PUT_SDB_TAG(a) \ +do { \ + extern FILE *asm_out_text_file; \ + fprintf (asm_out_text_file, "\t.tag\t"); \ + ASM_OUTPUT_LABELREF (asm_out_text_file, a); \ + fputc (';', asm_out_text_file); \ +} while (0) + +/* For block start and end, we create labels, so that + later we can figure out where the correct offset is. + The normal .ent/.end serve well enough for functions, + so those are just commented out. */ + +#define PUT_SDB_BLOCK_START(LINE) \ +do { \ + extern FILE *asm_out_text_file; \ + fprintf (asm_out_text_file, \ + "$Lb%d:\n\t#.begin\t$Lb%d\t%d\n", \ + sdb_label_count, \ + sdb_label_count, \ + (LINE)); \ + sdb_label_count++; \ +} while (0) + +#define PUT_SDB_BLOCK_END(LINE) \ +do { \ + extern FILE *asm_out_text_file; \ + fprintf (asm_out_text_file, \ + "$Le%d:\n\t#.bend\t$Le%d\t%d\n", \ + sdb_label_count, \ + sdb_label_count, \ + (LINE)); \ + sdb_label_count++; \ +} while (0) + +#define PUT_SDB_FUNCTION_START(LINE) + +#define PUT_SDB_FUNCTION_END(LINE) + +#define PUT_SDB_EPILOGUE_END(NAME) + +#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \ + sprintf ((BUFFER), ".%dfake", (NUMBER)); + +/* Correct the offset of automatic variables and arguments + if the frame pointer has been eliminated. */ + +#define DEBUGGER_AUTO_OFFSET(X) mips_debugger_offset (X, 0) +#define DEBUGGER_ARG_OFFSET(OFFSET, X) mips_debugger_offset (X, OFFSET) + + +/* Run-time compilation parameters selecting different hardware subsets. */ + +/* Macros used in the machine description to test the flags. */ + + /* 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_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 */ +#define MASK_STATS 0x00000040 /* print statistics to stderr */ +#define MASK_MEMCPY 0x00000080 /* call memcpy instead of inline code*/ +#define MASK_SOFT_FLOAT 0x00000100 /* software floating point */ +#define MASK_FLOAT64 0x00000200 /* fp registers are 64 bits */ +#define MASK_ABICALLS 0x00000400 /* emit .abicalls/.cprestore/.cpload */ +#define MASK_HALF_PIC 0x00000800 /* Emit OSF-style pic refs to externs*/ +#define MASK_UNUSED1 0x00001000 +#define MASK_UNUSED2 0x00002000 +#define MASK_UNUSED3 0x00004000 +#define MASK_UNUSED4 0x00008000 +#define MASK_UNUSED5 0x00010000 +#define MASK_UNUSED6 0x00020000 +#define MASK_UNUSED7 0x00040000 +#define MASK_UNUSED8 0x00080000 + + /* Dummy switches used only in spec's*/ +#define MASK_MIPS_TFILE 0x00000000 /* flag for mips-tfile usage */ + + /* switches not used yet */ +#define MASK_WC8 0x00000000 /* wchar's are 8 bits, not 32 */ +#define MASK_WC16 0x00000000 /* wchar's are 16 bits, not 32 */ +#define MASK_WC32 0x00000000 /* dummy for consistancy */ + + /* Debug switches, not documented */ +#define MASK_DEBUG 0x40000000 /* Eliminate version # in .s file */ +#define MASK_DEBUG_A 0x20000000 /* don't allow