cgen-opc.c

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

C
586
字号
  /* ??? This can be speeded up.  */  for (i = 0; i < cd->hw_table.num_entries; ++i)    if (hw[i] && hwnum == hw[i]->type)      return hw[i];  return NULL;}/* Operand support.  *//* Lookup an operand by its name.   Returns NULL if NAME is not supported by the currently selected   mach/isa.  */const CGEN_OPERAND *cgen_operand_lookup_by_name (cd, name)     CGEN_CPU_DESC cd;     const char *name;{  unsigned int i;  const CGEN_OPERAND **op = cd->operand_table.entries;  for (i = 0; i < cd->operand_table.num_entries; ++i)    if (op[i] && strcmp (name, op[i]->name) == 0)      return op[i];  return NULL;}/* Lookup an operand by its number.   Operands are enumerated, however it may be possible to add some   at runtime, thus OPNUM is not an enum type but rather an int.   Returns NULL if OPNUM is not supported by the currently selected   mach/isa.  */const CGEN_OPERAND *cgen_operand_lookup_by_num (cd, opnum)     CGEN_CPU_DESC cd;     int opnum;{  return cd->operand_table.entries[opnum];}/* Instruction support.  *//* Return number of instructions.  This includes any added at runtime.  */intcgen_insn_count (cd)     CGEN_CPU_DESC cd;{  int count = cd->insn_table.num_init_entries;  CGEN_INSN_LIST *rt_insns = cd->insn_table.new_entries;  for ( ; rt_insns != NULL; rt_insns = rt_insns->next)    ++count;  return count;}/* Return number of macro-instructions.   This includes any added at runtime.  */intcgen_macro_insn_count (cd)     CGEN_CPU_DESC cd;{  int count = cd->macro_insn_table.num_init_entries;  CGEN_INSN_LIST *rt_insns = cd->macro_insn_table.new_entries;  for ( ; rt_insns != NULL; rt_insns = rt_insns->next)    ++count;  return count;}/* Cover function to read and properly byteswap an insn value.  */CGEN_INSN_INTcgen_get_insn_value (cd, buf, length)     CGEN_CPU_DESC cd;     unsigned char *buf;     int length;{  bfd_get_bits (buf, length, cd->insn_endian == CGEN_ENDIAN_BIG);}/* Cover function to store an insn value properly byteswapped.  */voidcgen_put_insn_value (cd, buf, length, value)     CGEN_CPU_DESC cd;     unsigned char *buf;     int length;     CGEN_INSN_INT value;{  bfd_put_bits ((bfd_vma) value, buf, length,		cd->insn_endian == CGEN_ENDIAN_BIG);}/* Look up instruction INSN_*_VALUE and extract its fields.   INSN_INT_VALUE is used if CGEN_INT_INSN_P.   Otherwise INSN_BYTES_VALUE is used.   INSN, if non-null, is the insn table entry.   Otherwise INSN_*_VALUE is examined to compute it.   LENGTH is the bit length of INSN_*_VALUE if known, otherwise 0.   0 is only valid if `insn == NULL && ! CGEN_INT_INSN_P'.   If INSN != NULL, LENGTH must be valid.   ALIAS_P is non-zero if alias insns are to be included in the search.   The result is a pointer to the insn table entry, or NULL if the instruction   wasn't recognized.  *//* ??? Will need to be revisited for VLIW architectures.  */const CGEN_INSN *cgen_lookup_insn (cd, insn, insn_int_value, insn_bytes_value, length, fields,		  alias_p)     CGEN_CPU_DESC cd;     const CGEN_INSN *insn;     CGEN_INSN_INT insn_int_value;     /* ??? CGEN_INSN_BYTES would be a nice type name to use here.  */     unsigned char *insn_bytes_value;     int length;     CGEN_FIELDS *fields;     int alias_p;{  unsigned char *buf;  CGEN_INSN_INT base_insn;  CGEN_EXTRACT_INFO ex_info;  CGEN_EXTRACT_INFO *info;  if (cd->int_insn_p)    {      info = NULL;      buf = (unsigned char *) alloca (cd->max_insn_bitsize / 8);      cgen_put_insn_value (cd, buf, length, insn_int_value);      base_insn = insn_int_value;    }  else    {      info = &ex_info;      ex_info.dis_info = NULL;      ex_info.insn_bytes = insn_bytes_value;      ex_info.valid = -1;      buf = insn_bytes_value;      base_insn = cgen_get_insn_value (cd, buf, length);    }  if (!insn)    {      const CGEN_INSN_LIST *insn_list;      /* The instructions are stored in hash lists.	 Pick the first one and keep trying until we find the right one.  */      insn_list = cgen_dis_lookup_insn (cd, buf, base_insn);      while (insn_list != NULL)	{	  insn = insn_list->insn;	  if (alias_p	      /* FIXME: Ensure ALIAS attribute always has same index.  */	      || ! CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ALIAS))	    {	      /* Basic bit mask must be correct.  */	      /* ??? May wish to allow target to defer this check until the		 extract handler.  */	      if ((base_insn & CGEN_INSN_BASE_MASK (insn))		  == CGEN_INSN_BASE_VALUE (insn))		{		  /* ??? 0 is passed for `pc' */		  int elength = CGEN_EXTRACT_FN (cd, insn)		    (cd, insn, info, base_insn, fields, (bfd_vma) 0);		  if (elength > 0)		    {		      /* sanity check */		      if (length != 0 && length != elength)			abort ();		      return insn;		    }		}	    }	  insn_list = insn_list->next;	}    }  else    {      /* Sanity check: can't pass an alias insn if ! alias_p.  */      if (! alias_p	  && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ALIAS))	abort ();      /* Sanity check: length must be correct.  */      if (length != CGEN_INSN_BITSIZE (insn))	abort ();      /* ??? 0 is passed for `pc' */      length = CGEN_EXTRACT_FN (cd, insn)	(cd, insn, info, base_insn, fields, (bfd_vma) 0);      /* Sanity check: must succeed.	 Could relax this later if it ever proves useful.  */      if (length == 0)	abort ();      return insn;    }  return NULL;}/* Fill in the operand instances used by INSN whose operands are FIELDS.   INDICES is a pointer to a buffer of MAX_OPERAND_INSTANCES ints to be filled   in.  */voidcgen_get_insn_operands (cd, insn, fields, indices)     CGEN_CPU_DESC cd;     const CGEN_INSN *insn;     const CGEN_FIELDS *fields;     int *indices;{  const CGEN_OPINST *opinst;  int i;  if (insn->opinst == NULL)    abort ();  for (i = 0, opinst = insn->opinst; opinst->type != CGEN_OPINST_END; ++i, ++opinst)    {      enum cgen_operand_type op_type = opinst->op_type;      if (op_type == CGEN_OPERAND_NIL)	indices[i] = opinst->index;      else	indices[i] = (*cd->get_int_operand) (cd, op_type, fields);    }}/* Cover function to cgen_get_insn_operands when either INSN or FIELDS   isn't known.   The INSN, INSN_*_VALUE, and LENGTH arguments are passed to   cgen_lookup_insn unchanged.   INSN_INT_VALUE is used if CGEN_INT_INSN_P.   Otherwise INSN_BYTES_VALUE is used.   The result is the insn table entry or NULL if the instruction wasn't   recognized.  */const CGEN_INSN *cgen_lookup_get_insn_operands (cd, insn, insn_int_value, insn_bytes_value,			       length, indices, fields)     CGEN_CPU_DESC cd;     const CGEN_INSN *insn;     CGEN_INSN_INT insn_int_value;     /* ??? CGEN_INSN_BYTES would be a nice type name to use here.  */     unsigned char *insn_bytes_value;     int length;     int *indices;     CGEN_FIELDS *fields;{  /* Pass non-zero for ALIAS_P only if INSN != NULL.     If INSN == NULL, we want a real insn.  */  insn = cgen_lookup_insn (cd, insn, insn_int_value, insn_bytes_value,			   length, fields, insn != NULL);  if (! insn)    return NULL;  cgen_get_insn_operands (cd, insn, fields, indices);  return insn;}/* Allow signed overflow of instruction fields.  */voidcgen_set_signed_overflow_ok (cd)     CGEN_CPU_DESC cd;{  cd->signed_overflow_ok_p = 1;}/* Generate an error message if a signed field in an instruction overflows.  */voidcgen_clear_signed_overflow_ok (cd)     CGEN_CPU_DESC cd;{  cd->signed_overflow_ok_p = 0;}/* Will an error message be generated if a signed field in an instruction overflows ? */unsigned intcgen_signed_overflow_ok_p (cd)     CGEN_CPU_DESC cd;{  return cd->signed_overflow_ok_p;}

⌨️ 快捷键说明

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