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

📄 m68k.c

📁 linux下编程用 编译软件
💻 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, 2004, 2005   Free Software Foundation, Inc.This file is part of GCC.GCC 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.GCC 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 GCC; see the file COPYING.  If not, write tothe Free Software Foundation, 51 Franklin Street, Fifth Floor,Boston, MA 02110-1301, USA.  */#include "config.h"#include "system.h"#include "coretypes.h"#include "tm.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"#include "flags.h"enum reg_class regno_reg_class[] ={  DATA_REGS, DATA_REGS, DATA_REGS, DATA_REGS,  DATA_REGS, DATA_REGS, DATA_REGS, DATA_REGS,  ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,  ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,  FP_REGS, FP_REGS, FP_REGS, FP_REGS,  FP_REGS, FP_REGS, FP_REGS, FP_REGS,  ADDR_REGS};/* The ASM_DOT macro allows easy string pasting to handle the differences   between MOTOROLA and MIT syntaxes in asm_fprintf(), which doesn't   support the %. option.  */#if MOTOROLA# define ASM_DOT "."# define ASM_DOTW ".w"# define ASM_DOTL ".l"#else# define ASM_DOT ""# define ASM_DOTW ""# define ASM_DOTL ""#endif/* Structure describing stack frame layout.  */struct m68k_frame{  /* Stack pointer to frame pointer offset.  */  HOST_WIDE_INT offset;  /* Offset of FPU registers.  */  HOST_WIDE_INT foffset;  /* Frame size in bytes (rounded up).  */  HOST_WIDE_INT size;  /* Data and address register.  */  int reg_no;  unsigned int reg_mask;  unsigned int reg_rev_mask;  /* FPU registers.  */  int fpu_no;  unsigned int fpu_mask;  unsigned int fpu_rev_mask;  /* Offsets relative to ARG_POINTER.  */  HOST_WIDE_INT frame_pointer_offset;  HOST_WIDE_INT stack_pointer_offset;  /* Function which the above information refers to.  */  int funcdef_no;};/* Current frame information calculated by m68k_compute_frame_layout().  */static struct m68k_frame current_frame;static bool m68k_handle_option (size_t, const char *, int);static rtx find_addr_reg (rtx);static const char *singlemove_string (rtx *);static void m68k_output_function_prologue (FILE *, HOST_WIDE_INT);static void m68k_output_function_epilogue (FILE *, HOST_WIDE_INT);#ifdef M68K_TARGET_COFFstatic void m68k_coff_asm_named_section (const char *, unsigned int, tree);#endif /* M68K_TARGET_COFF */static void m68k_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,					  HOST_WIDE_INT, tree);static rtx m68k_struct_value_rtx (tree, int);static bool m68k_interrupt_function_p (tree func);static tree m68k_handle_fndecl_attribute (tree *node, tree name,					  tree args, int flags,					  bool *no_add_attrs);static void m68k_compute_frame_layout (void);static bool m68k_save_reg (unsigned int regno, bool interrupt_handler);static int const_int_cost (rtx);static bool m68k_rtx_costs (rtx, int, int, int *);/* Specify the identification number of the library being built */const char *m68k_library_id_string = "_current_shared_library_a5_offset_";/* 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_vcall#undef TARGET_ASM_FILE_START_APP_OFF#define TARGET_ASM_FILE_START_APP_OFF true#undef TARGET_DEFAULT_TARGET_FLAGS#define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | MASK_STRICT_ALIGNMENT)#undef TARGET_HANDLE_OPTION#define TARGET_HANDLE_OPTION m68k_handle_option#undef TARGET_RTX_COSTS#define TARGET_RTX_COSTS m68k_rtx_costs#undef TARGET_ATTRIBUTE_TABLE#define TARGET_ATTRIBUTE_TABLE m68k_attribute_table#undef TARGET_PROMOTE_PROTOTYPES#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true#undef TARGET_STRUCT_VALUE_RTX#define TARGET_STRUCT_VALUE_RTX m68k_struct_value_rtxstatic const struct attribute_spec m68k_attribute_table[] ={  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */  { "interrupt_handler", 0, 0, true,  false, false, m68k_handle_fndecl_attribute },  { NULL,                0, 0, false, false, false, NULL }};struct gcc_target targetm = TARGET_INITIALIZER;/* These bits are controlled by all CPU selection options.  Many options   also control MASK_68881, but some (notably -m68020) leave it alone.  */#define MASK_ALL_CPU_BITS \  (MASK_COLDFIRE | MASK_CF_HWDIV | MASK_68060 | MASK_68040 \   | MASK_68040_ONLY | MASK_68030 | MASK_68020 | MASK_BITFIELD)/* Implement TARGET_HANDLE_OPTION.  */static boolm68k_handle_option (size_t code, const char *arg, int value){  switch (code)    {    case OPT_m5200:      target_flags &= ~(MASK_ALL_CPU_BITS | MASK_68881);      target_flags |= MASK_5200;      return true;    case OPT_m5206e:      target_flags &= ~(MASK_ALL_CPU_BITS | MASK_68881);      target_flags |= MASK_5200 | MASK_CF_HWDIV;      return true;    case OPT_m528x:      target_flags &= ~(MASK_ALL_CPU_BITS | MASK_68881);      target_flags |= MASK_528x | MASK_CF_HWDIV;      return true;    case OPT_m5307:      target_flags &= ~(MASK_ALL_CPU_BITS | MASK_68881);      target_flags |= MASK_CFV3 | MASK_CF_HWDIV;      return true;    case OPT_m5407:      target_flags &= ~(MASK_ALL_CPU_BITS | MASK_68881);      target_flags |= MASK_CFV4 | MASK_CF_HWDIV;      return true;    case OPT_m68000:    case OPT_mc68000:      target_flags &= ~(MASK_ALL_CPU_BITS | MASK_68881);      return true;    case OPT_m68020:    case OPT_mc68020:      target_flags &= ~MASK_ALL_CPU_BITS;      target_flags |= MASK_68020 | MASK_BITFIELD;      return true;    case OPT_m68020_40:      target_flags &= ~MASK_ALL_CPU_BITS;      target_flags |= MASK_BITFIELD | MASK_68881 | MASK_68020 | MASK_68040;      return true;    case OPT_m68020_60:      target_flags &= ~MASK_ALL_CPU_BITS;      target_flags |= (MASK_BITFIELD | MASK_68881 | MASK_68020		       | MASK_68040 | MASK_68060);      return true;    case OPT_m68030:      target_flags &= ~MASK_ALL_CPU_BITS;      target_flags |= MASK_68020 | MASK_68030 | MASK_BITFIELD;      return true;    case OPT_m68040:      target_flags &= ~MASK_ALL_CPU_BITS;      target_flags |= (MASK_68020 | MASK_68881 | MASK_BITFIELD		       | MASK_68040_ONLY | MASK_68040);      return true;    case OPT_m68060:      target_flags &= ~MASK_ALL_CPU_BITS;      target_flags |= (MASK_68020 | MASK_68881 | MASK_BITFIELD		       | MASK_68040_ONLY | MASK_68060);      return true;    case OPT_m68302:      target_flags &= ~(MASK_ALL_CPU_BITS | MASK_68881);      return true;    case OPT_m68332:    case OPT_mcpu32:      target_flags &= ~(MASK_ALL_CPU_BITS | MASK_68881);      target_flags |= MASK_68020;      return true;    case OPT_mshared_library_id_:      if (value > MAX_LIBRARY_ID)	error ("-mshared-library-id=%s is not between 0 and %d",	       arg, MAX_LIBRARY_ID);      else	asprintf ((char **) &m68k_library_id_string, "%d", (value * -4) - 4);      return true;    default:      return true;    }}/* 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 (void){  /* Sanity check to ensure that msep-data and mid-sahred-library are not   * both specified together.  Doing so simply doesn't make sense.   */  if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)    error ("cannot specify both -msep-data and -mid-shared-library");  /* If we're generating code for a separate A5 relative data segment,   * we've got to enable -fPIC as well.  This might be relaxable to   * -fpic but it hasn't been tested properly.   */  if (TARGET_SEP_DATA || TARGET_ID_SHARED_LIBRARY)    flag_pic = 2;  /* -fPIC uses 32-bit pc-relative displacements, which don't exist     until the 68020.  */  if (!TARGET_68020 && !TARGET_COLDFIRE && (flag_pic == 2))    error ("-fPIC is not currently supported on the 68000 or 68010");  /* ??? 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;}/* Return nonzero if FUNC is an interrupt function as specified by the   "interrupt_handler" attribute.  */static boolm68k_interrupt_function_p(tree func){  tree a;  if (TREE_CODE (func) != FUNCTION_DECL)    return false;  a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));  return (a != NULL_TREE);}/* Handle an attribute requiring a FUNCTION_DECL; arguments as in   struct attribute_spec.handler.  */static treem68k_handle_fndecl_attribute (tree *node, tree name,			      tree args ATTRIBUTE_UNUSED,			      int flags ATTRIBUTE_UNUSED,			      bool *no_add_attrs){  if (TREE_CODE (*node) != FUNCTION_DECL)    {      warning (OPT_Wattributes, "%qs attribute only applies to functions",	       IDENTIFIER_POINTER (name));      *no_add_attrs = true;    }  return NULL_TREE;}static voidm68k_compute_frame_layout (void){  int regno, saved;  unsigned int mask, rmask;  bool interrupt_handler = m68k_interrupt_function_p (current_function_decl);  /* Only compute the frame once per function.     Don't cache information until reload has been completed.  */  if (current_frame.funcdef_no == current_function_funcdef_no      && reload_completed)    return;  current_frame.size = (get_frame_size () + 3) & -4;  mask = rmask = saved = 0;  for (regno = 0; regno < 16; regno++)    if (m68k_save_reg (regno, interrupt_handler))      {	mask |= 1 << regno;	rmask |= 1 << (15 - regno);	saved++;      }  current_frame.offset = saved * 4;  current_frame.reg_no = saved;  current_frame.reg_mask = mask;  current_frame.reg_rev_mask = rmask;  current_frame.foffset = 0;  mask = rmask = saved = 0;  if (TARGET_68881 /* || TARGET_CFV4E */)    {      for (regno = 16; regno < 24; regno++)	if (m68k_save_reg (regno, interrupt_handler))	  {	    mask |= 1 << (regno - 16);	    rmask |= 1 << (23 - regno);	    saved++;	  }      current_frame.foffset = saved * 12 /* (TARGET_CFV4E ? 8 : 12) */;      current_frame.offset += current_frame.foffset;    }  current_frame.fpu_no = saved;  current_frame.fpu_mask = mask;  current_frame.fpu_rev_mask = rmask;  /* Remember what function this frame refers to.  */  current_frame.funcdef_no = current_function_funcdef_no;}HOST_WIDE_INTm68k_initial_elimination_offset (int from, int to){  /* FIXME: The correct offset to compute here would appear to be

⌨️ 快捷键说明

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