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 + -
显示快捷键?