📄 arm.h
字号:
#define STARTING_FRAME_OFFSET 0/* If we generate an insn to push BYTES bytes, this says how many the stack pointer really advances by. *//* The push insns do not do this rounding implicitly. So don't define this. *//* #define PUSH_ROUNDING(NPUSHED) ROUND_UP (NPUSHED) *//* Define this if the maximum size of all the outgoing args is to be accumulated and pushed during the prologue. The amount can be found in the variable current_function_outgoing_args_size. */#define ACCUMULATE_OUTGOING_ARGS 1/* Offset of first parameter from the argument pointer register value. */#define FIRST_PARM_OFFSET(FNDECL) (TARGET_ARM ? 4 : 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 ARM, the caller does not pop any of its arguments that were passed on the stack. */#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, SIZE) 0/* Define how to find the value returned by a library function assuming the value has mode MODE. */#define LIBCALL_VALUE(MODE) \ (TARGET_ARM && TARGET_HARD_FLOAT && GET_MODE_CLASS (MODE) == MODE_FLOAT \ ? gen_rtx_REG (MODE, FIRST_ARM_FP_REGNUM) \ : gen_rtx_REG (MODE, ARG_REGISTER (1)))/* 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. */#define FUNCTION_VALUE(VALTYPE, FUNC) \ LIBCALL_VALUE (TYPE_MODE (VALTYPE))/* 1 if N is a possible register number for a function value. On the ARM, only r0 and f0 can return results. */#define FUNCTION_VALUE_REGNO_P(REGNO) \ ((REGNO) == ARG_REGISTER (1) \ || (TARGET_ARM && ((REGNO) == FIRST_ARM_FP_REGNUM) && TARGET_HARD_FLOAT))/* 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) arm_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/* Flags for the call/call_value rtl operations set up by function_arg. */#define CALL_NORMAL 0x00000000 /* No special processing. */#define CALL_LONG 0x00000001 /* Always call indirect. */#define CALL_SHORT 0x00000002 /* Never call indirect. *//* These bits describe the different types of function supported by the ARM backend. They are exclusive. ie a function cannot be both a normal function and an interworked function, for example. Knowing the type of a function is important for determining its prologue and epilogue sequences. Note value 7 is currently unassigned. Also note that the interrupt function types all have bit 2 set, so that they can be tested for easily. Note that 0 is deliberately chosen for ARM_FT_UNKNOWN so that when the machine_function structure is initialized (to zero) func_type will default to unknown. This will force the first use of arm_current_func_type to call arm_compute_func_type. */#define ARM_FT_UNKNOWN 0 /* Type has not yet been determined. */#define ARM_FT_NORMAL 1 /* Your normal, straightforward function. */#define ARM_FT_INTERWORKED 2 /* A function that supports interworking. */#define ARM_FT_EXCEPTION_HANDLER 3 /* A C++ exception handler. */#define ARM_FT_ISR 4 /* An interrupt service routine. */#define ARM_FT_FIQ 5 /* A fast interrupt service routine. */#define ARM_FT_EXCEPTION 6 /* An ARM exception handler (subcase of ISR). */#define ARM_FT_TYPE_MASK ((1 << 3) - 1)/* In addition functions can have several type modifiers, outlined by these bit masks: */#define ARM_FT_INTERRUPT (1 << 2) /* Note overlap with FT_ISR and above. */#define ARM_FT_NAKED (1 << 3) /* No prologue or epilogue. */#define ARM_FT_VOLATILE (1 << 4) /* Does not return. */#define ARM_FT_NESTED (1 << 5) /* Embedded inside another func. *//* Some macros to test these flags. */#define ARM_FUNC_TYPE(t) (t & ARM_FT_TYPE_MASK)#define IS_INTERRUPT(t) (t & ARM_FT_INTERRUPT)#define IS_VOLATILE(t) (t & ARM_FT_VOLATILE)#define IS_NAKED(t) (t & ARM_FT_NAKED)#define IS_NESTED(t) (t & ARM_FT_NESTED)/* A C structure for machine-specific, per-function data. This is added to the cfun structure. */typedef struct machine_function GTY(()){ /* Additionsl stack adjustment in __builtin_eh_throw. */ rtx eh_epilogue_sp_ofs; /* Records if LR has to be saved for far jumps. */ int far_jump_used; /* Records if ARG_POINTER was ever live. */ int arg_pointer_live; /* Records if the save of LR has been eliminated. */ int lr_save_eliminated; /* The size of the stack frame. Only valid after reload. */ int frame_size; /* Records the type of the current function. */ unsigned long func_type; /* Record if the function has a variable argument list. */ int uses_anonymous_args;}machine_function;/* A C type for declaring a variable that is used as the first argument of `FUNCTION_ARG' and other related values. For some target machines, the type `int' suffices and can hold the number of bytes of argument so far. */typedef struct{ /* This is the number of registers of arguments scanned so far. */ int nregs; /* One of CALL_NORMAL, CALL_LONG or CALL_SHORT . */ int call_cookie;} CUMULATIVE_ARGS;/* 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 the ARM, normally the first 16 bytes are passed in registers r0-r3; all other arguments are passed on the stack. If (NAMED == 0) (which happens only in assign_parms, since SETUP_INCOMING_VARARGS is defined), say it is passed in the stack (function_prologue will indeed make it pass in the stack if necessary). */#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ arm_function_arg (&(CUM), (MODE), (TYPE), (NAMED))/* 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. */#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ ( NUM_ARG_REGS > (CUM).nregs \ && (NUM_ARG_REGS < ((CUM).nregs + ARM_NUM_REGS2 (MODE, TYPE))) \ ? NUM_ARG_REGS - (CUM).nregs : 0)/* A C expression that indicates when an argument must be passed by reference. If nonzero for an argument, a copy of that argument is made in memory and a pointer to the argument is passed instead of the argument itself. The pointer is passed in whatever way is appropriate for passing a pointer to that type. */#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ arm_function_arg_pass_by_reference (&CUM, MODE, TYPE, NAMED)/* 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 the ARM, the offset starts at 0. */#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \ arm_init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME), (INDIRECT))/* 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) \ (CUM).nregs += ARM_NUM_REGS2 (MODE, TYPE)/* 1 if N is a possible register number for function argument passing. On the ARM, r0-r3 are used to pass args. */#define FUNCTION_ARG_REGNO_P(REGNO) (IN_RANGE ((REGNO), 0, 3))/* Implement `va_arg'. */#define EXPAND_BUILTIN_VA_ARG(valist, type) \ arm_va_arg (valist, type)/* Tail calling. *//* A C expression that evaluates to true if it is ok to perform a sibling call to DECL. */#define FUNCTION_OK_FOR_SIBCALL(DECL) arm_function_ok_for_sibcall ((DECL))/* Perform any actions needed for a function that is receiving a variable number of arguments. CUM is as above. MODE and TYPE are the mode and type of the current parameter. PRETEND_SIZE is a variable that should be set to the amount of stack that must be pushed by the prolog to pretend that our caller pushed it. Normally, this macro will push all remaining incoming registers on the stack and set PRETEND_SIZE to the length of the registers pushed. On the ARM, PRETEND_SIZE is set in order to have the prologue push the last named arg and all anonymous args onto the stack. XXX I know the prologue shouldn't be pushing registers, but it is faster that way. */#define SETUP_INCOMING_VARARGS(CUM, MODE, TYPE, PRETEND_SIZE, NO_RTL) \{ \ cfun->machine->uses_anonymous_args = 1; \ if ((CUM).nregs < NUM_ARG_REGS) \ (PRETEND_SIZE) = (NUM_ARG_REGS - (CUM).nregs) * UNITS_PER_WORD; \}/* If your target environment doesn't prefix user functions with an underscore, you may wish to re-define this to prevent any conflicts. e.g. AOF may prefix mcount with an underscore. */#ifndef ARM_MCOUNT_NAME#define ARM_MCOUNT_NAME "*mcount"#endif/* Call the function profiler with a given profile label. The Acorn compiler puts this BEFORE the prolog but gcc puts it afterwards. On the ARM the full profile code will look like: .data LP1 .word 0 .text mov ip, lr bl mcount .word LP1 profile_function() in final.c outputs the .data section, FUNCTION_PROFILER will output the .text section. The ``mov ip,lr'' seems like a good idea to stick with cc convention. ``prof'' doesn't seem to mind about this! Note - this version of the code is designed to work in both ARM and Thumb modes. */#ifndef ARM_FUNCTION_PROFILER#define ARM_FUNCTION_PROFILER(STREAM, LABELNO) \{ \ char temp[20]; \ rtx sym; \ \ asm_fprintf (STREAM, "\tmov\t%r, %r\n\tbl\t", \ IP_REGNUM, LR_REGNUM); \ assemble_name (STREAM, ARM_MCOUNT_NAME); \ fputc ('\n', STREAM); \ ASM_GENERATE_INTERNAL_LABEL (temp, "LP", LABELNO); \ sym = gen_rtx (SYMBOL_REF, Pmode, temp); \ assemble_aligned_integer (UNITS_PER_WORD, sym); \}#endif#ifdef THUMB_FUNCTION_PROFILER#define FUNCTION_PROFILER(STREAM, LABELNO) \ if (TARGET_ARM) \ ARM_FUNCTION_PROFILER (STREAM, LABELNO) \ else \ THUMB_FUNCTION_PROFILER (STREAM, LABELNO)#else#define FUNCTION_PROFILER(STREAM, LABELNO) \ ARM_FUNCTION_PROFILER (STREAM, LABELNO)#endif/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, the stack pointer does not matter. The value is tested only in functions that have frame pointers. No definition is equivalent to always zero. On the ARM, the function epilogue recovers the stack pointer from the frame. */#define EXIT_IGNORE_STACK 1#define EPILOGUE_USES(REGNO) (reload_completed && (REGNO) == LR_REGNUM)/* Determine if the epilogue should be output as RTL. You should override this if you define FUNCTION_EXTRA_EPILOGUE. */#define USE_RETURN_INSN(ISCOND) \ (TARGET_ARM ? use_return_insn (ISCOND) : 0)/* Definitions for register eliminations. This is an array of structures. Each structure initializes one pair of eliminable registers. The "from" register number is given first, followed by "to". Eliminations of the same "from" register are listed in order of preference. We have two registers that can be eliminated on the ARM. First, the arg pointer register can often be eliminated in favor of the stack pointer register. Secondly, the pseudo frame pointer register can always be eliminated; it is replaced with either the stack or the real frame pointer. Note we have to use {ARM|THUMB}_HARD_FRAME_POINTER_REGNUM because the definition of HARD_FRAME_POINTER_REGNUM is not a constant. */#define ELIMINABLE_REGS \{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM },\ { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM },\ { ARG_POINTER_REGNUM, ARM_HARD_FRAME_POINTER_REGNUM },\ { ARG_POINTER_REGNUM, THUMB_HARD_FRAME_POINTER_REGNUM },\ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM },\ { FRAME_POINTER_REGNUM, ARM_HARD_FRAME_POINTER_REGNUM },\ { FRAME_POINTER_REGNUM, THUMB_HARD_FRAME_POINTER_REGNUM }}/* Given FROM and TO register numbers, say whether this elimination is allowed. Frame pointer elimination is automatically handled. All eliminations are permissible. Note that ARG_POINTER_REGNUM and HARD_FRAME_POINTER_REGNUM are in fact the same thing. If we need a frame pointer, we must eliminate FRAME_POINTER_REGNUM into HARD_FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM or ARG_POINTER_REGNUM. */#define CAN_ELIMINATE(FROM, TO) \ (((TO) == FRAME_POINTER_REGNUM && (FROM) == ARG_POINTER_REGNUM) ? 0 : \ ((TO) == STACK_POINTER_REGNUM && frame_pointer_needed) ? 0 : \ ((TO) == ARM_HARD_FRAME_POINTER_REGNUM && TARGET_THUMB) ? 0 : \ ((TO) == THUMB_HARD_FRAME_POINTER_REGNUM && TARGET_ARM) ? 0 : \ 1)#define THUMB_REG_PUSHED_P(reg) \ (regs_ever_live [reg] \ && (! call_used_regs [reg] \ || (flag_pic && (reg) == PIC_OFFSET_TABLE_REGNUM)) \ && !(TARGET_SINGLE_PIC_BASE && ((reg) == arm_pic_register))) /* Define the offset between two registers, one to be eliminated, and the other its replacement, at the start of a routine. */#define ARM_INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ do \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -