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

📄 m68hc11.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines for code generation on Motorola 68HC11 and 68HC12.   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005   Free Software Foundation, Inc.   Contributed by Stephane Carrez (stcarrez@nerim.fr)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, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.Note:   A first 68HC11 port was made by Otto Lind (otto@coactive.com)   on gcc 2.6.3.  I have used it as a starting point for this port.   However, this new port is a complete re-write.  Its internal   design is completely different.  The generated code is not   compatible with the gcc 2.6.3 port.   The gcc 2.6.3 port is available at:   ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz*/#include <stdio.h>#include "config.h"#include "system.h"#include "coretypes.h"#include "tm.h"#include "rtl.h"#include "tree.h"#include "tm_p.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 "flags.h"#include "recog.h"#include "expr.h"#include "libfuncs.h"#include "toplev.h"#include "basic-block.h"#include "function.h"#include "ggc.h"#include "reload.h"#include "target.h"#include "target-def.h"static void emit_move_after_reload (rtx, rtx, rtx);static rtx simplify_logical (enum machine_mode, int, rtx, rtx *);static void m68hc11_emit_logical (enum machine_mode, int, rtx *);static void m68hc11_reorg (void);static int go_if_legitimate_address_internal (rtx, enum machine_mode, int);static int register_indirect_p (rtx, enum machine_mode, int);static rtx m68hc11_expand_compare (enum rtx_code, rtx, rtx);static int must_parenthesize (rtx);static int m68hc11_address_cost (rtx);static int m68hc11_shift_cost (enum machine_mode, rtx, int);static int m68hc11_rtx_costs_1 (rtx, enum rtx_code, enum rtx_code);static bool m68hc11_rtx_costs (rtx, int, int, int *);static int m68hc11_auto_inc_p (rtx);static tree m68hc11_handle_fntype_attribute (tree *, tree, tree, int, bool *);const struct attribute_spec m68hc11_attribute_table[];void create_regs_rtx (void);static void asm_print_register (FILE *, int);static void m68hc11_output_function_epilogue (FILE *, HOST_WIDE_INT);static void m68hc11_asm_out_constructor (rtx, int);static void m68hc11_asm_out_destructor (rtx, int);static void m68hc11_file_start (void);static void m68hc11_encode_section_info (tree, rtx, int);static const char *m68hc11_strip_name_encoding (const char* str);static unsigned int m68hc11_section_type_flags (tree, const char*, int);static int autoinc_mode (rtx);static int m68hc11_make_autoinc_notes (rtx *, void *);static void m68hc11_init_libfuncs (void);static rtx m68hc11_struct_value_rtx (tree, int);static bool m68hc11_return_in_memory (tree, tree);/* Must be set to 1 to produce debug messages.  */int debug_m6811 = 0;extern FILE *asm_out_file;rtx ix_reg;rtx iy_reg;rtx d_reg;rtx m68hc11_soft_tmp_reg;static GTY(()) rtx stack_push_word;static GTY(()) rtx stack_pop_word;static GTY(()) rtx z_reg;static GTY(()) rtx z_reg_qi;static int regs_inited = 0;/* Set to 1 by expand_prologue() when the function is an interrupt handler.  */int current_function_interrupt;/* Set to 1 by expand_prologue() when the function is a trap handler.  */int current_function_trap;/* Set to 1 when the current function is placed in 68HC12 banked   memory and must return with rtc.  */int current_function_far;/* Min offset that is valid for the indirect addressing mode.  */HOST_WIDE_INT m68hc11_min_offset = 0;/* Max offset that is valid for the indirect addressing mode.  */HOST_WIDE_INT m68hc11_max_offset = 256;/* The class value for base registers.  */enum reg_class m68hc11_base_reg_class = A_REGS;/* The class value for index registers.  This is NO_REGS for 68HC11.  */enum reg_class m68hc11_index_reg_class = NO_REGS;enum reg_class m68hc11_tmp_regs_class = NO_REGS;/* Tables that tell whether a given hard register is valid for   a base or an index register.  It is filled at init time depending   on the target processor.  */unsigned char m68hc11_reg_valid_for_base[FIRST_PSEUDO_REGISTER];unsigned char m68hc11_reg_valid_for_index[FIRST_PSEUDO_REGISTER];/* A correction offset which is applied to the stack pointer.   This is 1 for 68HC11 and 0 for 68HC12.  */int m68hc11_sp_correction;#define ADDR_STRICT       0x01  /* Accept only registers in class A_REGS  */#define ADDR_INCDEC       0x02  /* Post/Pre inc/dec */#define ADDR_INDEXED      0x04  /* D-reg index */#define ADDR_OFFSET       0x08#define ADDR_INDIRECT     0x10  /* Accept (mem (mem ...)) for [n,X] */#define ADDR_CONST        0x20  /* Accept const and symbol_ref  */int m68hc11_addr_mode;int m68hc11_mov_addr_mode;/* Comparison operands saved by the "tstxx" and "cmpxx" expand patterns.  */rtx m68hc11_compare_op0;rtx m68hc11_compare_op1;const struct processor_costs *m68hc11_cost;/* Costs for a 68HC11.  */static const struct processor_costs m6811_cost = {  /* add */  COSTS_N_INSNS (2),  /* logical */  COSTS_N_INSNS (2),  /* non-constant shift */  COSTS_N_INSNS (20),  /* shiftQI const */  { COSTS_N_INSNS (0), COSTS_N_INSNS (1), COSTS_N_INSNS (2),    COSTS_N_INSNS (3), COSTS_N_INSNS (4), COSTS_N_INSNS (3),    COSTS_N_INSNS (2), COSTS_N_INSNS (1) },  /* shiftHI const */  { COSTS_N_INSNS (0), COSTS_N_INSNS (1), COSTS_N_INSNS (4),    COSTS_N_INSNS (6), COSTS_N_INSNS (8), COSTS_N_INSNS (6),    COSTS_N_INSNS (4), COSTS_N_INSNS (2),    COSTS_N_INSNS (2), COSTS_N_INSNS (4),    COSTS_N_INSNS (6), COSTS_N_INSNS (8), COSTS_N_INSNS (10),    COSTS_N_INSNS (8), COSTS_N_INSNS (6), COSTS_N_INSNS (4)  },  /* mulQI */  COSTS_N_INSNS (20),  /* mulHI */  COSTS_N_INSNS (20 * 4),  /* mulSI */  COSTS_N_INSNS (20 * 16),  /* divQI */  COSTS_N_INSNS (20),  /* divHI */  COSTS_N_INSNS (80),  /* divSI */  COSTS_N_INSNS (100)};/* Costs for a 68HC12.  */static const struct processor_costs m6812_cost = {  /* add */  COSTS_N_INSNS (2),  /* logical */  COSTS_N_INSNS (2),  /* non-constant shift */  COSTS_N_INSNS (20),  /* shiftQI const */  { COSTS_N_INSNS (0), COSTS_N_INSNS (1), COSTS_N_INSNS (2),    COSTS_N_INSNS (3), COSTS_N_INSNS (4), COSTS_N_INSNS (3),    COSTS_N_INSNS (2), COSTS_N_INSNS (1) },  /* shiftHI const */  { COSTS_N_INSNS (0), COSTS_N_INSNS (1), COSTS_N_INSNS (4),    COSTS_N_INSNS (6), COSTS_N_INSNS (8), COSTS_N_INSNS (6),    COSTS_N_INSNS (4), COSTS_N_INSNS (2),    COSTS_N_INSNS (2), COSTS_N_INSNS (4), COSTS_N_INSNS (6),    COSTS_N_INSNS (8), COSTS_N_INSNS (10), COSTS_N_INSNS (8),    COSTS_N_INSNS (6), COSTS_N_INSNS (4)  },  /* mulQI */  COSTS_N_INSNS (3),  /* mulHI */  COSTS_N_INSNS (3),  /* mulSI */  COSTS_N_INSNS (3 * 4),  /* divQI */  COSTS_N_INSNS (12),  /* divHI */  COSTS_N_INSNS (12),  /* divSI */  COSTS_N_INSNS (100)};/* Machine specific options */const char *m68hc11_regparm_string;const char *m68hc11_reg_alloc_order;const char *m68hc11_soft_reg_count;static int nb_soft_regs;/* Initialize the GCC target structure.  */#undef TARGET_ATTRIBUTE_TABLE#define TARGET_ATTRIBUTE_TABLE m68hc11_attribute_table#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"#undef TARGET_ASM_FUNCTION_EPILOGUE#define TARGET_ASM_FUNCTION_EPILOGUE m68hc11_output_function_epilogue#undef TARGET_ASM_FILE_START#define TARGET_ASM_FILE_START m68hc11_file_start#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true#undef TARGET_ENCODE_SECTION_INFO#define TARGET_ENCODE_SECTION_INFO  m68hc11_encode_section_info#undef TARGET_SECTION_TYPE_FLAGS#define TARGET_SECTION_TYPE_FLAGS m68hc11_section_type_flags#undef TARGET_RTX_COSTS#define TARGET_RTX_COSTS m68hc11_rtx_costs#undef TARGET_ADDRESS_COST#define TARGET_ADDRESS_COST m68hc11_address_cost#undef TARGET_MACHINE_DEPENDENT_REORG#define TARGET_MACHINE_DEPENDENT_REORG m68hc11_reorg#undef TARGET_INIT_LIBFUNCS#define TARGET_INIT_LIBFUNCS m68hc11_init_libfuncs#undef TARGET_STRUCT_VALUE_RTX#define TARGET_STRUCT_VALUE_RTX m68hc11_struct_value_rtx#undef TARGET_RETURN_IN_MEMORY#define TARGET_RETURN_IN_MEMORY m68hc11_return_in_memory#undef TARGET_CALLEE_COPIES#define TARGET_CALLEE_COPIES hook_callee_copies_named#undef TARGET_STRIP_NAME_ENCODING#define TARGET_STRIP_NAME_ENCODING m68hc11_strip_name_encodingstruct gcc_target targetm = TARGET_INITIALIZER;intm68hc11_override_options (void){  memset (m68hc11_reg_valid_for_index, 0,	  sizeof (m68hc11_reg_valid_for_index));  memset (m68hc11_reg_valid_for_base, 0, sizeof (m68hc11_reg_valid_for_base));  /* Compilation with -fpic generates a wrong code.  */  if (flag_pic)    {      warning ("-f%s ignored for 68HC11/68HC12 (not supported)",	       (flag_pic > 1) ? "PIC" : "pic");      flag_pic = 0;    }  /* Do not enable -fweb because it breaks the 32-bit shift patterns     by breaking the match_dup of those patterns.  The shift patterns     will no longer be recognized after that.  */  flag_web = 0;  /* Configure for a 68hc11 processor.  */  if (TARGET_M6811)    {      /* If gcc was built for a 68hc12, invalidate that because         a -m68hc11 option was specified on the command line.  */      if (TARGET_DEFAULT != MASK_M6811)        target_flags &= ~TARGET_DEFAULT;      if (!TARGET_M6812)        target_flags &= ~(TARGET_AUTO_INC_DEC | TARGET_MIN_MAX);      m68hc11_cost = &m6811_cost;      m68hc11_min_offset = 0;      m68hc11_max_offset = 256;      m68hc11_index_reg_class = NO_REGS;      m68hc11_base_reg_class = A_REGS;      m68hc11_reg_valid_for_base[HARD_X_REGNUM] = 1;      m68hc11_reg_valid_for_base[HARD_Y_REGNUM] = 1;      m68hc11_reg_valid_for_base[HARD_Z_REGNUM] = 1;      m68hc11_sp_correction = 1;      m68hc11_tmp_regs_class = D_REGS;      m68hc11_addr_mode = ADDR_OFFSET;      m68hc11_mov_addr_mode = 0;      if (m68hc11_soft_reg_count == 0 && !TARGET_M6812)	m68hc11_soft_reg_count = "4";    }  /* Configure for a 68hc12 processor.  */  if (TARGET_M6812)    {      m68hc11_cost = &m6812_cost;      m68hc11_min_offset = -65536;      m68hc11_max_offset = 65536;      m68hc11_index_reg_class = D_REGS;      m68hc11_base_reg_class = A_OR_SP_REGS;      m68hc11_reg_valid_for_base[HARD_X_REGNUM] = 1;      m68hc11_reg_valid_for_base[HARD_Y_REGNUM] = 1;      m68hc11_reg_valid_for_base[HARD_Z_REGNUM] = 1;      m68hc11_reg_valid_for_base[HARD_SP_REGNUM] = 1;      m68hc11_reg_valid_for_index[HARD_D_REGNUM] = 1;      m68hc11_sp_correction = 0;      m68hc11_tmp_regs_class = TMP_REGS;      m68hc11_addr_mode = ADDR_INDIRECT | ADDR_OFFSET | ADDR_CONST        | (TARGET_AUTO_INC_DEC ? ADDR_INCDEC : 0);      m68hc11_mov_addr_mode = ADDR_OFFSET | ADDR_CONST        | (TARGET_AUTO_INC_DEC ? ADDR_INCDEC : 0);      target_flags &= ~MASK_M6811;      target_flags |= MASK_NO_DIRECT_MODE;      if (m68hc11_soft_reg_count == 0)	m68hc11_soft_reg_count = "0";      if (TARGET_LONG_CALLS)        current_function_far = 1;    }  return 0;}voidm68hc11_conditional_register_usage (void){  int i;  int cnt = atoi (m68hc11_soft_reg_count);  if (cnt < 0)    cnt = 0;  if (cnt > SOFT_REG_LAST - SOFT_REG_FIRST)    cnt = SOFT_REG_LAST - SOFT_REG_FIRST;  nb_soft_regs = cnt;  for (i = SOFT_REG_FIRST + cnt; i < SOFT_REG_LAST; i++)    {      fixed_regs[i] = 1;      call_used_regs[i] = 1;    }  /* For 68HC12, the Z register emulation is not necessary when the     frame pointer is not used.  The frame pointer is eliminated and     replaced by the stack register (which is a BASE_REG_CLASS).  */  if (TARGET_M6812 && flag_omit_frame_pointer && optimize)    {      fixed_regs[HARD_Z_REGNUM] = 1;    }}/* Reload and register operations.  */voidcreate_regs_rtx (void){  /*  regs_inited = 1; */  ix_reg = gen_rtx_REG (HImode, HARD_X_REGNUM);  iy_reg = gen_rtx_REG (HImode, HARD_Y_REGNUM);  d_reg = gen_rtx_REG (HImode, HARD_D_REGNUM);  m68hc11_soft_tmp_reg = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);  stack_push_word = gen_rtx_MEM (HImode,			     gen_rtx_PRE_DEC (HImode,				      gen_rtx_REG (HImode, HARD_SP_REGNUM)));  stack_pop_word = gen_rtx_MEM (HImode,			    gen_rtx_POST_INC (HImode,				     gen_rtx_REG (HImode, HARD_SP_REGNUM)));}/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.    - 8 bit values are stored anywhere (except the SP register).    - 16 bit values can be stored in any register whose mode is 16    - 32 bit values can be stored in D, X registers or in a soft register      (except the last one because we need 2 soft registers)    - Values whose size is > 32 bit are not stored in real hard      registers.  They may be stored in soft registers if there are      enough of them.  */inthard_regno_mode_ok (int regno, enum machine_mode mode){  switch (GET_MODE_SIZE (mode))    {    case 8:      return S_REGNO_P (regno) && nb_soft_regs >= 4;    case 4:      return X_REGNO_P (regno) || (S_REGNO_P (regno) && nb_soft_regs >= 2);    case 2:      return G_REGNO_P (regno);    case 1:      /* We have to accept a QImode in X or Y registers.  Otherwise, the         reload pass will fail when some (SUBREG:QI (REG:HI X)) are defined         in the insns.  Reload fails if the insn rejects the register class 'a'         as well as if it accepts it.  Patterns that failed were         zero_extend_qihi2 and iorqi3.  */      return G_REGNO_P (regno) && !SP_REGNO_P (regno);    default:      return 0;    }}intm68hc11_hard_regno_rename_ok (int reg1, int reg2){  /* Don't accept renaming to Z register.  We will replace it to     X,Y or D during machine reorg pass.  */  if (reg2 == HARD_Z_REGNUM)    return 0;  /* Don't accept renaming D,X to Y register as the code will be bigger.  */  if (TARGET_M6811 && reg2 == HARD_Y_REGNUM      && (D_REGNO_P (reg1) || X_REGNO_P (reg1)))    return 0;  return 1;}enum reg_classpreferred_reload_class (rtx operand, enum reg_class class){  enum machine_mode mode;  mode = GET_MODE (operand);  if (debug_m6811)    {      printf ("Preferred reload: (class=%s): ", reg_class_names[class]);    }  if (class == D_OR_A_OR_S_REGS && SP_REG_P (operand))    return m68hc11_base_reg_class;  if (class >= S_REGS && (GET_CODE (operand) == MEM			  || GET_CODE (operand) == CONST_INT))

⌨️ 快捷键说明

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