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

📄 m68hc11.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    {      /* S_REGS class must not be used.  The movhi template does not         work to move a memory to a soft register.         Restrict to a hard reg.  */      switch (class)	{	default:	case G_REGS:	case D_OR_A_OR_S_REGS:	  class = A_OR_D_REGS;	  break;	case A_OR_S_REGS:	  class = A_REGS;	  break;	case D_OR_SP_OR_S_REGS:	  class = D_OR_SP_REGS;	  break;	case D_OR_Y_OR_S_REGS:	  class = D_OR_Y_REGS;	  break;	case D_OR_X_OR_S_REGS:	  class = D_OR_X_REGS;	  break;	case SP_OR_S_REGS:	  class = SP_REGS;	  break;	case Y_OR_S_REGS:	  class = Y_REGS;	  break;	case X_OR_S_REGS:	  class = X_REGS;	  break;	case D_OR_S_REGS:	  class = D_REGS;	}    }  else if (class == Y_REGS && GET_CODE (operand) == MEM)    {      class = Y_REGS;    }  else if (class == A_OR_D_REGS && GET_MODE_SIZE (mode) == 4)    {      class = D_OR_X_REGS;    }  else if (class >= S_REGS && S_REG_P (operand))    {      switch (class)	{	default:	case G_REGS:	case D_OR_A_OR_S_REGS:	  class = A_OR_D_REGS;	  break;	case A_OR_S_REGS:	  class = A_REGS;	  break;	case D_OR_SP_OR_S_REGS:	  class = D_OR_SP_REGS;	  break;	case D_OR_Y_OR_S_REGS:	  class = D_OR_Y_REGS;	  break;	case D_OR_X_OR_S_REGS:	  class = D_OR_X_REGS;	  break;	case SP_OR_S_REGS:	  class = SP_REGS;	  break;	case Y_OR_S_REGS:	  class = Y_REGS;	  break;	case X_OR_S_REGS:	  class = X_REGS;	  break;	case D_OR_S_REGS:	  class = D_REGS;	}    }  else if (class >= S_REGS)    {      if (debug_m6811)	{	  printf ("Class = %s for: ", reg_class_names[class]);	  fflush (stdout);	  debug_rtx (operand);	}    }  if (debug_m6811)    {      printf (" => class=%s\n", reg_class_names[class]);      fflush (stdout);      debug_rtx (operand);    }  return class;}/* Return 1 if the operand is a valid indexed addressing mode.   For 68hc11:  n,r    with n in [0..255] and r in A_REGS class   For 68hc12:  n,r    no constraint on the constant, r in A_REGS class.  */static intregister_indirect_p (rtx operand, enum machine_mode mode, int addr_mode){  rtx base, offset;  switch (GET_CODE (operand))    {    case MEM:      if ((addr_mode & ADDR_INDIRECT) && GET_MODE_SIZE (mode) <= 2)        return register_indirect_p (XEXP (operand, 0), mode,                                    addr_mode & (ADDR_STRICT | ADDR_OFFSET));      return 0;    case POST_INC:    case PRE_INC:    case POST_DEC:    case PRE_DEC:      if (addr_mode & ADDR_INCDEC)	return register_indirect_p (XEXP (operand, 0), mode,                                    addr_mode & ADDR_STRICT);      return 0;    case PLUS:      base = XEXP (operand, 0);      if (GET_CODE (base) == MEM)	return 0;      offset = XEXP (operand, 1);      if (GET_CODE (offset) == MEM)	return 0;      /* Indexed addressing mode with 2 registers.  */      if (GET_CODE (base) == REG && GET_CODE (offset) == REG)        {          if (!(addr_mode & ADDR_INDEXED))            return 0;          addr_mode &= ADDR_STRICT;          if (REGNO_OK_FOR_BASE_P2 (REGNO (base), addr_mode)              && REGNO_OK_FOR_INDEX_P2 (REGNO (offset), addr_mode))            return 1;          if (REGNO_OK_FOR_BASE_P2 (REGNO (offset), addr_mode)              && REGNO_OK_FOR_INDEX_P2 (REGNO (base), addr_mode))            return 1;          return 0;        }      if (!(addr_mode & ADDR_OFFSET))        return 0;      if (GET_CODE (base) == REG)	{          if (!VALID_CONSTANT_OFFSET_P (offset, mode))	    return 0;	  if (!(addr_mode & ADDR_STRICT))	    return 1;	  return REGNO_OK_FOR_BASE_P2 (REGNO (base), 1);	}      if (GET_CODE (offset) == REG)	{	  if (!VALID_CONSTANT_OFFSET_P (base, mode))	    return 0;	  if (!(addr_mode & ADDR_STRICT))	    return 1;	  return REGNO_OK_FOR_BASE_P2 (REGNO (offset), 1);	}      return 0;    case REG:      return REGNO_OK_FOR_BASE_P2 (REGNO (operand), addr_mode & ADDR_STRICT);    case CONST_INT:      if (addr_mode & ADDR_CONST)        return VALID_CONSTANT_OFFSET_P (operand, mode);      return 0;    default:      return 0;    }}/* Returns 1 if the operand fits in a 68HC11 indirect mode or in   a 68HC12 1-byte index addressing mode.  */intm68hc11_small_indexed_indirect_p (rtx operand, enum machine_mode mode){  rtx base, offset;  int addr_mode;  if (GET_CODE (operand) == REG && reload_in_progress      && REGNO (operand) >= FIRST_PSEUDO_REGISTER      && reg_equiv_memory_loc[REGNO (operand)])    {      operand = reg_equiv_memory_loc[REGNO (operand)];      operand = eliminate_regs (operand, 0, NULL_RTX);    }  if (GET_CODE (operand) != MEM)    return 0;  operand = XEXP (operand, 0);  if (CONSTANT_ADDRESS_P (operand))    return 1;  if (PUSH_POP_ADDRESS_P (operand))    return 1;  addr_mode = m68hc11_mov_addr_mode | (reload_completed ? ADDR_STRICT : 0);  if (!register_indirect_p (operand, mode, addr_mode))    return 0;  if (TARGET_M6812 && GET_CODE (operand) == PLUS      && (reload_completed | reload_in_progress))    {      base = XEXP (operand, 0);      offset = XEXP (operand, 1);      /* The offset can be a symbol address and this is too big         for the operand constraint.  */      if (GET_CODE (base) != CONST_INT && GET_CODE (offset) != CONST_INT)        return 0;      if (GET_CODE (base) == CONST_INT)	offset = base;      switch (GET_MODE_SIZE (mode))	{	case 8:	  if (INTVAL (offset) < -16 + 6 || INTVAL (offset) > 15 - 6)	    return 0;	  break;	case 4:	  if (INTVAL (offset) < -16 + 2 || INTVAL (offset) > 15 - 2)	    return 0;	  break;	default:	  if (INTVAL (offset) < -16 || INTVAL (offset) > 15)	    return 0;	  break;	}    }  return 1;}intm68hc11_register_indirect_p (rtx operand, enum machine_mode mode){  int addr_mode;  if (GET_CODE (operand) == REG && reload_in_progress      && REGNO (operand) >= FIRST_PSEUDO_REGISTER      && reg_equiv_memory_loc[REGNO (operand)])    {      operand = reg_equiv_memory_loc[REGNO (operand)];      operand = eliminate_regs (operand, 0, NULL_RTX);    }  if (GET_CODE (operand) != MEM)    return 0;  operand = XEXP (operand, 0);  addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);  return register_indirect_p (operand, mode, addr_mode);}static intgo_if_legitimate_address_internal (rtx operand, enum machine_mode mode,                                   int strict){  int addr_mode;  if (CONSTANT_ADDRESS_P (operand) && TARGET_M6812)    {      /* Reject the global variables if they are too wide.  This forces         a load of their address in a register and generates smaller code.  */      if (GET_MODE_SIZE (mode) == 8)	return 0;      return 1;    }  addr_mode = m68hc11_addr_mode | (strict ? ADDR_STRICT : 0);  if (register_indirect_p (operand, mode, addr_mode))    {      return 1;    }  if (PUSH_POP_ADDRESS_P (operand))    {      return 1;    }  if (symbolic_memory_operand (operand, mode))    {      return 1;    }  return 0;}intm68hc11_go_if_legitimate_address (rtx operand, enum machine_mode mode,                                  int strict){  int result;  if (debug_m6811)    {      printf ("Checking: ");      fflush (stdout);      debug_rtx (operand);    }  result = go_if_legitimate_address_internal (operand, mode, strict);  if (debug_m6811)    {      printf (" -> %s\n", result == 0 ? "NO" : "YES");    }  if (result == 0)    {      if (debug_m6811)	{	  printf ("go_if_legitimate%s, ret 0: %d:",		  (strict ? "_strict" : ""), mode);	  fflush (stdout);	  debug_rtx (operand);	}    }  return result;}intm68hc11_legitimize_address (rtx *operand ATTRIBUTE_UNUSED,                            rtx old_operand ATTRIBUTE_UNUSED,                            enum machine_mode mode ATTRIBUTE_UNUSED){  return 0;}intm68hc11_reload_operands (rtx operands[]){  enum machine_mode mode;  if (regs_inited == 0)    create_regs_rtx ();  mode = GET_MODE (operands[1]);  /* Input reload of indirect addressing (MEM (PLUS (REG) (CONST))).  */  if (A_REG_P (operands[0]) && memory_reload_operand (operands[1], mode))    {      rtx big_offset = XEXP (XEXP (operands[1], 0), 1);      rtx base = XEXP (XEXP (operands[1], 0), 0);      if (GET_CODE (base) != REG)	{	  rtx tmp = base;	  base = big_offset;	  big_offset = tmp;	}      /* If the offset is out of range, we have to compute the address         with a separate add instruction.  We try to do with with an 8-bit         add on the A register.  This is possible only if the lowest part         of the offset (i.e., big_offset % 256) is a valid constant offset         with respect to the mode.  If it's not, we have to generate a         16-bit add on the D register.  From:                (SET (REG X (MEM (PLUS (REG X) (CONST_INT 1000)))))                we generate:                 [(SET (REG D) (REG X)) (SET (REG X) (REG D))]         (SET (REG A) (PLUS (REG A) (CONST_INT 1000 / 256)))         [(SET (REG D) (REG X)) (SET (REG X) (REG D))]         (SET (REG X) (MEM (PLUS (REG X) (CONST_INT 1000 % 256)))                (SET (REG X) (PLUS (REG X) (CONST_INT 1000 / 256 * 256)))         (SET (REG X) (MEM (PLUS (REG X) (CONST_INT 1000 % 256))))       */      if (!VALID_CONSTANT_OFFSET_P (big_offset, mode))	{	  int vh, vl;	  rtx reg = operands[0];	  rtx offset;	  int val = INTVAL (big_offset);	  /* We use the 'operands[0]' as a scratch register to compute the	     address. Make sure 'base' is in that register.  */	  if (!rtx_equal_p (base, operands[0]))	    {	      emit_move_insn (reg, base);	    }	  if (val > 0)	    {	      vh = val >> 8;	      vl = val & 0x0FF;	    }	  else	    {	      vh = (val >> 8) & 0x0FF;	      vl = val & 0x0FF;	    }	  /* Create the lowest part offset that still remains to be added.	     If it's not a valid offset, do a 16-bit add.  */	  offset = GEN_INT (vl);	  if (!VALID_CONSTANT_OFFSET_P (offset, mode))	    {	      emit_insn (gen_rtx_SET (VOIDmode, reg,				  gen_rtx_PLUS (HImode, reg, big_offset)));	      offset = const0_rtx;	    }	  else	    {	      emit_insn (gen_rtx_SET (VOIDmode, reg,				  gen_rtx_PLUS (HImode, reg,					   GEN_INT (vh << 8))));	    }	  emit_move_insn (operands[0],			  gen_rtx_MEM (GET_MODE (operands[1]),				   gen_rtx_PLUS (Pmode, reg, offset)));	  return 1;	}    }  /* Use the normal gen_movhi pattern.  */  return 0;}voidm68hc11_emit_libcall (const char *name, enum rtx_code code,                      enum machine_mode dmode, enum machine_mode smode,                      int noperands, rtx *operands){  rtx ret;  rtx insns;  rtx libcall;  rtx equiv;  start_sequence ();  libcall = gen_rtx_SYMBOL_REF (Pmode, name);  switch (noperands)    {    case 2:      ret = emit_library_call_value (libcall, NULL_RTX, LCT_CONST,                                     dmode, 1, operands[1], smode);      equiv = gen_rtx_fmt_e (code, dmode, operands[1]);      break;    case 3:      ret = emit_library_call_value (libcall, NULL_RTX,                                     LCT_CONST, dmode, 2,                                     operands[1], smode, operands[2],                                     smode);      equiv = gen_rtx_fmt_ee (code, dmode, operands[1], operands[2]);      break;    default:      abort ();    }  insns = get_insns ();  end_sequence ();  emit_libcall_block (insns, operands[0], ret, equiv);

⌨️ 快捷键说明

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