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

📄 m68k.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 5 页
字号:
       (frame_pointer_needed ? -UNITS_PER_WORD * 2 : -UNITS_PER_WORD);     but for some obscure reason, this must be 0 to get correct code.  */  if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)    return 0;  m68k_compute_frame_layout ();  gcc_assert (to == STACK_POINTER_REGNUM);  switch (from)    {      case ARG_POINTER_REGNUM:	return current_frame.offset + current_frame.size	  + (frame_pointer_needed ? -UNITS_PER_WORD * 2 : -UNITS_PER_WORD);    case FRAME_POINTER_REGNUM:      return current_frame.offset + current_frame.size;    default:      gcc_unreachable ();    }}/* Refer to the array `regs_ever_live' to determine which registers   to save; `regs_ever_live[I]' is nonzero if register number I   is ever used in the function.  This function is responsible for   knowing which registers should not be saved even if used.   Return true if we need to save REGNO.  */static boolm68k_save_reg (unsigned int regno, bool interrupt_handler){  if (flag_pic && regno == PIC_OFFSET_TABLE_REGNUM)    {      if (current_function_uses_pic_offset_table)	return true;      if (!current_function_is_leaf && TARGET_ID_SHARED_LIBRARY)	return true;    }  if (current_function_calls_eh_return)    {      unsigned int i;      for (i = 0; ; i++)	{	  unsigned int test = EH_RETURN_DATA_REGNO (i);	  if (test == INVALID_REGNUM)	    break;	  if (test == regno)	    return true;	}    }  /* Fixed regs we never touch.  */  if (fixed_regs[regno])    return false;  /* The frame pointer (if it is such) is handled specially.  */  if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)    return false;  /* Interrupt handlers must also save call_used_regs     if they are live or when calling nested functions.  */  if (interrupt_handler)  {     if (regs_ever_live[regno])       return true;     if (!current_function_is_leaf && call_used_regs[regno])       return true;  }  /* Never need to save registers that aren't touched.  */  if (!regs_ever_live[regno])    return false;  /* Otherwise save everything that isn't call-clobbered.  */  return !call_used_regs[regno];}/* This function generates the assembly code for function entry.   STREAM is a stdio stream to output the code to.   SIZE is an int: how many units of temporary storage to allocate.  */static voidm68k_output_function_prologue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED){  HOST_WIDE_INT fsize_with_regs;  HOST_WIDE_INT cfa_offset = INCOMING_FRAME_SP_OFFSET;  m68k_compute_frame_layout();  /* If the stack limit is a symbol, we can check it here,     before actually allocating the space.  */  if (current_function_limit_stack      && GET_CODE (stack_limit_rtx) == SYMBOL_REF)    asm_fprintf (stream, "\tcmp" ASM_DOT "l %I%s+%wd,%Rsp\n\ttrapcs\n",		 XSTR (stack_limit_rtx, 0), current_frame.size + 4);  /* 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 (0, "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

⌨️ 快捷键说明

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