fr30-ibld.c

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

C
1,541
字号
      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 *fr30_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 FR30_OPERAND_CRI :      errmsg = insert_normal (cd, fields->f_CRi, 0, 16, 12, 4, 16, total_length, buffer);      break;    case FR30_OPERAND_CRJ :      errmsg = insert_normal (cd, fields->f_CRj, 0, 16, 8, 4, 16, total_length, buffer);      break;    case FR30_OPERAND_R13 :      break;    case FR30_OPERAND_R14 :      break;    case FR30_OPERAND_R15 :      break;    case FR30_OPERAND_RI :      errmsg = insert_normal (cd, fields->f_Ri, 0, 0, 12, 4, 16, total_length, buffer);      break;    case FR30_OPERAND_RIC :      errmsg = insert_normal (cd, fields->f_Ric, 0, 16, 12, 4, 16, total_length, buffer);      break;    case FR30_OPERAND_RJ :      errmsg = insert_normal (cd, fields->f_Rj, 0, 0, 8, 4, 16, total_length, buffer);      break;    case FR30_OPERAND_RJC :      errmsg = insert_normal (cd, fields->f_Rjc, 0, 16, 8, 4, 16, total_length, buffer);      break;    case FR30_OPERAND_RS1 :      errmsg = insert_normal (cd, fields->f_Rs1, 0, 0, 8, 4, 16, total_length, buffer);      break;    case FR30_OPERAND_RS2 :      errmsg = insert_normal (cd, fields->f_Rs2, 0, 0, 12, 4, 16, total_length, buffer);      break;    case FR30_OPERAND_CC :      errmsg = insert_normal (cd, fields->f_cc, 0, 0, 4, 4, 16, total_length, buffer);      break;    case FR30_OPERAND_CCC :      errmsg = insert_normal (cd, fields->f_ccc, 0, 16, 0, 8, 16, total_length, buffer);      break;    case FR30_OPERAND_DIR10 :      {        long value = fields->f_dir10;        value = ((unsigned int) (value) >> (2));        errmsg = insert_normal (cd, value, 0, 0, 8, 8, 16, total_length, buffer);      }      break;    case FR30_OPERAND_DIR8 :      errmsg = insert_normal (cd, fields->f_dir8, 0, 0, 8, 8, 16, total_length, buffer);      break;    case FR30_OPERAND_DIR9 :      {        long value = fields->f_dir9;        value = ((unsigned int) (value) >> (1));        errmsg = insert_normal (cd, value, 0, 0, 8, 8, 16, total_length, buffer);      }      break;    case FR30_OPERAND_DISP10 :      {        long value = fields->f_disp10;        value = ((int) (value) >> (2));        errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED), 0, 4, 8, 16, total_length, buffer);      }      break;    case FR30_OPERAND_DISP8 :      errmsg = insert_normal (cd, fields->f_disp8, 0|(1<<CGEN_IFLD_SIGNED), 0, 4, 8, 16, total_length, buffer);      break;    case FR30_OPERAND_DISP9 :      {        long value = fields->f_disp9;        value = ((int) (value) >> (1));        errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED), 0, 4, 8, 16, total_length, buffer);      }      break;    case FR30_OPERAND_I20 :      {{  FLD (f_i20_4) = ((unsigned int) (FLD (f_i20)) >> (16));  FLD (f_i20_16) = ((FLD (f_i20)) & (65535));}        errmsg = insert_normal (cd, fields->f_i20_4, 0, 0, 8, 4, 16, total_length, buffer);        if (errmsg)          break;        errmsg = insert_normal (cd, fields->f_i20_16, 0, 16, 0, 16, 16, total_length, buffer);        if (errmsg)          break;      }      break;    case FR30_OPERAND_I32 :      errmsg = insert_normal (cd, fields->f_i32, 0|(1<<CGEN_IFLD_SIGN_OPT), 16, 0, 32, 32, total_length, buffer);      break;    case FR30_OPERAND_I8 :      errmsg = insert_normal (cd, fields->f_i8, 0, 0, 4, 8, 16, total_length, buffer);      break;    case FR30_OPERAND_LABEL12 :      {        long value = fields->f_rel12;        value = ((int) (((value) - (((pc) + (2))))) >> (1));        errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 5, 11, 16, total_length, buffer);      }      break;    case FR30_OPERAND_LABEL9 :      {        long value = fields->f_rel9;        value = ((int) (((value) - (((pc) + (2))))) >> (1));        errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 16, total_length, buffer);      }      break;    case FR30_OPERAND_M4 :      {        long value = fields->f_m4;        value = ((value) & (15));        errmsg = insert_normal (cd, value, 0, 0, 8, 4, 16, total_length, buffer);      }      break;    case FR30_OPERAND_PS :      break;    case FR30_OPERAND_REGLIST_HI_LD :      errmsg = insert_normal (cd, fields->f_reglist_hi_ld, 0, 0, 8, 8, 16, total_length, buffer);      break;    case FR30_OPERAND_REGLIST_HI_ST :      errmsg = insert_normal (cd, fields->f_reglist_hi_st, 0, 0, 8, 8, 16, total_length, buffer);      break;    case FR30_OPERAND_REGLIST_LOW_LD :      errmsg = insert_normal (cd, fields->f_reglist_low_ld, 0, 0, 8, 8, 16, total_length, buffer);      break;    case FR30_OPERAND_REGLIST_LOW_ST :      errmsg = insert_normal (cd, fields->f_reglist_low_st, 0, 0, 8, 8, 16, total_length, buffer);      break;    case FR30_OPERAND_S10 :      {        long value = fields->f_s10;        value = ((int) (value) >> (2));        errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED), 0, 8, 8, 16, total_length, buffer);      }      break;    case FR30_OPERAND_U10 :      {        long value = fields->f_u10;        value = ((unsigned int) (value) >> (2));        errmsg = insert_normal (cd, value, 0, 0, 8, 8, 16, total_length, buffer);      }      break;    case FR30_OPERAND_U4 :      errmsg = insert_normal (cd, fields->f_u4, 0, 0, 8, 4, 16, total_length, buffer);      break;    case FR30_OPERAND_U4C :      errmsg = insert_normal (cd, fields->f_u4c, 0, 0, 12, 4, 16, total_length, buffer);      break;    case FR30_OPERAND_U8 :      errmsg = insert_normal (cd, fields->f_u8, 0, 0, 8, 8, 16, total_length, buffer);      break;    case FR30_OPERAND_UDISP6 :      {        long value = fields->f_udisp6;        value = ((unsigned int) (value) >> (2));        errmsg = insert_normal (cd, value, 0, 0, 8, 4, 16, 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.*/intfr30_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 FR30_OPERAND_CRI :      length = extract_normal (cd, ex_info, insn_value, 0, 16, 12, 4, 16, total_length, pc, & fields->f_CRi);      break;    case FR30_OPERAND_CRJ :      length = extract_normal (cd, ex_info, insn_value, 0, 16, 8, 4, 16, total_length, pc, & fields->f_CRj);      break;    case FR30_OPERAND_R13 :      break;    case FR30_OPERAND_R14 :      break;    case FR30_OPERAND_R15 :      break;    case FR30_OPERAND_RI :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 16, total_length, pc, & fields->f_Ri);      break;    case FR30_OPERAND_RIC :      length = extract_normal (cd, ex_info, insn_value, 0, 16, 12, 4, 16, total_length, pc, & fields->f_Ric);      break;    case FR30_OPERAND_RJ :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 16, total_length, pc, & fields->f_Rj);      break;    case FR30_OPERAND_RJC :      length = extract_normal (cd, ex_info, insn_value, 0, 16, 8, 4, 16, total_length, pc, & fields->f_Rjc);      break;    case FR30_OPERAND_RS1 :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 16, total_length, pc, & fields->f_Rs1);      break;    case FR30_OPERAND_RS2 :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 16, total_length, pc, & fields->f_Rs2);      break;    case FR30_OPERAND_CC :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 4, 16, total_length, pc, & fields->f_cc);      break;    case FR30_OPERAND_CCC :      length = extract_normal (cd, ex_info, insn_value, 0, 16, 0, 8, 16, total_length, pc, & fields->f_ccc);      break;    case FR30_OPERAND_DIR10 :      {        long value;        length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 16, total_length, pc, & value);        value = ((value) << (2));        fields->f_dir10 = value;      }      break;    case FR30_OPERAND_DIR8 :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 16, total_length, pc, & fields->f_dir8);      break;    case FR30_OPERAND_DIR9 :      {        long value;        length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 16, total_length, pc, & value);        value = ((value) << (1));        fields->f_dir9 = value;      }      break;    case FR30_OPERAND_DISP10 :      {        long value;        length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 4, 8, 16, total_length, pc, & value);        value = ((value) << (2));        fields->f_disp10 = value;      }      break;    case FR30_OPERAND_DISP8 :      length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 4, 8, 16, total_length, pc, & fields->f_disp8);      break;    case FR30_OPERAND_DISP9 :      {        long value;        length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 4, 8, 16, total_length, pc, & value);        value = ((value) << (1));        fields->f_disp9 = value;      }      break;    case FR30_OPERAND_I20 :      {        length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 16, total_length, pc, & fields->f_i20_4);        if (length <= 0) break;        length = extract_normal (cd, ex_info, insn_value, 0, 16, 0, 16, 16, total_length, pc, & fields->f_i20_16);        if (length <= 0) break;{  FLD (f_i20) = ((((FLD (f_i20_4)) << (16))) | (FLD (f_i20_16)));}      }      break;    case FR30_OPERAND_I32 :      length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGN_OPT), 16, 0, 32, 32, total_length, pc, & fields->f_i32);      break;    case FR30_OPERAND_I8 :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 8, 16, total_length, pc, & fields->f_i8);      break;    case FR30_OPERAND_LABEL12 :      {        long value;        length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 5, 11, 16, total_length, pc, & value);        value = ((((value) << (1))) + (((pc) + (2))));        fields->f_rel12 = value;      }      break;    case FR30_OPERAND_LABEL9 :      {        long value;        length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 16, total_length, pc, & value);        value = ((((value) << (1))) + (((pc) + (2))));        fields->f_rel9 = value;      }      break;    case FR30_OPERAND_M4 :      {        long value;        length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 16, total_length, pc, & value);        value = ((value) | (((-1) << (4))));        fields->f_m4 = value;      }      break;    case FR30_OPERAND_PS :      break;    case FR30_OPERAND_REGLIST_HI_LD :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 16, total_length, pc, & fields->f_reglist_hi_ld);      break;    case FR30_OPERAND_REGLIST_HI_ST :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 16, total_length, pc, & fields->f_reglist_hi_st);      break;    case FR30_OPERAND_REGLIST_LOW_LD :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 16, total_length, pc, & fields->f_reglist_low_ld);      break;    case FR30_OPERAND_REGLIST_LOW_ST :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 16, total_length, pc, & fields->f_reglist_low_st);      break;    case FR30_OPERAND_S10 :      {        long value;        length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 8, 8, 16, total_length, pc, & value);        value = ((value) << (2));        fields->f_s10 = value;      }      break;    case FR30_OPERAND_U10 :      {        long value;        length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 16, total_length, pc, & value);        value = ((value) << (2));        fields->f_u10 = value;      }      break;    case FR30_OPERAND_U4 :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 16, total_length, pc, & fields->f_u4);      break;    case FR30_OPERAND_U4C :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 16, total_length, pc, & fields->f_u4c);      break;    case FR30_OPERAND_U8 :      length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 16, total_length, pc, & fields->f_u8);      break;    case FR30_OPERAND_UDISP6 :      {        long value;        length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 16, total_length, pc, & value);        value = ((value) << (2));        fields->f_udisp6 = value;      }      break;    default :      /* xgettext:c-format */      fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),	       opindex);      abort ();    }  return length;}cgen_insert_fn * const fr30_cgen_insert_handlers[] = {  insert_insn_normal,};cgen_extract_fn * const fr30_cgen_extract_handlers[] = {  extract_insn_normal,};/* Getting values from cgen_fields is handled by a collection of functions.   They are distinguished by the type of the VALUE argument they return.   TODO: floating point, inlining support, remove cases where result type   not appropriate.  */intfr30_cgen_get_int_operand (cd, opindex, fields)     CGEN_CPU_DESC cd;     int opindex;     const CGEN_FIELDS * fields;{  int value;  switch (opindex)    {    case FR30_OPERAND_CRI :      value = fields->f_CRi;

⌨️ 快捷键说明

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