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

📄 tc-m68hc11.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
	  input_line_pointer = p;	  oper->reg2 = reg;	  return 1;	}      return 1;    }  /* In MRI mode, isolate the operand because we can't distinguish     operands from comments.  */  if (flag_mri)    {      char c = 0;      p = skip_whites (p);      while (*p && *p != ' ' && *p != '\t')	p++;      if (*p)	{	  c = *p;	  *p = 0;	}      /* Parse as an expression.  */      expression (&oper->exp);      if (c)	{	  *p = c;	}    }  else    {      expression (&oper->exp);    }  if (oper->exp.X_op == O_illegal)    {      as_bad (_("Illegal operand."));      return -1;    }  else if (oper->exp.X_op == O_absent)    {      as_bad (_("Missing operand."));      return -1;    }  p = input_line_pointer;  if (mode == M6811_OP_NONE || mode == M6811_OP_DIRECT      || mode == M6812_OP_IDX_2)    {      p = skip_whites (input_line_pointer);      if (*p == ',')	{	  int possible_mode = M6811_OP_NONE;	  char *old_input_line;	  p++;	  /* 68HC12 pre increment or decrement.  */	  if (mode == M6811_OP_NONE)	    {	      if (*p == '-')		{		  possible_mode = M6812_PRE_DEC;		  p++;		}	      else if (*p == '+')		{		  possible_mode = M6812_PRE_INC;		  p++;		}	      p = skip_whites (p);	    }	  old_input_line = input_line_pointer;	  input_line_pointer = p;	  reg = register_name ();	  /* Backtrack if we have a valid constant expression and	     it does not correspond to the offset of the 68HC12 indexed	     addressing mode (as in N,x).  */	  if (reg == REG_NONE && mode == M6811_OP_NONE	      && possible_mode != M6811_OP_NONE)	    {	      oper->mode = M6811_OP_IND16 | M6811_OP_JUMP_REL;	      input_line_pointer = skip_whites (old_input_line);	      return 1;	    }	  if (possible_mode != M6811_OP_NONE)	    mode = possible_mode;	  if ((current_architecture & cpu6811)	      && possible_mode != M6811_OP_NONE)	    as_bad (_("Pre-increment mode is not valid for 68HC11"));	  /* Backtrack.  */	  if (which == 0 && opmode & M6812_OP_IDX_P2	      && reg != REG_X && reg != REG_Y	      && reg != REG_PC && reg != REG_SP)	    {	      reg = REG_NONE;	      input_line_pointer = p;	    }	  if (reg == REG_NONE && mode != M6811_OP_DIRECT	      && !(mode == M6811_OP_NONE && opmode & M6811_OP_IND16))	    {	      as_bad (_("Wrong register in register indirect mode."));	      return -1;	    }	  if (mode == M6812_OP_IDX_2)	    {	      p = skip_whites (input_line_pointer);	      if (*p++ != ']')		{		  as_bad (_("Missing `]' to close register indirect operand."));		  return -1;		}	      input_line_pointer = p;	    }	  if (reg != REG_NONE)	    {	      oper->reg1 = reg;	      if (mode == M6811_OP_NONE)		{		  p = input_line_pointer;		  if (*p == '-')		    {		      mode = M6812_POST_DEC;		      p++;		      if (current_architecture & cpu6811)			as_bad			  (_("Post-decrement mode is not valid for 68HC11."));		    }		  else if (*p == '+')		    {		      mode = M6812_POST_INC;		      p++;		      if (current_architecture & cpu6811)			as_bad			  (_("Post-increment mode is not valid for 68HC11."));		    }		  else		    mode = M6812_OP_IDX;		  input_line_pointer = p;		}	      else		mode |= M6812_OP_IDX;	      oper->mode = mode;	      return 1;	    }	}      if (mode == M6812_OP_D_IDX_2)	{	  as_bad (_("Invalid indexed indirect mode."));	  return -1;	}    }  /* If the mode is not known until now, this is either a label     or an indirect address.  */  if (mode == M6811_OP_NONE)    mode = M6811_OP_IND16 | M6811_OP_JUMP_REL;  p = input_line_pointer;  while (*p == ' ' || *p == '\t')    p++;  input_line_pointer = p;  oper->mode = mode;  return 1;}#define M6812_AUTO_INC_DEC (M6812_PRE_INC | M6812_PRE_DEC \                            | M6812_POST_INC | M6812_POST_DEC)/* Checks that the number 'num' fits for a given mode.  */static intcheck_range (num, mode)     long num;     int mode;{  /* Auto increment and decrement are ok for [-8..8] without 0.  */  if (mode & M6812_AUTO_INC_DEC)    return (num != 0 && num <= 8 && num >= -8);  /* The 68HC12 supports 5, 9 and 16-bit offsets.  */  if (mode & (M6812_INDEXED_IND | M6812_INDEXED | M6812_OP_IDX))    mode = M6811_OP_IND16;  if (mode & M6812_OP_JUMP_REL16)    mode = M6811_OP_IND16;  switch (mode)    {    case M6811_OP_IX:    case M6811_OP_IY:    case M6811_OP_DIRECT:      return (num >= 0 && num <= 255) ? 1 : 0;    case M6811_OP_BITMASK:    case M6811_OP_IMM8:      return (((num & 0xFFFFFF00) == 0) || ((num & 0xFFFFFF00) == 0xFFFFFF00))	? 1 : 0;    case M6811_OP_JUMP_REL:      return (num >= -128 && num <= 127) ? 1 : 0;    case M6811_OP_IND16:    case M6811_OP_IMM16:      return (((num & 0xFFFF0000) == 0) || ((num & 0xFFFF0000) == 0xFFFF0000))	? 1 : 0;    case M6812_OP_IBCC_MARKER:    case M6812_OP_TBCC_MARKER:    case M6812_OP_DBCC_MARKER:      return (num >= -256 && num <= 255) ? 1 : 0;    case M6812_OP_TRAP_ID:      return ((num >= 0x30 && num <= 0x39)	      || (num >= 0x40 && num <= 0x0ff)) ? 1 : 0;    default:      return 0;    }}/* Gas fixup generation.  *//* Put a 1 byte expression described by 'oper'.  If this expression contains   unresolved symbols, generate an 8-bit fixup.  */static voidfixup8 (oper, mode, opmode)     expressionS *oper;     int mode;     int opmode;{  char *f;  f = frag_more (1);  if (oper->X_op == O_constant)    {      if (mode & M6812_OP_TRAP_ID	  && !check_range (oper->X_add_number, M6812_OP_TRAP_ID))	{	  static char trap_id_warn_once = 0;	  as_bad (_("Trap id `%ld' is out of range."), oper->X_add_number);	  if (trap_id_warn_once == 0)	    {	      trap_id_warn_once = 1;	      as_bad (_("Trap id must be within [0x30..0x39] or [0x40..0xff]."));	    }	}      if (!(mode & M6812_OP_TRAP_ID)	  && !check_range (oper->X_add_number, mode))	{	  as_bad (_("Operand out of 8-bit range: `%ld'."), oper->X_add_number);	}      number_to_chars_bigendian (f, oper->X_add_number & 0x0FF, 1);    }  else if (oper->X_op != O_register)    {      if (mode & M6812_OP_TRAP_ID)	as_bad (_("The trap id must be a constant."));      if (mode == M6811_OP_JUMP_REL)	{	  fixS *fixp;	  fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 1,			      oper, true, BFD_RELOC_8_PCREL);	  fixp->fx_pcrel_adjust = 1;	}      else	{	  /* Now create an 8-bit fixup.  If there was some %hi or %lo	     modifier, generate the reloc accordingly.  */	  fix_new_exp (frag_now, f - frag_now->fr_literal, 1,		       oper, false,		       ((opmode & M6811_OP_HIGH_ADDR)			? BFD_RELOC_M68HC11_HI8			: ((opmode & M6811_OP_LOW_ADDR)			   ? BFD_RELOC_M68HC11_LO8 : BFD_RELOC_8)));	}      number_to_chars_bigendian (f, 0, 1);    }  else    {      as_fatal (_("Operand `%x' not recognized in fixup8."), oper->X_op);    }}/* Put a 2 byte expression described by 'oper'.  If this expression contains   unresolved symbols, generate a 16-bit fixup.  */static voidfixup16 (oper, mode, opmode)     expressionS *oper;     int mode;     int opmode ATTRIBUTE_UNUSED;{  char *f;  f = frag_more (2);  if (oper->X_op == O_constant)    {      if (!check_range (oper->X_add_number, mode))	{	  as_bad (_("Operand out of 16-bit range: `%ld'."),		  oper->X_add_number);	}      number_to_chars_bigendian (f, oper->X_add_number & 0x0FFFF, 2);    }  else if (oper->X_op != O_register)    {      fixS *fixp;      /* Now create a 16-bit fixup.  */      fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 2,			  oper,			  (mode & M6812_OP_JUMP_REL16 ? true : false),			  (mode & M6812_OP_JUMP_REL16			   ? BFD_RELOC_16_PCREL : BFD_RELOC_16));      number_to_chars_bigendian (f, 0, 2);      if (mode & M6812_OP_JUMP_REL16)	fixp->fx_pcrel_adjust = 2;    }  else    {      as_fatal (_("Operand `%x' not recognized in fixup16."), oper->X_op);    }}/* 68HC11 and 68HC12 code generation.  *//* Translate the short branch/bsr instruction into a long branch.  */static unsigned charconvert_branch (code)     unsigned char code;{  if (IS_OPCODE (code, M6812_BSR))    return M6812_JSR;  else if (IS_OPCODE (code, M6811_BSR))    return M6811_JSR;  else if (IS_OPCODE (code, M6811_BRA))    return (current_architecture & cpu6812) ? M6812_JMP : M6811_JMP;  else    as_fatal (_("Unexpected branch conversion with `%x'"), code);  /* Keep gcc happy.  */  return M6811_JSR;}/* Start a new insn that contains at least 'size' bytes.  Record the   line information of that insn in the dwarf2 debug sections.  */static char *m68hc11_new_insn (size)     int size;{  char *f;  f = frag_more (size);  dwarf2_emit_insn (size);  return f;}/* Builds a jump instruction (bra, bcc, bsr).  */static voidbuild_jump_insn (opcode, operands, nb_operands, jmp_mode)     struct m68hc11_opcode *opcode;     operand operands[];     int nb_operands;     int jmp_mode;{  unsigned char code;  char *f;  unsigned long n;  /* The relative branch convertion is not supported for     brclr and brset.  */  assert ((opcode->format & M6811_OP_BITMASK) == 0);  assert (nb_operands == 1);  assert (operands[0].reg1 == REG_NONE && operands[0].reg2 == REG_NONE);  code = opcode->opcode;  n = operands[0].exp.X_add_number;  /* Turn into a long branch:     - when force long branch option (and not for jbcc pseudos),     - when jbcc and the constant is out of -128..127 range,     - when branch optimization is allowed and branch out of range.  */  if ((jmp_mode == 0 && flag_force_long_jumps)      || (operands[0].exp.X_op == O_constant	  && (!check_range (n, opcode->format) &&	      (jmp_mode == 1 || flag_fixed_branchs == 0))))    {      if (code == M6811_BSR || code == M6811_BRA || code == M6812_BSR)	{	  code = convert_branch (code);	  f = m68hc11_new_insn (1);	  number_to_chars_bigendian (f, code, 1);	}      else if (current_architecture & cpu6812)	{	  /* 68HC12: translate the bcc into a lbcc.  */	  f = m68hc11_new_insn (2);	  number_to_chars_bigendian (f, M6811_OPCODE_PAGE2, 1);	  number_to_chars_bigendian (f + 1, code, 1);	  fixup16 (&operands[0].exp, M6812_OP_JUMP_REL16,		   M6812_OP_JUMP_REL16);	  return;	}      else	{	  /* 68HC11: translate the bcc into b!cc +3; jmp <L>.  */	  f = m68hc11_new_insn (3);	  code ^= 1;	  number_to_chars_bigendian (f, code, 1);	  number_to_chars_bigendian (f + 1, 3, 1);	  number_to_chars_bigendian (f + 2, M6811_JMP, 1);	}      fixup16 (&operands[0].exp, M6811_OP_IND16, M6811_OP_IND16);      return;    }  /* Branch with a constant that must fit in 8-bits.  */  if (operands[0].exp.X_op == O_constant)    {      if (!check_range (n, opcode->format))	{	  as_bad (_("Operand out of range for a relative branch: `%ld'"),                  n);	}      else if (opcode->format & M6812_OP_JUMP_REL16)	{	  f = m68hc11_new_insn (4);	  number_to_chars_bigendian (f, M6811_OPCODE_PAGE2, 1);	  number_to_chars_bigendian (f + 1, code, 1);	  number_to_chars_bigendian (f + 2, n & 0x0ffff, 2);	}      else	{	  f = m68hc11_new_insn (2);	  number_to_chars_bigendian (f, code, 1);	  number_to_chars_bigendian (f + 1, n & 0x0FF, 1);	}    }  else if (opcode->format & M6812_OP_JUMP_REL16)    {      f = m68hc11_new_insn (2);      number_to_chars_bigendian (f, M6811_OPCODE_PAGE2, 1);      number_to_chars_bigendian (f + 1, code, 1);      fixup16 (&operands[0].exp, M6812_OP_JUMP_REL16, M6812_OP_JUMP_REL16);    }  else    {      char *opcode;      /* Branch offset must fit in 8-bits, don't do some relax.  */      if (jmp_mode == 0 && flag_fixed_branchs)	{	  opcode = m68hc11_new_insn (1);	  number_to_chars_bigendian (opcode, code, 1);	  fixup8 (&operands[0].exp, M6811_OP_JUMP_REL, M6811_OP_JUMP_REL);	}      /* bra/bsr made be changed into jmp/jsr.  */      else if (code == M6811_BSR || code == M6811_BRA || code == M6812_BSR)	{	  opcode = m68hc11_new_insn (2);	  number_to_chars_bigendian (opcode, code, 1);	  number_to_chars_bigendian (opcode + 1, 0, 1);	  frag_var (rs_machine_dependent, 2, 1,		    ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF),		    operands[0].exp.X_add_symbol, (offsetT) n, opcode);	}      else if (current_architecture & cpu6812)	{	  opcode = m68hc11_new_insn (2);	  number_to_chars_bigendian (opcode, code, 1);	  number_to_chars_bigendian (opcode + 1, 0, 1);	  frag_var (rs_machine_dependent, 2, 2,		    ENCODE_RELAX (STATE_CONDITIONAL_BRANCH_6812, STATE_UNDF),		    operands[0].exp.X_add_symbol, (offsetT) n, opcode);	}      else	{	  opcode = m68hc11_new_insn (2);	  number_to_chars_bigendian (opcode, code, 1);	  number_to_chars_bigendian (opcode + 1, 0, 1);	  frag_var (rs_machine_dependent, 3, 3,		    ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_UNDF),		    operands[0].exp.X_add_symbol, (offsetT) n, opcode);	}    }}/* Builds a dbne/dbeq/tbne/tbeq instruction.  */static voidbuild_dbranch_insn (opcode, operands, nb_operands, jmp_mode)     struct m68hc11_opcode *opcode;

⌨️ 快捷键说明

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