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

📄 i386.h

📁 gcc编译工具没有什么特别
💻 H
📖 第 1 页 / 共 5 页
字号:
	has to be stored.	The basic block number is given by BLOCKNO.	The address of the block is given by the label created with 	    ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0);	by FUNCTION_BLOCK_PROFILER.	Of course, since you are writing the definition of	`ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you	can take a short cut in the definition of this macro and use the	name that you know will result.	If described in a virtual assembler language the code to be	output looks like:		move BLOCKNO -> (__bb)		move LPBX0 -> (__bb+4)		call __bb_trace_func	Note that function `__bb_trace_func' must not change the	machine state, especially the flag register. To grant	this, you must output code to save and restore registers	either in this macro or in the macros MACHINE_STATE_SAVE	and MACHINE_STATE_RESTORE. The last two macros will be	used in the function `__bb_trace_func', so you must make	sure that the function prologue does not change any 	register prior to saving it with MACHINE_STATE_SAVE.   else if profile_block_flag != 0	Output code to increment the counter directly.	Basic blocks are numbered separately from zero within each	compiled object module. The count associated with block number	BLOCKNO is at index BLOCKNO in an array of words; the name of 	this array is a local symbol made with this statement:	    ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 2);	Of course, since you are writing the definition of	`ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you	can take a short cut in the definition of this macro and use the	name that you know will result. 	If described in a virtual assembler language the code to be	output looks like:		inc (LPBX2+4*BLOCKNO)*/#define BLOCK_PROFILER(FILE, BLOCKNO)					\do									\  {									\    rtx xops[8], cnt_rtx;						\    char counts[80];							\    char *block_table = counts;						\									\    switch (profile_block_flag) 					\      {									\									\      case 2:								\									\        ASM_GENERATE_INTERNAL_LABEL (block_table, "LPBX", 0);		\									\	xops[1] = gen_rtx_SYMBOL_REF (VOIDmode, block_table);		\        xops[2] = GEN_INT ((BLOCKNO));					\        xops[3] = gen_rtx_MEM (Pmode, gen_rtx_SYMBOL_REF (VOIDmode, "__bb_trace_func")); \        xops[4] = gen_rtx_SYMBOL_REF (VOIDmode, "__bb");		\	xops[5] = plus_constant (xops[4], 4);				\	xops[0] = gen_rtx_MEM (SImode, xops[4]);			\	xops[6] = gen_rtx_MEM (SImode, xops[5]);			\									\	CONSTANT_POOL_ADDRESS_P (xops[1]) = TRUE;			\									\	fprintf(FILE, "\tpushf\n");					\        output_asm_insn (AS2(mov%L0,%2,%0), xops);			\	if (flag_pic)							\	  {								\            xops[7] = gen_rtx_REG (Pmode, 0);	/* eax */		\            output_asm_insn (AS1(push%L7,%7), xops);			\            output_asm_insn (AS2(lea%L7,%a1,%7), xops);			\            output_asm_insn (AS2(mov%L6,%7,%6), xops);			\            output_asm_insn (AS1(pop%L7,%7), xops);			\	  }								\        else								\          output_asm_insn (AS2(mov%L6,%1,%6), xops);			\        output_asm_insn (AS1(call,%P3), xops);				\	fprintf(FILE, "\tpopf\n");					\									\        break;								\									\      default:								\									\        ASM_GENERATE_INTERNAL_LABEL (counts, "LPBX", 2);		\        cnt_rtx = gen_rtx_SYMBOL_REF (VOIDmode, counts);		\        SYMBOL_REF_FLAG (cnt_rtx) = TRUE;				\									\        if (BLOCKNO)							\          cnt_rtx = plus_constant (cnt_rtx, (BLOCKNO)*4);		\									\        if (flag_pic)							\          cnt_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, cnt_rtx);	\									\        xops[0] = gen_rtx_MEM (SImode, cnt_rtx);			\        output_asm_insn (AS1(inc%L0,%0), xops);				\									\        break;								\									\    }									\  }									\while (0)/* The following macro shall output assembler code to FILE   to indicate a return from function during basic-block profiling.   If profiling_block_flag == 2:	Output assembler code to call function `__bb_trace_ret'.	Note that function `__bb_trace_ret' must not change the	machine state, especially the flag register. To grant	this, you must output code to save and restore registers	either in this macro or in the macros MACHINE_STATE_SAVE_RET	and MACHINE_STATE_RESTORE_RET. The last two macros will be	used in the function `__bb_trace_ret', so you must make	sure that the function prologue does not change any 	register prior to saving it with MACHINE_STATE_SAVE_RET.   else if profiling_block_flag != 0:	The macro will not be used, so it need not distinguish	these cases.*/#define FUNCTION_BLOCK_PROFILER_EXIT(FILE) \do									\  {									\    rtx xops[1];							\									\    xops[0] = gen_rtx_MEM (Pmode, gen_rtx_SYMBOL_REF (VOIDmode, "__bb_trace_ret")); \									\    output_asm_insn (AS1(call,%P0), xops);				\									\  }									\while (0)/* The function `__bb_trace_func' is called in every basic block   and is not allowed to change the machine state. Saving (restoring)   the state can either be done in the BLOCK_PROFILER macro,   before calling function (rsp. after returning from function)   `__bb_trace_func', or it can be done inside the function by   defining the macros:	MACHINE_STATE_SAVE(ID)	MACHINE_STATE_RESTORE(ID)   In the latter case care must be taken, that the prologue code   of function `__bb_trace_func' does not already change the   state prior to saving it with MACHINE_STATE_SAVE.   The parameter `ID' is a string identifying a unique macro use.   On the i386 the initialization code at the begin of   function `__bb_trace_func' contains a `sub' instruction   therefore we handle save and restore of the flag register    in the BLOCK_PROFILER macro. */#define MACHINE_STATE_SAVE(ID) \  asm ("	pushl %eax"); \  asm ("	pushl %ecx"); \  asm ("	pushl %edx"); \  asm ("	pushl %esi");#define MACHINE_STATE_RESTORE(ID) \  asm ("	popl %esi"); \  asm ("	popl %edx"); \  asm ("	popl %ecx"); \  asm ("	popl %eax");/* 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.  *//* Note on the 386 it might be more efficient not to define this since    we have to restore it ourselves from the frame pointer, in order to   use pop */#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.   The function epilogue should not depend on the current stack pointer!   It should use the frame pointer only.  This is mandatory because   of alloca; we also take advantage of it to omit stack adjustments   before returning.   If the last non-note insn in the function is a BARRIER, then there   is no need to emit a function prologue, because control does not fall   off the end.  This happens if the function ends in an "exit" call, or   if a `return' insn is emitted directly into the function. */#if 0#define FUNCTION_BEGIN_EPILOGUE(FILE)		\do {						\  rtx last = get_last_insn ();			\  if (last && GET_CODE (last) == NOTE)		\    last = prev_nonnote_insn (last);		\/*  if (! last || GET_CODE (last) != BARRIER)	\    function_epilogue (FILE, SIZE);*/		\} while (0)#endif#define FUNCTION_EPILOGUE(FILE, SIZE)     \  function_epilogue (FILE, SIZE)/* Output assembler code for a block containing the constant parts   of a trampoline, leaving space for the variable parts.  *//* On the 386, the trampoline contains two instructions:     mov #STATIC,ecx     jmp FUNCTION   The trampoline is generated entirely at runtime.  The operand of JMP   is the address of FUNCTION relative to the instruction following the   JMP (which is 5 bytes long).  *//* Length in units of the trampoline for entering a nested function.  */#define TRAMPOLINE_SIZE 10/* 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)			\{									\  /* Compute offset from the end of the jmp to the target function.  */	\  rtx disp = expand_binop (SImode, sub_optab, FNADDR,			\			   plus_constant (TRAMP, 10),			\			   NULL_RTX, 1, OPTAB_DIRECT);			\  emit_move_insn (gen_rtx_MEM (QImode, TRAMP), GEN_INT (0xb9));		\  emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 1)), CXT); \  emit_move_insn (gen_rtx_MEM (QImode, plus_constant (TRAMP, 5)), GEN_INT (0xe9));\  emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 6)), disp); \}/* 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 i386.  First, the   frame pointer register can often be eliminated in favor of the stack   pointer register.  Secondly, the argument pointer register can always be   eliminated; it is replaced with either the stack or frame pointer. */#define ELIMINABLE_REGS				\{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM},	\ { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM},   \ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}/* Given FROM and TO register numbers, say whether this elimination is allowed.   Frame pointer elimination is automatically handled.   For the i386, if frame pointer elimination is being done, we would like to   convert ap into sp, not fp.   All other eliminations are valid.  */#define CAN_ELIMINATE(FROM, TO)					\ ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM	\  ? ! frame_pointer_needed					\  : 1)/* Define the offset between two registers, one to be eliminated, and the other   its replacement, at the start of a routine.  */#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)			\{									\  if ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM)	\    (OFFSET) = 8;	/* Skip saved PC and previous frame pointer */	\  else									\    {									\      int nregs;							\      int offset;							\      int preferred_alignment = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT; \      HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (),	\						     &nregs);		\									\      (OFFSET) = (tsize + nregs * UNITS_PER_WORD);			\									\      offset = 4;							\      if (frame_pointer_needed)						\	offset += UNITS_PER_WORD;					\									\      if ((FROM) == ARG_POINTER_REGNUM)					\	(OFFSET) += offset;						\      else								\	(OFFSET) -= ((offset + preferred_alignment - 1)			\		     & -preferred_alignment) - offset;			\    }									\}/* Addressing modes, and classification of registers for them.  *//* #define HAVE_POST_INCREMENT 0 *//* #define HAVE_POST_DECREMENT 0 *//* #define HAVE_PRE_DECREMENT 0 *//* #define HAVE_PRE_INCREMENT 0 *//* 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) < STACK_POINTER_REGNUM \   || (unsigned) reg_renumber[REGNO] < STACK_POINTER_REGNUM)#define REGNO_OK_FOR_BASE_P(REGNO) \  ((REGNO) <= STACK_POINTER_REGNUM \   || (REGNO) == ARG_POINTER_REGNUM \   || (unsigned) reg_renumber[REGNO] <= STACK_POINTER_REGNUM)#define REGN

⌨️ 快捷键说明

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