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

📄 tc-sh.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
   provided.  */static sh_opcode_info *get_specific (opcode, operands)     sh_opcode_info *opcode;     sh_operand_info *operands;{  sh_opcode_info *this_try = opcode;  char *name = opcode->name;  int n = 0;  while (opcode->name)    {      this_try = opcode++;      if (this_try->name != name)	{	  /* We've looked so far down the table that we've run out of	     opcodes with the same name.  */	  return 0;	}      /* Look at both operands needed by the opcodes and provided by         the user - since an arg test will often fail on the same arg         again and again, we'll try and test the last failing arg the         first on each opcode try.  */      for (n = 0; this_try->arg[n]; n++)	{	  sh_operand_info *user = operands + n;	  sh_arg_type arg = this_try->arg[n];	  switch (arg)	    {	    case A_IMM:	    case A_BDISP12:	    case A_BDISP8:	    case A_DISP_GBR:	    case A_DISP_PC:	    case A_MACH:	    case A_PR:	    case A_MACL:	      if (user->type != arg)		goto fail;	      break;	    case A_R0:	      /* opcode needs r0 */	      if (user->type != A_REG_N || user->reg != 0)		goto fail;	      break;	    case A_R0_GBR:	      if (user->type != A_R0_GBR || user->reg != 0)		goto fail;	      break;	    case F_FR0:	      if (user->type != F_REG_N || user->reg != 0)		goto fail;	      break;	    case A_REG_N:	    case A_INC_N:	    case A_DEC_N:	    case A_IND_N:	    case A_IND_R0_REG_N:	    case A_DISP_REG_N:	    case F_REG_N:	    case D_REG_N:	    case X_REG_N:	    case V_REG_N:	    case FPUL_N:	    case FPSCR_N:	    case A_PMOD_N:	    case A_PMODY_N:	    case DSP_REG_N:	      /* Opcode needs rn */	      if (user->type != arg)		goto fail;	      reg_n = user->reg;	      break;	    case DX_REG_N:	      if (user->type != D_REG_N && user->type != X_REG_N)		goto fail;	      reg_n = user->reg;	      break;	    case A_GBR:	    case A_SR:	    case A_VBR:	    case A_DSR:	    case A_MOD:	    case A_RE:	    case A_RS:	    case A_SSR:	    case A_SPC:	    case A_SGR:	    case A_DBR:	      if (user->type != arg)		goto fail;	      break;	    case A_REG_B:	      if (user->type != arg)		goto fail;	      reg_b = user->reg;	      break;	    case A_REG_M:	    case A_INC_M:	    case A_DEC_M:	    case A_IND_M:	    case A_IND_R0_REG_M:	    case A_DISP_REG_M:	    case DSP_REG_M:	      /* Opcode needs rn */	      if (user->type != arg - A_REG_M + A_REG_N)		goto fail;	      reg_m = user->reg;	      break;	    case DSP_REG_X:	      if (user->type != DSP_REG_N)		goto fail;	      switch (user->reg)		{		case A_X0_NUM:		  reg_x = 0;		  break;		case A_X1_NUM:		  reg_x = 1;		  break;		case A_A0_NUM:		  reg_x = 2;		  break;		case A_A1_NUM:		  reg_x = 3;		  break;		default:		  goto fail;		}	      break;	    case DSP_REG_Y:	      if (user->type != DSP_REG_N)		goto fail;	      switch (user->reg)		{		case A_Y0_NUM:		  reg_y = 0;		  break;		case A_Y1_NUM:		  reg_y = 1;		  break;		case A_M0_NUM:		  reg_y = 2;		  break;		case A_M1_NUM:		  reg_y = 3;		  break;		default:		  goto fail;		}	      break;	    case DSP_REG_E:	      if (user->type != DSP_REG_N)		goto fail;	      switch (user->reg)		{		case A_X0_NUM:		  reg_efg = 0 << 10;		  break;		case A_X1_NUM:		  reg_efg = 1 << 10;		  break;		case A_Y0_NUM:		  reg_efg = 2 << 10;		  break;		case A_A1_NUM:		  reg_efg = 3 << 10;		  break;		default:		  goto fail;		}	      break;	    case DSP_REG_F:	      if (user->type != DSP_REG_N)		goto fail;	      switch (user->reg)		{		case A_Y0_NUM:		  reg_efg |= 0 << 8;		  break;		case A_Y1_NUM:		  reg_efg |= 1 << 8;		  break;		case A_X0_NUM:		  reg_efg |= 2 << 8;		  break;		case A_A1_NUM:		  reg_efg |= 3 << 8;		  break;		default:		  goto fail;		}	      break;	    case DSP_REG_G:	      if (user->type != DSP_REG_N)		goto fail;	      switch (user->reg)		{		case A_M0_NUM:		  reg_efg |= 0 << 2;		  break;		case A_M1_NUM:		  reg_efg |= 1 << 2;		  break;		case A_A0_NUM:		  reg_efg |= 2 << 2;		  break;		case A_A1_NUM:		  reg_efg |= 3 << 2;		  break;		default:		  goto fail;		}	      break;	    case A_A0:	      if (user->type != DSP_REG_N || user->reg != A_A0_NUM)		goto fail;	      break;	    case A_X0:	      if (user->type != DSP_REG_N || user->reg != A_X0_NUM)		goto fail;	      break;	    case A_X1:	      if (user->type != DSP_REG_N || user->reg != A_X1_NUM)		goto fail;	      break;	    case A_Y0:	      if (user->type != DSP_REG_N || user->reg != A_Y0_NUM)		goto fail;	      break;	    case A_Y1:	      if (user->type != DSP_REG_N || user->reg != A_Y1_NUM)		goto fail;	      break;	    case F_REG_M:	    case D_REG_M:	    case X_REG_M:	    case V_REG_M:	    case FPUL_M:	    case FPSCR_M:	      /* Opcode needs rn */	      if (user->type != arg - F_REG_M + F_REG_N)		goto fail;	      reg_m = user->reg;	      break;	    case DX_REG_M:	      if (user->type != D_REG_N && user->type != X_REG_N)		goto fail;	      reg_m = user->reg;	      break;	    case XMTRX_M4:	      if (user->type != XMTRX_M4)		goto fail;	      reg_m = 4;	      break;	    default:	      printf (_("unhandled %d\n"), arg);	      goto fail;	    }	}      if ( !(valid_arch & this_try->arch))	goto fail;      valid_arch &= this_try->arch;      return this_try;    fail:      ;    }  return 0;}intcheck (operand, low, high)     expressionS *operand;     int low;     int high;{  if (operand->X_op != O_constant      || operand->X_add_number < low      || operand->X_add_number > high)    {      as_bad (_("operand must be absolute in range %d..%d"), low, high);    }  return operand->X_add_number;}static voidinsert (where, how, pcrel, op)     char *where;     int how;     int pcrel;     sh_operand_info *op;{  fix_new_exp (frag_now,	       where - frag_now->fr_literal,	       2,	       &op->immediate,	       pcrel,	       how);}static voidbuild_relax (opcode, op)     sh_opcode_info *opcode;     sh_operand_info *op;{  int high_byte = target_big_endian ? 0 : 1;  char *p;  if (opcode->arg[0] == A_BDISP8)    {      int what = (opcode->nibbles[1] & 4) ? COND_JUMP_DELAY : COND_JUMP;      p = frag_var (rs_machine_dependent,		    md_relax_table[C (what, COND32)].rlx_length,		    md_relax_table[C (what, COND8)].rlx_length,		    C (what, 0),		    op->immediate.X_add_symbol,		    op->immediate.X_add_number,		    0);      p[high_byte] = (opcode->nibbles[0] << 4) | (opcode->nibbles[1]);    }  else if (opcode->arg[0] == A_BDISP12)    {      p = frag_var (rs_machine_dependent,		    md_relax_table[C (UNCOND_JUMP, UNCOND32)].rlx_length,		    md_relax_table[C (UNCOND_JUMP, UNCOND12)].rlx_length,		    C (UNCOND_JUMP, 0),		    op->immediate.X_add_symbol,		    op->immediate.X_add_number,		    0);      p[high_byte] = (opcode->nibbles[0] << 4);    }}/* Insert ldrs & ldre with fancy relocations that relaxation can recognize.  */static char *insert_loop_bounds (output, operand)     char *output;     sh_operand_info *operand;{  char *name;  symbolS *end_sym;  /* Since the low byte of the opcode will be overwritten by the reloc, we     can just stash the high byte into both bytes and ignore endianness.  */  output[0] = 0x8c;  output[1] = 0x8c;  insert (output, BFD_RELOC_SH_LOOP_START, 1, operand);  insert (output, BFD_RELOC_SH_LOOP_END, 1, operand + 1);  if (sh_relax)    {      static int count = 0;      /* If the last loop insn is a two-byte-insn, it is in danger of being	 swapped with the insn after it.  To prevent this, create a new	 symbol - complete with SH_LABEL reloc - after the last loop insn.	 If the last loop insn is four bytes long, the symbol will be	 right in the middle, but four byte insns are not swapped anyways.  */      /* A REPEAT takes 6 bytes.  The SH has a 32 bit address space.	 Hence a 9 digit number should be enough to count all REPEATs.  */      name = alloca (11);      sprintf (name, "_R%x", count++ & 0x3fffffff);      end_sym = symbol_new (name, undefined_section, 0, &zero_address_frag);      /* Make this a local symbol.  */#ifdef OBJ_COFF      SF_SET_LOCAL (end_sym);#endif /* OBJ_COFF */      symbol_table_insert (end_sym);      end_sym->sy_value = operand[1].immediate;      end_sym->sy_value.X_add_number += 2;      fix_new (frag_now, frag_now_fix (), 2, end_sym, 0, 1, BFD_RELOC_SH_LABEL);    }  output = frag_more (2);  output[0] = 0x8e;  output[1] = 0x8e;  insert (output, BFD_RELOC_SH_LOOP_START, 1, operand);  insert (output, BFD_RELOC_SH_LOOP_END, 1, operand + 1);  return frag_more (2);}/* Now we know what sort of opcodes it is, let's build the bytes.  */static unsigned intbuild_Mytes (opcode, operand)     sh_opcode_info *opcode;     sh_operand_info *operand;{  int index;  char nbuf[4];  char *output = frag_more (2);  unsigned int size = 2;  int low_byte = target_big_endian ? 1 : 0;  nbuf[0] = 0;  nbuf[1] = 0;  nbuf[2] = 0;  nbuf[3] = 0;  for (index = 0; index < 4; index++)    {      sh_nibble_type i = opcode->nibbles[index];      if (i < 16)	{	  nbuf[index] = i;	}      else	{	  switch (i)	    {	    case REG_N:	      nbuf[index] = reg_n;	      break;	    case REG_M:	      nbuf[index] = reg_m;	      break;	    case SDT_REG_N:	      if (reg_n < 2 || reg_n > 5)		as_bad (_("Invalid register: 'r%d'"), reg_n);	      nbuf[index] = (reg_n & 3) | 4;	      break;	    case REG_NM:	      nbuf[index] = reg_n | (reg_m >> 2);	      break;	    case REG_B:	      nbuf[index] = reg_b | 0x08;	      break;	    case IMM0_4BY4:	      insert (output + low_byte, BFD_RELOC_SH_IMM4BY4, 0, operand);	      break;	    case IMM0_4BY2:	      insert (output + low_byte, BFD_RELOC_SH_IMM4BY2, 0, operand);	      break;	    case IMM0_4:	      insert (output + low_byte, BFD_RELOC_SH_IMM4, 0, operand);	      break;	    case IMM1_4BY4:	      insert (output + low_byte, BFD_RELOC_SH_IMM4BY4, 0, operand + 1);	      break;	    case IMM1_4BY2:	      insert (output + low_byte, BFD_RELOC_SH_IMM4BY2, 0, operand + 1);	      break;	    case IMM1_4:	      insert (output + low_byte, BFD_RELOC_SH_IMM4, 0, operand + 1);	      break;	    case IMM0_8BY4:	      insert (output + low_byte, BFD_RELOC_SH_IMM8BY4, 0, operand);	      break;	    case IMM0_8BY2:	      insert (output + low_byte, BFD_RELOC_SH_IMM8BY2, 0, operand);	      break;	    case IMM0_8:	      insert (output + low_byte, BFD_RELOC_SH_IMM8, 0, operand);	      break;	    case IMM1_8BY4:	      insert (output + low_byte, BFD_RELOC_SH_IMM8BY4, 0, operand + 1);	      break;	    case IMM1_8BY2:	      insert (output + low_byte, BFD_RELOC_SH_IMM8BY2, 0, operand + 1);	      break;	    case IMM1_8:	      insert (output + low_byte, BFD_RELOC_SH_IMM8, 0, operand + 1);	      break;	    case PCRELIMM_8BY4:	      insert (output, BFD_RELOC_SH_PCRELIMM8BY4, 1, operand);	      break;	    case PCRELIMM_8BY2:	      insert (output, BFD_RELOC_SH_PCRELIMM8BY2, 1, operand);	      break;	    case REPEAT:	      output = insert_loop_bounds (output, operand);	      nbuf[index] = opcode->nibbles[3];	      operand += 2;	      break;	    default:	      printf (_("failed for %d\n"), i);	    }	}    }  if (!target_big_endian)    {      output[1] = (nbuf[0] << 4) | (nbuf[1]);      output[0] = (nbuf[2] << 4) | (nbuf[3]);    }  else    {      output[0] = (nbuf[0] << 4) | (nbuf[1]);      output[1] = (nbuf[2] << 4) | (nbuf[3]);    }  return size;}/* Find an opcode at the start of *STR_P in the hash table, and set   *STR_P to the first character after the last one read.  */static sh_opcode_info *find_cooked_opcode (str_p)     char **str_p;{  char *str = *str_p;  unsigned char *op_start;  unsigned char *op_end;  char name[20];  int nlen = 0;  /* Drop leading whitespace.  */  while (*str == ' ')    str++;  /* Find the op code end.     The pre-processor will eliminate whitespace in front of     any '@' after the first argument; we may be called from     assemble_ppi, so the opcode might be terminated by an '@'.  */  for (op_start = op_end = (unsigned char *) (str);       *op_end       && nlen < 20       && !is_end_of_line[*op_end] && *op_end != ' ' && *op_end != '@';       op_end++)    {      unsigned char c = op_start[nlen];      /* The machine independent code will convert CMP/EQ into cmp/EQ	 because it thinks the '/' is the end of the symbol.  Moreover,	 all but the first sub-insn is a parallel processing insn won't	 be capitailzed.  Instead of hacking up the machine independent	 code, we just deal with it here.  */      c = isupper (c) ? tolower (c) : c;      name[nlen] = c;      nlen++;    }

⌨️ 快捷键说明

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