m68k.c

来自「gcc3.2.1源代码」· C语言 代码 · 共 2,431 行 · 第 1/5 页

C
2,431
字号
    }  else if (fsize)    {      if (fsize + 4 < 0x8000)	{#ifndef NO_ADDSUB_Q	  if (fsize + 4 <= 8)	    {	      if (!TARGET_5200)		{		  /* asm_fprintf() cannot handle %.  */#ifdef MOTOROLA		  asm_fprintf (stream, "\tsubq.w %0I%d,%Rsp\n", fsize + 4);#else		  asm_fprintf (stream, "\tsubqw %0I%d,%Rsp\n", fsize + 4);#endif		}	      else		{		  /* asm_fprintf() cannot handle %.  */#ifdef MOTOROLA		  asm_fprintf (stream, "\tsubq.l %0I%d,%Rsp\n", fsize + 4);#else		  asm_fprintf (stream, "\tsubql %0I%d,%Rsp\n", fsize + 4);#endif		}	    }	  else if (fsize + 4 <= 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() cannot handle %.  */#ifdef MOTOROLA	      asm_fprintf (stream, "\tsubq.w %0I8,%Rsp\n\tsubq.w %0I%d,%Rsp\n",			   fsize + 4 - 8);#else	      asm_fprintf (stream, "\tsubqw %0I8,%Rsp\n\tsubqw %0I%d,%Rsp\n",			   fsize + 4 - 8);#endif	    }	  else #endif /* not NO_ADDSUB_Q */	  if (TARGET_68040)	    {	      /* Adding negative number is faster on the 68040.  */	      /* asm_fprintf() cannot handle %.  */#ifdef MOTOROLA	      asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", - (fsize + 4));#else	      asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", - (fsize + 4));#endif	    }	  else	    {#ifdef MOTOROLA	      asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", - (fsize + 4));#else	      asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", - (fsize + 4));#endif	    }	}      else	{	/* asm_fprintf() cannot handle %.  */#ifdef MOTOROLA	  asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", - (fsize + 4));#else	  asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", - (fsize + 4));#endif	}      if (dwarf2out_do_frame ())	{	  cfa_store_offset += fsize;	  cfa_offset = cfa_store_offset;	  dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset);	}    }#ifdef SUPPORT_SUN_FPA  for (regno = 24; regno < 56; regno++)    if (regs_ever_live[regno] && ! call_used_regs[regno])      {#ifdef MOTOROLA	asm_fprintf (stream, "\tfpmovd %s,-(%Rsp)\n",		     reg_names[regno]);#else	asm_fprintf (stream, "\tfpmoved %s,%Rsp@-\n",		     reg_names[regno]);#endif	if (dwarf2out_do_frame ())	  {	    char *l = dwarf2out_cfi_label ();	    cfa_store_offset += 8;	    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 (TARGET_68881)    {      for (regno = 16; regno < 24; regno++)	if (regs_ever_live[regno] && ! call_used_regs[regno])	  {	    mask |= 1 << (regno - 16);	    num_saved_regs++;	  }      if ((mask & 0xff) != 0)	{#ifdef MOTOROLA	  asm_fprintf (stream, "\tfmovm %0I0x%x,-(%Rsp)\n", mask & 0xff);#else	  asm_fprintf (stream, "\tfmovem %0I0x%x,%Rsp@-\n", mask & 0xff);#endif	  if (dwarf2out_do_frame ())	    {	      char *l = (char *) dwarf2out_cfi_label ();	      int n_regs;	      cfa_store_offset += num_saved_regs * 12;	      if (! frame_pointer_needed)		{		  cfa_offset = cfa_store_offset;		  dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);		}	      for (regno = 16, n_regs = 0; regno < 24; regno++)		if (mask & (1 << (regno - 16)))		  dwarf2out_reg_save (l, regno,				      -cfa_store_offset + n_regs++ * 12);	    }	}      mask = 0;      num_saved_regs = 0;    }  for (regno = 0; regno < 16; regno++)    if (regs_ever_live[regno] && ! call_used_regs[regno])      {        mask |= 1 << (15 - regno);        num_saved_regs++;      }  if (frame_pointer_needed)    {      mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM));      num_saved_regs--;    }  if (flag_pic && current_function_uses_pic_offset_table)    {      mask |= 1 << (15 - PIC_OFFSET_TABLE_REGNUM);      num_saved_regs++;    }#if NEED_PROBE#ifdef MOTOROLA  asm_fprintf (stream, "\ttst.l %d(%Rsp)\n", NEED_PROBE - num_saved_regs * 4);#else  asm_fprintf (stream, "\ttstl %Rsp@(%d)\n", NEED_PROBE - num_saved_regs * 4);#endif#endif  /* 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))	{#if defined (MOTOROLA)	  asm_fprintf (stream, "\tcmp.l %s,%Rsp\n\ttrapcs\n",		       reg_names[REGNO (stack_limit_rtx)]);#else	  asm_fprintf (stream, "\tcmpl %s,%Rsp\n\ttrapcs\n",		       reg_names[REGNO (stack_limit_rtx)]);#endif	}      else if (GET_CODE (stack_limit_rtx) != SYMBOL_REF)	warning ("stack limit expression is not supported");    }    if (num_saved_regs <= 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;      /* Undo the work from above.  */      for (i = 0; i< 16; i++)        if (mask & (1 << i))	  {	    asm_fprintf (stream,#ifdef MOTOROLA			 "\t%Omove.l %s,-(%Rsp)\n",#else			 "\tmovel %s,%Rsp@-\n",#endif			 reg_names[15 - i]);	    if (dwarf2out_do_frame ())	      {		char *l = (char *) 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, 15 - i, -cfa_store_offset);	      }	  }    }  else if (mask)    {      if (TARGET_5200)	{	  /* The coldfire does not support the predecrement form of the 	     movml instruction, so we must adjust the stack pointer and	     then use the plain address register indirect mode.  We also	     have to invert the register save mask to use the new mode.	     FIXME: if num_saved_regs was calculated earlier, we could	     combine the stack pointer adjustment with any adjustment	     done when the initial stack frame is created.  This would	     save an instruction */	     	  int newmask = 0;	  int i;	  for (i = 0; i < 16; i++)	    if (mask & (1 << i))		newmask |= (1 << (15-i));#ifdef MOTOROLA	  asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", -num_saved_regs*4);	  asm_fprintf (stream, "\tmovm.l %0I0x%x,(%Rsp)\n", newmask);#else	  asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", -num_saved_regs*4);	  asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@\n", newmask);#endif	}      else	{#ifdef MOTOROLA	  asm_fprintf (stream, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask);#else	  asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@-\n", mask);#endif	}      if (dwarf2out_do_frame ())	{	  char *l = (char *) dwarf2out_cfi_label ();	  int n_regs;	  cfa_store_offset += num_saved_regs * 4;	  if (! frame_pointer_needed)	    {	      cfa_offset = cfa_store_offset;	      dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);	    }	  for (regno = 0, n_regs = 0; regno < 16; regno++)	    if (mask & (1 << (15 - regno)))	      dwarf2out_reg_save (l, regno,				  -cfa_store_offset + n_regs++ * 4);	}    }  if (flag_pic && current_function_uses_pic_offset_table)    {#ifdef MOTOROLA      asm_fprintf (stream, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",		   reg_names[PIC_OFFSET_TABLE_REGNUM]);#else      asm_fprintf (stream, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n",		   reg_names[PIC_OFFSET_TABLE_REGNUM]);      asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n",		   reg_names[PIC_OFFSET_TABLE_REGNUM],		   reg_names[PIC_OFFSET_TABLE_REGNUM]);#endif    }}#endif   /* ! (DPX2 && MOTOROLA)  */#endif   /* ! (NEWS && MOTOROLA)  */#endif   /* !CRDS  *//* Return true if this function's epilogue can be output as RTL.  */intuse_return_insn (){  int regno;  if (!reload_completed || frame_pointer_needed || get_frame_size () != 0)    return 0;    /* Copied from output_function_epilogue ().  We should probably create a     separate layout routine to perform the common work.  */    for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++)    if (regs_ever_live[regno] && ! call_used_regs[regno])      return 0;  if (flag_pic && current_function_uses_pic_offset_table)    return 0;  return 1;}/* 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.  */#ifdef CRDSstatic voidm68k_output_function_epilogue (stream, size)     FILE *stream;     HOST_WIDE_INT size;{  register int regno;  register int mask, fmask;  register int nregs;  HOST_WIDE_INT offset, foffset, fpoffset;  HOST_WIDE_INT fsize = ((size) + 3) & -4;  int big = 0;  nregs = 0;  fmask = 0; fpoffset = 0;  for (regno = 16; regno < 24; regno++)    if (regs_ever_live[regno] && ! call_used_regs[regno])      {	nregs++;	fmask |= 1 << (23 - regno);      }  foffset = fpoffset + nregs * 12;  nregs = 0;  mask = 0;  if (frame_pointer_needed)    regs_ever_live[FRAME_POINTER_REGNUM] = 0;  for (regno = 0; regno < 16; regno++)    if (regs_ever_live[regno] && ! call_used_regs[regno])      {	nregs++;	mask |= 1 << regno;      }  offset = foffset + nregs * 4;  if (offset + fsize >= 0x8000      && frame_pointer_needed      && (mask || fmask || fpoffset))    {      fprintf (stream, "\tmovel $%d,a0\n", -fsize);      fsize = 0, big = 1;    }  if (exact_log2 (mask) >= 0)    {      if (big)	fprintf (stream, "\tmovel -%d(a6,a0.l),%s\n",		 offset + fsize, reg_names[exact_log2 (mask)]);      else if (! frame_pointer_needed)	fprintf (stream, "\tmovel (sp)+,%s\n",		 reg_names[exact_log2 (mask)]);      else	fprintf (stream, "\tmovel -%d(a6),%s\n",		 offset + fsize, reg_names[exact_log2 (mask)]);    }  else if (mask)    {      if (big)	fprintf (stream, "\tmovem -%d(a6,a0.l),$0x%x\n",		 offset + fsize, mask);      else if (! frame_pointer_needed)	fprintf (stream, "\tmovem (sp)+,$0x%x\n", mask);      else	fprintf (stream, "\tmovem -%d(a6),$0x%x\n",		 offset + fsize, mask);    }  if (fmask)    {      if (big)	fprintf (stream, "\tfmovem -%d(a6,a0.l),$0x%x\n",		 foffset + fsize, fmask);      else if (! frame_pointer_needed)	fprintf (stream, "\tfmovem (sp)+,$0x%x\n", fmask);      else	fprintf (stream, "\tfmovem -%d(a6),$0x%x\n",		 foffset + fsize, fmask);    }  if (fpoffset != 0)    for (regno = 55; regno >= 24; regno--)      if (regs_ever_live[regno] && ! call_used_regs[regno])	{	  if (big)	    fprintf(stream, "\tfpmoved -%d(a6,a0.l), %s\n",		    fpoffset + fsize, reg_names[regno]);	  else if (! frame_pointer_needed)	    fprintf(stream, "\tfpmoved (sp)+, %s\n",		    reg_names[regno]);	  else	    fprintf(stream, "\tfpmoved -%d(a6), %s\n",		    fpoffset + fsize, reg_names[regno]);	  fpoffset -= 8;	}  if (frame_pointer_needed)    fprintf (stream, "\tunlk a6\n");  else if (fsize)    {      if (fsize + 4 < 0x8000)	fprintf (stream, "\tadd.w #%d,sp\n", fsize + 4);      else	fprintf (stream, "\tadd.l #%d,sp\n", fsize + 4);    }  if (current_function_pops_args)    fprintf (stream, "\trtd $%d\n", current_function_pops_args);  else    fprintf (stream, "\trts\n");}#else#if defined (DPX2) && defined (MOTOROLA)static voidm68k_output_function_epilogue (stream, size)     FILE *stream;     HOST_WIDE_INT size;{  register int regno;  register int mask, fmask;  register int nregs;  HOST_WIDE_INT offset, foffset, fpoffset, first = 1;  HOST_WIDE_INT fsize = ((size) + 3) & -4;  int big = 0;  rtx insn = get_last_insn ();  /* 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;    }  nregs = 0;  fmask = 0; fpoffset = 0;  for (regno = 16; regno < 24; regno++)    if (regs_ever_live[regno] && ! call_used_regs[regno])      {        nregs++;	fmask |= 1 << (23 - regno);      }  foffset = fpoffset + nregs * 12;  nregs = 0;  mask = 0;  if (frame_pointer_needed)    regs_ever_live[FRAME_POINTER_REGNUM] = 0;  for (regno = 0; regno < 16; regno++)    if (regs_ever_live[regno] && ! call_used_regs[regno])      {        nregs++;	mask |= 1 << regno;      }  offset = foffset + nregs * 4;  if (offset + fsize >= 0x8000      && frame_pointer_needed      && (mask || fmask || fpoffset))    {      fprintf (stream, "\tmove.l #%d,a0\n", -fsize);      fsize = 0, big = 1;    }  if (nregs <= 2)    {      /* Restore each separately in the same order moveml does.

⌨️ 快捷键说明

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