📄 c4x.h
字号:
{0x000000ff}, /* 'q' R0-R7 . */ \ {0xf00000ff}, /* 'f' R0-R11 */ \ {0x0000ff00}, /* 'a' AR0-AR7. */ \ {0x00060000}, /* 'x' IR0-IR1. */ \ {0x00080000}, /* 'k' BK. */ \ {0x00100000}, /* 'b' SP. */ \ {0x08000000}, /* 'v' RC. */ \ {0x0800ff00}, /* RC,AR0-AR7. */ \ {0x0e1eff00}, /* 'c' AR0-AR7, IR0-IR1, BK, SP, RS, RE, RC. */ \ {0xfe1effff}, /* 'r' R0-R11, AR0-AR7, IR0-IR1, BK, SP, RS, RE, RC. */\ {0x00010000}, /* 'z' DP. */ \ {0x00200000}, /* 'y' ST. */ \ {0xffffffff}, /* All registers. */ \}/* The same information, inverted: Return the class number of the smallest class containing reg number REGNO. This could be a conditional expression or could index an array. */#define REGNO_REG_CLASS(REGNO) (c4x_regclass_map[REGNO])/* When SMALL_REGISTER_CLASSES is defined, the lifetime of registers explicitly used in the rtl is kept as short as possible. We only need to define SMALL_REGISTER_CLASSES if TARGET_PARALLEL_MPY is defined since the MPY|ADD insns require the classes R0R1_REGS and R2R3_REGS which are used by the function return registers (R0,R1) and the register arguments (R2,R3), respectively. I'm reluctant to define this macro since it stomps on many potential optimisations. Ideally it should have a register class argument so that not all the register classes gets penalised for the sake of a naughty few... For long double arithmetic we need two additional registers that we can use as spill registers. */#define SMALL_REGISTER_CLASSES (TARGET_SMALL_REG_CLASS && TARGET_PARALLEL_MPY)#define BASE_REG_CLASS ADDR_REGS#define INDEX_REG_CLASS INDEX_REGS/* Register constraints for the C4x a - address reg (ar0-ar7) b - stack reg (sp) c - other gp int-only reg d - data/int reg (equiv. to f) f - data/float reg h - data/long double reg (equiv. to f) k - block count (bk) q - r0-r7 t - r0-r1 u - r2-r3 v - repeat count (rc) x - index register (ir0-ir1) y - status register (st) z - dp reg (dp) Memory/constant constraints for the C4x G - short float 16-bit I - signed 16-bit constant (sign extended) J - signed 8-bit constant (sign extended) (C4x only) K - signed 5-bit constant (sign extended) (C4x only for stik) L - unsigned 16-bit constant M - unsigned 8-bit constant (C4x only) N - ones complement of unsigned 16-bit constant Q - indirect arx + 9-bit signed displacement (a *-arx(n) or *+arx(n) is used to account for the sign bit) R - indirect arx + 5-bit unsigned displacement (C4x only) S - indirect arx + 0, 1, or irn displacement T - direct symbol ref > - indirect with autoincrement < - indirect with autodecrement } - indirect with post-modify { - indirect with pre-modify */#define REG_CLASS_FROM_LETTER(CC) \ ( ((CC) == 'a') ? ADDR_REGS \ : ((CC) == 'b') ? SP_REG \ : ((CC) == 'c') ? INT_REGS \ : ((CC) == 'd') ? EXT_REGS \ : ((CC) == 'f') ? EXT_REGS \ : ((CC) == 'h') ? EXT_REGS \ : ((CC) == 'k') ? BK_REG \ : ((CC) == 'q') ? EXT_LOW_REGS \ : ((CC) == 't') ? R0R1_REGS \ : ((CC) == 'u') ? R2R3_REGS \ : ((CC) == 'v') ? RC_REG \ : ((CC) == 'x') ? INDEX_REGS \ : ((CC) == 'y') ? ST_REG \ : ((CC) == 'z') ? DP_REG \ : NO_REGS )/* These assume that REGNO is a hard or pseudo reg number. They give nonzero only if REGNO is a hard reg of the suitable class or a pseudo reg currently allocated to a suitable hard reg. Since they use reg_renumber, they are safe only once reg_renumber has been allocated, which happens in local-alloc.c. */#define REGNO_OK_FOR_BASE_P(REGNO) \ (IS_ADDR_REGNO(REGNO) || IS_ADDR_REGNO((unsigned)reg_renumber[REGNO]))#define REGNO_OK_FOR_INDEX_P(REGNO) \ (IS_INDEX_REGNO(REGNO) || IS_INDEX_REGNO((unsigned)reg_renumber[REGNO]))/* If we have to generate framepointer + constant prefer an ADDR_REGS register. This avoids using EXT_REGS in addqi3_noclobber_reload. */#define PREFERRED_RELOAD_CLASS(X, CLASS) \ (GET_CODE (X) == PLUS \ && GET_MODE (X) == Pmode \ && GET_CODE (XEXP ((X), 0)) == REG \ && GET_MODE (XEXP ((X), 0)) == Pmode \ && REGNO (XEXP ((X), 0)) == FRAME_POINTER_REGNUM \ && GET_CODE (XEXP ((X), 1)) == CONST_INT \ ? ADDR_REGS : (CLASS))#define LIMIT_RELOAD_CLASS(X, CLASS) (CLASS)#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) 0#define CLASS_MAX_NREGS(CLASS, MODE) \(((MODE) == CCmode || (MODE) == CC_NOOVmode) ? 1 : ((MODE) == HFmode) ? 1 : \((GET_MODE_SIZE(MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))#define IS_INT5_CONST(VAL) (((VAL) <= 15) && ((VAL) >= -16)) /* 'K'. */#define IS_UINT5_CONST(VAL) (((VAL) <= 31) && ((VAL) >= 0)) /* 'R'. */#define IS_INT8_CONST(VAL) (((VAL) <= 127) && ((VAL) >= -128)) /* 'J'. */#define IS_UINT8_CONST(VAL) (((VAL) <= 255) && ((VAL) >= 0)) /* 'M'. */#define IS_INT16_CONST(VAL) (((VAL) <= 32767) && ((VAL) >= -32768)) /* 'I'. */#define IS_UINT16_CONST(VAL) (((VAL) <= 65535) && ((VAL) >= 0)) /* 'L'. */#define IS_NOT_UINT16_CONST(VAL) IS_UINT16_CONST(~(VAL)) /* 'N'. */#define IS_HIGH_CONST(VAL) \(! TARGET_C3X && (((VAL) & 0xffff) == 0)) /* 'O'. */#define IS_DISP1_CONST(VAL) (((VAL) <= 1) && ((VAL) >= -1)) /* 'S'. */#define IS_DISP8_CONST(VAL) (((VAL) <= 255) && ((VAL) >= -255)) /* 'Q'. */#define IS_DISP1_OFF_CONST(VAL) (IS_DISP1_CONST (VAL) \ && IS_DISP1_CONST (VAL + 1))#define IS_DISP8_OFF_CONST(VAL) (IS_DISP8_CONST (VAL) \ && IS_DISP8_CONST (VAL + 1))#define CONST_OK_FOR_LETTER_P(VAL, C) \ ( ((C) == 'I') ? (IS_INT16_CONST (VAL)) \ : ((C) == 'J') ? (! TARGET_C3X && IS_INT8_CONST (VAL)) \ : ((C) == 'K') ? (! TARGET_C3X && IS_INT5_CONST (VAL)) \ : ((C) == 'L') ? (IS_UINT16_CONST (VAL)) \ : ((C) == 'M') ? (! TARGET_C3X && IS_UINT8_CONST (VAL)) \ : ((C) == 'N') ? (IS_NOT_UINT16_CONST (VAL)) \ : ((C) == 'O') ? (IS_HIGH_CONST (VAL)) \ : 0 ) #define CONST_DOUBLE_OK_FOR_LETTER_P(OP, C) \ ( ((C) == 'G') ? (fp_zero_operand (OP, QFmode)) \ : ((C) == 'H') ? (c4x_H_constant (OP)) \ : 0 )#define EXTRA_CONSTRAINT(OP, C) \ ( ((C) == 'Q') ? (c4x_Q_constraint (OP)) \ : ((C) == 'R') ? (c4x_R_constraint (OP)) \ : ((C) == 'S') ? (c4x_S_constraint (OP)) \ : ((C) == 'T') ? (c4x_T_constraint (OP)) \ : ((C) == 'U') ? (c4x_U_constraint (OP)) \ : 0 )#define SMALL_CONST(VAL, insn) \ ( ((insn == NULL_RTX) || (get_attr_data (insn) == DATA_INT16)) \ ? IS_INT16_CONST (VAL) \ : ( (get_attr_data (insn) == DATA_NOT_UINT16) \ ? IS_NOT_UINT16_CONST (VAL) \ : ( (get_attr_data (insn) == DATA_HIGH_16) \ ? IS_HIGH_CONST (VAL) \ : IS_UINT16_CONST (VAL) \ ) \ ) \ )/* I. Routine calling with arguments in registers ---------------------------------------------- The TI C3x compiler has a rather unusual register passing algorithm. Data is passed in the following registers (in order): AR2, R2, R3, RC, RS, RE However, the first and second floating point values are always in R2 and R3 (and all other floats are on the stack). Structs are always passed on the stack. If the last argument is an ellipsis, the previous argument is passed on the stack so that its address can be taken for the stdargs macros. Because of this, we have to pre-scan the list of arguments to figure out what goes where in the list. II. Routine calling with arguments on stack ------------------------------------------- Let the subroutine declared as "foo(arg0, arg1, arg2);" have local variables loc0, loc1, and loc2. After the function prologue has been executed, the stack frame will look like: [stack grows towards increasing addresses] I-------------I 5 I saved reg1 I <= SP points here I-------------I 4 I saved reg0 I I-------------I 3 I loc2 I I-------------I 2 I loc1 I I-------------I 1 I loc0 I I-------------I 0 I old FP I <= FP (AR3) points here I-------------I -1 I return PC I I-------------I -2 I arg0 I I-------------I -3 I arg1 I I-------------I -4 I arg2 I I-------------I All local variables (locn) are accessible by means of +FP(n+1) addressing, where n is the local variable number. All stack arguments (argn) are accessible by means of -FP(n-2). The stack pointer (SP) points to the last register saved in the prologue (regn). Note that a push instruction performs a preincrement of the stack pointer. (STACK_PUSH_CODE == PRE_INC) III. Registers used in function calling convention -------------------------------------------------- Preserved across calls: R4...R5 (only by PUSH, i.e. lower 32 bits) R6...R7 (only by PUSHF, i.e. upper 32 bits) AR3...AR7 (Because of this model, we only assign FP values in R6, R7 and only assign integer values in R4, R5.) These registers are saved at each function entry and restored at the exit. Also it is expected any of these not affected by any call to user-defined (not service) functions. Not preserved across calls: R0...R3 R4...R5 (upper 8 bits) R6...R7 (lower 8 bits) AR0...AR2, IR0, IR1, BK, ST, RS, RE, RC These registers are used arbitrary in a function without being preserved. It is also expected that any of these can be clobbered by any call. Not used by GCC (except for in user "asm" statements): IE (DIE), IF (IIE), IOF (IIF) These registers are never used by GCC for any data, but can be used with "asm" statements. */#define C4X_ARG0 -2#define C4X_LOC0 1/* Basic Stack Layout. */ /* The stack grows upward, stack frame grows upward, and args grow downward. */#define STARTING_FRAME_OFFSET C4X_LOC0#define FIRST_PARM_OFFSET(FNDECL) (C4X_ARG0 + 1)#define ARGS_GROW_DOWNWARD#define STACK_POINTER_OFFSET 1/* Define this if pushing a word on the stack makes the stack pointer a smaller address. *//* #define STACK_GROWS_DOWNWARD. *//* Like the dsp16xx, i370, i960, and we32k ports. *//* Define this if the nominal address of the stack frame is at the high-address end of the local variables; that is, each additional local variable allocated goes at a more negative offset in the frame. *//* #define FRAME_GROWS_DOWNWARD. *//* Registers That Address the Stack Frame. */#define STACK_POINTER_REGNUM SP_REGNO /* SP. */#define FRAME_POINTER_REGNUM AR3_REGNO /* AR3. */#define ARG_POINTER_REGNUM AR3_REGNO /* AR3. */#define STATIC_CHAIN_REGNUM AR0_REGNO /* AR0. *//* Eliminating Frame Pointer and Arg Pointer. */#define FRAME_POINTER_REQUIRED 0#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) \{ \ int regno; \ int offset = 0; \ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \ if (regs_ever_live[regno] && ! call_used_regs[regno]) \ offset += TARGET_PRESERVE_FLOAT \ && IS_FLOAT_CALL_SAVED_REGNO (regno) ? 2 : 1; \ (DEPTH) = -(offset + get_frame_size ()); \}/* This is a hack... We need to specify a register. */#define ELIMINABLE_REGS \ {{ FRAME_POINTER_REGNUM, FRAME_POINTER_REGNUM }}#define CAN_ELIMINATE(FROM, TO) \ (! (((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ || ((FROM) == FRAME_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM)))#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \{ \ int regno; \ int offset = 0; \ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \ if (regs_ever_live[regno] && ! call_used_regs[regno]) \ offset += TARGET_PRESERVE_FLOAT \ && IS_FLOAT_CALL_SAVED_REGNO (regno) ? 2 : 1; \ (OFFSET) = -(offset + get_frame_size ()); \}/* Passing Function Arguments on the Stack. */#define PUSH_ARGS 1#define PUSH_ROUNDING(BYTES) (BYTES)#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0/* The following structure is used by calls.c, function.c, c4x.c. */typedef struct c4x_args{ int floats; int ints; int maxfloats; int maxints; int init; int var; int prototype; int args;}CUMULATIVE_ARGS;#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \ (c4x_init_cumulative_args (&CUM, FNTYPE, LIBNAME))#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ (c4x_function_arg_advance (&CUM, MODE, TYPE, NAMED))#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -