📄 xtensa.h
字号:
: (C) == 'N' ? (xtensa_simm8x256 (VALUE)) \ : (C) == 'O' ? (xtensa_ai4const (VALUE)) \ : (C) == 'P' ? (xtensa_mask_immediate (VALUE)) \ : FALSE)/* 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) (0)/* Other letters can be defined in a machine-dependent fashion to stand for particular classes of registers or other arbitrary operand types. R = memory that can be accessed with a 4-bit unsigned offset S = memory where the second word can be addressed with a 4-bit offset T = memory in a constant pool (addressable with a pc-relative load) U = memory *NOT* in a constant pool The offset range should not be checked here (except to distinguish denser versions of the instructions for which more general versions are available). Doing so leads to problems in reloading: an argptr-relative address may become invalid when the phony argptr is eliminated in favor of the stack pointer (the offset becomes too large to fit in the instruction's immediate field); a reload is generated to fix this but the RTL is not immediately updated; in the meantime, the constraints are checked and none match. The solution seems to be to simply skip the offset check here. The address will be checked anyway because of the code in GO_IF_LEGITIMATE_ADDRESS. */#define EXTRA_CONSTRAINT(OP, CODE) \ ((GET_CODE (OP) != MEM) ? \ ((CODE) >= 'R' && (CODE) <= 'U' \ && reload_in_progress && GET_CODE (OP) == REG \ && REGNO (OP) >= FIRST_PSEUDO_REGISTER) \ : ((CODE) == 'R') ? smalloffset_mem_p (OP) \ : ((CODE) == 'S') ? smalloffset_double_mem_p (OP) \ : ((CODE) == 'T') ? constantpool_mem_p (OP) \ : ((CODE) == 'U') ? !constantpool_mem_p (OP) \ : FALSE)#define PREFERRED_RELOAD_CLASS(X, CLASS) \ xtensa_preferred_reload_class (X, CLASS, 0)#define PREFERRED_OUTPUT_RELOAD_CLASS(X, CLASS) \ xtensa_preferred_reload_class (X, CLASS, 1) #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \ xtensa_secondary_reload_class (CLASS, MODE, X, 0)#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \ xtensa_secondary_reload_class (CLASS, MODE, X, 1)/* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. */#define CLASS_UNITS(mode, size) \ ((GET_MODE_SIZE (mode) + (size) - 1) / (size))#define CLASS_MAX_NREGS(CLASS, MODE) \ (CLASS_UNITS (MODE, UNITS_PER_WORD))/* Stack layout; function entry, exit and calling. */#define STACK_GROWS_DOWNWARD/* Offset within stack frame to start allocating local variables at. */#define STARTING_FRAME_OFFSET \ current_function_outgoing_args_size/* The ARG_POINTER and FRAME_POINTER are not real Xtensa registers, so they are eliminated to either the stack pointer or hard frame pointer. */#define ELIMINABLE_REGS \{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}#define CAN_ELIMINATE(FROM, TO) 1/* Specify the initial difference between the specified pair of registers. */#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ do { \ compute_frame_size (get_frame_size ()); \ if ((FROM) == FRAME_POINTER_REGNUM) \ (OFFSET) = 0; \ else if ((FROM) == ARG_POINTER_REGNUM) \ (OFFSET) = xtensa_current_frame_size; \ else \ abort (); \ } while (0)/* If defined, the maximum amount of space required for outgoing arguments will be computed and placed into the variable 'current_function_outgoing_args_size'. No space will be pushed onto the stack for each call; instead, the function prologue should increase the stack frame size by this amount. */#define ACCUMULATE_OUTGOING_ARGS 1/* Offset from the argument pointer register to the first argument's address. On some machines it may depend on the data type of the function. If 'ARGS_GROW_DOWNWARD', this is the offset to the location above the first argument's address. */#define FIRST_PARM_OFFSET(FNDECL) 0/* Align stack frames on 128 bits for Xtensa. This is necessary for 128-bit datatypes defined in TIE (e.g., for Vectra). */#define STACK_BOUNDARY 128/* Functions do not pop arguments off the stack. */#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, SIZE) 0/* Use a fixed register window size of 8. */#define WINDOW_SIZE 8/* Symbolic macros for the registers used to return integer, floating point, and values of coprocessor and user-defined modes. */#define GP_RETURN (GP_REG_FIRST + 2 + WINDOW_SIZE)#define GP_OUTGOING_RETURN (GP_REG_FIRST + 2)/* Symbolic macros for the first/last argument registers. */#define GP_ARG_FIRST (GP_REG_FIRST + 2)#define GP_ARG_LAST (GP_REG_FIRST + 7)#define GP_OUTGOING_ARG_FIRST (GP_REG_FIRST + 2 + WINDOW_SIZE)#define GP_OUTGOING_ARG_LAST (GP_REG_FIRST + 7 + WINDOW_SIZE)#define MAX_ARGS_IN_REGISTERS 6/* Don't worry about compatibility with PCC. */#define DEFAULT_PCC_STRUCT_RETURN 0/* For Xtensa, up to 4 words can be returned in registers. (It would have been nice to allow up to 6 words in registers but GCC cannot support that. The return value must be given one of the standard MODE_INT modes, and there is no 6 word mode. Instead, if we try to return a 6 word structure, GCC selects the next biggest mode (OImode, 8 words) and then the register allocator fails because there is no 8-register group beginning with a10.) */#define RETURN_IN_MEMORY(TYPE) \ ((unsigned HOST_WIDE_INT) int_size_in_bytes (TYPE) > 4 * UNITS_PER_WORD)/* Define how to find the value returned by a library function assuming the value has mode MODE. Because we have defined PROMOTE_FUNCTION_RETURN, we have to perform the same promotions as PROMOTE_MODE. */#define XTENSA_LIBCALL_VALUE(MODE, OUTGOINGP) \ gen_rtx_REG ((GET_MODE_CLASS (MODE) == MODE_INT \ && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \ ? SImode : (MODE), \ OUTGOINGP ? GP_OUTGOING_RETURN : GP_RETURN)#define LIBCALL_VALUE(MODE) \ XTENSA_LIBCALL_VALUE ((MODE), 0)#define LIBCALL_OUTGOING_VALUE(MODE) \ XTENSA_LIBCALL_VALUE ((MODE), 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 XTENSA_FUNCTION_VALUE(VALTYPE, FUNC, OUTGOINGP) \ gen_rtx_REG ((INTEGRAL_TYPE_P (VALTYPE) \ && TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \ ? SImode: TYPE_MODE (VALTYPE), \ OUTGOINGP ? GP_OUTGOING_RETURN : GP_RETURN)#define FUNCTION_VALUE(VALTYPE, FUNC) \ XTENSA_FUNCTION_VALUE (VALTYPE, FUNC, 0)#define FUNCTION_OUTGOING_VALUE(VALTYPE, FUNC) \ XTENSA_FUNCTION_VALUE (VALTYPE, FUNC, 1)/* A C expression that is nonzero if REGNO is the number of a hard register in which the values of called function may come back. A register whose use for returning values is limited to serving as the second of a pair (for a value of type 'double', say) need not be recognized by this macro. If the machine has register windows, so that the caller and the called function use different registers for the return value, this macro should recognize only the caller's register numbers. */#define FUNCTION_VALUE_REGNO_P(N) \ ((N) == GP_RETURN)/* A C expression that is nonzero if REGNO is the number of a hard register in which function arguments are sometimes passed. This does *not* include implicit arguments such as the static chain and the structure-value address. On many machines, no registers can be used for this purpose since all function arguments are pushed on the stack. */#define FUNCTION_ARG_REGNO_P(N) \ ((N) >= GP_OUTGOING_ARG_FIRST && (N) <= GP_OUTGOING_ARG_LAST)/* Record the number of argument words seen so far, along with a flag to indicate whether these are incoming arguments. (FUNCTION_INCOMING_ARG is used for both incoming and outgoing args, so a separate flag is needed. */typedef struct xtensa_args{ int arg_words; int incoming;} CUMULATIVE_ARGS;#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \ init_cumulative_args (&CUM, 0)#define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) \ init_cumulative_args (&CUM, 1)/* 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) \ function_arg_advance (&CUM, MODE, TYPE)#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ function_arg (&CUM, MODE, TYPE, FALSE)#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \ function_arg (&CUM, MODE, TYPE, TRUE)/* Arguments are never passed partly in memory and partly in registers. */#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) (0)/* Specify function argument alignment. */#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \ ((TYPE) != 0 \ ? (TYPE_ALIGN (TYPE) <= PARM_BOUNDARY \ ? PARM_BOUNDARY \ : TYPE_ALIGN (TYPE)) \ : (GET_MODE_ALIGNMENT (MODE) <= PARM_BOUNDARY \ ? PARM_BOUNDARY \ : GET_MODE_ALIGNMENT (MODE)))/* Nonzero if we do not know how to pass TYPE solely in registers. We cannot do so in the following cases: - if the type has variable size - if the type is marked as addressable (it is required to be constructed into the stack) This differs from the default in that it does not check if the padding and mode of the type are such that a copy into a register would put it into the wrong part of the register. */#define MUST_PASS_IN_STACK(MODE, TYPE) \ ((TYPE) != 0 \ && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ || TREE_ADDRESSABLE (TYPE)))/* Profiling Xtensa code is typically done with the built-in profiling feature of Tensilica's instruction set simulator, which does not require any compiler support. Profiling code on a real (i.e., non-simulated) Xtensa processor is currently only supported by GNU/Linux with glibc. The glibc version of _mcount doesn't require counter variables. The _mcount function needs the current PC and the current return address to identify an arc in the call graph. Pass the current return address as the first argument; the current PC is available as a0 in _mcount's register window. Both of these values contain window size information in the two most significant bits; we assume that _mcount will mask off those bits. The call to _mcount uses a window size of 8 to make sure that it doesn't clobber any incoming argument values. */#define NO_PROFILE_COUNTERS#define FUNCTION_PROFILER(FILE, LABELNO) \ do { \ fprintf (FILE, "\t%s\ta10, a0\n", TARGET_DENSITY ? "mov.n" : "mov"); \ if (flag_pic) \ { \ fprintf (FILE, "\tmovi\ta8, _mcount@PLT\n"); \ fprintf (FILE, "\tcallx8\ta8\n"); \ } \ else \ fprintf (FILE, "\tcall8\t_mcount\n"); \ } while (0)/* Stack pointer value doesn't matter at exit. */#define EXIT_IGNORE_STACK 1/* A C statement to output, on the stream FILE, assembler code for a block of data that contains the constant parts of a trampoline. This code should not include a label--the label is taken care of automatically. For Xtensa, the trampoline must perform an entry instruction with a minimal stack frame in order to get some free registers. Once the actual call target is known, the proper stack frame size is extracted from the entry instruction at the target and the current frame is adjusted to match. The trampoline then transfers control to the instruction following the entry at the target. Note: this assumes that the target begins with an entry instruction. *//* minimum frame = reg save area (4 words) plus static chain (1 word) and the total number of words must be a multiple of 128 bits */#define MIN_FRAME_SIZE (8 * UNITS_PER_WORD)#define TRAMPOLINE_TEMPLATE(STREAM) \ do { \ fprintf (STREAM, "\t.begin no-generics\n"); \ fprintf (STREAM, "\tentry\tsp, %d\n", MIN_FRAME_SIZE); \ \ /* GCC isn't prepared to deal with data at the beginning of the \ trampoline, and the Xtensa l32r instruction requires that the \ constant pool be located before the code. We put the constant \ pool in the middle of the trampoline and jump around it. */ \ \ fprintf (STREAM, "\tj\t.Lskipconsts\n"); \ fprintf (STREAM, "\t.align\t4\n"); \ fprintf (STREAM, ".Lfnaddr:%s0\n", integer_asm_op (4, TRUE)); \ fprintf (STREAM, ".Lchainval:%s0\n", integer_asm_op (4, TRUE)); \ fprintf (STREAM, ".Lskipconsts:\n"); \ \ /* store the static chain */ \ fprintf (STREAM, "\tl32r\ta8, .Lchainval\n"); \ fprintf (STREAM, "\ts32i\ta8, sp, %d\n", \ MIN_FRAME_SIZE - (5 * UNITS_PER_WORD)); \ \ /* set the proper stack pointer value */ \ fprintf (STREAM, "\tl32r\ta8, .Lfnaddr\n"); \ fprintf (STREAM, "\tl32i\ta9, a8, 0\n"); \ fprintf (STREAM, "\textui\ta9, a9, %d, 12\n", \ TARGET_BIG_ENDIAN ? 8 : 12); \ fprintf (STREAM, "\tslli\ta9, a9, 3\n"); \ fprintf (STREAM, "\taddi\ta9, a9, %d\n", -MIN_FRAME_SIZE); \ fprintf (STREAM, "\tsub\ta9, sp, a9\n"); \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -