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

📄 tc-mcore.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 4 页
字号:
  for (i = 0; i < 2; i++)    buf[i] = isascii (s[i]) ? tolower (s[i]) : 0;  for (i = sizeof (psrmods) / sizeof (psrmods[0]); i--;)    {      if (! strncmp (psrmods[i].name, buf, 2))	{          * reg = psrmods[i].value;          return s + 2;	}    }  as_bad (_("bad/missing psr specifier"));  * reg = 0;  return s;}static char *parse_exp (s, e)     char * s;     expressionS * e;{  char * save;  char * new;  /* Skip whitespace.  */  while (isspace (* s))    ++ s;  save = input_line_pointer;  input_line_pointer = s;  expression (e);  if (e->X_op == O_absent)    as_bad (_("missing operand"));  new = input_line_pointer;  input_line_pointer = save;  return new;}static voidmake_name (s, p, n)     char * s;     char * p;     int n;{  static const char hex[] = "0123456789ABCDEF";  s[0] = p[0];  s[1] = p[1];  s[2] = p[2];  s[3] = hex[(n >> 12) & 0xF];  s[4] = hex[(n >>  8) & 0xF];  s[5] = hex[(n >>  4) & 0xF];  s[6] = hex[(n)       & 0xF];  s[7] = 0;}#define POOL_END_LABEL   ".LE"#define POOL_START_LABEL ".LS"static voiddump_literals (isforce)     int isforce;{  int i;  struct literal * p;  symbolS * brarsym;  if (poolsize == 0)    return;  /* Must we branch around the literal table? */  if (isforce)    {      char * output;      char brarname[8];      make_name (brarname, POOL_END_LABEL, poolnumber);      brarsym = symbol_make (brarname);      symbol_table_insert (brarsym);      output = frag_var (rs_machine_dependent,			 md_relax_table[C (UNCD_JUMP, DISP32)].rlx_length,			 md_relax_table[C (UNCD_JUMP, DISP12)].rlx_length,			 C (UNCD_JUMP, 0), brarsym, 0, 0);      output[0] = INST_BYTE0 (MCORE_INST_BR);	/* br .+xxx */      output[1] = INST_BYTE1 (MCORE_INST_BR);    }  /* Make sure that the section is sufficiently aligned and that     the literal table is aligned within it.  */  record_alignment (now_seg, 2);  frag_align (2, 0, 0);  colon (S_GET_NAME (poolsym));  for (i = 0, p = litpool; i < poolsize; i++, p++)    emit_expr (& p->e, 4);  if (isforce)    colon (S_GET_NAME (brarsym));   poolsize = 0;}static voidcheck_literals (kind, offset)     int kind;     int offset;{  poolspan += offset;  /* SPANCLOSE and SPANEXIT are smaller numbers than SPANPANIC.     SPANPANIC means that we must dump now.     kind == 0 is any old instruction.     kind  > 0 means we just had a control transfer instruction.     kind == 1 means within a function     kind == 2 means we just left a function     The dump_literals (1) call inserts a branch around the table, so     we first look to see if its a situation where we won't have to     insert a branch (e.g., the previous instruction was an unconditional     branch).     SPANPANIC is the point where we must dump a single-entry pool.     it accounts for alignments and an inserted branch.     the 'poolsize*2' accounts for the scenario where we do:       lrw r1,lit1; lrw r2,lit2; lrw r3,lit3     Note that the 'lit2' reference is 2 bytes further along     but the literal it references will be 4 bytes further along,     so we must consider the poolsize into this equation.     This is slightly over-cautious, but guarantees that we won't     panic because a relocation is too distant.  */  if (poolspan > SPANCLOSE && kind > 0)    dump_literals (0);  else if (poolspan > SPANEXIT && kind > 1)    dump_literals (0);  else if (poolspan >= (SPANPANIC - poolsize * 2))    dump_literals (1);}static intenter_literal (e, ispcrel)     expressionS * e;     int ispcrel;{  int i;  struct literal * p;  if (poolsize >= MAX_POOL_SIZE - 2)    {      /* The literal pool is as full as we can handle. We have         to be 2 entries shy of the 1024/4=256 entries because we         have to allow for the branch (2 bytes) and the alignment         (2 bytes before the first insn referencing the pool and         2 bytes before the pool itself) == 6 bytes, rounds up         to 2 entries.  */      dump_literals (1);    }  if (poolsize == 0)    {      /* Create new literal pool.  */      if (++ poolnumber > 0xFFFF)	as_fatal (_("more than 65K literal pools"));      make_name (poolname, POOL_START_LABEL, poolnumber);      poolsym = symbol_make (poolname);      symbol_table_insert (poolsym);      poolspan = 0;    }  /* Search pool for value so we don't have duplicates.  */  for (p = litpool, i = 0; i < poolsize; i++, p++)    {      if (e->X_op == p->e.X_op	  && e->X_add_symbol == p->e.X_add_symbol	  && e->X_add_number == p->e.X_add_number	  && ispcrel == p->ispcrel)	{	  p->refcnt ++;	  return i;	}    }  p->refcnt  = 1;  p->ispcrel = ispcrel;  p->e       = * e;  poolsize ++;  return i;}/* Parse a literal specification. -- either new or old syntax.   old syntax: the user supplies the label and places the literal.   new syntax: we put it into the literal pool.  */static char *parse_rt (s, outputp, ispcrel, ep)     char * s;     char ** outputp;     int ispcrel;     expressionS * ep;{  expressionS e;  int n;  if (ep)    /* Indicate nothing there.  */    ep->X_op = O_absent;  if (*s == '[')    {      s = parse_exp (s + 1, & e);      if (*s == ']')	s++;      else	as_bad (_("missing ']'"));    }  else    {      s = parse_exp (s, & e);      n = enter_literal (& e, ispcrel);      if (ep)	*ep = e;      /* Create a reference to pool entry.  */      e.X_op         = O_symbol;      e.X_add_symbol = poolsym;      e.X_add_number = n << 2;    }  * outputp = frag_more (2);  fix_new_exp (frag_now, (*outputp) - frag_now->fr_literal, 2, & e, 1,	       BFD_RELOC_MCORE_PCREL_IMM8BY4);  return s;}static char *parse_imm (s, val, min, max)     char * s;     unsigned * val;     unsigned min;     unsigned max;{  char * new;  expressionS e;  new = parse_exp (s, & e);  if (e.X_op == O_absent)    ; /* An error message has already been emitted.  */  else if (e.X_op != O_constant)    as_bad (_("operand must be a constant"));  else if (e.X_add_number < min || e.X_add_number > max)    as_bad (_("operand must be absolute in range %d..%d, not %d"),	    min, max, e.X_add_number);  * val = e.X_add_number;  return new;}static char *parse_mem (s, reg, off, siz)     char * s;     unsigned * reg;     unsigned * off;     unsigned siz;{  char * new;  * off = 0;  while (isspace (* s))    ++ s;  if (* s == '(')    {      s = parse_reg (s + 1, reg);      while (isspace (* s))	++ s;      if (* s == ',')	{	  s = parse_imm (s + 1, off, 0, 63);	  if (siz > 1)	    {	      if (siz > 2)		{		  if (* off & 0x3)		    as_bad (_("operand must be a multiple of 4"));		  * off >>= 2;		}	      else		{		  if (* off & 0x1)		    as_bad (_("operand must be a multiple of 2"));		  * off >>= 1;		}	    }	}      while (isspace (* s))	++ s;      if (* s == ')')	s ++;    }  else    as_bad (_("base register expected"));  return s;}/* This is the guts of the machine-dependent assembler.  STR points to a   machine dependent instruction.  This function is supposed to emit   the frags/bytes it assembles to.  */voidmd_assemble (str)     char * str;{  char * op_start;  char * op_end;  mcore_opcode_info * opcode;  char * output;  int nlen = 0;  unsigned short inst;  unsigned reg;  unsigned off;  unsigned isize;  expressionS e;  char name[20];  /* Drop leading whitespace.  */  while (isspace (* str))    str ++;  /* Find the op code end.  */  for (op_start = op_end = str;       nlen < 20 && !is_end_of_line [(unsigned char) *op_end] && *op_end != ' ';       op_end++)    {      name[nlen] = op_start[nlen];      nlen++;    }  name [nlen] = 0;  if (nlen == 0)    {      as_bad (_("can't find opcode "));      return;    }  opcode = (mcore_opcode_info *) hash_find (opcode_hash_control, name);  if (opcode == NULL)    {      as_bad (_("unknown opcode \"%s\""), name);      return;    }  inst = opcode->inst;  isize = 2;  switch (opcode->opclass)    {    case O0:      output = frag_more (2);      break;    case OT:      op_end = parse_imm (op_end + 1, & reg, 0, 3);      inst |= reg;      output = frag_more (2);      break;    case O1:      op_end = parse_reg (op_end + 1, & reg);      inst |= reg;      output = frag_more (2);      break;    case JMP:      op_end = parse_reg (op_end + 1, & reg);      inst |= reg;      output = frag_more (2);      /* In a sifilter mode, we emit this insn 2 times,         fixes problem of an interrupt during a jmp..  */      if (sifilter_mode)	{	  output[0] = INST_BYTE0 (inst);	  output[1] = INST_BYTE1 (inst);	  output = frag_more (2);	}      break;    case JSR:      op_end = parse_reg (op_end + 1, & reg);      if (reg == 15)	as_bad (_("invalid register: r15 illegal"));      inst |= reg;      output = frag_more (2);      if (sifilter_mode)	{	  /* Replace with:  bsr .+2 ; addi r15,6; jmp rx ; jmp rx */	  inst = MCORE_INST_BSR;	/* with 0 displacement */	  output[0] = INST_BYTE0 (inst);	  output[1] = INST_BYTE1 (inst);	  output = frag_more (2);	  inst = MCORE_INST_ADDI;	  inst |= 15;			/* addi r15,6 */	  inst |= (6 - 1) << 4;		/* over the jmp's */	  output[0] = INST_BYTE0 (inst);	  output[1] = INST_BYTE1 (inst);	  output = frag_more (2);	  inst = MCORE_INST_JMP | reg;	  output[0] = INST_BYTE0 (inst);	  output[1] = INST_BYTE1 (inst);	  output = frag_more (2);		/* 2nd emitted in fallthru */	}      break;    case OC:      op_end = parse_reg (op_end + 1, & reg);      inst |= reg;      /* Skip whitespace.  */      while (isspace (* op_end))	++ op_end;      if (*op_end == ',')	{	  op_end = parse_creg (op_end + 1, & reg);	  inst |= reg << 4;	}      output = frag_more (2);      break;    case MULSH:      if (cpu == M210)	{	  as_bad (_("M340 specific opcode used when assembling for M210"));	  break;	}      /* drop through...  */    case O2:      op_end = parse_reg (op_end + 1, & reg);      inst |= reg;      /* Skip whitespace.  */      while (isspace (* op_end))	++ op_end;      if (* op_end == ',')	{	  op_end = parse_reg (op_end + 1, & reg);	  inst |= reg << 4;	}      else	as_bad (_("second operand missing"));      output = frag_more (2);      break;    case X1:	/* Handle both syntax-> xtrb- r1,rx OR xtrb- rx */      op_end = parse_reg (op_end + 1, & reg);      /* Skip whitespace.  */      while (isspace (* op_end))	++ op_end;      if (* op_end == ',')	/* xtrb- r1,rx */	{	  if (reg != 1)	    as_bad (_("destination register must be r1"));	  op_end = parse_reg (op_end + 1, & reg);	}      inst |= reg;      output = frag_more (2);      break;    case O1R1:  /* div- rx,r1 */      op_end = parse_reg (op_end + 1, & reg);      inst |= reg;      /* Skip whitespace.  */      while (isspace (* op_end))	++ op_end;      if (* op_end == ',')	{	  op_end = parse_reg (op_end + 1, & reg);	  if (reg != 1)	    as_bad (_("source register must be r1"));	}      else	as_bad (_("second operand missing"));      output = frag_more (2);      break;    case OI:      op_end = parse_reg (op_end + 1, & reg);      inst |= reg;      /* Skip whitespace.  */      while (isspace (* op_end))	++ op_end;      if (* op_end == ',')	{	  op_end = parse_imm (op_end + 1, & reg, 1, 32);	  inst |= (reg - 1) << 4;	}      else	as_bad (_("second operand missing"));      output = frag_more (2);      break;    case OB:      op_end = parse_reg (op_end + 1, & reg);      inst |= reg;      /* Skip whitespace.  */      while (isspace (* op_end))	++ op_end;      if (* op_end == ',')	{	  op_end = parse_imm (op_end + 1, & reg, 0, 31);	  inst |= reg << 4;	}      else	as_bad (_("second operand missing"));      output = frag_more (2);      break;    case OB2:		/* like OB, but arg is 2^n instead of n */      op_end = parse_reg (op_end + 1, & reg);      inst |= reg;      /* Skip whitespace.  */      while (isspace (* op_end))	++ op_end;      if (* op_end == ',')	{	  op_end = parse_imm (op_end + 1, & reg, 1, 1 << 31);	  /* Further restrict the immediate to a power of two.  */	  if ((reg & (reg - 1)) == 0)	    reg = log2 (reg);	  else	    {	      reg = 0;	      as_bad (_("immediate is not a power of two"));	    }	  inst |= (reg) << 4;	}      else	as_bad (_("second operand missing"));      output = frag_more (2);      break;    case OBRa:	/* Specific for bgeni: imm of 0->6 translate to movi.  */    case OBRb:    case OBRc:      op_end = parse_reg (op_end + 1, & reg);      inst |= reg;      /* Skip whitespace.  */      while (isspace (* op_end))	++ op_end;      if (* op_end == ',')	{	  op_end = parse_imm (op_end + 1, & reg, 0, 31);	  /* immediate values of 0 -> 6 translate to movi */	  if (reg <= 6)	    {	      inst = (inst & 0xF) | MCORE_INST_BGENI_ALT;	      reg = 0x1 << reg;

⌨️ 快捷键说明

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