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

📄 tc-avr.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 3 页
字号:
  if (ex.X_add_number > max || ex.X_add_number < 0)    as_bad (_("number must be less than %d"), max + 1);  return ex.X_add_number;}/* Parse instruction operands.   Return binary opcode.  */static unsigned intavr_operands (opcode, line)     struct avr_opcodes_s *opcode;     char **line;{  char *op = opcode->constraints;  unsigned int bin = opcode->bin_opcode;  char *frag = frag_more (opcode->insn_size * 2);  char *str = *line;  int where = frag - frag_now->fr_literal;  static unsigned int prev = 0;  /* Previous opcode.  */  /* Opcode have operands.  */  if (*op)    {      unsigned int reg1 = 0;      unsigned int reg2 = 0;      int reg1_present = 0;      int reg2_present = 0;      /* Parse first operand.  */      if (REGISTER_P (*op))	reg1_present = 1;      reg1 = avr_operand (opcode, where, op, &str);      ++op;      /* Parse second operand.  */      if (*op)	{	  if (*op == ',')	    ++op;	  if (*op == '=')	    {	      reg2 = reg1;	      reg2_present = 1;	    }	  else	    {	      if (REGISTER_P (*op))		reg2_present = 1;	      str = skip_space (str);	      if (*str++ != ',')		as_bad (_("`,' required"));	      str = skip_space (str);	      reg2 = avr_operand (opcode, where, op, &str);	    }	  if (reg1_present && reg2_present)	    reg2 = (reg2 & 0xf) | ((reg2 << 5) & 0x200);	  else if (reg2_present)	    reg2 <<= 4;	}      if (reg1_present)	reg1 <<= 4;      bin |= reg1 | reg2;    }  /* Detect undefined combinations (like ld r31,Z+).  */  if (!avr_opt.all_opcodes && AVR_UNDEF_P (bin))    as_warn (_("undefined combination of operands"));  if (opcode->insn_size == 2)    {      /* Warn if the previous opcode was cpse/sbic/sbis/sbrc/sbrs         (AVR core bug, fixed in the newer devices).  */      if (!(avr_opt.no_skip_bug || (avr_mcu->isa & AVR_ISA_MUL))	  && AVR_SKIP_P (prev))	as_warn (_("skipping two-word instruction"));      bfd_putl32 ((bfd_vma) bin, frag);    }  else    bfd_putl16 ((bfd_vma) bin, frag);  prev = bin;  *line = str;  return bin;}/* Parse one instruction operand.   Return operand bitmask.  Also fixups can be generated.  */static unsigned intavr_operand (opcode, where, op, line)     struct avr_opcodes_s *opcode;     int where;     char *op;     char **line;{  expressionS op_expr;  unsigned int op_mask = 0;  char *str = skip_space (*line);  switch (*op)    {      /* Any register operand.  */    case 'w':    case 'd':    case 'r':    case 'a':    case 'v':      if (*str == 'r' || *str == 'R')	{	  char r_name[20];	  str = extract_word (str, r_name, sizeof (r_name));	  op_mask = 0xff;	  if (isdigit (r_name[1]))	    {	      if (r_name[2] == '\0')		op_mask = r_name[1] - '0';	      else if (r_name[1] != '0'		       && isdigit (r_name[2])		       && r_name[3] == '\0')		op_mask = (r_name[1] - '0') * 10 + r_name[2] - '0';	    }	}      else	{	  op_mask = avr_get_constant (str, 31);	  str = input_line_pointer;	}      if (op_mask <= 31)	{	  switch (*op)	    {	    case 'a':	      if (op_mask < 16 || op_mask > 23)		as_bad (_("register r16-r23 required"));	      op_mask -= 16;	      break;	    case 'd':	      if (op_mask < 16)		as_bad (_("register number above 15 required"));	      op_mask -= 16;	      break;	    case 'v':	      if (op_mask & 1)		as_bad (_("even register number required"));	      op_mask >>= 1;	      break;	    case 'w':	      if ((op_mask & 1) || op_mask < 24)		as_bad (_("register r24, r26, r28 or r30 required"));	      op_mask = (op_mask - 24) >> 1;	      break;	    }	  break;	}      as_bad (_("register name or number from 0 to 31 required"));      break;    case 'e':      {	char c;	if (*str == '-')	  {	    str = skip_space (str + 1);	    op_mask = 0x1002;	  }	c = tolower (*str);	if (c == 'x')	  op_mask |= 0x100c;	else if (c == 'y')	  op_mask |= 0x8;	else if (c != 'z')	  as_bad (_("pointer register (X, Y or Z) required"));	str = skip_space (str + 1);	if (*str == '+')	  {	    ++str;	    if (op_mask & 2)	      as_bad (_("cannot both predecrement and postincrement"));	    op_mask |= 0x1001;	  }	/* avr1 can do "ld r,Z" and "st Z,r" but no other pointer	   registers, no predecrement, no postincrement.  */	if (!avr_opt.all_opcodes && (op_mask & 0x100F)	    && !(avr_mcu->isa & AVR_ISA_SRAM))	  as_bad (_("addressing mode not supported"));      }      break;    case 'z':      if (*str == '-')	as_bad (_("can't predecrement"));      if (! (*str == 'z' || *str == 'Z'))	as_bad (_("pointer register Z required"));      str = skip_space (str + 1);      if (*str == '+')	{	  ++str;	  op_mask |= 1;	}      break;    case 'b':      {	char c = tolower (*str++);	if (c == 'y')	  op_mask |= 0x8;	else if (c != 'z')	  as_bad (_("pointer register (Y or Z) required"));	str = skip_space (str);	if (*str++ == '+')	  {	    unsigned int x;	    x = avr_get_constant (str, 63);	    str = input_line_pointer;	    op_mask |= (x & 7) | ((x & (3 << 3)) << 7) | ((x & (1 << 5)) << 8);	  }      }      break;    case 'h':      str = parse_exp (str, &op_expr);      fix_new_exp (frag_now, where, opcode->insn_size * 2,		   &op_expr, false, BFD_RELOC_AVR_CALL);      break;    case 'L':      str = parse_exp (str, &op_expr);      fix_new_exp (frag_now, where, opcode->insn_size * 2,		   &op_expr, true, BFD_RELOC_AVR_13_PCREL);      break;    case 'l':      str = parse_exp (str, &op_expr);      fix_new_exp (frag_now, where, opcode->insn_size * 2,		   &op_expr, true, BFD_RELOC_AVR_7_PCREL);      break;    case 'i':      str = parse_exp (str, &op_expr);      fix_new_exp (frag_now, where + 2, opcode->insn_size * 2,		   &op_expr, false, BFD_RELOC_16);      break;    case 'M':      {	bfd_reloc_code_real_type r_type;	input_line_pointer = str;	r_type = avr_ldi_expression (&op_expr);	str = input_line_pointer;	fix_new_exp (frag_now, where, 3,		     &op_expr, false, r_type);      }      break;    case 'n':      {	unsigned int x;	x = ~avr_get_constant (str, 255);	str = input_line_pointer;	op_mask |= (x & 0xf) | ((x << 4) & 0xf00);      }      break;    case 'K':      {	unsigned int x;	x = avr_get_constant (str, 63);	str = input_line_pointer;	op_mask |= (x & 0xf) | ((x & 0x30) << 2);      }      break;    case 'S':    case 's':      {	unsigned int x;	x = avr_get_constant (str, 7);	str = input_line_pointer;	if (*op == 'S')	  x <<= 4;	op_mask |= x;      }      break;    case 'P':      {	unsigned int x;	x = avr_get_constant (str, 63);	str = input_line_pointer;	op_mask |= (x & 0xf) | ((x & 0x30) << 5);      }      break;    case 'p':      {	unsigned int x;	x = avr_get_constant (str, 31);	str = input_line_pointer;	op_mask |= x << 3;      }      break;    case '?':      break;    default:      as_bad (_("unknown constraint `%c'"), *op);    }  *line = str;  return op_mask;}/* GAS will call this function for each section at the end of the assembly,   to permit the CPU backend to adjust the alignment of a section.  */valueTmd_section_align (seg, addr)     asection *seg;     valueT addr;{  int align = bfd_get_section_alignment (stdoutput, seg);  return ((addr + (1 << align) - 1) & (-1 << align));}/* If you define this macro, it should return the offset between the   address of a PC relative fixup and the position from which the PC   relative adjustment should be made.  On many processors, the base   of a PC relative instruction is the next instruction, so this   macro would return the length of an instruction.  */longmd_pcrel_from_section (fixp, sec)     fixS *fixp;     segT sec;{  if (fixp->fx_addsy != (symbolS *) NULL      && (!S_IS_DEFINED (fixp->fx_addsy)	  || (S_GET_SEGMENT (fixp->fx_addsy) != sec)))    return 0;  return fixp->fx_frag->fr_address + fixp->fx_where;}/* GAS will call this for each fixup.  It should store the correct   value in the object file.  */intmd_apply_fix3 (fixp, valuep, seg)     fixS *fixp;     valueT *valuep;     segT seg;{  unsigned char *where;  unsigned long insn;  long value;  if (fixp->fx_addsy == (symbolS *) NULL)    {      value = *valuep;      fixp->fx_done = 1;    }  else if (fixp->fx_pcrel)    {      segT s = S_GET_SEGMENT (fixp->fx_addsy);      if (fixp->fx_addsy && (s == seg || s == absolute_section))	{	  value = S_GET_VALUE (fixp->fx_addsy) + *valuep;	  fixp->fx_done = 1;	}      else	value = *valuep;    }  else    {      value = fixp->fx_offset;      if (fixp->fx_subsy != (symbolS *) NULL)	{	  if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)	    {	      value -= S_GET_VALUE (fixp->fx_subsy);	      fixp->fx_done = 1;	    }	  else	    {	      /* We don't actually support subtracting a symbol.  */	      as_bad_where (fixp->fx_file, fixp->fx_line,			    _("expression too complex"));	    }	}    }  switch (fixp->fx_r_type)    {    default:      fixp->fx_no_overflow = 1;      break;    case BFD_RELOC_AVR_7_PCREL:    case BFD_RELOC_AVR_13_PCREL:    case BFD_RELOC_32:    case BFD_RELOC_16:    case BFD_RELOC_AVR_CALL:      break;    }  if (fixp->fx_done)

⌨️ 快捷键说明

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