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

📄 m68k.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* On ColdFire add register save into initial stack frame setup, if possible.  */  fsize_with_regs = current_frame.size;  if (TARGET_COLDFIRE && current_frame.reg_no > 2)    fsize_with_regs += current_frame.reg_no * 4;  if (frame_pointer_needed)    {      if (current_frame.size == 0 && TARGET_68040)	/* on the 68040, pea + move is faster than link.w 0 */	fprintf (stream, MOTOROLA ?			   "\tpea (%s)\n\tmove.l %s,%s\n" :			   "\tpea %s@\n\tmovel %s,%s\n",		 M68K_REGNAME(FRAME_POINTER_REGNUM),		 M68K_REGNAME(STACK_POINTER_REGNUM),		 M68K_REGNAME(FRAME_POINTER_REGNUM));      else if (fsize_with_regs < 0x8000)	asm_fprintf (stream, "\tlink" ASM_DOTW " %s,%I%wd\n",		     M68K_REGNAME(FRAME_POINTER_REGNUM), -fsize_with_regs);      else if (TARGET_68020)	asm_fprintf (stream, "\tlink" ASM_DOTL " %s,%I%wd\n",		     M68K_REGNAME(FRAME_POINTER_REGNUM), -fsize_with_regs);      else	/* Adding negative number is faster on the 68040.  */	asm_fprintf (stream, "\tlink" ASM_DOTW " %s,%I0\n"			     "\tadd" ASM_DOT "l %I%wd,%Rsp\n",		     M68K_REGNAME(FRAME_POINTER_REGNUM), -fsize_with_regs);      if (dwarf2out_do_frame ())	{	  char *l;          l = (char *) dwarf2out_cfi_label ();	  cfa_offset += 4;	  dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, -cfa_offset);	  dwarf2out_def_cfa (l, FRAME_POINTER_REGNUM, cfa_offset);	  cfa_offset += current_frame.size;	}    }  else if (fsize_with_regs) /* !frame_pointer_needed */    {      if (fsize_with_regs < 0x8000)	{	  if (fsize_with_regs <= 8)	    {	      if (!TARGET_COLDFIRE)		asm_fprintf (stream, "\tsubq" ASM_DOT "w %I%wd,%Rsp\n",		             fsize_with_regs);	      else		asm_fprintf (stream, "\tsubq" ASM_DOT "l %I%wd,%Rsp\n",		             fsize_with_regs);	    }	  else if (fsize_with_regs <= 16 && TARGET_CPU32)	    /* On the CPU32 it is faster to use two subqw instructions to	       subtract a small integer (8 < N <= 16) to a register.  */	    asm_fprintf (stream,			 "\tsubq" ASM_DOT "w %I8,%Rsp\n"			 "\tsubq" ASM_DOT "w %I%wd,%Rsp\n",			 fsize_with_regs - 8);	  else if (TARGET_68040)	    /* Adding negative number is faster on the 68040.  */	    asm_fprintf (stream, "\tadd" ASM_DOT "w %I%wd,%Rsp\n",			 -fsize_with_regs);	  else	    asm_fprintf (stream, MOTOROLA ?				   "\tlea (%wd,%Rsp),%Rsp\n" :				   "\tlea %Rsp@(%wd),%Rsp\n",			 -fsize_with_regs);	}      else /* fsize_with_regs >= 0x8000 */	asm_fprintf (stream, "\tadd" ASM_DOT "l %I%wd,%Rsp\n", -fsize_with_regs);      if (dwarf2out_do_frame ())	{	  cfa_offset += current_frame.size + 4;	  dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset);	}    } /* !frame_pointer_needed */  if (current_frame.fpu_mask)    {      asm_fprintf (stream, MOTOROLA ?			     "\tfmovm %I0x%x,-(%Rsp)\n" :			     "\tfmovem %I0x%x,%Rsp@-\n",		   current_frame.fpu_mask);      if (dwarf2out_do_frame ())	{	  char *l = (char *) dwarf2out_cfi_label ();	  int n_regs, regno;	  cfa_offset += current_frame.fpu_no * 12;	  if (! frame_pointer_needed)	    dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);	  for (regno = 16, n_regs = 0; regno < 24; regno++)	    if (current_frame.fpu_mask & (1 << (regno - 16)))	      dwarf2out_reg_save (l, regno, -cfa_offset + n_regs++ * 12);	}    }  /* If the stack limit is not a symbol, check it here.     This has the disadvantage that it may be too late...  */  if (current_function_limit_stack)    {      if (REG_P (stack_limit_rtx))	asm_fprintf (stream, "\tcmp" ASM_DOT "l %s,%Rsp\n\ttrapcs\n",		     M68K_REGNAME(REGNO (stack_limit_rtx)));      else if (GET_CODE (stack_limit_rtx) != SYMBOL_REF)	warning ("stack limit expression is not supported");    }  if (current_frame.reg_no <= 2)    {      /* Store each separately in the same order moveml uses.         Using two movel instructions instead of a single moveml         is about 15% faster for the 68020 and 68030 at no expense         in code size.  */      int i;      for (i = 0; i < 16; i++)        if (current_frame.reg_rev_mask & (1 << i))	  {	    asm_fprintf (stream, MOTOROLA ?				   "\t%Omove.l %s,-(%Rsp)\n" :				   "\tmovel %s,%Rsp@-\n",			 M68K_REGNAME(15 - i));	    if (dwarf2out_do_frame ())	      {		char *l = (char *) dwarf2out_cfi_label ();		cfa_offset += 4;		if (! frame_pointer_needed)		  dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);		dwarf2out_reg_save (l, 15 - i, -cfa_offset);	      }	  }    }  else if (current_frame.reg_rev_mask)    {      if (TARGET_COLDFIRE)	/* The ColdFire does not support the predecrement form of the	   MOVEM instruction, so we must adjust the stack pointer and	   then use the plain address register indirect mode.	   The required register save space was combined earlier with	   the fsize_with_regs amount.  */	asm_fprintf (stream, MOTOROLA ?			       "\tmovm.l %I0x%x,(%Rsp)\n" :			       "\tmoveml %I0x%x,%Rsp@\n",		     current_frame.reg_mask);      else	asm_fprintf (stream, MOTOROLA ?			       "\tmovm.l %I0x%x,-(%Rsp)\n" :			       "\tmoveml %I0x%x,%Rsp@-\n",		     current_frame.reg_rev_mask);      if (dwarf2out_do_frame ())	{	  char *l = (char *) dwarf2out_cfi_label ();	  int n_regs, regno;	  cfa_offset += current_frame.reg_no * 4;	  if (! frame_pointer_needed)	    dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);	  for (regno = 0, n_regs = 0; regno < 16; regno++)	    if (current_frame.reg_mask & (1 << regno))	      dwarf2out_reg_save (l, regno, -cfa_offset + n_regs++ * 4);	}    }  if (!TARGET_SEP_DATA && flag_pic &&      (current_function_uses_pic_offset_table ||        (!current_function_is_leaf && TARGET_ID_SHARED_LIBRARY)))    {      if (TARGET_ID_SHARED_LIBRARY)	{	  asm_fprintf (stream, "\tmovel %s@(%s), %s\n",		       M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM),		       m68k_library_id_string,		       M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM));	}      else	{	  if (MOTOROLA)	    asm_fprintf (stream, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",			 M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM));	  else	    {	      asm_fprintf (stream, "\tmovel %I%U_GLOBAL_OFFSET_TABLE_, %s\n",			   M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM));	      asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n",			   M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM),			   M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM));	    }	}    }}/* Return true if this function's epilogue can be output as RTL.  */booluse_return_insn (void){  if (!reload_completed || frame_pointer_needed || get_frame_size () != 0)    return false;  /* We can output the epilogue as RTL only if no registers need to be     restored.  */  m68k_compute_frame_layout();  return current_frame.reg_no ? false : true;}/* This function generates the assembly code for function exit,   on machines that need it.   The function epilogue should not depend on the current stack pointer!   It should use the frame pointer only, if there is a frame pointer.   This is mandatory because of alloca; we also take advantage of it to   omit stack adjustments before returning.  */static voidm68k_output_function_epilogue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED){  HOST_WIDE_INT fsize, fsize_with_regs;  bool big = false;  bool restore_from_sp = false;  rtx insn = get_last_insn ();  m68k_compute_frame_layout();  /* If the last insn was a BARRIER, we don't have to write any code.  */  if (GET_CODE (insn) == NOTE)    insn = prev_nonnote_insn (insn);  if (insn && GET_CODE (insn) == BARRIER)    {      /* Output just a no-op so that debuggers don't get confused	 about which function the pc is in at this address.  */      fprintf (stream, "\tnop\n");      return;    }#ifdef FUNCTION_EXTRA_EPILOGUE  FUNCTION_EXTRA_EPILOGUE (stream, size);#endif  fsize = current_frame.size;  /* FIXME : leaf_function_p below is too strong.     What we really need to know there is if there could be pending     stack adjustment needed at that point.  */  restore_from_sp = ! frame_pointer_needed	     || (! current_function_calls_alloca && leaf_function_p ());  /* fsize_with_regs is the size we need to adjust the sp when     popping the frame.  */  fsize_with_regs = fsize;  /* Because the ColdFire doesn't support moveml with     complex address modes, we must adjust the stack manually     after restoring registers. When the frame pointer isn't used,     we can merge movem adjustment into frame unlinking     made immediately after it.  */  if (TARGET_COLDFIRE && restore_from_sp && (current_frame.reg_no > 2))    fsize_with_regs += current_frame.reg_no * 4;  if (current_frame.offset + fsize >= 0x8000      && ! restore_from_sp      && (current_frame.reg_mask || current_frame.fpu_mask))    {      /* Because the ColdFire doesn't support moveml with         complex address modes we make an extra correction here.  */      if (TARGET_COLDFIRE)        fsize += current_frame.offset;      asm_fprintf (stream, "\t%Omove" ASM_DOT "l %I%wd,%Ra1\n", -fsize);      fsize = 0, big = true;    }  if (current_frame.reg_no <= 2)    {      /* Restore each separately in the same order moveml does.         Using two movel instructions instead of a single moveml         is about 15% faster for the 68020 and 68030 at no expense         in code size.  */      int i;      HOST_WIDE_INT offset = current_frame.offset + fsize;      for (i = 0; i < 16; i++)        if (current_frame.reg_mask & (1 << i))          {            if (big)	      {		if (MOTOROLA)		  asm_fprintf (stream, "\t%Omove.l -%wd(%s,%Ra1.l),%s\n",			       offset,			       M68K_REGNAME(FRAME_POINTER_REGNUM),			       M68K_REGNAME(i));		else		  asm_fprintf (stream, "\tmovel %s@(-%wd,%Ra1:l),%s\n",			       M68K_REGNAME(FRAME_POINTER_REGNUM),			       offset,			       M68K_REGNAME(i));	      }            else if (restore_from_sp)	      asm_fprintf (stream, MOTOROLA ?				     "\t%Omove.l (%Rsp)+,%s\n" :				     "\tmovel %Rsp@+,%s\n",			   M68K_REGNAME(i));            else	      {	        if (MOTOROLA)		  asm_fprintf (stream, "\t%Omove.l -%wd(%s),%s\n",			       offset,			       M68K_REGNAME(FRAME_POINTER_REGNUM),			       M68K_REGNAME(i));		else		  asm_fprintf (stream, "\tmovel %s@(-%wd),%s\n",			       M68K_REGNAME(FRAME_POINTER_REGNUM),			       offset,			       M68K_REGNAME(i));	      }            offset -= 4;          }    }  else if (current_frame.reg_mask)    {      /* The ColdFire requires special handling due to its limited moveml insn.  */      if (TARGET_COLDFIRE)        {          if (big)            {              asm_fprintf (stream, "\tadd" ASM_DOT "l %s,%Ra1\n",			   M68K_REGNAME(FRAME_POINTER_REGNUM));              asm_fprintf (stream, MOTOROLA ?				     "\tmovm.l (%Ra1),%I0x%x\n" :				     "\tmoveml %Ra1@,%I0x%x\n",			   current_frame.reg_mask);	     }	   else if (restore_from_sp)	     asm_fprintf (stream, MOTOROLA ?				    "\tmovm.l (%Rsp),%I0x%x\n" :				    "\tmoveml %Rsp@,%I0x%x\n",			  current_frame.reg_mask);          else            {	      if (MOTOROLA)		asm_fprintf (stream, "\tmovm.l -%wd(%s),%I0x%x\n",			     current_frame.offset + fsize,			     M68K_REGNAME(FRAME_POINTER_REGNUM),			     current_frame.reg_mask);	      else		asm_fprintf (stream, "\tmoveml %s@(-%wd),%I0x%x\n",			     M68K_REGNAME(FRAME_POINTER_REGNUM),			     current_frame.offset + fsize,			     current_frame.reg_mask);	    }        }      else /* !TARGET_COLDFIRE */	{	  if (big)	    {	      if (MOTOROLA)		asm_fprintf (stream, "\tmovm.l -%wd(%s,%Ra1.l),%I0x%x\n",			     current_frame.offset + fsize,			     M68K_REGNAME(FRAME_POINTER_REGNUM),			     current_frame.reg_mask);	      else		asm_fprintf (stream, "\tmoveml %s@(-%wd,%Ra1:l),%I0x%x\n",			     M68K_REGNAME(FRAME_POINTER_REGNUM),			     current_frame.offset + fsize,			     current_frame.reg_mask);	    }	  else if (restore_from_sp)	    {	      asm_fprintf (stream, MOTOROLA ?				     "\tmovm.l (%Rsp)+,%I0x%x\n" :				     "\tmoveml %Rsp@+,%I0x%x\n",			   current_frame.reg_mask);	    }	  else	    {	      if (MOTOROLA)		asm_fprintf (stream, "\tmovm.l -%wd(%s),%I0x%x\n",			     current_frame.offset + fsize,			     M68K_REGNAME(FRAME_POINTER_REGNUM),			     current_frame.reg_mask);	      else		asm_fprintf (stream, "\tmoveml %s@(-%wd),%I0x%x\n",			     M68K_REGNAME(FRAME_POINTER_REGNUM),			     current_frame.offset + fsize,			     current_frame.reg_mask);	    }	}    }  if (current_frame.fpu_rev_mask)    {      if (big)	{	  if (MOTOROLA)	    asm_fprintf (stream, "\tfmovm -%wd(%s,%Ra1.l),%I0x%x\n",		         current_frame.foffset + fsize,		         M68K_REGNAME(FRAME_POINTER_REGNUM),		         current_frame.fpu_rev_mask);	  else	    asm_fprintf (stream, "\tfmovem %s@(-%wd,%Ra1:l),%I0x%x\n",			 M68K_REGNAME(FRAME_POINTER_REGNUM),			 current_frame.foffset + fsize,			 current_frame.fpu_rev_mask);	}      else if (restore_from_sp)	{	  if (MOTOROLA)	    asm_fprintf (stream, "\tfmovm (%Rsp)+,%I0x%x\n",			 current_frame.fpu_rev_mask);	  else	    asm_fprintf (stream, "\tfmovem %Rsp@+,%I0x%x\n",			 current_frame.fpu_rev_mask);	}      else	{	  if (MOTOROLA)	    asm_fprintf (stream, "\tfmovm -%wd(%s),%I0x%x\n",			 current_frame.foffset + fsize,			 M68K_REGNAME(FRAME_POINTER_REGNUM),			 current_frame.fpu_rev_mask);	  else	    asm_fprintf (stream, "\tfmovem %s@(-%wd),%I0x%x\n",			 M68K_REGNAME(FRAME_POINTER_REGNUM),			 current_frame.foffset + fsize,			 current_frame.fpu_rev_mask);	}    }  if (frame_pointer_needed)    fprintf (stream, "\tunlk %s\n", M68K_REGNAME(FRAME_POINTER_REGNUM));  else if (fsize_with_regs)    {      if (fsize_with_regs <= 8)	{	  if (!TARGET_COLDFIRE)	    asm_fprintf (stream, "\taddq" ASM_DOT "w %I%wd,%Rsp\n",			 fsize_with_regs);	  else	    asm_fprintf (stream, "\taddq" ASM_DOT "l %I%wd,%Rsp\n",

⌨️ 快捷键说明

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