⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mips.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines for insn-output.c for MIPS   Copyright (C) 1989, 90, 91, 93, 94, 1995 Free Software Foundation, Inc.   Contributed by A. Lichnewsky, lich@inria.inria.fr.   Changes by Michael Meissner, meissner@osf.org.   64 bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and   Brendan Eich, brendan@microunity.com.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  *//* ??? The TARGET_FP_CALL_32 macros are intended to simulate a 32 bit   calling convention in 64 bit mode.  It doesn't work though, and should   be replaced with something better designed.  */#include "config.h"#include "rtl.h"#include "regs.h"#include "hard-reg-set.h"#include "real.h"#include "insn-config.h"#include "conditions.h"#include "insn-flags.h"#include "insn-attr.h"#include "insn-codes.h"#include "recog.h"#include "output.h"#undef MAX			/* sys/param.h may also define these */#undef MIN#include <stdio.h>#include <signal.h>#include <sys/types.h>#include <sys/file.h>#include <ctype.h>#include "tree.h"#include "expr.h"#include "flags.h"#ifndef R_OK#define R_OK 4#define W_OK 2#define X_OK 1#endif#if defined(USG) || defined(NO_STAB_H)#include "gstab.h"  /* If doing DBX on sysV, use our own stab.h.  */#else#include <stab.h>  /* On BSD, use the system's stab.h.  */#endif /* not USG */#ifdef __GNU_STAB__#define STAB_CODE_TYPE enum __stab_debug_code#else#define STAB_CODE_TYPE int#endifextern void   abort ();extern int    atoi ();extern char  *getenv ();extern char  *mktemp (); extern rtx    adj_offsettable_operand ();extern rtx    copy_to_reg ();extern void   error ();extern void   fatal ();extern tree   lookup_name ();extern void   pfatal_with_name ();extern void   warning ();extern FILE  *asm_out_file;/* Enumeration for all of the relational tests, so that we can build   arrays indexed by the test type, and not worry about the order   of EQ, NE, etc. */enum internal_test {    ITEST_EQ,    ITEST_NE,    ITEST_GT,    ITEST_GE,    ITEST_LT,    ITEST_LE,    ITEST_GTU,    ITEST_GEU,    ITEST_LTU,    ITEST_LEU,    ITEST_MAX  };/* Global variables for machine-dependent things.  *//* Threshold for data being put into the small data/bss area, instead   of the normal data area (references to the small data/bss area take   1 instruction, and use the global pointer, references to the normal   data area takes 2 instructions).  */int mips_section_threshold = -1;/* Count the number of .file directives, so that .loc is up to date.  */int num_source_filenames = 0;/* Count the number of sdb related labels are generated (to find block   start and end boundaries).  */int sdb_label_count = 0;/* Next label # for each statement for Silicon Graphics IRIS systems. */int sym_lineno = 0;/* Non-zero if inside of a function, because the stupid MIPS asm can't   handle .files inside of functions.  */int inside_function = 0;/* Files to separate the text and the data output, so that all of the data   can be emitted before the text, which will mean that the assembler will   generate smaller code, based on the global pointer.  */FILE *asm_out_data_file;FILE *asm_out_text_file;/* Linked list of all externals that are to be emitted when optimizing   for the global pointer if they haven't been declared by the end of   the program with an appropriate .comm or initialization.  */struct extern_list {  struct extern_list *next;	/* next external */  char *name;			/* name of the external */  int size;			/* size in bytes */} *extern_head = 0;/* Name of the file containing the current function.  */char *current_function_file = "";/* Warning given that Mips ECOFF can't support changing files   within a function.  */int file_in_function_warning = FALSE;/* Whether to suppress issuing .loc's because the user attempted   to change the filename within a function.  */int ignore_line_number = FALSE;/* Number of nested .set noreorder, noat, nomacro, and volatile requests.  */int set_noreorder;int set_noat;int set_nomacro;int set_volatile;/* The next branch instruction is a branch likely, not branch normal.  */int mips_branch_likely;/* Count of delay slots and how many are filled.  */int dslots_load_total;int dslots_load_filled;int dslots_jump_total;int dslots_jump_filled;/* # of nops needed by previous insn */int dslots_number_nops;/* Number of 1/2/3 word references to data items (ie, not jal's).  */int num_refs[3];/* registers to check for load delay */rtx mips_load_reg, mips_load_reg2, mips_load_reg3, mips_load_reg4;/* Cached operands, and operator to compare for use in set/branch on   condition codes.  */rtx branch_cmp[2];/* what type of branch to use */enum cmp_type branch_type;/* Number of previously seen half-pic pointers and references.  */static int prev_half_pic_ptrs = 0;static int prev_half_pic_refs = 0;/* which cpu are we scheduling for */enum processor_type mips_cpu;/* which instruction set architecture to use.  */int mips_isa;/* Strings to hold which cpu and instruction set architecture to use.  */char *mips_cpu_string;		/* for -mcpu=<xxx> */char *mips_isa_string;		/* for -mips{1,2,3,4} *//* Generating calls to position independent functions?  */enum mips_abicalls_type mips_abicalls;/* High and low marks for floating point values which we will accept   as legitimate constants for LEGITIMATE_CONSTANT_P.  These are   initialized in override_options.  */REAL_VALUE_TYPE dfhigh, dflow, sfhigh, sflow;/* Array giving truth value on whether or not a given hard register   can support a given mode.  */char mips_hard_regno_mode_ok[(int)MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER];/* Current frame information calculated by compute_frame_size.  */struct mips_frame_info current_frame_info;/* Zero structure to initialize current_frame_info.  */struct mips_frame_info zero_frame_info;/* Temporary filename used to buffer .text until end of program   for -mgpopt.  */static char *temp_filename;/* Pseudo-reg holding the address of the current function when   generating embedded PIC code.  Created by LEGITIMIZE_ADDRESS, used   by mips_finalize_pic if it was created.  */rtx embedded_pic_fnaddr_rtx;/* List of all MIPS punctuation characters used by print_operand.  */char mips_print_operand_punct[256];/* Map GCC register number to debugger register number.  */int mips_dbx_regno[FIRST_PSEUDO_REGISTER];/* Buffer to use to enclose a load/store operation with %{ %} to   turn on .set volatile.  */static char volatile_buffer[60];/* Hardware names for the registers.  If -mrnames is used, this   will be overwritten with mips_sw_reg_names.  */char mips_reg_names[][8] ={ "$0",   "$1",   "$2",   "$3",   "$4",   "$5",   "$6",   "$7", "$8",   "$9",   "$10",  "$11",  "$12",  "$13",  "$14",  "$15", "$16",  "$17",  "$18",  "$19",  "$20",  "$21",  "$22",  "$23", "$24",  "$25",  "$26",  "$27",  "$28",  "$sp",  "$fp",  "$31", "$f0",  "$f1",  "$f2",  "$f3",  "$f4",  "$f5",  "$f6",  "$f7", "$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",   "accum","$fcr31"};/* Mips software names for the registers, used to overwrite the   mips_reg_names array.  */char mips_sw_reg_names[][8] ={  "$zero","$at",  "$v0",  "$v1",  "$a0",  "$a1",  "$a2",  "$a3",  "$t0",  "$t1",  "$t2",  "$t3",  "$t4",  "$t5",  "$t6",  "$t7",  "$s0",  "$s1",  "$s2",  "$s3",  "$s4",  "$s5",  "$s6",  "$s7",  "$t8",  "$t9",  "$k0",  "$k1",  "$gp",  "$sp",  "$fp",  "$ra",  "$f0",  "$f1",  "$f2",  "$f3",  "$f4",  "$f5",  "$f6",  "$f7",  "$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",   "accum","$fcr31"};/* Map hard register number to register class */enum reg_class mips_regno_to_class[] ={  GR_REGS,	GR_REGS,	GR_REGS,	GR_REGS,  GR_REGS,	GR_REGS,	GR_REGS,	GR_REGS,  GR_REGS,	GR_REGS,	GR_REGS,	GR_REGS,  GR_REGS,	GR_REGS,	GR_REGS,	GR_REGS,  GR_REGS,	GR_REGS,	GR_REGS,	GR_REGS,  GR_REGS,	GR_REGS,	GR_REGS,	GR_REGS,  GR_REGS,	GR_REGS,	GR_REGS,	GR_REGS,  GR_REGS,	GR_REGS,	GR_REGS,	GR_REGS,  FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,  FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,  FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,  FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,  FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,  FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,  FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,  FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,  HI_REG,	LO_REG,		HILO_REG,	ST_REGS};/* Map register constraint character to register class.  */enum reg_class mips_char_to_class[256] ={  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,};/* Return truth value of whether OP can be used as an operands   where a register or 16 bit unsigned integer is needed.  */intuns_arith_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (op))    return TRUE;  return register_operand (op, mode);}/* Return truth value of whether OP can be used as an operands   where a 16 bit integer is needed  */intarith_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == CONST_INT && SMALL_INT (op))    return TRUE;  return register_operand (op, mode);}/* Return truth value of whether OP can be used as an operand in a two   address arithmetic insn (such as set 123456,%o4) of mode MODE.  */intarith32_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == CONST_INT)    return TRUE;  return register_operand (op, mode);}/* Return truth value of whether OP is a integer which fits in 16 bits  */intsmall_int (op, mode)     rtx op;     enum machine_mode mode;{  return (GET_CODE (op) == CONST_INT && SMALL_INT (op));}/* Return truth value of whether OP is a 32 bit integer which is too big to   be loaded with one instruction.  */intlarge_int (op, mode)     rtx op;     enum machine_mode mode;{  HOST_WIDE_INT value;  if (GET_CODE (op) != CONST_INT)    return FALSE;  value = INTVAL (op);  if ((value & ~0x0000ffff) == 0)			/* ior reg,$r0,value */    return FALSE;  if (((unsigned long)(value + 32768)) <= 32767)	/* subu reg,$r0,value */    return FALSE;  if ((value & 0x0000ffff) == 0)			/* lui reg,value>>16 */    return FALSE;  return TRUE;}/* Return truth value of whether OP is a register or the constant 0.  */intreg_or_0_operand (op, mode)     rtx op;     enum machine_mode mode;{  switch (GET_CODE (op))    {    default:      break;    case CONST_INT:      return (INTVAL (op) == 0);    case CONST_DOUBLE:      if (op != CONST0_RTX (mode))	return FALSE;      return TRUE;    case REG:    case SUBREG:      return register_operand (op, mode);    }  return FALSE;}/* Return truth value if a CONST_DOUBLE is ok to be a legitimate constant.  */intmips_const_double_ok (op, mode)     rtx op;     enum machine_mode mode;{  REAL_VALUE_TYPE d;  if (GET_CODE (op) != CONST_DOUBLE)    return FALSE;  if (mode == VOIDmode)    return TRUE;  if (mode != SFmode && mode != DFmode)    return FALSE;  if (op == CONST0_RTX (mode))    return TRUE;  /* ??? li.s does not work right with SGI's Irix 6 assembler.  */  if (ABI_64BIT)    return FALSE;  REAL_VALUE_FROM_CONST_DOUBLE (d, op);  if (REAL_VALUE_ISNAN (d))    return FALSE;  if (REAL_VALUE_NEGATIVE (d))    d = REAL_VALUE_NEGATE (d);  if (mode == DFmode)    {      if (REAL_VALUES_LESS (d, dfhigh)	  && REAL_VALUES_LESS (dflow, d))	return TRUE;    }  else    {      if (REAL_VALUES_LESS (d, sfhigh)	  && REAL_VALUES_LESS (sflow, d))	return TRUE;    }  return FALSE;}/* Return truth value if a memory operand fits in a single instruction   (ie, register + small offset).  */intsimple_memory_operand (op, mode)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -