m32r-ibld.c

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

C
1,246
字号
      break;    case 16:      if (big_p)	x = bfd_getb16 (bufp);      else	x = bfd_getl16 (bufp);      break;    case 24:      /* ??? This may need reworking as these cases don't necessarily	 want the first byte and the last two bytes handled like this.  */      if (big_p)	x = (bufp[0] << 16) | bfd_getb16 (bufp + 1);      else	x = bfd_getl16 (bufp) | (bufp[2] << 16);      break;    case 32:      if (big_p)	x = bfd_getb32 (bufp);      else	x = bfd_getl32 (bufp);      break;    default :      abort ();    }  /* Written this way to avoid undefined behaviour.  */  mask = (((1L << (length - 1)) - 1) << 1) | 1;  if (CGEN_INSN_LSB0_P)    shift = (start + 1) - length;  else    shift = (word_length - (start + length));  return (x >> shift) & mask;}#endif /* ! CGEN_INT_INSN_P *//* Default extraction routine.   INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,   or sometimes less for cases like the m32r where the base insn size is 32   but some insns are 16 bits.   ATTRS is a mask of the boolean attributes.  We only need `SIGNED',   but for generality we take a bitmask of all of them.   WORD_OFFSET is the offset in bits from the start of the insn of the value.   WORD_LENGTH is the length of the word in bits in which the value resides.   START is the starting bit number in the word, architecture origin.   LENGTH is the length of VALUE in bits.   TOTAL_LENGTH is the total length of the insn in bits.   Returns 1 for success, 0 for failure.  *//* ??? The return code isn't properly used.  wip.  *//* ??? This doesn't handle bfd_vma's.  Create another function when   necessary.  */static intextract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length,		word_length, total_length, pc, valuep)     CGEN_CPU_DESC cd;#if ! CGEN_INT_INSN_P     CGEN_EXTRACT_INFO *ex_info;#else     CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED;#endif     CGEN_INSN_INT insn_value;     unsigned int attrs;     unsigned int word_offset, start, length, word_length, total_length;#if ! CGEN_INT_INSN_P     bfd_vma pc;#else     bfd_vma pc ATTRIBUTE_UNUSED;#endif     long *valuep;{  CGEN_INSN_INT value;  /* If LENGTH is zero, this operand doesn't contribute to the value     so give it a standard value of zero.  */  if (length == 0)    {      *valuep = 0;      return 1;    }#if 0  if (CGEN_INT_INSN_P      && word_offset != 0)    abort ();#endif  if (word_length > 32)    abort ();  /* For architectures with insns smaller than the insn-base-bitsize,     word_length may be too big.  */  if (cd->min_insn_bitsize < cd->base_insn_bitsize)    {      if (word_offset == 0	  && word_length > total_length)	word_length = total_length;    }  /* Does the value reside in INSN_VALUE?  */  if (CGEN_INT_INSN_P || word_offset == 0)    {      /* Written this way to avoid undefined behaviour.  */      CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;      if (CGEN_INSN_LSB0_P)	value = insn_value >> ((word_offset + start + 1) - length);      else	value = insn_value >> (total_length - ( word_offset + start + length));      value &= mask;      /* sign extend? */      if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)	  && (value & (1L << (length - 1))))	value |= ~mask;    }#if ! CGEN_INT_INSN_P  else    {      unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;      if (word_length > 32)	abort ();      if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)	return 0;      value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);    }#endif /* ! CGEN_INT_INSN_P */  *valuep = value;  return 1;}/* Default insn extractor.   INSN_VALUE is the first base_insn_bitsize bits, translated to host order.   The extracted fields are stored in FIELDS.   EX_INFO is used to handle reading variable length insns.   Return the length of the insn in bits, or 0 if no match,   or -1 if an error occurs fetching data (memory_error_func will have   been called).  */static intextract_insn_normal (cd, insn, ex_info, insn_value, fields, pc)     CGEN_CPU_DESC cd;     const CGEN_INSN *insn;     CGEN_EXTRACT_INFO *ex_info;     CGEN_INSN_INT insn_value;     CGEN_FIELDS *fields;     bfd_vma pc;{  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);  const unsigned char *syn;  CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);  CGEN_INIT_EXTRACT (cd);  for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)    {      int length;      if (CGEN_SYNTAX_CHAR_P (*syn))	continue;      length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),					ex_info, insn_value, fields, pc);      if (length <= 0)	return length;    }  /* We recognized and successfully extracted this insn.  */  return CGEN_INSN_BITSIZE (insn);}/* machine generated code added here *//* Main entry point for operand insertion.   This function is basically just a big switch statement.  Earlier versions   used tables to look up the function to use, but   - if the table contains both assembler and disassembler functions then     the disassembler contains much of the assembler and vice-versa,   - there's a lot of inlining possibilities as things grow,   - using a switch statement avoids the function call overhead.   This function could be moved into `parse_insn_normal', but keeping it   separate makes clear the interface between `parse_insn_normal' and each of   the handlers.  It's also needed by GAS to insert operands that couldn't be   resolved during parsing.*/const char *m32r_cgen_insert_operand (cd, opindex, fields, buffer, pc)     CGEN_CPU_DESC cd;     int opindex;     CGEN_FIELDS * fields;     CGEN_INSN_BYTES_PTR buffer;     bfd_vma pc;{  const char * errmsg = NULL;  unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);  switch (opindex)    {    case M32R_OPERAND_ACC :      errmsg = insert_normal (cd, fields->f_acc, 0, 0, 8, 1, 32, total_length, buffer);      break;    case M32R_OPERAND_ACCD :      errmsg = insert_normal (cd, fields->f_accd, 0, 0, 4, 2, 32, total_length, buffer);      break;    case M32R_OPERAND_ACCS :      errmsg = insert_normal (cd, fields->f_accs, 0, 0, 12, 2, 32, total_length, buffer);      break;    case M32R_OPERAND_DCR :      errmsg = insert_normal (cd, fields->f_r1, 0, 0, 4, 4, 32, total_length, buffer);      break;    case M32R_OPERAND_DISP16 :      {        long value = fields->f_disp16;        value = ((int) (((value) - (pc))) >> (2));        errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 16, 16, 32, total_length, buffer);      }      break;    case M32R_OPERAND_DISP24 :      {        long value = fields->f_disp24;        value = ((int) (((value) - (pc))) >> (2));        errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 24, 32, total_length, buffer);      }      break;    case M32R_OPERAND_DISP8 :      {        long value = fields->f_disp8;        value = ((int) (((value) - (((pc) & (-4))))) >> (2));        errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, buffer);      }      break;    case M32R_OPERAND_DR :      errmsg = insert_normal (cd, fields->f_r1, 0, 0, 4, 4, 32, total_length, buffer);      break;    case M32R_OPERAND_HASH :      break;    case M32R_OPERAND_HI16 :      errmsg = insert_normal (cd, fields->f_hi16, 0|(1<<CGEN_IFLD_SIGN_OPT), 0, 16, 16, 32, total_length, buffer);      break;    case M32R_OPERAND_IMM1 :      {        long value = fields->f_imm1;        value = ((value) - (1));        errmsg = insert_normal (cd, value, 0, 0, 15, 1, 32, total_length, buffer);      }      break;    case M32R_OPERAND_SCR :      errmsg = insert_normal (cd, fields->f_r2, 0, 0, 12, 4, 32, total_length, buffer);      break;    case M32R_OPERAND_SIMM16 :      errmsg = insert_normal (cd, fields->f_simm16, 0|(1<<CGEN_IFLD_SIGNED), 0, 16, 16, 32, total_length, buffer);      break;    case M32R_OPERAND_SIMM8 :      errmsg = insert_normal (cd, fields->f_simm8, 0|(1<<CGEN_IFLD_SIGNED), 0, 8, 8, 32, total_length, buffer);      break;    case M32R_OPERAND_SLO16 :      errmsg = insert_normal (cd, fields->f_simm16, 0|(1<<CGEN_IFLD_SIGNED), 0, 16, 16, 32, total_length, buffer);      break;    case M32R_OPERAND_SR :      errmsg = insert_normal (cd, fields->f_r2, 0, 0, 12, 4, 32, total_length, buffer);      break;    case M32R_OPERAND_SRC1 :      errmsg = insert_normal (cd, fields->f_r1, 0, 0, 4, 4, 32, total_length, buffer);      break;    case M32R_OPERAND_SRC2 :      errmsg = insert_normal (cd, fields->f_r2, 0, 0, 12, 4, 32, total_length, buffer);      break;    case M32R_OPERAND_UIMM16 :      errmsg = insert_normal (cd, fields->f_uimm16, 0, 0, 16, 16, 32, total_length, buffer);      break;    case M32R_OPERAND_UIMM24 :      errmsg = insert_normal (cd, fields->f_uimm24, 0|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 24, 32, total_length, buffer);      break;    case M32R_OPERAND_UIMM4 :      errmsg = insert_normal (cd, fields->f_uimm4, 0, 0, 12, 4, 32, total_length, buffer);      break;    case M32R_OPERAND_UIMM5 :      errmsg = insert_normal (cd, fields->f_uimm5, 0, 0, 11, 5, 32, total_length, buffer);      break;    case M32R_OPERAND_ULO16 :      errmsg = insert_normal (cd, fields->f_uimm16, 0, 0, 16, 16, 32, total_length, buffer);      break;    default :      /* xgettext:c-format */      fprintf (stderr, _("Unrecognized field %d while building insn.\n"),	       opindex);      abort ();  }  return errmsg;}/* Main entry point for operand extraction.   The result is <= 0 for error, >0 for success.   ??? Actual values aren't well defined right now.   This function is basically just a big switch statement.  Earlier versions   used tables to look up the function to use, but   - if the table contains both assembler and disassembler functions then     the disassembler contains much of the assembler and vice-versa,   - there's a lot of inlining possibilities as things grow,   - using a switch statement avoids the function call overhead.   This function could be moved into `print_insn_normal', but keeping it   separate makes clear the interface between `print_insn_normal' and each of   the handlers.*/intm32r_cgen_extract_operand (cd, opindex, ex_info, insn_value, fields, pc)     CGEN_CPU_DESC cd;     int opindex;     CGEN_EXTRACT_INFO *ex_info;     CGEN_INSN_INT insn_value;     CGEN_FIELDS * fields;     bfd_vma pc;{  /* Assume success (for those operands that are nops).  */  int length = 1;  unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);  switch (opindex)    {    case M32R_OPERAND_ACC :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 1, 32, total_length, pc, & fields->f_acc);      break;    case M32R_OPERAND_ACCD :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 2, 32, total_length, pc, & fields->f_accd);      break;    case M32R_OPERAND_ACCS :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 2, 32, total_length, pc, & fields->f_accs);      break;    case M32R_OPERAND_DCR :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 4, 32, total_length, pc, & fields->f_r1);      break;    case M32R_OPERAND_DISP16 :      {        long value;        length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 16, 16, 32, total_length, pc, & value);        value = ((((value) << (2))) + (pc));        fields->f_disp16 = value;      }      break;    case M32R_OPERAND_DISP24 :      {        long value;        length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 24, 32, total_length, pc, & value);        value = ((((value) << (2))) + (pc));        fields->f_disp24 = value;      }      break;    case M32R_OPERAND_DISP8 :      {        long value;        length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, pc, & value);        value = ((((value) << (2))) + (((pc) & (-4))));        fields->f_disp8 = value;      }      break;    case M32R_OPERAND_DR :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 4, 32, total_length, pc, & fields->f_r1);      break;    case M32R_OPERAND_HASH :      break;    case M32R_OPERAND_HI16 :      length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGN_OPT), 0, 16, 16, 32, total_length, pc, & fields->f_hi16);      break;    case M32R_OPERAND_IMM1 :      {        long value;        length = extract_normal (cd, ex_info, insn_value, 0, 0, 15, 1, 32, total_length, pc, & value);        value = ((value) + (1));        fields->f_imm1 = value;      }      break;    case M32R_OPERAND_SCR :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 32, total_length, pc, & fields->f_r2);      break;    case M32R_OPERAND_SIMM16 :      length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 16, 16, 32, total_length, pc, & fields->f_simm16);      break;    case M32R_OPERAND_SIMM8 :      length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 8, 8, 32, total_length, pc, & fields->f_simm8);      break;    case M32R_OPERAND_SLO16 :      length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 16, 16, 32, total_length, pc, & fields->f_simm16);      break;    case M32R_OPERAND_SR :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 32, total_length, pc, & fields->f_r2);      break;    case M32R_OPERAND_SRC1 :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 4, 32, total_length, pc, & fields->f_r1);      break;    case M32R_OPERAND_SRC2 :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 32, total_length, pc, & fields->f_r2);      break;    case M32R_OPERAND_UIMM16 :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 16, 16, 32, total_length, pc, & fields->f_uimm16);

⌨️ 快捷键说明

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