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

📄 tc-i960.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
  parse_expr (arg[1], &e);  switch (e.X_op)    {    default:      /* We're dependent on one or more symbols -- use "lda" */      arg[0] = "lda";      break;    case O_constant:      /* Try the following mappings:       *      ldconst 0,<reg>  ->mov  0,<reg>       *        ldconst 31,<reg> ->mov  31,<reg>       *        ldconst 32,<reg> ->addo 1,31,<reg>       *        ldconst 62,<reg> ->addo 31,31,<reg>       *        ldconst 64,<reg> ->shlo 8,3,<reg>       *        ldconst -1,<reg> ->subo 1,0,<reg>       *        ldconst -31,<reg>->subo 31,0,<reg>       *       * anthing else becomes:       *        lda xxx,<reg>       */      n = offs (e);      if ((0 <= n) && (n <= 31))	{	  arg[0] = "mov";	}      else if ((-31 <= n) && (n <= -1))	{	  arg[0] = "subo";	  arg[3] = arg[2];	  sprintf (buf, "%d", -n);	  arg[1] = buf;	  arg[2] = "0";	}      else if ((32 <= n) && (n <= 62))	{	  arg[0] = "addo";	  arg[3] = arg[2];	  arg[1] = "31";	  sprintf (buf, "%d", n - 31);	  arg[2] = buf;	}      else if ((shift = shift_ok (n)) != 0)	{	  arg[0] = "shlo";	  arg[3] = arg[2];	  sprintf (buf, "%d", shift);	  arg[1] = buf;	  sprintf (buf2, "%d", n >> shift);	  arg[2] = buf2;	}      else	{	  arg[0] = "lda";	}      break;    case O_illegal:      as_bad (_("invalid constant"));      return -1;      break;    }  return (arg[3] == 0) ? 2 : 3;}/*****************************************************************************   parse_memop:	parse a memory operand  	This routine is based on the observation that the 4 mode bits of the  	MEMB format, taken individually, have fairly consistent meaning:  		 M3 (bit 13): 1 if displacement is present (D_BIT)  		 M2 (bit 12): 1 for MEMB instructions (MEMB_BIT)  		 M1 (bit 11): 1 if index is present (I_BIT)  		 M0 (bit 10): 1 if abase is present (A_BIT)  	So we parse the memory operand and set bits in the mode as we find  	things.  Then at the end, if we go to MEMB format, we need only set  	the MEMB bit (M2) and our mode is built for us.  	Unfortunately, I said "fairly consistent".  The exceptions:  		 DBIA  		 0100	Would seem illegal, but means "abase-only".  		 0101	Would seem to mean "abase-only" -- it means IP-relative.  			Must be converted to 0100.  		 0110	Would seem to mean "index-only", but is reserved.  			We turn on the D bit and provide a 0 displacement.  	The other thing to observe is that we parse from the right, peeling  	things * off as we go:  first any index spec, then any abase, then  	the displacement.  *************************************************************************** */staticvoidparse_memop (memP, argP, optype)     memS *memP;		/* Where to put the results */     char *argP;		/* Text of the operand to be parsed */     int optype;		/* MEM1, MEM2, MEM4, MEM8, MEM12, or MEM16 */{  char *indexP;			/* Pointer to index specification with "[]" removed */  char *p;			/* Temp char pointer */  char iprel_flag;		/* True if this is an IP-relative operand */  int regnum;			/* Register number */  /* Scale factor: 1,2,4,8, or 16.  Later converted to internal format     (0,1,2,3,4 respectively).  */  int scale;  int mode;			/* MEMB mode bits */  int *intP;			/* Pointer to register number */  /* The following table contains the default scale factors for each     type of memory instruction.  It is accessed using (optype-MEM1)     as an index -- thus it assumes the 'optype' constants are     assigned consecutive values, in the order they appear in this     table.  */  static const int def_scale[] =  {    1,				/* MEM1 */    2,				/* MEM2 */    4,				/* MEM4 */    8,				/* MEM8 */    -1,				/* MEM12 -- no valid default */    16				/* MEM16 */  };  iprel_flag = mode = 0;  /* Any index present? */  indexP = get_ispec (argP);  if (indexP)    {      p = strchr (indexP, '*');      if (p == NULL)	{	  /* No explicit scale -- use default for this instruction	     type and assembler mode.  */	  if (flag_mri)	    scale = 1;	  else	    /* GNU960 compatibility */	    scale = def_scale[optype - MEM1];	}      else	{	  *p++ = '\0';		/* Eliminate '*' */	  /* Now indexP->a '\0'-terminated register name,	     * and p->a scale factor.	   */	  if (!strcmp (p, "16"))	    {	      scale = 16;	    }	  else if (strchr ("1248", *p) && (p[1] == '\0'))	    {	      scale = *p - '0';	    }	  else	    {	      scale = -1;	    }	}      regnum = get_regnum (indexP);	/* Get index reg. # */      if (!IS_RG_REG (regnum))	{	  as_bad (_("invalid index register"));	  return;	}      /* Convert scale to its binary encoding */      switch (scale)	{	case 1:	  scale = 0 << 7;	  break;	case 2:	  scale = 1 << 7;	  break;	case 4:	  scale = 2 << 7;	  break;	case 8:	  scale = 3 << 7;	  break;	case 16:	  scale = 4 << 7;	  break;	default:	  as_bad (_("invalid scale factor"));	  return;	};      memP->opcode |= scale | regnum;	/* Set index bits in opcode */      mode |= I_BIT;		/* Found a valid index spec */    }  /* Any abase (Register Indirect) specification present? */  if ((p = strrchr (argP, '(')) != NULL)    {      /* "(" is there -- does it start a legal abase spec?  If not, it         could be part of a displacement expression.  */      intP = (int *) hash_find (areg_hash, p);      if (intP != NULL)	{	  /* Got an abase here */	  regnum = *intP;	  *p = '\0';		/* discard register spec */	  if (regnum == IPREL)	    {	      /* We have to specialcase ip-rel mode */	      iprel_flag = 1;	    }	  else	    {	      memP->opcode |= regnum << 14;	      mode |= A_BIT;	    }	}    }  /* Any expression present? */  memP->e = argP;  if (*argP != '\0')    {      mode |= D_BIT;    }  /* Special-case ip-relative addressing */  if (iprel_flag)    {      if (mode & I_BIT)	{	  syntax ();	}      else	{	  memP->opcode |= 5 << 10;	/* IP-relative mode */	  memP->disp = 32;	}      return;    }  /* Handle all other modes */  switch (mode)    {    case D_BIT | A_BIT:      /* Go with MEMA instruction format for now (grow to MEMB later         if 12 bits is not enough for the displacement).  MEMA format         has a single mode bit: set it to indicate that abase is         present.  */      memP->opcode |= MEMA_ABASE;      memP->disp = 12;      break;    case D_BIT:      /* Go with MEMA instruction format for now (grow to MEMB later         if 12 bits is not enough for the displacement).  */      memP->disp = 12;      break;    case A_BIT:      /* For some reason, the bit string for this mode is not         consistent: it should be 0 (exclusive of the MEMB bit), so we         set it "by hand" here.  */      memP->opcode |= MEMB_BIT;      break;    case A_BIT | I_BIT:      /* set MEMB bit in mode, and OR in mode bits */      memP->opcode |= mode | MEMB_BIT;      break;    case I_BIT:      /* Treat missing displacement as displacement of 0.  */      mode |= D_BIT;      /* Fall into next case.  */    case D_BIT | A_BIT | I_BIT:    case D_BIT | I_BIT:      /* set MEMB bit in mode, and OR in mode bits */      memP->opcode |= mode | MEMB_BIT;      memP->disp = 32;      break;    default:      syntax ();      break;    }}/*****************************************************************************   parse_po:	parse machine-dependent pseudo-op  	This is a top-level routine for machine-dependent pseudo-ops.  It slurps  	up the rest of the input line, breaks out the individual arguments,  	and dispatches them to the correct handler.  *************************************************************************** */staticvoidparse_po (po_num)     int po_num;		/* Pseudo-op number:  currently S_LEAFPROC or S_SYSPROC */{  /* Pointers operands, with no embedded whitespace.     arg[0] unused, arg[1-3]->operands */  char *args[4];  int n_ops;			/* Number of operands */  char *p;			/* Pointer to beginning of unparsed argument string */  char eol;			/* Character that indicated end of line */  extern char is_end_of_line[];  /* Advance input pointer to end of line.  */  p = input_line_pointer;  while (!is_end_of_line[(unsigned char) *input_line_pointer])    {      input_line_pointer++;    }  eol = *input_line_pointer;	/* Save end-of-line char */  *input_line_pointer = '\0';	/* Terminate argument list */  /* Parse out operands */  n_ops = get_args (p, args);  if (n_ops == -1)    {      return;    }  /* Dispatch to correct handler */  switch (po_num)    {    case S_SYSPROC:      s_sysproc (n_ops, args);      break;    case S_LEAFPROC:      s_leafproc (n_ops, args);      break;    default:      BAD_CASE (po_num);      break;    }  /* Restore eol, so line numbers get updated correctly.  Base     assembler assumes we leave input pointer pointing at char     following the eol.  */  *input_line_pointer++ = eol;}/*****************************************************************************   parse_regop: parse a register operand.  	In case of illegal operand, issue a message and return some valid  	information so instruction processing can continue.  *************************************************************************** */staticvoidparse_regop (regopP, optext, opdesc)     struct regop *regopP;	/* Where to put description of register operand */     char *optext;		/* Text of operand */     char opdesc;		/* Descriptor byte:  what's legal for this operand */{  int n;			/* Register number */  expressionS e;		/* Parsed expression */  /* See if operand is a register */  n = get_regnum (optext);  if (n >= 0)    {      if (IS_RG_REG (n))	{	  /* global or local register */	  if (!REG_ALIGN (opdesc, n))	    {	      as_bad (_("unaligned register"));	    }	  regopP->n = n;	  regopP->mode = 0;	  regopP->special = 0;	  return;	}      else if (IS_FP_REG (n) && FP_OK (opdesc))	{	  /* Floating point register, and it's allowed */	  regopP->n = n - FP0;	  regopP->mode = 1;	  regopP->special = 0;	  return;	}      else if (IS_SF_REG (n) && SFR_OK (opdesc))	{	  /* Special-function register, and it's allowed */	  regopP->n = n - SF0;	  regopP->mode = 0;	  regopP->special = 1;	  if (!targ_has_sfr (regopP->n))	    {	      as_bad (_("no such sfr in this architecture"));	    }	  return;	}    }  else if (LIT_OK (opdesc))    {      /* How about a literal?  */      regopP->mode = 1;      regopP->special = 0;      if (FP_OK (opdesc))	{			/* floating point literal acceptable */	  /* Skip over 0f, 0d, or 0e prefix */	  if ((optext[0] == '0')	      && (optext[1] >= 'd')	      && (optext[1] <= 'f'))	    {	      optext += 2;	    }	  if (!strcmp (optext, "0.0") || !strcmp (optext, "0"))	    {	      regopP->n = 0x10;	      return;	    }	  if (!strcmp (optext, "1.0") || !strcmp (optext, "1"))	    {	      regopP->n = 0x16;	      return;	    }	}      else	{			/* fixed point literal acceptable */	  parse_expr (optext, &e);	  if (e.X_op != O_constant	      || (offs (e) < 0) || (offs (e) > 31))	    {	      as_bad (_("illegal literal"));	      offs (e) = 0;	    }	  regopP->n = offs (e);	  return;	}    }  /* Nothing worked */  syntax ();  regopP->mode = 0;		/* Register r0 is always a good one */  regopP->n = 0;  regopP->special = 0;}				/* parse_regop() *//*****************************************************************************   reg_fmt:	generate a REG-format instruction  ***************************************************************************

⌨️ 快捷键说明

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