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

📄 clipper.h

📁 GCC编译器源代码
💻 H
📖 第 1 页 / 共 3 页
字号:
/* Offset of first parameter from the argument pointer register value.   size of PC + FP  */#define FIRST_PARM_OFFSET(FNDECL) 8/* Value is the number of bytes 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. */#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0/* 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)  \  gen_rtx (REG, TYPE_MODE (VALTYPE), ((TYPE_MODE (VALTYPE) == SFmode ||\				       TYPE_MODE (VALTYPE) == DFmode) ? \				        16 : 0))/* Define how to find the value returned by a library function   assuming the value has mode MODE.  */#define LIBCALL_VALUE(MODE)  \  gen_rtx (REG, (MODE), ((MODE) == SFmode || (MODE) == DFmode ? 16 : 0))/* 1 if N is a possible register number for a function value   as seen by the caller.  */#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N) == 16)/* 1 if N is a possible register number for function argument passing.  */#define FUNCTION_ARG_REGNO_P(N) \  ((N) == 0 || (N) == 1 || (N) == 16 || (N) == 17)/* Define this if PCC uses the nonreentrant convention for returning   structure and union values. Old Green Hills C-Clipper returns static   structs but the newer Apogee compiler passes structs as hidden arg 0.   Structs etc are always passed in memory *//* #define PCC_STATIC_STRUCT_RETURN *//* Define a data type for recording info about an argument list   during the scan of that argument list.  This data type should   hold all necessary information about the function itself   and about the args processed so far, enough to enable macros   such as FUNCTION_ARG to determine where the next arg should go.   Clipper uses 2 register 'slots' that pass arguments in r0/r1 or f0/f1.   An argument that must be passed in memory (struct... ) leaves that slot   free.   We pass 'long long' only in registers when both slots are free.   Returned structs must be allocated by the caller, the address is passed   in r0.   struct ss {..}   fun (i,j,k)		i in r0, j in r1, k on stack   fun (s,j,k)		s on stack, j in r1, k on stack   fun (i,s,k)		i in r0, s on stack, k on stack   s1 = fun (i,s,k)	&s1 in r0, i in r1, s on stack, k on stack   We must keep enough information for varargs/stdargs.   _clipper_cum_args is a struct of 2 integers, with	num =  slots used	size = size of all stack args = offset to next arg without alignment   If we use stdarg.h, size points to the first unnamed arg,   see va-clipper.h */struct _clipper_cum_args { int num; int size; };#define CUMULATIVE_ARGS struct _clipper_cum_args/* 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.   clipper passes the address of a struct in r0, set num = 1 in this case */#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \  ((CUM).num = ((FNTYPE) != 0 && aggregate_value_p (TREE_TYPE (FNTYPE))), \   (CUM).size = 0)/* internal helper : size of an argument */#define CLIPPER_ARG_SIZE(MODE, TYPE)				\(((MODE) != BLKmode							\  ? (GET_MODE_SIZE (MODE) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD 	\  : (int_size_in_bytes (TYPE) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)	\ * UNITS_PER_WORD)/* 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)			      \do									      \{									      \  int reg = 0;								      \									      \  if ((CUM).num < 2							      \      && (GET_MODE_CLASS(MODE)==MODE_INT || GET_MODE_CLASS(MODE)==MODE_FLOAT) \      && (GET_MODE_SIZE (MODE) <= 8)					      \      && ((TYPE) == NULL || !AGGREGATE_TYPE_P(TYPE))			      \      && ((MODE) != DImode || (CUM).num == 0))				      \    {									      \      reg = 1;								      \      if ((MODE) == DImode)						      \	(CUM).num = 1;							      \    }									      \									      \  (CUM).num++;								      \									      \  if (! reg)								      \    {									      \      int align = FUNCTION_ARG_BOUNDARY (MODE, TYPE) / BITS_PER_UNIT;	      \      (CUM).size += align - 1;						      \      (CUM).size &= ~(align - 1);					      \      (CUM).size += CLIPPER_ARG_SIZE (MODE, TYPE);			      \    }									      \} while (0)/* 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).   2 args may go into regs. These must be MODE_INT or MODE_FLOAT but only   if they really fit into ONE register. The exception is a DImode arg   that occupies both register slots. */#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED)				     \  (((CUM).num < 2							     \    && (GET_MODE_CLASS(MODE)==MODE_INT || GET_MODE_CLASS(MODE)==MODE_FLOAT)  \    && (GET_MODE_SIZE (MODE) <= 8)					     \    && ((TYPE) == NULL || !AGGREGATE_TYPE_P(TYPE))			     \    && ((MODE) != DImode || (CUM).num == 0))				     \   ? gen_rtx (REG, (MODE),						     \	      GET_MODE_CLASS(MODE) == MODE_FLOAT ? (CUM).num+16 : (CUM).num) \   : 0)/* If defined, a C expression that gives the alignment boundary, in bits,   of an argument with the specified mode and type.  If it is not defined,   `PARM_BOUNDARY' is used for all arguments.  */#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \  (((TYPE) ? TYPE_ALIGN (TYPE) : GET_MODE_SIZE (MODE)) <= PARM_BOUNDARY \    ? PARM_BOUNDARY : 2 * PARM_BOUNDARY)/* 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.   Clipper never passed args partially in regs/mem. *//* #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED)  0 *//* Generate necessary RTL for __builtin_saveregs().   ARGLIST is the argument list; see expr.c.  */#define EXPAND_BUILTIN_SAVEREGS(ARGLIST) clipper_builtin_saveregs (ARGLIST)/* This macro generates the assembly code for function entry.   FILE is a stdio stream to output the code to.   SIZE is an int: how many units of temporary storage to allocate.   Refer to the array `regs_ever_live' to determine which registers   to save; `regs_ever_live[I]' is nonzero if register number I   is ever used in the function.  This macro is responsible for   knowing which registers should not be saved even if used.  */#define FUNCTION_PROLOGUE(FILE, SIZE) output_function_prologue (FILE,SIZE)/* Output assembler code to FILE to increment profiler label # LABELNO   for profiling a function entry.  */#define FUNCTION_PROFILER(FILE, LABELNO)  /* FIXME *//* Output assembler code to FILE to initialize this source file's   basic block profiling info, if that has not already been done.  */#define FUNCTION_BLOCK_PROFILER(FILE, LABELNO)  /* FIXME *//* Output assembler code to FILE to increment the entry-count for   the BLOCKNO'th basic block in this source file.  */#define BLOCK_PROFILER(FILE, BLOCKNO)	/* FIXME *//* 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.  */#define EXIT_IGNORE_STACK 1/* This macro generates the assembly code for function exit,   on machines that need it.  If FUNCTION_EPILOGUE is not defined   then individual return instructions are generated for each   return statement.  Args are same as for FUNCTION_PROLOGUE.  */#define FUNCTION_EPILOGUE(FILE, SIZE) output_function_epilogue(FILE,SIZE)/* Store in the variable DEPTH the initial difference between the   frame pointer reg contents and the stack pointer reg contents,   as of the start of the function body.  This depends on the layout   of the fixed parts of the stack frame and on how registers are saved. */#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) \  DEPTH = clipper_frame_size (get_frame_size ())/* Output assembler code for a block containing the constant parts   of a trampoline, leaving space for the variable parts.  */#define TRAMPOLINE_TEMPLATE(FILE)					      \{									      \  fputs ("\t.word  0x459F,0x0004\t# call   sp,.+4\n", FILE);		      \  fputs ("\tmovw   (sp),r3\n", FILE);					      \  fputs ("\taddq   $4,sp\n", FILE);					      \  fputs ("\tloadw  20(r3),r2\n", FILE);					      \  fputs ("\tloadw  24(r3),r3\n", FILE);					      \  fputs ("\tb      (r3)\n", FILE);					      \  fputs ("\t.long  0,0\n", FILE);					      \}/* Length in units of the trampoline for entering a nested function.  */#define TRAMPOLINE_SIZE 32/* Alignment required for a trampoline.  128 is used to find the   beginning of a line in the instruction cache and to allow for   instruction cache lines of up to 128 bytes.  */#define TRAMPOLINE_ALIGNMENT 128/* Section in which to place the trampoline.  */#define TRAMPOLINE_SECTION text_section/* Emit RTL insns to initialize the variable parts of a trampoline.   FNADDR is an RTX for the address of the function's pure code.   CXT is an RTX for the static chain value for the function.  */#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT)			\{									\  emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 24)), CXT); \  emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 28)), FNADDR); \}/* Addressing modes, and classification of registers for them.  *//* #define HAVE_POST_DECREMENT *//* #define HAVE_PRE_INCREMENT *//* Macros to check register numbers against specific register classes.  *//* 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_INDEX_P(regno)  \((regno) < 16 || (unsigned)reg_renumber[regno] < 16)#define REGNO_OK_FOR_BASE_P(regno) \((regno) < 16 || (unsigned)reg_renumber[regno] < 16)/* Maximum number of registers that can appear in a valid memory address.  */#define MAX_REGS_PER_ADDRESS 2/* 1 if X is an rtx for a constant that is a valid address.  */#define CONSTANT_ADDRESS_P(X)   \  (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF		\   || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST		\   || GET_CODE (X) == HIGH)/* Nonzero if the constant value X is a legitimate general operand.   It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */#define LEGITIMATE_CONSTANT_P(X) 1/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx   and check its validity for a certain class.   We have two alternate definitions for each of them.   The usual definition accepts all pseudo regs; the other rejects   them unless they have been allocated suitable hard regs.   The symbol REG_OK_STRICT causes the latter definition to be used.   Most source files want to accept pseudo regs in the hope that   they will get allocated to the class that the insn wants them to be in.   Source files for reload pass need to be strict.   After reload, it makes no difference, since pseudo regs have   been eliminated by then.  */  /* clipper doesn't have true indexing */#ifndef REG_OK_STRICT/* Nonzero if X is a hard reg that can be used as an index   or if it is a pseudo reg.  */#define REG_OK_FOR_INDEX_P(X) \  (REGNO (X) < 16 || REGNO(X) >= FIRST_PSEUDO_REGISTER)/* Nonzero if X is a hard reg that can be used as a base reg   or if it is a pseudo reg.  */#define REG_OK_FOR_BASE_P(X) \  (REGNO (X) < 16 || REGNO(X) >= FIRST_PSEUDO_REGISTER)#else/* Nonzero if X is a hard reg that can be used as an index.  */#define REG_OK_FOR_INDEX_P(X) (REGNO(X) < 16)/* Nonzero if X is a hard reg that can be used as a base reg.  */#define REG_OK_FOR_BASE_P(X) (REGNO(X) < 16)#endif/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression   that is a valid memory address for an instruction.   The MODE argument is the machine mode for the MEM expression   that wants to use this address.   The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS,   except for CONSTANT_ADDRESS_P which is actually machine-independent.  *//* Non-zero if X is an address which can be indirected. */#define INDIRECTABLE_CONSTANT_ADDRESS_P(X) 0#define INDIRECTABLE_ADDRESS_P(X)  \  (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X))/* Go to ADDR if X is a valid address not using indexing.   (This much is the easy part.)  */#define GO_IF_NONINDEXED_ADDRESS(X, ADDR)	\{ if (CONSTANT_ADDRESS_P (X)) goto ADDR;	\  if (INDIRECTABLE_ADDRESS_P (X)) goto ADDR; }#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \{ register rtx xfoo = (X);			\  GO_IF_NONINDEXED_ADDRESS (xfoo, ADDR);	\  if (GET_CODE (xfoo) == PLUS)			\    { register rtx xfoo0, xfoo1;		\      xfoo0 = XEXP (xfoo, 0);			\      xfoo1 = XEXP (xfoo, 1);			\    /* handle reg + reg -> [r1](r0) */		\      if (INDIRECTABLE_ADDRESS_P (xfoo0) && INDIRECTABLE_ADDRESS_P (xfoo1)) \	goto ADDR;							\    /* Handle <symbol>(reg) -> xxx(r0) */				\      if (INDIRECTABLE_ADDRESS_P (xfoo0) && CONSTANT_ADDRESS_P (xfoo1))	\	goto ADDR;							\      if (INDIRECTABLE_ADDRESS_P (xfoo1) && CONSTANT_ADDRESS_P (xfoo0))	\	goto ADDR; }}

⌨️ 快捷键说明

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