📄 sh.h
字号:
extending the lifetime of these registers. */#define SMALL_REGISTER_CLASSES 1/* The order in which register should be allocated. *//* Sometimes FP0_REGS becomes the preferred class of a floating point pseudo, and GENERAL_FP_REGS the alternate class. Since FP0 is likely to be spilled or used otherwise, we better have the FP_REGS allocated first. */#define REG_ALLOC_ORDER \ { 25,26,27,28,29,30,31,24,32,33,34,35,36,37,38,39, \ 40,41,42,43,44,45,46,47,48, \ 1,2,3,7,6,5,4,0,8,9,10,11,12,13,14, \ 22,15,16,17,18,19,20,21,23 }/* The class value for index registers, and the one for base regs. */#define INDEX_REG_CLASS R0_REGS#define BASE_REG_CLASS GENERAL_REGS/* Get reg_class from a letter such as appears in the machine description. */extern enum reg_class reg_class_from_letter[];#define REG_CLASS_FROM_LETTER(C) \ ( (C) >= 'a' && (C) <= 'z' ? reg_class_from_letter[(C)-'a'] : NO_REGS )/* The letters I, J, K, L and M in a register constraint string can be used to stand for particular ranges of immediate operands. This macro defines what the ranges are. C is the letter, and VALUE is a constant value. Return 1 if VALUE is in the range specified by C. I: arithmetic operand -127..128, as used in add, sub, etc K: shift operand 1,2,8 or 16 L: logical operand 0..255, as used in and, or, etc. M: constant 1 N: constant 0 */#define CONST_OK_FOR_I(VALUE) (((int)(VALUE))>= -128 && ((int)(VALUE)) <= 127)#define CONST_OK_FOR_K(VALUE) ((VALUE)==1||(VALUE)==2||(VALUE)==8||(VALUE)==16)#define CONST_OK_FOR_L(VALUE) (((int)(VALUE))>= 0 && ((int)(VALUE)) <= 255)#define CONST_OK_FOR_M(VALUE) ((VALUE)==1)#define CONST_OK_FOR_N(VALUE) ((VALUE)==0)#define CONST_OK_FOR_LETTER_P(VALUE, C) \ ((C) == 'I' ? CONST_OK_FOR_I (VALUE) \ : (C) == 'K' ? CONST_OK_FOR_K (VALUE) \ : (C) == 'L' ? CONST_OK_FOR_L (VALUE) \ : (C) == 'M' ? CONST_OK_FOR_M (VALUE) \ : (C) == 'N' ? CONST_OK_FOR_N (VALUE) \ : 0)/* Similar, but for floating constants, and defining letters G and H. Here VALUE is the CONST_DOUBLE rtx itself. */#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \((C) == 'G' ? fp_zero_operand (VALUE) \ : (C) == 'H' ? fp_one_operand (VALUE) \ : (C) == 'F')/* Given an rtx X being reloaded into a reg required to be in class CLASS, return the class of reg to actually use. In general this is just CLASS; but on some machines in some cases it is preferable to use a more restrictive class. */#define PREFERRED_RELOAD_CLASS(X, CLASS) (CLASS)#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,X) \ ((((((CLASS) == FP_REGS || (CLASS) == FP0_REGS \ || (CLASS) == DF_REGS) \ && (GET_CODE (X) == REG && REGNO (X) <= AP_REG)) \ || (((CLASS) == GENERAL_REGS || (CLASS) == R0_REGS) \ && GET_CODE (X) == REG \ && REGNO (X) >= FIRST_FP_REG && REGNO (X) <= LAST_FP_REG)) \ && MODE == SFmode) \ ? FPUL_REGS \ : ((CLASS) == FPUL_REGS \ && (GET_CODE (X) == MEM \ || (GET_CODE (X) == REG && REGNO (X) >= FIRST_PSEUDO_REGISTER)))\ ? GENERAL_REGS \ : (((CLASS) == MAC_REGS || (CLASS) == PR_REGS) \ && GET_CODE (X) == REG && REGNO (X) > 15 \ && (CLASS) != REGNO_REG_CLASS (REGNO (X))) \ ? GENERAL_REGS : NO_REGS)#define SECONDARY_INPUT_RELOAD_CLASS(CLASS,MODE,X) \ ((((CLASS) == FP_REGS || (CLASS) == FP0_REGS || (CLASS) == DF_REGS) \ && immediate_operand ((X), (MODE)) \ && ! ((fp_zero_operand (X) || fp_one_operand (X)) && (MODE) == SFmode))\ ? R0_REGS \ : CLASS == FPUL_REGS && immediate_operand ((X), (MODE)) \ ? (GET_CODE (X) == CONST_INT && CONST_OK_FOR_I (INTVAL (X)) \ ? GENERAL_REGS \ : R0_REGS) \ : (CLASS == FPSCR_REGS \ && ((GET_CODE (X) == REG && REGNO (X) >= FIRST_PSEUDO_REGISTER) \ || GET_CODE (X) == MEM && GET_CODE (XEXP ((X), 0)) == PLUS)) \ ? GENERAL_REGS \ : SECONDARY_OUTPUT_RELOAD_CLASS((CLASS),(MODE),(X)))/* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. On SH this is the size of MODE in words. */#define CLASS_MAX_NREGS(CLASS, MODE) \ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)/* If defined, gives a class of registers that cannot be used as the operand of a SUBREG that changes the size of the object. */#define CLASS_CANNOT_CHANGE_SIZE DF_REGS/* Stack layout; function entry, exit and calling. *//* Define the number of registers that can hold parameters. These macros are used only in other macro definitions below. */#define NPARM_REGS(MODE) \ (TARGET_SH3E && (MODE) == SFmode \ ? 8 \ : TARGET_SH4 && (GET_MODE_CLASS (MODE) == MODE_FLOAT \ || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \ ? 8 \ : 4)#define FIRST_PARM_REG 4#define FIRST_RET_REG 0#define FIRST_FP_PARM_REG (FIRST_FP_REG + 4)#define FIRST_FP_RET_REG FIRST_FP_REG/* Define this if pushing a word on the stack makes the stack pointer a smaller address. */#define STACK_GROWS_DOWNWARD/* Define this macro if the addresses of local variable slots are at negative offsets from the frame pointer. The SH only has positive indexes, so grow the frame up. *//* #define FRAME_GROWS_DOWNWARD *//* Offset from the frame pointer to the first local variable slot to be allocated. */#define STARTING_FRAME_OFFSET 0/* If we generate an insn to push BYTES bytes, this says how many the stack pointer really advances by. *//* Don't define PUSH_ROUNDING, since the hardware doesn't do this. When PUSH_ROUNDING is not defined, PARM_BOUNDARY will cause gcc to do correct alignment. */#if 0#define PUSH_ROUNDING(NPUSHED) (((NPUSHED) + 3) & ~3)#endif/* Offset of first parameter from the argument pointer register value. */#define FIRST_PARM_OFFSET(FNDECL) 0/* Value is the number of byte of arguments automatically popped when returning from a subroutine call. FUNDECL is the declaration node of the function (as a tree), FUNTYPE is the data type of the function (as a tree), or for a library call it is an identifier node for the subroutine name. SIZE is the number of bytes of arguments passed on the stack. On the SH, the caller does not pop any of its arguments that were passed on the stack. */#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0/* Nonzero if we do not know how to pass TYPE solely in registers. Values that come in registers with inconvenient padding are stored to memory at the function start. */#define MUST_PASS_IN_STACK(MODE,TYPE) \ ((TYPE) != 0 \ && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ || TREE_ADDRESSABLE (TYPE)))/* Some subroutine macros specific to this machine. */#define BASE_RETURN_VALUE_REG(MODE) \ ((TARGET_SH3E && ((MODE) == SFmode)) \ ? FIRST_FP_RET_REG \ : TARGET_SH3E && (MODE) == SCmode \ ? FIRST_FP_RET_REG \ : (TARGET_SH4 \ && ((MODE) == DFmode || (MODE) == SFmode \ || (MODE) == DCmode || (MODE) == SCmode )) \ ? FIRST_FP_RET_REG \ : FIRST_RET_REG)#define BASE_ARG_REG(MODE) \ ((TARGET_SH3E && ((MODE) == SFmode)) \ ? FIRST_FP_PARM_REG \ : TARGET_SH4 && (GET_MODE_CLASS (MODE) == MODE_FLOAT \ || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)\ ? FIRST_FP_PARM_REG \ : FIRST_PARM_REG)/* Define how to find the value returned by a function. VALTYPE is the data type of the value (as a tree). If the precise function being called is known, FUNC is its FUNCTION_DECL; otherwise, FUNC is 0. For the SH, this is like LIBCALL_VALUE, except that we must change the mode like PROMOTE_MODE does. ??? PROMOTE_MODE is ignored for non-scalar types. The set of types tested here has to be kept in sync with the one in explow.c:promote_mode. */#define FUNCTION_VALUE(VALTYPE, FUNC) \ gen_rtx (REG, \ ((GET_MODE_CLASS (TYPE_MODE (VALTYPE)) == MODE_INT \ && GET_MODE_SIZE (TYPE_MODE (VALTYPE)) < UNITS_PER_WORD \ && (TREE_CODE (VALTYPE) == INTEGER_TYPE \ || TREE_CODE (VALTYPE) == ENUMERAL_TYPE \ || TREE_CODE (VALTYPE) == BOOLEAN_TYPE \ || TREE_CODE (VALTYPE) == CHAR_TYPE \ || TREE_CODE (VALTYPE) == REAL_TYPE \ || TREE_CODE (VALTYPE) == OFFSET_TYPE)) \ ? SImode : TYPE_MODE (VALTYPE)), \ BASE_RETURN_VALUE_REG (TYPE_MODE (VALTYPE))) /* Define how to find the value returned by a library function assuming the value has mode MODE. */#define LIBCALL_VALUE(MODE) \ gen_rtx (REG, (MODE), BASE_RETURN_VALUE_REG (MODE))/* 1 if N is a possible register number for a function value. */#define FUNCTION_VALUE_REGNO_P(REGNO) \ ((REGNO) == FIRST_RET_REG || (TARGET_SH3E && (REGNO) == FIRST_FP_RET_REG))/* 1 if N is a possible register number for function argument passing. */#define FUNCTION_ARG_REGNO_P(REGNO) \ (((REGNO) >= FIRST_PARM_REG && (REGNO) < (FIRST_PARM_REG + 4)) \ || (TARGET_SH3E \ && (REGNO) >= FIRST_FP_PARM_REG && (REGNO) < (FIRST_FP_PARM_REG + 8)))/* Define a data type for recording info about an argument list during the scan of that argument list. This data type should hold all necessary information about the function itself and about the args processed so far, enough to enable macros such as FUNCTION_ARG to determine where the next arg should go. On SH, this is a single integer, which is a number of words of arguments scanned so far (including the invisible argument, if any, which holds the structure-value-address). Thus NARGREGS or more means all following args should go on the stack. */enum sh_arg_class { SH_ARG_INT = 0, SH_ARG_FLOAT = 1 };struct sh_args { int arg_count[2];};#define CUMULATIVE_ARGS struct sh_args#define GET_SH_ARG_CLASS(MODE) \ ((TARGET_SH3E && (MODE) == SFmode) \ ? SH_ARG_FLOAT \ : TARGET_SH4 && (GET_MODE_CLASS (MODE) == MODE_FLOAT \ || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \ ? SH_ARG_FLOAT : SH_ARG_INT)#define ROUND_ADVANCE(SIZE) \ (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)/* Round a register number up to a proper boundary for an arg of mode MODE. The SH doesn't care about double alignment, so we only round doubles to even regs when asked to explicitly. */#define ROUND_REG(CUM, MODE) \ (((TARGET_ALIGN_DOUBLE \ || (TARGET_SH4 && ((MODE) == DFmode || (MODE) == DCmode) \ && (CUM).arg_count[(int) SH_ARG_FLOAT] < NPARM_REGS (MODE)))\ && GET_MODE_UNIT_SIZE ((MODE)) > UNITS_PER_WORD) \ ? ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)] \ + ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)] & 1)) \ : (CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)])/* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE. For a library call, FNTYPE is 0. On SH, the offset always starts at 0: the first parm reg is always the same reg for a given argument class. */#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \ do { \ (CUM).arg_count[(int) SH_ARG_INT] = 0; \ (CUM).arg_count[(int) SH_ARG_FLOAT] = 0; \ } while (0)/* Update the data in CUM to advance over an argument of mode MODE and data type TYPE. (TYPE is null for libcalls where that information may not be available.) */#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ if (! TARGET_SH4 || PASS_IN_REG_P ((CUM), (MODE), (TYPE))) \ ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)] \ = (ROUND_REG ((CUM), (MODE)) \ + ((MODE) == BLKmode \ ? ROUND_ADVANCE (int_size_in_bytes (TYPE)) \ : ROUND_ADVANCE (GET_MODE_SIZE (MODE)))))/* Return boolean indicating arg of mode MODE will be passed in a reg. This macro is only used in this file. */#define PASS_IN_REG_P(CUM, MODE, TYPE) \ (((TYPE) == 0 \ || (! TREE_ADDRESSABLE ((tree)(TYPE))) \ && (! TARGET_HITACHI || ! AGGREGATE_TYPE_P (TYPE))) \ && (TARGET_SH3E \ ? ((MODE) == BLKmode \ ? (((CUM).arg_count[(int) SH_ARG_INT] * UNITS_PER_WORD \ + int_size_in_bytes (TYPE)) \ <= NPARM_REGS (SImode) * UNITS_PER_WORD) \ : ((ROUND_REG((CUM), (MODE)) \ + HARD_REGNO_NREGS (BASE_ARG_REG (MODE), (MODE))) \ <= NPARM_REGS (MODE))) \ : ROUND_REG ((CUM), (MODE)) < NPARM_REGS (MODE)))/* Define where to put the arguments to a function. Value is zero to push the argument on the stack, or a hard register in which to store the argument. MODE is the argument's machine mode. TYPE is the data type of the argument (as a tree). This is null for libcalls where that information may not be available. CUM is a variable of type CUMULATIVE_ARGS which gives info about the preceding args and about the function being called. NAMED is nonzero if this argument is a named parameter (otherwise it is an extra parameter matching an ellipsis). On SH the first args are normally in registers and the rest are pushed. Any arg that starts within the first NPARM_REGS words is at least partially passed in a register unless its data type forbids. */extern int current_function_varargs;#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ ((PASS_IN_REG_P ((CUM), (MODE), (TYPE)) \ && ((NAMED) \ || (! TARGET_HITACHI && (TARGET_SH3E || ! current_function_varargs)))) \ ? gen_rtx (REG, (MODE), \ ((BASE_ARG_REG (MODE) + ROUND_REG ((CUM), (MODE))) \ ^ ((MODE) == SFmode && TARGET_SH4 \ && TARGET_LITTLE_ENDIAN != 0))) \ : 0)#define PRETEND_OUTGOING_VARARGS_NAMED (! TARGET_HITACHI)/* For an arg passed partly in registers and partly in memory, this is the number of registers used. For args passed entirely in registers or entirely in memory, zero.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -