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

📄 i386.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
						    "$_GLOBAL_OFFSET_TABLE_"), 					   xops[1]));	}      else	{	  output_asm_insn (AS1 (call,%P1), xops);	  output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_,%0", xops);	  pic_label_rtx = 0;	}    }  else    {      xops[0] = pic_offset_table_rtx;      xops[1] = gen_label_rtx ();       if (do_rtl)	{	  /* We can't put a raw CODE_LABEL into the RTL, and we can't emit	     a new CODE_LABEL after reload, so we need a single pattern to	     emit the 3 necessary instructions.  */	  emit_insn (gen_prologue_get_pc_and_set_got (xops[0]));	}      else	{	  output_asm_insn (AS1 (call,%P1), xops);	  ASM_OUTPUT_INTERNAL_LABEL (asm_out_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);	}    }   /* When -fpic, we must emit a scheduling barrier, so that the instruction     that restores %ebx (which is PIC_OFFSET_TABLE_REGNUM), does not get     moved before any instruction which implicitly uses the got.   */  if (do_rtl)    emit_insn (gen_blockage ());}static voidix86_prologue (do_rtl)     int do_rtl;{  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);  long tsize = get_frame_size ();  rtx insn;  int cfa_offset = INCOMING_FRAME_SP_OFFSET, cfa_store_offset = cfa_offset;    xops[0] = stack_pointer_rtx;  xops[1] = frame_pointer_rtx;  xops[2] = GEN_INT (tsize);  if (frame_pointer_needed)    {      if (do_rtl)	{	  insn = emit_insn (gen_rtx (SET, VOIDmode,				     gen_rtx (MEM, SImode,					      gen_rtx (PRE_DEC, SImode,						       stack_pointer_rtx)),				     frame_pointer_rtx));	  RTX_FRAME_RELATED_P (insn) = 1;	  insn = emit_move_insn (xops[1], xops[0]);	  RTX_FRAME_RELATED_P (insn) = 1;	}      else	{	  output_asm_insn ("push%L1 %1", xops); #ifdef INCOMING_RETURN_ADDR_RTX 	  if (dwarf2out_do_frame ()) 	    { 	      char *l = dwarf2out_cfi_label (); 	      cfa_store_offset += 4; 	      cfa_offset = cfa_store_offset; 	      dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset); 	      dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, - cfa_store_offset); 	    }#endif	  output_asm_insn (AS2 (mov%L0,%0,%1), xops); #ifdef INCOMING_RETURN_ADDR_RTX 	  if (dwarf2out_do_frame ()) 	    dwarf2out_def_cfa ("", FRAME_POINTER_REGNUM, cfa_offset);#endif	}    }  if (tsize == 0)    ;  else if (! TARGET_STACK_PROBE || tsize < CHECK_STACK_LIMIT)    {      if (do_rtl)	{	  insn = emit_insn (gen_prologue_set_stack_ptr (xops[2]));	  RTX_FRAME_RELATED_P (insn) = 1;	}      else 	{	  output_asm_insn (AS2 (sub%L0,%2,%0), xops);#ifdef INCOMING_RETURN_ADDR_RTX 	  if (dwarf2out_do_frame ()) 	    { 	      cfa_store_offset += tsize; 	      if (! frame_pointer_needed) 		{ 		  cfa_offset = cfa_store_offset; 		  dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset); 		} 	    }#endif	}    }  else     {      xops[3] = gen_rtx (REG, SImode, 0);      if (do_rtl)      emit_move_insn (xops[3], xops[2]);      else	output_asm_insn (AS2 (mov%L0,%2,%3), xops);      xops[3] = gen_rtx (MEM, FUNCTION_MODE,			 gen_rtx (SYMBOL_REF, Pmode, "_alloca"));      if (do_rtl)	emit_call_insn (gen_rtx (CALL, VOIDmode, xops[3], const0_rtx));      else	output_asm_insn (AS1 (call,%P3), 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);	if (do_rtl)	  {	    insn = emit_insn (gen_rtx (SET, VOIDmode,				       gen_rtx (MEM, SImode,						gen_rtx (PRE_DEC, SImode,							 stack_pointer_rtx)),				       xops[0]));	    RTX_FRAME_RELATED_P (insn) = 1;	  }	else	  {	    output_asm_insn ("push%L0 %0", xops);#ifdef INCOMING_RETURN_ADDR_RTX 	    if (dwarf2out_do_frame ()) 	      { 		char *l = dwarf2out_cfi_label (); 		cfa_store_offset += 4; 		if (! frame_pointer_needed) 		  { 		    cfa_offset = cfa_store_offset; 		    dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset); 		  } 		dwarf2out_reg_save (l, regno, - cfa_store_offset); 	      }#endif 	  }      }  if (pic_reg_used)    load_pic_register (do_rtl);  /* If we are profiling, make sure no instructions are scheduled before     the call to mcount.  However, if -fpic, the above call will have     done that.  */  if ((profile_flag || profile_block_flag)      && ! pic_reg_used && do_rtl)    emit_insn (gen_blockage ());}/* 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.  Return 0 if there is no frame    marker to de-allocate.   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.  */intix86_can_use_return_insn_p (){  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;{    return;}/* Restore function stack, frame, and registers. */ voidix86_expand_epilogue (){  ix86_epilogue (1);}static voidix86_epilogue (do_rtl)     int do_rtl;{  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);  long tsize = get_frame_size ();  /* 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 = - tsize - (nregs * UNITS_PER_WORD);  xops[2] = stack_pointer_rtx;  /* When -fpic, we must emit a scheduling barrier, so that the instruction     that restores %ebx (which is PIC_OFFSET_TABLE_REGNUM), does not get     moved before any instruction which implicitly uses the got.  This     includes any instruction which uses a SYMBOL_REF or a LABEL_REF.     Alternatively, this could be fixed by making the dependence on the     PIC_OFFSET_TABLE_REGNUM explicit in the RTL.  */  if (flag_pic || profile_flag || profile_block_flag)    emit_insn (gen_blockage ());  if (nregs > 1 || ! frame_pointer_needed)    {      if (frame_pointer_needed)	{	  xops[0] = adj_offsettable_operand (AT_BP (QImode), offset);	  if (do_rtl)	    emit_insn (gen_movsi_lea (xops[2], XEXP (xops[0], 0)));	  else	    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);	    if (do_rtl)	      emit_insn (gen_pop (xops[0]));	    else	      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);	  if (do_rtl)	    emit_move_insn (xops[0], xops[1]);	  else	    output_asm_insn (AS2 (mov%L0,%1,%0), xops);	  offset += 4;	}  if (frame_pointer_needed)    {      /* If not an i386, mov & pop is faster than "leave". */      if (TARGET_USE_LEAVE)	{	  if (do_rtl)	    emit_insn (gen_leave());	  else	    output_asm_insn ("leave", xops);	}      else	{	  xops[0] = frame_pointer_rtx;	  xops[1] = stack_pointer_rtx;	  if (do_rtl)	    {	      emit_insn (gen_epilogue_set_stack_ptr());	      emit_insn (gen_pop (xops[0]));	    }	  else	    {	      output_asm_insn (AS2 (mov%L2,%0,%2), xops);	      output_asm_insn ("pop%L0 %0", xops);	    }	}    }  else if (tsize)    {      /* If there is no frame pointer, we must still release the frame. */      xops[0] = GEN_INT (tsize);      if (do_rtl)	emit_insn (gen_rtx (SET, VOIDmode, xops[2],			    gen_rtx (PLUS, SImode, xops[2], xops[0])));      else	output_asm_insn (AS2 (add%L2,%0,%2), xops);    }#ifdef FUNCTION_BLOCK_PROFILER_EXIT  if (profile_block_flag == 2)    {      FUNCTION_BLOCK_PROFILER_EXIT(file);    }#endif  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);	  if (do_rtl)	    {	      emit_insn (gen_pop (xops[0]));	      emit_insn (gen_rtx (SET, VOIDmode, xops[2],				  gen_rtx (PLUS, SImode, xops[1], xops[2])));	      emit_jump_insn (xops[0]);	    }	  else	    {	      output_asm_insn ("pop%L0 %0", xops);	      output_asm_insn (AS2 (add%L2,%1,%2), xops);	      output_asm_insn ("jmp %*%0", xops);	    }	}      else 	{	  if (do_rtl)	    emit_jump_insn (gen_return_pop_internal (xops[1]));	  else	    output_asm_insn ("ret %1", xops);	}    }  else    {      if (do_rtl)	emit_jump_insn (gen_return_internal ());      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);    }

⌨️ 快捷键说明

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