⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xtensa.h

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 H
📖 第 1 页 / 共 4 页
字号:
   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/* Define how to find the value returned by a library function   assuming the value has mode MODE.  Because we have defined   TARGET_PROMOTE_FUNCTION_RETURN that returns true, 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, N_NAMED_ARGS) \  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)/* 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)))/* 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	1#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);		\									\    /* save the return address */					\    fprintf (STREAM, "\tmov\ta10, a0\n");				\									\    /* Use a CALL0 instruction to skip past the constants and in the	\       process get the PC into A0.  This allows PC-relative access to	\       the constants without relying on L32R, which may not always be	\       available.  */							\									\    fprintf (STREAM, "\tcall0\t.Lskipconsts\n");			\    fprintf (STREAM, "\t.align\t4\n");					\    fprintf (STREAM, ".Lchainval:%s0\n", integer_asm_op (4, TRUE));	\    fprintf (STREAM, ".Lfnaddr:%s0\n", integer_asm_op (4, TRUE));	\    fprintf (STREAM, ".Lskipconsts:\n");				\									\    /* store the static chain */					\    fprintf (STREAM, "\taddi\ta0, a0, 3\n");				\    fprintf (STREAM, "\tl32i\ta8, a0, 0\n");				\    fprintf (STREAM, "\ts32i\ta8, sp, %d\n", MIN_FRAME_SIZE - 20);	\									\    /* set the proper stack pointer value */				\    fprintf (STREAM, "\tl32i\ta8, a0, 4\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");				\    fprintf (STREAM, "\tmovsp\tsp, a9\n");				\									\    /* restore the return address */					\    fprintf (STREAM, "\tmov\ta0, a10\n");				\									\    /* jump to the instruction following the entry */			\    fprintf (STREAM, "\taddi\ta8, a8, 3\n");				\    fprintf (STREAM, "\tjx\ta8\n");					\    fprintf (STREAM, "\t.end no-generics\n");				\  } while (0)/* Size in bytes of the trampoline, as an integer.  */#define TRAMPOLINE_SIZE 59/* Alignment required for trampolines, in bits.  */#define TRAMPOLINE_ALIGNMENT (32)/* A C statement to initialize the variable parts of a trampoline.  */#define INITIALIZE_TRAMPOLINE(ADDR, FUNC, CHAIN)			\  do {									\    rtx addr = ADDR;							\    emit_move_insn (gen_rtx_MEM (SImode, plus_constant (addr, 12)), CHAIN); \    emit_move_insn (gen_rtx_MEM (SImode, plus_constant (addr, 16)), FUNC); \    emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_sync_caches"), \		       0, VOIDmode, 1, addr, Pmode);			\  } while (0)/* Implement `va_start' for varargs and stdarg.  */#define EXPAND_BUILTIN_VA_START(valist, nextarg) \  xtensa_va_start (valist, nextarg)/* If defined, a C expression that produces the machine-specific code   to setup the stack so that arbitrary frames can be accessed.   On Xtensa, a stack back-trace must always begin from the stack pointer,   so that the register overflow save area can be located.  However, the   stack-walking code in GCC always begins from the hard_frame_pointer   register, not the stack pointer.  The frame pointer is usually equal   to the stack pointer, but the __builtin_return_address and   __builtin_frame_address functions will not work if count > 0 and   they are called from a routine that uses alloca.  These functions   are not guaranteed to work at all if count > 0 so maybe that is OK.   A nicer solution would be to allow the architecture-specific files to   specify whether to start from the stack pointer or frame pointer.  That   would also allow us to skip the machine->accesses_prev_frame stuff that   we currently need to ensure that there is a frame pointer when these   builtin functions are used.  */#define SETUP_FRAME_ADDRESSES  xtensa_setup_frame_addresses/* A C expression whose value is RTL representing the address in a   stack frame where the pointer to the caller's frame is stored.   Assume that FRAMEADDR is an RTL expression for the address of the   stack frame itself.   For Xtensa, there is no easy way to get the frame pointer if it is   not equivalent to the stack pointer.  Moreover, the result of this   macro is used for continuing to walk back up the stack, so it must   return the stack pointer address.  Thus, there is some inconsistency   here in that __builtin_frame_address will return the frame pointer   when count == 0 and the stack pointer when count > 0.  */#define DYNAMIC_CHAIN_ADDRESS(frame)					\  gen_rtx_PLUS (Pmode, frame, GEN_INT (-3 * UNITS_PER_WORD))/* Define this if the return address of a particular stack frame is   accessed from the frame pointer of the previous stack frame.  */#define RETURN_ADDR_IN_PREVIOUS_FRAME/* A C expression whose value is RTL representing the value of the   return address for the frame COUNT steps up from the current   frame, after the prologue.  */#define RETURN_ADDR_RTX  xtensa_return_addr/* Addressing modes, and classification of registers for them.  *//* C expressions which are nonzero if register number NUM is suitable   for use as a base or index register in operand addresses.  It may   be either a suitable hard register or a pseudo register that has   been allocated such a hard register. The difference between an   index register and a base register is that the index register may   be scaled.  */#define REGNO_OK_FOR_BASE_P(NUM) \  (GP_REG_P (NUM) || GP_REG_P ((unsigned) reg_renumber[NUM]))#define REGNO_OK_FOR_INDEX_P(NUM) 0/* C expressions that are nonzero if X (assumed to be a `reg' RTX) is   valid for use as a base or index register.  For hard registers, it   should always accept those which the hardware permits and reject   the others.  Whether the macro accepts or rejects pseudo registers   must be controlled by `REG_OK_STRICT'.  This usually requires two   variant definitions, of which `REG_OK_STRICT' controls the one   actually used. The difference between an index register and a base   register is that the index register may be scaled.  */#ifdef REG_OK_STRICT#define REG_OK_FOR_INDEX_P(X) 0#define REG_OK_FOR_BASE_P(X) \  REGNO_OK_FOR_BASE_P (REGNO (X))#else /* !REG_OK_STRICT */#define REG_OK_FOR_INDEX_P(X) 0#define REG_OK_FOR_BASE_P(X) \  ((REGNO (X) >= FIRST_PSEUDO_REGISTER) || (GP_REG_P (REGNO (X))))#endif /* !REG_OK_STRICT *//* Maximum number of registers that can appear in a valid memory address.  */#define MAX_REGS_PER_ADDRESS 1/* Identify valid Xtensa addresses.  */#define GO_IF_LEGITIMATE_ADDRESS(MODE, ADDR, LABEL)			\  do {									\    rtx xinsn = (ADDR);							\									\    /* allow constant pool addresses */					\    if ((MODE) != BLKmode && GET_MODE_SIZE (MODE) >= UNITS_PER_WORD	\	&& !TARGET_CONST16 && constantpool_address_p (xinsn))		\      goto LABEL;							\									\    while (GET_CODE (xinsn) == SUBREG)					\      xinsn = SUBREG_REG (xinsn);					\									\    /* allow base registers */						\    if (GET_CODE (xinsn) == REG && REG_OK_FOR_BASE_P (xinsn))		\

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -