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

📄 pa.h

📁 linux下编程用 编译软件
💻 H
📖 第 1 页 / 共 5 页
字号:
   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.   On the HP-PA, the WORDS field holds the number of words   of arguments scanned so far (including the invisible argument,   if any, which holds the structure-value-address).  Thus, 4 or   more means all following args should go on the stack.      The INCOMING field tracks whether this is an "incoming" or   "outgoing" argument.      The INDIRECT field indicates whether this is is an indirect   call or not.      The NARGS_PROTOTYPE field indicates that an argument does not   have a prototype when it less than or equal to 0.  */struct hppa_args {int words, nargs_prototype, incoming, indirect; };#define CUMULATIVE_ARGS struct hppa_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.  */#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \  (CUM).words = 0, 							\  (CUM).incoming = 0,							\  (CUM).indirect = (FNTYPE) && !(FNDECL),				\  (CUM).nargs_prototype = (FNTYPE && TYPE_ARG_TYPES (FNTYPE)		\			   ? (list_length (TYPE_ARG_TYPES (FNTYPE)) - 1	\			      + (TYPE_MODE (TREE_TYPE (FNTYPE)) == BLKmode \				 || pa_return_in_memory (TREE_TYPE (FNTYPE), 0))) \			   : 0)/* Similar, but when scanning the definition of a procedure.  We always   set NARGS_PROTOTYPE large so we never return a PARALLEL.  */#define INIT_CUMULATIVE_INCOMING_ARGS(CUM,FNTYPE,IGNORE) \  (CUM).words = 0,				\  (CUM).incoming = 1,				\  (CUM).indirect = 0,				\  (CUM).nargs_prototype = 1000/* Figure out the size in words of the function argument.  The size   returned by this macro should always be greater than zero because   we pass variable and zero sized objects by reference.  */#define FUNCTION_ARG_SIZE(MODE, TYPE)	\  ((((MODE) != BLKmode \     ? (HOST_WIDE_INT) GET_MODE_SIZE (MODE) \     : int_size_in_bytes (TYPE)) + UNITS_PER_WORD - 1) / 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)			\{ (CUM).nargs_prototype--;						\  (CUM).words += FUNCTION_ARG_SIZE(MODE, TYPE)	 			\    + (((CUM).words & 01) && (TYPE) != 0				\	&& FUNCTION_ARG_SIZE(MODE, TYPE) > 1);				\}/* Determine where to put an argument 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 HP-PA the first four words of args are normally in registers   and the rest are pushed.  But any arg that won't entirely fit in regs   is pushed.   Arguments passed in registers are either 1 or 2 words long.   The caller must make a distinction between calls to explicitly named   functions and calls through pointers to functions -- the conventions   are different!  Calls through pointers to functions only use general   registers for the first four argument words.   Of course all this is different for the portable runtime model   HP wants everyone to use for ELF.  Ugh.  Here's a quick description   of how it's supposed to work.   1) callee side remains unchanged.  It expects integer args to be   in the integer registers, float args in the float registers and   unnamed args in integer registers.   2) caller side now depends on if the function being called has   a prototype in scope (rather than if it's being called indirectly).      2a) If there is a prototype in scope, then arguments are passed      according to their type (ints in integer registers, floats in float      registers, unnamed args in integer registers.      2b) If there is no prototype in scope, then floating point arguments      are passed in both integer and float registers.  egad.  FYI: The portable parameter passing conventions are almost exactly like  the standard parameter passing conventions on the RS6000.  That's why  you'll see lots of similar code in rs6000.h.  *//* If defined, a C expression which determines whether, and in which   direction, to pad out an argument with extra space.  */#define FUNCTION_ARG_PADDING(MODE, TYPE) function_arg_padding ((MODE), (TYPE))/* Specify padding for the last element of a block move between registers   and memory.   The 64-bit runtime specifies that objects need to be left justified   (i.e., the normal justification for a big endian target).  The 32-bit   runtime specifies right justification for objects smaller than 64 bits.   We use a DImode register in the parallel for 5 to 7 byte structures   so that there is only one element.  This allows the object to be   correctly padded.  */#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \  function_arg_padding ((MODE), (TYPE))/* Do not expect to understand this without reading it several times.  I'm   tempted to try and simply it, but I worry about breaking something.  */#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \  function_arg (&CUM, MODE, TYPE, NAMED)/* 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.  *//* Arguments larger than one word are double word aligned.  */#define FUNCTION_ARG_BOUNDARY(MODE, TYPE)				\  (((TYPE)								\    ? (integer_zerop (TYPE_SIZE (TYPE))					\       || !TREE_CONSTANT (TYPE_SIZE (TYPE))				\       || int_size_in_bytes (TYPE) <= UNITS_PER_WORD)			\    : GET_MODE_SIZE(MODE) <= UNITS_PER_WORD)				\   ? PARM_BOUNDARY : MAX_PARM_BOUNDARY)extern GTY(()) rtx hppa_compare_op0;extern GTY(()) rtx hppa_compare_op1;extern enum cmp_type hppa_branch_type;/* On HPPA, we emit profiling code as rtl via PROFILE_HOOK rather than   as assembly via FUNCTION_PROFILER.  Just output a local label.   We can't use the function label because the GAS SOM target can't   handle the difference of a global symbol and a local symbol.  */#ifndef FUNC_BEGIN_PROLOG_LABEL#define FUNC_BEGIN_PROLOG_LABEL        "LFBP"#endif#define FUNCTION_PROFILER(FILE, LABEL) \  (*targetm.asm_out.internal_label) (FILE, FUNC_BEGIN_PROLOG_LABEL, LABEL)#define PROFILE_HOOK(label_no) hppa_profile_hook (label_no)void hppa_profile_hook (int label_no);/* The profile counter if emitted must come before the prologue.  */#define PROFILE_BEFORE_PROLOGUE 1/* We never want final.c to emit profile counters.  When profile   counters are required, we have to defer emitting them to the end   of the current file.  */#define NO_PROFILE_COUNTERS 1/* 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.  */extern int may_call_alloca;#define EXIT_IGNORE_STACK	\ (get_frame_size () != 0	\  || current_function_calls_alloca || current_function_outgoing_args_size)/* Output assembler code for a block containing the constant parts   of a trampoline, leaving space for the variable parts.\   The trampoline sets the static chain pointer to STATIC_CHAIN_REGNUM   and then branches to the specified routine.   This code template is copied from text segment to stack location   and then patched with INITIALIZE_TRAMPOLINE to contain   valid values, and then entered as a subroutine.   It is best to keep this as small as possible to avoid having to   flush multiple lines in the cache.  */#define TRAMPOLINE_TEMPLATE(FILE) 					\  {									\    if (!TARGET_64BIT)							\      {									\	fputs ("\tldw	36(%r22),%r21\n", FILE);			\	fputs ("\tbb,>=,n	%r21,30,.+16\n", FILE);			\	if (ASSEMBLER_DIALECT == 0)					\	  fputs ("\tdepi	0,31,2,%r21\n", FILE);			\	else								\	  fputs ("\tdepwi	0,31,2,%r21\n", FILE);			\	fputs ("\tldw	4(%r21),%r19\n", FILE);				\	fputs ("\tldw	0(%r21),%r21\n", FILE);				\	if (TARGET_PA_20)						\	  {								\	    fputs ("\tbve	(%r21)\n", FILE);			\	    fputs ("\tldw	40(%r22),%r29\n", FILE);		\	    fputs ("\t.word	0\n", FILE);				\	    fputs ("\t.word	0\n", FILE);				\	  }								\	else								\	  {								\	    fputs ("\tldsid	(%r21),%r1\n", FILE);			\	    fputs ("\tmtsp	%r1,%sr0\n", FILE);			\	    fputs ("\tbe	0(%sr0,%r21)\n", FILE);			\	    fputs ("\tldw	40(%r22),%r29\n", FILE);		\	  }								\	fputs ("\t.word	0\n", FILE);					\	fputs ("\t.word	0\n", FILE);					\	fputs ("\t.word	0\n", FILE);					\	fputs ("\t.word	0\n", FILE);					\      }									\    else								\      {									\	fputs ("\t.dword 0\n", FILE);					\	fputs ("\t.dword 0\n", FILE);					\	fputs ("\t.dword 0\n", FILE);					\	fputs ("\t.dword 0\n", FILE);					\	fputs ("\tmfia	%r31\n", FILE);					\	fputs ("\tldd	24(%r31),%r1\n", FILE);				\	fputs ("\tldd	24(%r1),%r27\n", FILE);				\	fputs ("\tldd	16(%r1),%r1\n", FILE);				\	fputs ("\tbve	(%r1)\n", FILE);				\	fputs ("\tldd	32(%r31),%r31\n", FILE);			\	fputs ("\t.dword 0  ; fptr\n", FILE);				\	fputs ("\t.dword 0  ; static link\n", FILE);			\      }									\  }/* Length in units of the trampoline for entering a nested function.  */#define TRAMPOLINE_SIZE (TARGET_64BIT ? 72 : 52)/* Length in units of the trampoline instruction code.  */#define TRAMPOLINE_CODE_SIZE (TARGET_64BIT ? 24 : (TARGET_PA_20 ? 32 : 40))/* Minimum length of a cache line.  A length of 16 will work on all   PA-RISC processors.  All PA 1.1 processors have a cache line of   32 bytes.  Most but not all PA 2.0 processors have a cache line   of 64 bytes.  As cache flushes are expensive and we don't support   PA 1.0, we use a minimum length of 32.  */#define MIN_CACHELINE_SIZE 32/* 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.   Move the function address to the trampoline template at offset 36.   Move the static chain value to trampoline template at offset 40.   Move the trampoline address to trampoline template at offset 44.   Move r19 to trampoline template at offset 48.  The latter two   words create a plabel for the indirect call to the trampoline.   A similar sequence is used for the 64-bit port but the plabel is   at the beginning of the trampoline.   Finally, the cache entries for the trampoline code are flushed.   This is necessary to ensure that the trampoline instruction sequence   is written to memory prior to any attempts at prefetching the code   sequence.  */#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) 			\{									\  rtx start_addr = gen_reg_rtx (Pmode);					\  rtx end_addr = gen_reg_rtx (Pmode);					\  rtx line_length = gen_reg_rtx (Pmode);				\  rtx tmp;								\									\  if (!TARGET_64BIT)							\    {									\      tmp = memory_address (Pmode, plus_constant ((TRAMP), 36));	\      emit_move_insn (gen_rtx_MEM (Pmode, tmp), (FNADDR));		\      tmp = memory_address (Pmode, plus_constant ((TRAMP), 40));	\      emit_move_insn (gen_rtx_MEM (Pmode, tmp), (CXT));			\									\      /* Create a fat pointer for the trampoline.  */			\      tmp = memory_address (Pmode, plus_constant ((TRAMP), 44));	\      emit_move_insn (gen_rtx_MEM (Pmode, tmp), (TRAMP));		\      tmp = memory_address (Pmode, plus_constant ((TRAMP), 48));	\      emit_move_insn (gen_rtx_MEM (Pmode, tmp),				\		      gen_rtx_REG (Pmode, 19));				\									\      /* fdc and fic only use registers for the address to flush,	\	 they do not accept integer displacements.  We align the	\	 start and end addresses to the beginning of their respective	\	 cache lines to minimize the number of lines flushed.  */	\      tmp = force_reg (Pmode, (TRAMP));					\      emit_insn (gen_andsi3 (start_addr, tmp,				\			     GEN_INT (-MIN_CACHELINE_SIZE)));		\      tmp = force_reg (Pmode,						\		       plus_constant (tmp, TRAMPOLINE_CODE_SIZE - 1));	\      emit_insn (gen_andsi3 (end_addr, tmp,				\			     GEN_INT (-MIN_CACHELINE_SIZE)));		\      emit_move_insn (line_length, GEN_INT (MIN_CACHELINE_SIZE));	\      emit_insn (gen_dcacheflush (start_addr, end_addr, line_length));	\      emit_insn (gen_icacheflush (start_addr, end_addr, line_length,	\				  gen_reg_rtx (Pmode),			\				  gen_reg_rtx (Pmode)));		\    }									\  else									\    {									\      tmp = memory_address (Pmode, plus_constant ((TRAMP), 56));	\      emit_move_insn (gen_rtx_MEM (Pmode, tmp), (FNADDR));		\      tmp = memory_address (Pmode, plus_constant ((TRAMP), 64));	\      emit_move_insn (gen_rtx_MEM (Pmode, tmp), (CXT));			\									\      /* Create a fat pointer for the trampoline.  */			\      tmp = memory_address (Pmode, plus_constant ((TRAMP), 16));	\      emit_move_insn (gen_rtx_MEM (Pmode, tmp),				\

⌨️ 快捷键说明

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