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

📄 i386.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
     FILE *file;     int size;{  register int regno;  int limit;  rtx xops[4];  int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table				  || current_function_uses_const_pool);  xops[0] = stack_pointer_rtx;  xops[1] = frame_pointer_rtx;  xops[2] = GEN_INT (size);  if (frame_pointer_needed)    {      output_asm_insn ("push%L1 %1", xops);      output_asm_insn (AS2 (mov%L0,%0,%1), xops);    }  if (size)    output_asm_insn (AS2 (sub%L0,%2,%0), xops);  /* Note If use enter it is NOT reversed args.     This one is not reversed from intel!!     I think enter is slower.  Also sdb doesn't like it.     But if you want it the code is:     {     xops[3] = const0_rtx;     output_asm_insn ("enter %2,%3", xops);     }     */  limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);  for (regno = limit - 1; regno >= 0; regno--)    if ((regs_ever_live[regno] && ! call_used_regs[regno])	|| (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))      {	xops[0] = gen_rtx (REG, SImode, regno);	output_asm_insn ("push%L0 %0", xops);      }  if (pic_reg_used)    {      xops[0] = pic_offset_table_rtx;      xops[1] = (rtx) gen_label_rtx ();      output_asm_insn (AS1 (call,%P1), xops);      ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (xops[1]));      output_asm_insn (AS1 (pop%L0,%0), xops);      output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_+[.-%P1],%0", xops);    }}/* Return 1 if it is appropriate to emit `ret' instructions in the   body of a function.  Do this only if the epilogue is simple, needing a   couple of insns.  Prior to reloading, we can't tell how many registers   must be saved, so return 0 then.   If NON_SAVING_SETJMP is defined and true, then it is not possible   for the epilogue to be simple, so return 0.  This is a special case   since NON_SAVING_SETJMP will not cause regs_ever_live to change until   final, but jump_optimize may need to know sooner if a `return' is OK.  */intsimple_386_epilogue (){  int regno;  int nregs = 0;  int reglimit = (frame_pointer_needed		  ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);  int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table				  || current_function_uses_const_pool);#ifdef NON_SAVING_SETJMP  if (NON_SAVING_SETJMP && current_function_calls_setjmp)    return 0;#endif  if (! reload_completed)    return 0;  for (regno = reglimit - 1; regno >= 0; regno--)    if ((regs_ever_live[regno] && ! call_used_regs[regno])	|| (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))      nregs++;  return nregs == 0 || ! frame_pointer_needed;}/* This function generates the assembly code for function exit.   FILE is an stdio stream to output the code to.   SIZE is an int: how many units of temporary storage to deallocate. */voidfunction_epilogue (file, size)     FILE *file;     int size;{  register int regno;  register int nregs, limit;  int offset;  rtx xops[3];  int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table				  || current_function_uses_const_pool);  /* Compute the number of registers to pop */  limit = (frame_pointer_needed	   ? FRAME_POINTER_REGNUM	   : STACK_POINTER_REGNUM);  nregs = 0;  for (regno = limit - 1; regno >= 0; regno--)    if ((regs_ever_live[regno] && ! call_used_regs[regno])	|| (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))      nregs++;  /* sp is often  unreliable so we must go off the frame pointer,   */  /* In reality, we may not care if sp is unreliable, because we can     restore the register relative to the frame pointer.  In theory,     since each move is the same speed as a pop, and we don't need the     leal, this is faster.  For now restore multiple registers the old     way. */  offset = -size - (nregs * UNITS_PER_WORD);  xops[2] = stack_pointer_rtx;  if (nregs > 1 || ! frame_pointer_needed)    {      if (frame_pointer_needed)	{	  xops[0] = adj_offsettable_operand (AT_BP (Pmode), offset);	  output_asm_insn (AS2 (lea%L2,%0,%2), xops);	}      for (regno = 0; regno < limit; regno++)	if ((regs_ever_live[regno] && ! call_used_regs[regno])	    || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))	  {	    xops[0] = gen_rtx (REG, SImode, regno);	    output_asm_insn ("pop%L0 %0", xops);	  }    }  else    for (regno = 0; regno < limit; regno++)      if ((regs_ever_live[regno] && ! call_used_regs[regno])	  || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))	{	  xops[0] = gen_rtx (REG, SImode, regno);	  xops[1] = adj_offsettable_operand (AT_BP (Pmode), offset);	  output_asm_insn (AS2 (mov%L0,%1,%0), xops);	  offset += 4;	}  if (frame_pointer_needed)    {      /* On i486, mov & pop is faster than "leave". */      if (!TARGET_386)	{	  xops[0] = frame_pointer_rtx;	  output_asm_insn (AS2 (mov%L2,%0,%2), xops);	  output_asm_insn ("pop%L0 %0", xops);	}      else	output_asm_insn ("leave", xops);    }  else if (size)    {      /* If there is no frame pointer, we must still release the frame. */      xops[0] = GEN_INT (size);      output_asm_insn (AS2 (add%L2,%0,%2), xops);    }  if (current_function_pops_args && current_function_args_size)    {      xops[1] = GEN_INT (current_function_pops_args);      /* i386 can only pop 32K bytes (maybe 64K?  Is it signed?).  If	 asked to pop more, pop return address, do explicit add, and jump	 indirectly to the caller. */      if (current_function_pops_args >= 32768)	{	  /* ??? Which register to use here? */	  xops[0] = gen_rtx (REG, SImode, 2);	  output_asm_insn ("pop%L0 %0", xops);	  output_asm_insn (AS2 (add%L2,%1,%2), xops);	  output_asm_insn ("jmp %*%0", xops);	}      else	  output_asm_insn ("ret %1", xops);    }  else    output_asm_insn ("ret", xops);}/* 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.   On x86, legitimate addresses are:	base				movl (base),reg	displacement			movl disp,reg	base + displacement		movl disp(base),reg	index + base			movl (base,index),reg	(index + base) + displacement	movl disp(base,index),reg	index*scale			movl (,index,scale),reg	index*scale + disp		movl disp(,index,scale),reg	index*scale + base 		movl (base,index,scale),reg	(index*scale + base) + disp	movl disp(base,index,scale),reg	In each case, scale can be 1, 2, 4, 8.  *//* This is exactly the same as print_operand_addr, except that   it recognizes addresses instead of printing them.   It only recognizes address in canonical form.  LEGITIMIZE_ADDRESS should   convert common non-canonical forms to canonical form so that they will   be recognized.  */#define ADDR_INVALID(msg,insn)						\do {									\  if (TARGET_DEBUG_ADDR)						\    {									\      fprintf (stderr, msg);						\      debug_rtx (insn);							\    }									\} while (0)intlegitimate_address_p (mode, addr, strict)     enum machine_mode mode;     register rtx addr;     int strict;{  rtx base  = NULL_RTX;  rtx indx  = NULL_RTX;  rtx scale = NULL_RTX;  rtx disp  = NULL_RTX;  if (TARGET_DEBUG_ADDR)    {      fprintf (stderr,	       "\n==========\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n",	       GET_MODE_NAME (mode), strict);      debug_rtx (addr);    }  if (GET_CODE (addr) == REG || GET_CODE (addr) == SUBREG)      base = addr;				/* base reg */  else if (GET_CODE (addr) == PLUS)    {      rtx op0 = XEXP (addr, 0);      rtx op1 = XEXP (addr, 1);      enum rtx_code code0 = GET_CODE (op0);      enum rtx_code code1 = GET_CODE (op1);      if (code0 == REG || code0 == SUBREG)	{	  if (code1 == REG || code1 == SUBREG)	    {	      indx = op0;			/* index + base */	      base = op1;	    }	  else	    {	      base = op0;			/* base + displacement */	      disp = op1;	    }	}      else if (code0 == MULT)	{	  indx  = XEXP (op0, 0);	  scale = XEXP (op0, 1);	  if (code1 == REG || code1 == SUBREG)	    base = op1;				/* index*scale + base */	  else	    disp = op1;				/* index*scale + disp */	}      else if (code0 == PLUS && GET_CODE (XEXP (op0, 0)) == MULT)	{	  indx  = XEXP (XEXP (op0, 0), 0);	/* index*scale + base + disp */	  scale = XEXP (XEXP (op0, 0), 1);	  base  = XEXP (op0, 1);	  disp  = op1;	}      else if (code0 == PLUS)	{	  indx = XEXP (op0, 0);			/* index + base + disp */	  base = XEXP (op0, 1);	  disp = op1;	}      else	{	  ADDR_INVALID ("PLUS subcode is not valid.\n", op0);	  return FALSE;	}    }  else if (GET_CODE (addr) == MULT)    {      indx  = XEXP (addr, 0);			/* index*scale */      scale = XEXP (addr, 1);    }  else    disp = addr;				/* displacement */  /* Allow arg pointer and stack pointer as index if there is not scaling */  if (base && indx && !scale      && (indx == arg_pointer_rtx || indx == stack_pointer_rtx))    {      rtx tmp = base;      base = indx;      indx = tmp;    }  /* Validate base register */  /* Don't allow SUBREG's here, it can lead to spill failures when the base     is one word out of a two word structure, which is represented internally     as a DImode int.  */  if (base)    {      if (GET_CODE (base) != REG)	{	  ADDR_INVALID ("Base is not a register.\n", base);	  return FALSE;	}      if ((strict && !REG_OK_FOR_BASE_STRICT_P (base))	  || (!strict && !REG_OK_FOR_BASE_NONSTRICT_P (base)))	{	  ADDR_INVALID ("Base is not valid.\n", base);	  return FALSE;	}    }  /* Validate index register */  /* Don't allow SUBREG's here, it can lead to spill failures when the index     is one word out of a two word structure, which is represented internally     as a DImode int.  */  if (indx)    {      if (GET_CODE (indx) != REG)	{	  ADDR_INVALID ("Index is not a register.\n", indx);	  return FALSE;	}      if ((strict && !REG_OK_FOR_INDEX_STRICT_P (indx))	  || (!strict && !REG_OK_FOR_INDEX_NONSTRICT_P (indx)))	{	  ADDR_INVALID ("Index is not valid.\n", indx);	  return FALSE;	}    }  else if (scale)    abort ();					/* scale w/o index invalid */  /* Validate scale factor */  if (scale)    {      HOST_WIDE_INT value;      if (GET_CODE (scale) != CONST_INT)	{	  ADDR_INVALID ("Scale is not valid.\n", scale);	  return FALSE;	}      value = INTVAL (scale);      if (value != 1 && value != 2 && value != 4 && value != 8)	{	  ADDR_INVALID ("Scale is not a good multiplier.\n", scale);	  return FALSE;	}    }  /* Validate displacement */  if (disp)    {      if (!CONSTANT_ADDRESS_P (disp))	{	  ADDR_INVALID ("Displacement is not valid.\n", disp);	  return FALSE;	}      if (GET_CODE (disp) == CONST_DOUBLE)	{	  ADDR_INVALID ("Displacement is a const_double.\n", disp);	  return FALSE;	}      if (flag_pic && SYMBOLIC_CONST (disp) && base != pic_offset_table_rtx	  && (indx != pic_offset_table_rtx || scale != NULL_RTX))	{	  ADDR_INVALID ("Displacement is an invalid pic reference.\n", disp);	  return FALSE;	}      if (HALF_PIC_P () && HALF_PIC_ADDRESS_P (disp)	  && (base != NULL_RTX || indx != NULL_RTX))	{	  ADDR_INVALID ("Displacement is an invalid half-pic reference.\n", disp);	  return FALSE;	}    }  if (TARGET_DEBUG_ADDR)    fprintf (stderr, "Address is valid.\n");  /* Everything looks valid, return true */  return TRUE;}/* Return a legitimate reference for ORIG (an address) using the   register REG.  If REG is 0, a new pseudo is generated.   There are three types of references that must be handled:   1. Global data references must load the address from the GOT, via      the PIC reg.  An insn is emitted to do this load, and the reg is      returned.   2. Static data references must compute the address as an offset      from the GOT, whose base is in the PIC reg.  An insn is emitted to      compute the address into a reg, and the reg is returned.  Static      data objects have SYMBOL_REF_FLAG set to differentiate them from      global data objects.   3. Constant pool addresses must be handled special.  They are      considered legitimate addresses, but only if not used with regs.      When printed, the output routines know to print the reference with the      PIC reg, even though the PIC reg doesn't appear in the RTL.   GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC   reg also appears in the address (except for constant pool references,   noted above).   "switch" statements also require special handling when generating   PIC code.  See comments by the `casesi' insn in i386.md for details.  */rtxlegitimize_pic_address (orig, reg)     rtx orig;     rtx reg;{  rtx addr = orig;  rtx new = orig;  if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)    {      if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))	reg = new = orig;      else	{	  if (reg == 0)	    reg = gen_reg_rtx (Pmode);	  if ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr))	      || GET_CODE (addr) == LABEL_REF)	    new = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig);	  else	    new = gen_rtx (MEM, Pmode,			   gen_rtx (PLUS, Pmode,				    pic_offset_table_rtx, orig));	  emit_move_insn (reg, new);

⌨️ 快捷键说明

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