📄 thumb.h
字号:
&& GET_MODE_SIZE (MODE) < 4) \ { \ (UNSIGNEDP) = 1; \ (MODE) = SImode; \ } \}#define PARM_BOUNDARY 32#define STACK_BOUNDARY 32#define FUNCTION_BOUNDARY 32#define BIGGEST_ALIGNMENT 32/* Make strings word-aligned so strcpy from constants will be faster. */#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ (TREE_CODE (EXP) == STRING_CST \ && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))#define EMPTY_FIELD_BOUNDARY 32#define STRUCTURE_SIZE_BOUNDARY 32/* Used when parsing command line option -mstructure_size_boundary. */extern char * structure_size_string;#define STRICT_ALIGNMENT 1#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT/* Layout of Source Language Data Types */#define DEFAULT_SIGNED_CHAR 0#define TARGET_BELL 007#define TARGET_BS 010#define TARGET_TAB 011#define TARGET_NEWLINE 012#define TARGET_VT 013#define TARGET_FF 014#define TARGET_CR 015/* Register Usage *//* Note there are 16 hard registers on the Thumb. We invent a 17th register which is assigned to ARG_POINTER_REGNUM, but this is later removed by elimination passes in the compiler. */#define FIRST_PSEUDO_REGISTER 17/* ??? This is questionable. */#define FIXED_REGISTERS \{ \ 0,0,0,0, \ 0,0,0,0, \ 0,0,0,1, \ 0,1,1,1,1 \}/* ??? This is questionable. */#define CALL_USED_REGISTERS \{ \ 1,1,1,1, \ 0,0,0,0, \ 0,0,0,1, \ 1,1,1,1,1 \}#define HARD_REGNO_NREGS(REGNO,MODE) \ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \ / UNITS_PER_WORD)/* ??? Probably should only allow DImode/DFmode in even numbered registers. */#define HARD_REGNO_MODE_OK(REGNO,MODE) ((GET_MODE_SIZE (MODE) > UNITS_PER_WORD) ? (REGNO < 7) : 1)#define MODES_TIEABLE_P(MODE1,MODE2) 1/* The NOARG_LO_REGS class is the set of LO_REGS that are not used for passing arguments to functions. These are the registers that are available for spilling during reload. The code in reload1.c:init_reload() will detect this class and place it into 'reload_address_base_reg_class'. */enum reg_class{ NO_REGS, NONARG_LO_REGS, LO_REGS, STACK_REG, BASE_REGS, HI_REGS, ALL_REGS, LIM_REG_CLASSES};#define GENERAL_REGS ALL_REGS#define N_REG_CLASSES (int) LIM_REG_CLASSES#define REG_CLASS_NAMES \{ \ "NO_REGS", \ "NONARG_LO_REGS", \ "LO_REGS", \ "STACK_REG", \ "BASE_REGS", \ "HI_REGS", \ "ALL_REGS" \}#define REG_CLASS_CONTENTS \{ \ 0x00000, \ 0x000f0, \ 0x000ff, \ 0x02000, \ 0x020ff, \ 0x0ff00, \ 0x1ffff, \}#define REGNO_REG_CLASS(REGNO) \ ((REGNO) == STACK_POINTER_REGNUM ? STACK_REG \ : (REGNO) < 8 ? ((REGNO) < 4 ? LO_REGS \ : NONARG_LO_REGS) \ : HI_REGS)#define BASE_REG_CLASS BASE_REGS#define INDEX_REG_CLASS LO_REGS/* When SMALL_REGISTER_CLASSES is nonzero, the compiler allows registers explicitly used in the rtl to be used as spill registers but prevents the compiler from extending the lifetime of these registers. */#define SMALL_REGISTER_CLASSES 1#define REG_CLASS_FROM_LETTER(C) \ ((C) == 'l' ? LO_REGS \ : (C) == 'h' ? HI_REGS \ : (C) == 'b' ? BASE_REGS \ : (C) == 'k' ? STACK_REG \ : NO_REGS)#define REGNO_OK_FOR_BASE_P(REGNO) \ ((REGNO) < 8 \ || (REGNO) == STACK_POINTER_REGNUM \ || (unsigned) reg_renumber[REGNO] < 8 \ || (unsigned) reg_renumber[REGNO] == STACK_POINTER_REGNUM)#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \ ((REGNO) < 8 \ || (unsigned) reg_renumber[REGNO] < 8 \ || (GET_MODE_SIZE (MODE) >= 4 \ && ((REGNO) == STACK_POINTER_REGNUM \ || (unsigned) reg_renumber[REGNO] == STACK_POINTER_REGNUM)))#define REGNO_OK_FOR_INDEX_P(REGNO) \ ((REGNO) < 8 \ || (unsigned) reg_renumber[REGNO] < 8)/* ??? This looks suspiciously wrong. *//* We need to leave BASE_REGS reloads alone, in order to avoid caller_save lossage. Caller_saves requests a BASE_REGS reload (caller_save_spill_class) and then later we verify that one was allocated. If PREFERRED_RELOAD_CLASS says to allocate a LO_REGS spill instead, then this mismatch gives an abort. Alternatively, this could be fixed by modifying BASE_REG_CLASS to be LO_REGS instead of BASE_REGS. It is not clear what affect this change would have. *//* ??? This looks even more suspiciously wrong. PREFERRED_RELOAD_CLASS must always return a strict subset of the input class. Just blindly returning LO_REGS is safe only if the input class is a superset of LO_REGS, but there is no check for this. Added another exception for NONARG_LO_REGS because it is not a superset of LO_REGS. *//* ??? We now use NONARG_LO_REGS for caller_save_spill_class, so the comments about BASE_REGS are now obsolete. */#define PREFERRED_RELOAD_CLASS(X,CLASS) \ ((CLASS) == BASE_REGS || (CLASS) == NONARG_LO_REGS ? (CLASS) \ : LO_REGS)/* ((CONSTANT_P ((X)) && GET_CODE ((X)) != CONST_INT \ && ! CONSTANT_POOL_ADDRESS_P((X))) ? NO_REGS \ : (GET_CODE ((X)) == CONST_INT \ && (unsigned HOST_WIDE_INT) INTVAL ((X)) > 255) ? NO_REGS \ : LO_REGS) *//* Must leave BASE_REGS and NONARG_LO_REGS reloads alone, see comment above. */#define SECONDARY_RELOAD_CLASS(CLASS,MODE,X) \ ((CLASS) != LO_REGS && (CLASS) != BASE_REGS && (CLASS) != NONARG_LO_REGS \ ? ((true_regnum (X) == -1 ? LO_REGS \ : (true_regnum (X) + HARD_REGNO_NREGS (0, MODE) > 8) ? LO_REGS \ : NO_REGS)) \ : NO_REGS)#define CLASS_MAX_NREGS(CLASS,MODE) HARD_REGNO_NREGS(0,(MODE))int thumb_shiftable_const ();#define CONST_OK_FOR_LETTER_P(VAL,C) \ ((C) == 'I' ? (unsigned HOST_WIDE_INT) (VAL) < 256 \ : (C) == 'J' ? (VAL) > -256 && (VAL) <= 0 \ : (C) == 'K' ? thumb_shiftable_const (VAL) \ : (C) == 'L' ? (VAL) > -8 && (VAL) < 8 \ : (C) == 'M' ? ((unsigned HOST_WIDE_INT) (VAL) < 1024 \ && ((VAL) & 3) == 0) \ : (C) == 'N' ? ((unsigned HOST_WIDE_INT) (VAL) < 32) \ : (C) == 'O' ? ((VAL) >= -508 && (VAL) <= 508) \ : 0)#define CONST_DOUBLE_OK_FOR_LETTER_P(VAL,C) 0#define EXTRA_CONSTRAINT(X,C) \ ((C) == 'Q' ? (GET_CODE (X) == MEM \ && GET_CODE (XEXP (X, 0)) == LABEL_REF) : 0)/* Stack Layout and Calling Conventions */#define STACK_GROWS_DOWNWARD 1/* #define FRAME_GROWS_DOWNWARD 1 *//* #define ARGS_GROW_DOWNWARD 1 */#define STARTING_FRAME_OFFSET 0#define FIRST_PARM_OFFSET(FNDECL) 0/* Registers that address the stack frame */#define STACK_POINTER_REGNUM 13 /* Defined by the TPCS. */#define FRAME_POINTER_REGNUM 7 /* TPCS defines this as 11 but it does not really mean it. */#define ARG_POINTER_REGNUM 16 /* A fake hard register that is eliminated later on. */#define STATIC_CHAIN_REGNUM 9#define FRAME_POINTER_REQUIRED 0#define ELIMINABLE_REGS \{{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}/* On the Thumb we always want to perform the eliminations as we actually only have one real register pointing to the stashed variables: the stack pointer, and we never use the frame pointer. */#define CAN_ELIMINATE(FROM,TO) 1/* Note: This macro must match the code in thumb_function_prologue() in thumb.c. */#define INITIAL_ELIMINATION_OFFSET(FROM,TO,OFFSET) \{ \ (OFFSET) = 0; \ if ((FROM) == ARG_POINTER_REGNUM) \ { \ int count_regs = 0; \ int regno; \ (OFFSET) += get_frame_size (); \ for (regno = 8; regno < 13; regno++) \ if (regs_ever_live[regno] && ! call_used_regs[regno]) \ count_regs++; \ if (count_regs) \ (OFFSET) += 4 * count_regs; \ count_regs = 0; \ for (regno = 0; regno < 8; regno++) \ if (regs_ever_live[regno] && ! call_used_regs[regno]) \ count_regs++; \ if (count_regs || ! leaf_function_p () || far_jump_used_p()) \ (OFFSET) += 4 * (count_regs + 1); \ if (TARGET_BACKTRACE) { \ if ((count_regs & 0xFF) == 0 && (regs_ever_live[3] != 0)) \ (OFFSET) += 20; \ else \ (OFFSET) += 16; } \ } \ if ((TO) == STACK_POINTER_REGNUM) \ (OFFSET) += current_function_outgoing_args_size; \}/* Passing Arguments on the stack */#define PROMOTE_PROTOTYPES 1#define ACCUMULATE_OUTGOING_ARGS 1#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0#define FUNCTION_ARG(CUM,MODE,TYPE,NAMED) \ ((NAMED) ? ((CUM) >= 16 ? 0 : gen_rtx (REG, (MODE), (CUM) / 4)) \ : 0)#define FUNCTION_ARG_PARTIAL_NREGS(CUM,MODE,TYPE,NAMED) \ (((CUM) < 16 && (CUM) + (((MODE) == BLKmode) \ ? int_size_in_bytes (TYPE) \ : HARD_REGNO_NREGS (0, (MODE)) * 4) > 16) \ ? 4 - (CUM) / 4 : 0)#define CUMULATIVE_ARGS int#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \ ((CUM) = ((FNTYPE) && aggregate_value_p (TREE_TYPE (FNTYPE))) ? 4 : 0)#define FUNCTION_ARG_ADVANCE(CUM,MODE,TYPE,NAMED) \ (CUM) += ((((MODE) == BLKmode) \ ? int_size_in_bytes (TYPE) \ : GET_MODE_SIZE (MODE)) + 3) & ~3#define FUNCTION_ARG_REGNO_P(REGNO) \ ((REGNO) >=0 && (REGNO) <= 3)#define FUNCTION_VALUE(VALTYPE,FUNC) gen_rtx (REG, TYPE_MODE (VALTYPE), 0)#define LIBCALL_VALUE(MODE) gen_rtx (REG, (MODE), 0)#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == 0) /* How large values are returned *//* A C expression which can inhibit the returning of certain function values in registers, based on the type of value. */#define RETURN_IN_MEMORY(TYPE) thumb_return_in_memory (TYPE) /* Define DEFAULT_PCC_STRUCT_RETURN to 1 if all structure and union return values must be in memory. On the ARM, they need only do so if larger than a word, or if they contain elements offset from zero in the struct. */#define DEFAULT_PCC_STRUCT_RETURN 0#define STRUCT_VALUE_REGNUM 0#define FUNCTION_PROLOGUE(FILE,SIZE) thumb_function_prologue((FILE),(SIZE))#define FUNCTION_EPILOGUE(FILE,SIZE) thumb_function_epilogue((FILE),(SIZE))/* Generating code for profiling */#define FUNCTION_PROFILER(STREAM,LABELNO) \{ \ fprintf ((STREAM), "\tmov\\tip, lr\n"); \ fprintf ((STREAM), "\tbl\tmcount\n"); \ fprintf ((STREAM), "\t.word\tLP%d\n", (LABELNO)); \}/* Implementing the Varargs Macros */#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \{ \ extern int current_function_anonymous_args; \ current_function_anonymous_args = 1; \ if ((CUM) < 16) \ (PRETEND_SIZE) = 16 - (CUM); \}/* Trampolines for nested functions *//* Output assembler code for a block containing the constant parts of a trampoline, leaving space for the variable parts. On the Thumb we always switch into ARM mode to execute the trampoline. Why - because it is easier. This code will always be branched to via a BX instruction and since the compiler magically generates the address of the function the linker has no opportunity to ensure that the bottom bit is set. Thus the processor will be in ARM mode when it reaches this code. So we duplicate the ARM trampoline code and add a switch into Thumb mode as well. On the ARM, (if r8 is the static chain regnum, and remembering that referencing pc adds an offset of 8) the trampoline looks like: ldr r8, [pc, #0] ldr pc, [pc] .word static chain value .word function's address ??? FIXME: When the trampoline returns, r8 will be clobbered. */#define TRAMPOLINE_TEMPLATE(FILE) \{ \ fprintf ((FILE), "\t.code 32\n"); \ fprintf ((FILE), ".Ltrampoline_start:\n"); \ fprintf ((FILE), "\tldr\t%s, [%spc, #8]\n", \ reg_names[STATIC_CHAIN_REGNUM], REGISTER_PREFIX); \ fprintf ((FILE), "\tldr\t%sip, [%spc, #8]\n", \ REGISTER_PREFIX, REGISTER_PREFIX); \ fprintf ((FILE), "\torr\t%sip, %sip, #1\n", \ REGISTER_PREFIX, REGISTER_PREFIX); \ fprintf ((FILE), "\tbx\t%sip\n", REGISTER_PREFIX); \ fprintf ((FILE), "\t.word\t0\n"); \ fprintf ((FILE), "\t.word\t0\n"); \ fprintf ((FILE), "\t.code 16\n"); \}/* Length in units of the trampoline for entering a nested function. */#define TRAMPOLINE_SIZE 24/* Alignment required for a trampoline in units. */#define TRAMPOLINE_ALIGN 4#define INITIALIZE_TRAMPOLINE(ADDR,FNADDR,CHAIN) \{ \ emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((ADDR), 16)), \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -