📄 tahoe.h
字号:
/* Definitions of target machine for GNU compiler. Tahoe version. Copyright (C) 1989, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.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. *//* * Original port made at the University of Buffalo by Devon Bowen, * Dale Wiles and Kevin Zachmann. * * HCX/UX version by Piet van Oostrum (piet@cs.ruu.nl) * * Performance hacking by Michael Tiemann (tiemann@cygnus.com) *//* define this for the HCX/UX version *//* #define HCX_UX *//* * Run-time Target Specification */#ifdef HCX_UX/* no predefines, see Makefile and hcx-universe.c *//* have cc1 print that this is the hcx version */#define TARGET_VERSION printf (" (hcx)");#else/* we want "tahoe" and "unix" defined for all future compilations */#define CPP_PREDEFINES "-Dtahoe -Dunix -Asystem(unix) -Acpu(tahoe) -Amachine(tahoe)"/* have cc1 print that this is the tahoe version */#define TARGET_VERSION printf (" (tahoe)");#endif/* this is required in all tm files to hold flags */extern int target_flags;/* Zero if it is safe to output .dfloat and .float pseudos. */#define TARGET_HEX_FLOAT (target_flags & 1)#define TARGET_DEFAULT 1#define TARGET_SWITCHES \ { {"hex-float", 1}, \ {"no-hex-float", -1}, \ { "", TARGET_DEFAULT} }/* * Storage Layout *//* This symbol was previously not mentioned, so apparently the tahoe is little-endian for bits, or else doesn't care. */#define BITS_BIG_ENDIAN 0/* tahoe uses a big endian byte order */#define BYTES_BIG_ENDIAN 1/* tahoe uses a big endian word order */#define WORDS_BIG_ENDIAN 1/* standard byte size is usable on tahoe */#define BITS_PER_UNIT 8/* longs on the tahoe are 4 byte groups */#define BITS_PER_WORD 32/* from the last two params we get 4 bytes per word */#define UNITS_PER_WORD 4/* addresses are 32 bits (one word) */#define POINTER_SIZE 32/* all parameters line up on 32 boundaries */#define PARM_BOUNDARY 32/* stack should line up on 32 boundaries */#define STACK_BOUNDARY 32/* line functions up on 32 bits */#define FUNCTION_BOUNDARY 32/* the biggest alignment the tahoe needs in 32 bits */#define BIGGEST_ALIGNMENT 32/* we have to align after an 'int : 0' in a structure */#define EMPTY_FIELD_BOUNDARY 32#ifdef HCX_UX/* structures must be made of full words */#define STRUCTURE_SIZE_BOUNDARY 32#else/* structures must be made of full bytes */#define STRUCTURE_SIZE_BOUNDARY 8#endif/* tahoe is picky about data alignment */#define STRICT_ALIGNMENT 1/* keep things standard with pcc */#define PCC_BITFIELD_TYPE_MATTERS 1/* this section is borrowed from the vax version since the *//* formats are the same in both of the architectures */#define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) \ if (OVERFLOW) \ (D) = 1.7014117331926443e+38; \ else if ((MODE) == SFmode) \ { \ if ((D) > 1.7014117331926443e+38) \ (OVERFLOW) = 1, (D) = 1.7014117331926443e+38; \ else if ((D) < -1.7014117331926443e+38) \ (OVERFLOW) = 1, (D) = -1.7014117331926443e+38; \ else if (((D) > 0) && ((D) < 2.9387358770557188e-39)) \ (OVERFLOW) = 1, (D) = 0.0; \ else if (((D) < 0) && ((D) > -2.9387358770557188e-39)) \ (OVERFLOW) = 1, (D) = 0.0; \ }/* * Register Usage *//* define 15 general regs plus one for the floating point reg (FPP) */#define FIRST_PSEUDO_REGISTER 17/* let the compiler know what the fp, sp and pc are */#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0}/* lots of regs aren't guaranteed to return from a call. The FPP reg *//* must be included in these since it can't be saved by the reg mask */#define CALL_USED_REGISTERS {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}/* A single fp reg can handle any type of float. CPU regs hold just 32 bits. */#define HARD_REGNO_NREGS(REGNO, MODE) \ (REGNO != 16 ? ((GET_MODE_SIZE(MODE)+UNITS_PER_WORD-1) / UNITS_PER_WORD) \ : GET_MODE_NUNITS ((MODE)))/* any mode greater than 4 bytes (doubles) can only go in an even regs *//* and the FPP can only hold SFmode and DFmode */#define HARD_REGNO_MODE_OK(REGNO, MODE) \ (REGNO != 16 \ ? (GET_MODE_UNIT_SIZE (MODE) <= 4 ? 1 : (REGNO % 2 - 1)) \ : ((MODE) == SFmode || (MODE) == DFmode \ || (MODE) == SCmode || (MODE) == DCmode))/* if mode1 or mode2, but not both, are doubles then modes cannot be tied */#define MODES_TIEABLE_P(MODE1, MODE2) \ (((MODE1) == DFmode || (MODE1) == DCmode) \ == ((MODE2) == DFmode || (MODE2) == DCmode))/* return nonzero if register variable of mode MODE is not a priori a bad idea. Used only if defined. */#define MODE_OK_FOR_USERVAR(MODE) \ ((MODE) == SImode)/* the program counter is reg 15 */#define PC_REGNUM 15/* the stack pointer is reg 14 */#define STACK_POINTER_REGNUM 14/* the frame pointer is reg 13 */#define FRAME_POINTER_REGNUM 13/* tahoe does require an fp */#define FRAME_POINTER_REQUIRED 1/* since tahoe doesn't have a argument pointer, make it the fp */#define ARG_POINTER_REGNUM 13/* this isn't currently used since C doesn't support this feature */#define STATIC_CHAIN_REGNUM 0/* we'll use reg 1 for structure passing cause the destination *//* of the eventual movblk requires it to be there anyway. */#define STRUCT_VALUE_REGNUM 1/* * Register Classes *//* tahoe has two types of regs. GENERAL_REGS are all the regs up *//* to number 15. FPP_REG is the special floating point processor *//* register class (only one reg). */enum reg_class {NO_REGS,GENERAL_REGS,FPP_REG,ALL_REGS,LIM_REG_CLASSES};/* defines the number of reg classes. */#define N_REG_CLASSES (int) LIM_REG_CLASSES/* this defines what the classes are officially named for debugging */#define REG_CLASS_NAMES \ {"NO_REGS","GENERAL_REGS","FPP_REG","ALL_REGS"}/* set general regs to be the first 16 regs and the fpp reg to be 17th */#define REG_CLASS_CONTENTS {0,0xffff,0x10000,0x1ffff}/* register class for the fpp reg is FPP_REG, all others are GENERAL_REGS */#define REGNO_REG_CLASS(REGNO) (REGNO == 16 ? FPP_REG : GENERAL_REGS)/* only general registers can be used as a base reg */#define BASE_REG_CLASS GENERAL_REGS/* only general registers can be used to index */#define INDEX_REG_CLASS GENERAL_REGS/* 'a' as a constraint in the md file means the FFP_REG class */#define REG_CLASS_FROM_LETTER(C) (C == 'a' ? FPP_REG : NO_REGS)/* any general reg but the fpp can be a base reg */#define REGNO_OK_FOR_BASE_P(regno) \((regno) < FIRST_PSEUDO_REGISTER - 1 || reg_renumber[regno] >= 0)/* any general reg except the pc and fpp can be an index reg */#define REGNO_OK_FOR_INDEX_P(regno) \((regno) < FIRST_PSEUDO_REGISTER - 2 || reg_renumber[regno] >= 0)/* if your loading a floating point constant, it can't be done *//* through a register. Force it to be a memory constant. */#define PREFERRED_RELOAD_CLASS(X,CLASS) \ ((GET_CODE (X) == CONST_DOUBLE) ? NO_REGS : CLASS)/* for the fpp reg, all modes fit; for any others, you need two for doubles */#define CLASS_MAX_NREGS(CLASS, MODE) \ (CLASS != FPP_REG ? ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) : 1)/* we don't define any special constant sizes so all should fail */#define CONST_OK_FOR_LETTER_P(VALUE, C) 0/* we don't define any special double sizes so all should fail */#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0/* * Describing Stack Layout *//* tahoe stack grows from high to low memory */#define STACK_GROWS_DOWNWARD/* Define this if longjmp restores from saved registers rather than from what setjmp saved. */#define LONGJMP_RESTORE_FROM_STACK/* tahoe call frames grow from high to low memory on the stack */#define FRAME_GROWS_DOWNWARD/* the tahoe fp points to the *top* of the frame instead of the *//* bottom, so we have to make this offset a constant large enough *//* to jump over the biggest frame possible. */#define STARTING_FRAME_OFFSET -52/* tahoe always pushes 4 bytes unless it's a double in which case *//* it pushes a full 8 bytes. */#define PUSH_ROUNDING(BYTES) (BYTES <= 4 ? 4 : 8)/* the first parameter in a function is at the fp + 4 */#define FIRST_PARM_OFFSET(FNDECL) 4/* the tahoe return function takes care of everything on the stack */#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) (SIZE)/* function values for all types are returned in register 0 */#define FUNCTION_VALUE(VALTYPE, FUNC) \ gen_rtx (REG, TYPE_MODE (VALTYPE), 0)/* library routines also return things in reg 0 */#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 0)/* Tahoe doesn't return structures in a reentrant way */#define PCC_STATIC_STRUCT_RETURN/* we only return values from a function in reg 0 */#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0)/* we never pass args through a register */#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0/* int is fine to hold the argument summary in FUNCTION_ARG */#define CUMULATIVE_ARGS int/* we just set CUM to 0 before the FUNCTION_ARG call. No matter what *//* we make it, FUNCTION_ARG will return 0 anyway */#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \ ((CUM) = 0)/* all modes push their size rounded to the nearest word boundary *//* except block which is the size of the block rounded up */#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ ((CUM) += ((MODE) != BLKmode \ ? (GET_MODE_SIZE (MODE) + 3) & ~3 \ : (int_size_in_bytes (TYPE) + 3) & ~3))/* this is always false since we never pass params in regs */#define FUNCTION_ARG_REGNO_P(N) 0/* this code calculates the register entry mask and sets up *//* the stack pointer for the function. The stack is set down *//* far enough from the fp to jump over any push regs and local *//* vars. This is a problem since the tahoe has the fp pointing *//* to the top of the frame and the compiler must know the off- *//* set off the fp to the local vars. */#define FUNCTION_PROLOGUE(FILE, SIZE) \{ register int regno; \ register int mask = 0; \ extern char call_used_regs[]; \ for (regno = 0; regno < FIRST_PSEUDO_REGISTER-1; regno++) \ if (regs_ever_live[regno] && !call_used_regs[regno]) \ mask |= 1 << regno; \ fprintf (FILE, "\t.word 0x%x\n", mask); \ if (SIZE != 0) fprintf (FILE, "\tsubl3 $%d,fp,sp\n", (SIZE) - STARTING_FRAME_OFFSET); }/* Zero out global variable in case it was used in this function. */#define FUNCTION_EPILOGUE(FILE, SIZE) \{ extern rtx tahoe_reg_conversion_loc; \ tahoe_reg_conversion_loc = 0; \}#ifdef HCX_UX/* to call the profiler, the address of the counter var is placed *//* on the stack and then passed into mcount this way */#define FUNCTION_PROFILER(FILE, LABELNO) \ fprintf (FILE, "\tpushal LP%d\n\tcallf $8,mcount\n", (LABELNO));#else/* to call the profiler, push the variable value onto the stack *//* and call mcount like a regular function. */#define FUNCTION_PROFILER(FILE, LABELNO) \ fprintf (FILE, "\tpushl $LP%d\n\tcallf $8,mcount\n", (LABELNO));#endif/* all stack handling at the end of a function is handled by the *//* return command. */#define EXIT_IGNORE_STACK 1/* * Library Subroutine Names *//* udiv is a valid C library routine in libc.a, so we call that */#define UDIVSI3_LIBCALL "*udiv"/* urem is a valid C library routine in libc.a, so we call that *//* but not so on hcx/ux */#ifdef HCX_UX#undef UMODSI3_LIBCALL#else#define UMODSI3_LIBCALL "*urem"#endif/* * Addressing Modes *//* constant addresses can be treated exactly the same as normal constants */#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)/* we can have as many as two regs in any given address */#define MAX_REGS_PER_ADDRESS 2/* The following is all the code for GO_IF_LEGITIMATE_ADDRESS *//* most of this taken directly from the vax tm file since the *//* tahoe and vax addressing modes are nearly identical. *//* Is x an indirectable address? */#define INDIRECTABLE_ADDRESS_P(X) \ (CONSTANT_ADDRESS_P (X) \ || (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \ || (GET_CODE (X) == PLUS \ && GET_CODE (XEXP (X, 0)) == REG \ && REG_OK_FOR_BASE_P (XEXP (X, 0)) \ && CONSTANT_ADDRESS_P (XEXP (X, 1))))/* If x is a non-indexed-address, go to ADDR. */#define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \{ register rtx xfoob = (X); \ if (GET_CODE (xfoob) == REG) goto ADDR; \ if (INDIRECTABLE_ADDRESS_P (xfoob)) goto ADDR; \ xfoob = XEXP (X, 0); \ if (GET_CODE (X) == MEM && INDIRECTABLE_ADDRESS_P (xfoob)) \ goto ADDR; \ if ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC) \ && GET_CODE (xfoob) == REG && REGNO (xfoob) == 14) \ goto ADDR; }/* Is PROD an index term in mode MODE. */#define INDEX_TERM_P(PROD, MODE) \(GET_MODE_SIZE (MODE) == 1 \ ? (GET_CODE (PROD) == REG && REG_OK_FOR_BASE_P (PROD)) \ : (GET_CODE (PROD) == MULT \ && \ (xfoo0 = XEXP (PROD, 0), xfoo1 = XEXP (PROD, 1), \ ((GET_CODE (xfoo0) == CONST_INT \ && INTVAL (xfoo0) == GET_MODE_SIZE (MODE) \ && GET_CODE (xfoo1) == REG \ && REG_OK_FOR_INDEX_P (xfoo1)) \ || \ (GET_CODE (xfoo1) == CONST_INT \ && INTVAL (xfoo1) == GET_MODE_SIZE (MODE) \ && GET_CODE (xfoo0) == REG \ && REG_OK_FOR_INDEX_P (xfoo0))))))/* Is the addition to the index a reg? */#define GO_IF_REG_PLUS_INDEX(X, MODE, ADDR) \{ register rtx xfooa; \ if (GET_CODE (X) == PLUS) \ { if (GET_CODE (XEXP (X, 0)) == REG \ && REG_OK_FOR_BASE_P (XEXP (X, 0)) \ && (xfooa = XEXP (X, 1), \ INDEX_TERM_P (xfooa, MODE))) \ goto ADDR; \ if (GET_CODE (XEXP (X, 1)) == REG \ && REG_OK_FOR_BASE_P (XEXP (X, 1)) \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -