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

📄 m68k.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines for insn-output.c for Motorola 68000 family.   Copyright (C) 1987, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003   Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  */#include "config.h"#include "system.h"#include "tree.h"#include "rtl.h"#include "function.h"#include "regs.h"#include "hard-reg-set.h"#include "real.h"#include "insn-config.h"#include "conditions.h"#include "output.h"#include "insn-attr.h"#include "recog.h"#include "toplev.h"#include "expr.h"#include "reload.h"#include "tm_p.h"#include "target.h"#include "target-def.h"#include "debug.h"/* Needed for use_return_insn.  */#include "flags.h"#ifdef SUPPORT_SUN_FPA/* Index into this array by (register number >> 3) to find the   smallest class which contains that register.  */const enum reg_class regno_reg_class[]  = { DATA_REGS, ADDR_REGS, FP_REGS,      LO_FPA_REGS, LO_FPA_REGS, FPA_REGS, FPA_REGS };#endif /* defined SUPPORT_SUN_FPA *//* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,   if SGS_SWITCH_TABLE.  */int switch_table_difference_label_flag;static rtx find_addr_reg PARAMS ((rtx));static const char *singlemove_string PARAMS ((rtx *));static void m68k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));static void m68k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));static void m68k_coff_asm_named_section PARAMS ((const char *, unsigned int));#ifdef CTOR_LIST_BEGINstatic void m68k_svr3_asm_out_constructor PARAMS ((rtx, int));#endifstatic void m68k_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,					  HOST_WIDE_INT, tree));static int m68k_save_reg PARAMS ((unsigned int));/* Alignment to use for loops and jumps *//* Specify power of two alignment used for loops.  */const char *m68k_align_loops_string;/* Specify power of two alignment used for non-loop jumps.  */const char *m68k_align_jumps_string;/* Specify power of two alignment used for functions.  */const char *m68k_align_funcs_string;/* Specify power of two alignment used for loops.  */int m68k_align_loops;/* Specify power of two alignment used for non-loop jumps.  */int m68k_align_jumps;/* Specify power of two alignment used for functions.  */int m68k_align_funcs;/* Nonzero if the last compare/test insn had FP operands.  The   sCC expanders peek at this to determine what to do for the   68060, which has no fsCC instructions.  */int m68k_last_compare_had_fp_operands;/* Initialize the GCC target structure.  */#if INT_OP_GROUP == INT_OP_DOT_WORD#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"#endif#if INT_OP_GROUP == INT_OP_NO_DOT#undef TARGET_ASM_BYTE_OP#define TARGET_ASM_BYTE_OP "\tbyte\t"#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP "\tshort\t"#undef TARGET_ASM_ALIGNED_SI_OP#define TARGET_ASM_ALIGNED_SI_OP "\tlong\t"#endif#if INT_OP_GROUP == INT_OP_DC#undef TARGET_ASM_BYTE_OP#define TARGET_ASM_BYTE_OP "\tdc.b\t"#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP "\tdc.w\t"#undef TARGET_ASM_ALIGNED_SI_OP#define TARGET_ASM_ALIGNED_SI_OP "\tdc.l\t"#endif#undef TARGET_ASM_UNALIGNED_HI_OP#define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP#undef TARGET_ASM_UNALIGNED_SI_OP#define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP#undef TARGET_ASM_FUNCTION_PROLOGUE#define TARGET_ASM_FUNCTION_PROLOGUE m68k_output_function_prologue#undef TARGET_ASM_FUNCTION_EPILOGUE#define TARGET_ASM_FUNCTION_EPILOGUE m68k_output_function_epilogue#undef TARGET_ASM_OUTPUT_MI_THUNK#define TARGET_ASM_OUTPUT_MI_THUNK m68k_output_mi_thunk#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcallstruct gcc_target targetm = TARGET_INITIALIZER;/* Sometimes certain combinations of command options do not make   sense on a particular target machine.  You can define a macro   `OVERRIDE_OPTIONS' to take account of this.  This macro, if   defined, is executed once just after all the command options have   been parsed.   Don't use this macro to turn on various extra optimizations for   `-O'.  That is what `OPTIMIZATION_OPTIONS' is for.  */voidoverride_options (){  int def_align;  int i;  def_align = 1;  /* Validate -malign-loops= value, or provide default */  m68k_align_loops = def_align;  if (m68k_align_loops_string)    {      i = atoi (m68k_align_loops_string);      if (i < 1 || i > MAX_CODE_ALIGN)	error ("-malign-loops=%d is not between 1 and %d", i, MAX_CODE_ALIGN);      else	m68k_align_loops = i;    }  /* Validate -malign-jumps= value, or provide default */  m68k_align_jumps = def_align;  if (m68k_align_jumps_string)    {      i = atoi (m68k_align_jumps_string);      if (i < 1 || i > MAX_CODE_ALIGN)	error ("-malign-jumps=%d is not between 1 and %d", i, MAX_CODE_ALIGN);      else	m68k_align_jumps = i;    }  /* Validate -malign-functions= value, or provide default */  m68k_align_funcs = def_align;  if (m68k_align_funcs_string)    {      i = atoi (m68k_align_funcs_string);      if (i < 1 || i > MAX_CODE_ALIGN)	error ("-malign-functions=%d is not between 1 and %d",	       i, MAX_CODE_ALIGN);      else	m68k_align_funcs = i;    }  /* -fPIC uses 32-bit pc-relative displacements, which don't exist     until the 68020.  */  if (! TARGET_68020 && flag_pic == 2)    error("-fPIC is not currently supported on the 68000 or 68010\n");  /* ??? A historic way of turning on pic, or is this intended to     be an embedded thing that doesn't have the same name binding     significance that it does on hosted ELF systems?  */  if (TARGET_PCREL && flag_pic == 0)    flag_pic = 1;  /* Turn off function cse if we are doing PIC.  We always want function call     to be done as `bsr foo@PLTPC', so it will force the assembler to create     the PLT entry for `foo'. Doing function cse will cause the address of     `foo' to be loaded into a register, which is exactly what we want to     avoid when we are doing PIC on svr4 m68k.  */  if (flag_pic)    flag_no_function_cse = 1;  SUBTARGET_OVERRIDE_OPTIONS;  /* Tell the compiler which flavor of XFmode we're using.  */  real_format_for_mode[XFmode - QFmode] = &ieee_extended_motorola_format;}/* Return 1 if we need to save REGNO.  */static intm68k_save_reg (regno)     unsigned int regno;{  if (flag_pic && current_function_uses_pic_offset_table      && regno == PIC_OFFSET_TABLE_REGNUM)    return 1;  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 1;	}    }  return (regs_ever_live[regno]	  && !call_used_regs[regno]	  && !fixed_regs[regno]	  && !(regno == FRAME_POINTER_REGNUM && frame_pointer_needed));}/* 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.   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.  *//* Note that the order of the bit mask for fmovem is the opposite   of the order for movem!  */#ifdef CRDSstatic voidm68k_output_function_prologue (stream, size)     FILE *stream;     HOST_WIDE_INT size;{  register int regno;  register int mask = 0;  HOST_WIDE_INT fsize = ((size) + 3) & -4;  /* unos stack probe */  if (fsize > 30000)    {      fprintf (stream, "\tmovel sp,a0\n");      fprintf (stream, "\taddl $-%d,a0\n", 2048 + fsize);      fprintf (stream, "\ttstb (a0)\n");    }  else    fprintf (stream, "\ttstb -%d(sp)\n", 2048 + fsize);  if (frame_pointer_needed)    {      if (TARGET_68020 || fsize < 0x8000)	fprintf (stream, "\tlink a6,$%d\n", -fsize);      else	fprintf (stream, "\tlink a6,$0\n\tsubl $%d,sp\n", fsize);    }  else if (fsize)    {      /* Adding negative number is faster on the 68040.  */      if (fsize + 4 < 0x8000)	fprintf (stream, "\tadd.w $%d,sp\n", - (fsize + 4));      else	fprintf (stream, "\tadd.l $%d,sp\n", - (fsize + 4));    }  for (regno = 16; regno < 24; regno++)    if (m68k_save_reg (regno))      mask |= 1 << (regno - 16);  if ((mask & 0xff) != 0)    fprintf (stream, "\tfmovem $0x%x,-(sp)\n", mask & 0xff);  mask = 0;  for (regno = 0; regno < 16; regno++)    if (m68k_save_reg (regno))      mask |= 1 << (15 - regno);  if (exact_log2 (mask) >= 0)    fprintf (stream, "\tmovel %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]);  else if (mask)    fprintf (stream, "\tmovem $0x%x,-(sp)\n", mask);}#else  /* !CRDS */static voidm68k_output_function_prologue (stream, size)     FILE *stream;     HOST_WIDE_INT size;{  register int regno;  register int mask = 0;  int num_saved_regs = 0;  HOST_WIDE_INT fsize = (size + 3) & -4;  HOST_WIDE_INT cfa_offset = INCOMING_FRAME_SP_OFFSET;  HOST_WIDE_INT cfa_store_offset = cfa_offset;    /* 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)    {#if defined (MOTOROLA)      asm_fprintf (stream, "\tcmp.l %0I%s+%d,%Rsp\n\ttrapcs\n",		   XSTR (stack_limit_rtx, 0), fsize + 4);#else      asm_fprintf (stream, "\tcmpl %0I%s+%d,%Rsp\n\ttrapcs\n",		   XSTR (stack_limit_rtx, 0), fsize + 4);#endif    }  if (frame_pointer_needed)    {      if (fsize == 0 && TARGET_68040)	{	/* on the 68040, pea + move is faster than link.w 0 */#ifdef MOTOROLA	  fprintf (stream, "\tpea (%s)\n\tmove.l %s,%s\n",		   reg_names[FRAME_POINTER_REGNUM],		   reg_names[STACK_POINTER_REGNUM],		   reg_names[FRAME_POINTER_REGNUM]);#else	  fprintf (stream, "\tpea %s@\n\tmovel %s,%s\n",		   reg_names[FRAME_POINTER_REGNUM],		   reg_names[STACK_POINTER_REGNUM],		   reg_names[FRAME_POINTER_REGNUM]);#endif	}      else if (fsize < 0x8000)	{#ifdef MOTOROLA	  asm_fprintf (stream, "\tlink.w %s,%0I%d\n",		       reg_names[FRAME_POINTER_REGNUM], -fsize);#else	  asm_fprintf (stream, "\tlink %s,%0I%d\n",		       reg_names[FRAME_POINTER_REGNUM], -fsize);#endif	}      else if (TARGET_68020)	{#ifdef MOTOROLA	  asm_fprintf (stream, "\tlink.l %s,%0I%d\n",		       reg_names[FRAME_POINTER_REGNUM], -fsize);#else	  asm_fprintf (stream, "\tlink %s,%0I%d\n",		       reg_names[FRAME_POINTER_REGNUM], -fsize);#endif	}      else	{      /* Adding negative number is faster on the 68040.  */#ifdef MOTOROLA	  asm_fprintf (stream, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n",		       reg_names[FRAME_POINTER_REGNUM], -fsize);#else	  asm_fprintf (stream, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n",		       reg_names[FRAME_POINTER_REGNUM], -fsize);#endif	}      if (dwarf2out_do_frame ())	{	  char *l;          l = (char *) dwarf2out_cfi_label ();   	  cfa_store_offset += 4;	  cfa_offset = cfa_store_offset;	  dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, -cfa_store_offset);	  dwarf2out_def_cfa (l, FRAME_POINTER_REGNUM, cfa_offset);	  cfa_store_offset += fsize;	}    }  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 + 4;	  cfa_offset = cfa_store_offset;	  dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset);	}    }#ifdef SUPPORT_SUN_FPA  for (regno = 24; regno < 56; regno++)    if (m68k_save_reg (regno))

⌨️ 快捷键说明

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