arc-opc.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,826 行 · 第 1/4 页

C
1,826
字号
/* ??? Actually, there's little for us to do as we can't call frag_more, the   caller must do that.  The extract fns take a pointer to two words.  The   insert fns could be converted and then we could do something useful, but   then the reloc handlers would have to know to work on the second word of   a 2 word quantity.  That's too much so we don't handle them.   We do check for correct usage of the nullify suffix, or we   set the default correctly, though.  */static arc_insninsert_absaddr (insn, operand, mods, reg, value, errmsg)     arc_insn insn;     const struct arc_operand *operand ATTRIBUTE_UNUSED;     int mods ATTRIBUTE_UNUSED;     const struct arc_operand_value *reg ATTRIBUTE_UNUSED;     long value ATTRIBUTE_UNUSED;     const char **errmsg;{  if (limm_p)    {      /* if it is a jump and link, .jd must be specified.  */      if (insn & R(-1,9,1))	{	  if (!nullify_p)	    {	      insn |=  0x02 << 5;  /* default nullify to .jd.  */	    }	  else	    {	      if (nullify != 0x02)		{		  *errmsg = "must specify .jd or no nullify suffix";		}	    }	}    }  return insn;}/* Extraction functions.   The suffix extraction functions' return value is redundant since it can be   obtained from (*OPVAL)->value.  However, the boolean suffixes don't have   a suffix table entry for the "false" case, so values of zero must be   obtained from the return value (*OPVAL == NULL).  */static const struct arc_operand_value *lookup_register (int type, long regno);/* Called by the disassembler before printing an instruction.  */voidarc_opcode_init_extract (){  arc_opcode_init_insert();}/* As we're extracting registers, keep an eye out for the 'f' indicator   (ARC_REG_SHIMM_UPDATE).  If we find a register (not a constant marker,   like ARC_REG_SHIMM), set OPVAL so our caller will know this is a register.   We must also handle auxiliary registers for lr/sr insns.  They are just   constants with special names.  */static longextract_reg (insn, operand, mods, opval, invalid)     arc_insn *insn;     const struct arc_operand *operand;     int mods;     const struct arc_operand_value **opval;     int *invalid ATTRIBUTE_UNUSED;{  int regno;  long value;  enum operand op_type;  /* Get the register number.  */  regno = (*insn >> operand->shift) & ((1 << operand->bits) - 1);  /* Is it a constant marker?  */  if (regno == ARC_REG_SHIMM)    {      op_type = OP_SHIMM;      /* always return zero if dest is a shimm  mlm.  */      if ('a' != operand->fmt)	{	  value = *insn & 511;	  if ((operand->flags & ARC_OPERAND_SIGNED)	      && (value & 256))	    value -= 512;	  if (!flagshimm_handled_p)	    flag_p = 0;	  flagshimm_handled_p = 1;	}      else	{	  value = 0;	}    }  else if (regno == ARC_REG_SHIMM_UPDATE)    {      op_type = OP_SHIMM;      /* always return zero if dest is a shimm  mlm.  */      if ('a' != operand->fmt)	{	  value = *insn & 511;	  if ((operand->flags & ARC_OPERAND_SIGNED) && (value & 256))	    value -= 512;	}      else	{	  value = 0;	}      flag_p = 1;      flagshimm_handled_p = 1;    }  else if (regno == ARC_REG_LIMM)    {      op_type = OP_LIMM;      value = insn[1];      limm_p = 1;      /* if this is a jump instruction (j,jl), show new pc correctly.  */      if (0x07 == ((*insn & I(-1)) >> 27))	{	  value = (value & 0xffffff);	}    }  /* It's a register, set OPVAL (that's the only way we distinguish registers     from constants here).  */  else    {      const struct arc_operand_value *reg = lookup_register (REG, regno);      op_type = OP_REG;      if (reg == NULL)	abort ();      if (opval != NULL)	*opval = reg;      value = regno;    }  /* If this field takes an auxiliary register, see if it's a known one.  */  if ((mods & ARC_MOD_AUXREG)      && ARC_REG_CONSTANT_P (regno))    {      const struct arc_operand_value *reg = lookup_register (AUXREG, value);      /* This is really a constant, but tell the caller it has a special	 name.  */      if (reg != NULL && opval != NULL)	*opval = reg;    }  switch(operand->fmt)    {    case 'a':      ls_operand[LS_DEST] = op_type;      break;    case 's':      ls_operand[LS_BASE] = op_type;      break;    case 'c':      if ((insn[0]& I(-1)) == I(2))	ls_operand[LS_VALUE] = op_type;      else	ls_operand[LS_OFFSET] = op_type;      break;    case 'o': case 'O':      ls_operand[LS_OFFSET] = op_type;      break;    }  return value;}/* Return the value of the "flag update" field for shimm insns.   This value is actually stored in the register field.  */static longextract_flag (insn, operand, mods, opval, invalid)     arc_insn *insn;     const struct arc_operand *operand;     int mods ATTRIBUTE_UNUSED;     const struct arc_operand_value **opval;     int *invalid ATTRIBUTE_UNUSED;{  int f;  const struct arc_operand_value *val;  if (flagshimm_handled_p)    f = flag_p != 0;  else    f = (*insn & (1 << operand->shift)) != 0;  /* There is no text for zero values.  */  if (f == 0)    return 0;  flag_p = 1;  val = arc_opcode_lookup_suffix (operand, 1);  if (opval != NULL && val != NULL)    *opval = val;  return val->value;}/* Extract the condition code (if it exists).   If we've seen a shimm value in this insn (meaning that the insn can't have   a condition code field), then we don't store anything in OPVAL and return   zero.  */static longextract_cond (insn, operand, mods, opval, invalid)     arc_insn *insn;     const struct arc_operand *operand;     int mods ATTRIBUTE_UNUSED;     const struct arc_operand_value **opval;     int *invalid ATTRIBUTE_UNUSED;{  long cond;  const struct arc_operand_value *val;  if (flagshimm_handled_p)    return 0;  cond = (*insn >> operand->shift) & ((1 << operand->bits) - 1);  val = arc_opcode_lookup_suffix (operand, cond);  /* Ignore NULL values of `val'.  Several condition code values are     reserved for extensions.  */  if (opval != NULL && val != NULL)    *opval = val;  return cond;}/* Extract a branch address.   We return the value as a real address (not right shifted by 2).  */static longextract_reladdr (insn, operand, mods, opval, invalid)     arc_insn *insn;     const struct arc_operand *operand;     int mods ATTRIBUTE_UNUSED;     const struct arc_operand_value **opval ATTRIBUTE_UNUSED;     int *invalid ATTRIBUTE_UNUSED;{  long addr;  addr = (*insn >> operand->shift) & ((1 << operand->bits) - 1);  if ((operand->flags & ARC_OPERAND_SIGNED)      && (addr & (1 << (operand->bits - 1))))    addr -= 1 << operand->bits;  return addr << 2;}/* extract the flags bits from a j or jl long immediate.  */static longextract_jumpflags(insn, operand, mods, opval, invalid)     arc_insn *insn;     const struct arc_operand *operand;     int mods ATTRIBUTE_UNUSED;     const struct arc_operand_value **opval ATTRIBUTE_UNUSED;     int *invalid;{  if (!flag_p || !limm_p)    *invalid = 1;  return ((flag_p && limm_p)	  ? (insn[1] >> operand->shift) & ((1 << operand->bits) -1): 0);}/* extract st insn's offset.  */static longextract_st_offset (insn, operand, mods, opval, invalid)     arc_insn *insn;     const struct arc_operand *operand;     int mods ATTRIBUTE_UNUSED;     const struct arc_operand_value **opval ATTRIBUTE_UNUSED;     int *invalid;{  int value = 0;  if (ls_operand[LS_VALUE] != OP_SHIMM || ls_operand[LS_BASE] != OP_LIMM)    {      value = insn[0] & 511;      if ((operand->flags & ARC_OPERAND_SIGNED) && (value & 256))	value -= 512;      if (value)	ls_operand[LS_OFFSET] = OP_SHIMM;    }  else    {      *invalid = 1;    }  return(value);}/* extract ld insn's offset.  */static longextract_ld_offset (insn, operand, mods, opval, invalid)     arc_insn *insn;     const struct arc_operand *operand;     int mods;     const struct arc_operand_value **opval;     int *invalid;{  int test = insn[0] & I(-1);  int value;  if (test)    {      value = insn[0] & 511;      if ((operand->flags & ARC_OPERAND_SIGNED) && (value & 256))	value -= 512;      if (value)	ls_operand[LS_OFFSET] = OP_SHIMM;      return(value);    }  /* if it isn't in the insn, it's concealed behind reg 'c'.  */  return extract_reg (insn, &arc_operands[arc_operand_map['c']],		      mods, opval, invalid);}/* The only thing this does is set the `invalid' flag if B != C.   This is needed because the "mov" macro appears before it's real insn "and"   and we don't want the disassembler to confuse them.  */static longextract_unopmacro (insn, operand, mods, opval, invalid)     arc_insn *insn;     const struct arc_operand *operand ATTRIBUTE_UNUSED;     int mods ATTRIBUTE_UNUSED;     const struct arc_operand_value **opval ATTRIBUTE_UNUSED;     int *invalid;{  /* This misses the case where B == ARC_REG_SHIMM_UPDATE &&     C == ARC_REG_SHIMM (or vice versa).  No big deal.  Those insns will get     printed as "and"s.  */  if (((*insn >> ARC_SHIFT_REGB) & ARC_MASK_REG)      != ((*insn >> ARC_SHIFT_REGC) & ARC_MASK_REG))    if (invalid != NULL)      *invalid = 1;  return 0;}/* Utility for the extraction functions to return the index into   `arc_suffixes'.  */const struct arc_operand_value *arc_opcode_lookup_suffix (type, value)     const struct arc_operand *type;     int value;{  register const struct arc_operand_value *v,*end;  struct arc_ext_operand_value *ext_oper = arc_ext_operands;  while (ext_oper)    {      if (type == &arc_operands[ext_oper->operand.type]	  && value == ext_oper->operand.value)	return (&ext_oper->operand);      ext_oper = ext_oper->next;    }  /* ??? This is a little slow and can be speeded up.  */  for (v = arc_suffixes, end = arc_suffixes + arc_suffixes_count; v < end; ++v)    if (type == &arc_operands[v->type]	&& value == v->value)      return v;  return 0;}static const struct arc_operand_value *lookup_register (type, regno)     int type;     long regno;{  register const struct arc_operand_value *r,*end;  struct arc_ext_operand_value *ext_oper = arc_ext_operands;  while (ext_oper)    {      if (ext_oper->operand.type == type && ext_oper->operand.value == regno)	return (&ext_oper->operand);      ext_oper = ext_oper->next;    }  if (type == REG)    return &arc_reg_names[regno];  /* ??? This is a little slow and can be speeded up.  */  for (r = arc_reg_names, end = arc_reg_names + arc_reg_names_count;       r < end; ++r)    if (type == r->type	&& regno == r->value)      return r;  return 0;}intarc_insn_is_j(insn)     arc_insn insn;{  return (insn & (I(-1))) == I(0x7);}intarc_insn_not_jl(insn)     arc_insn insn;{  return ((insn & (I(-1)|A(-1)|C(-1)|R(-1,7,1)|R(-1,9,1)))	  != (I(0x7) | R(-1,9,1)));}intarc_operand_type(int opertype){  switch (opertype)    {    case 0:      return(COND);      break;    case 1:      return(REG);      break;    case 2:      return(AUXREG);      break;    }  return -1;}struct arc_operand_value *get_ext_suffix(s)     char *s;{  struct arc_ext_operand_value *suffix = arc_ext_operands;  while (suffix)    {      if ((COND == suffix->operand.type)	  && !strcmp(s,suffix->operand.name))	return(&suffix->operand);      suffix = suffix->next;    }  return NULL;}intarc_get_noshortcut_flag(){  return ARC_REGISTER_NOSHORT_CUT;}

⌨️ 快捷键说明

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