arc-dis.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,222 行 · 第 1/2 页
C
1,222 行
case 2: instrName = "ldw"; state->_load_len = 2; break; default: instrName = "??? (1[3])"; state->flow = invalid_instr; break; } decodingClass = 6; } break; case op_ST: if (BIT (state->words[0],25)) { instrName = "sr"; decodingClass = 8; } else { switch (BITS (state->words[0],22,23)) { case 0: instrName = "st"; break; case 1: instrName = "stb"; break; case 2: instrName = "stw"; break; default: instrName = "??? (2[3])"; state->flow = invalid_instr; break; } decodingClass = 7; } break; case op_3: decodingClass = 1; /* default for opcode 3... */ switch (FIELDC (state->words[0])) { case 0: instrName = "flag"; decodingClass = 2; break; case 1: instrName = "asr"; break; case 2: instrName = "lsr"; break; case 3: instrName = "ror"; break; case 4: instrName = "rrc"; break; case 5: instrName = "sexb"; break; case 6: instrName = "sexw"; break; case 7: instrName = "extb"; break; case 8: instrName = "extw"; break; case 0x3f: { decodingClass = 9; switch( FIELDD (state->words[0]) ) { case 0: instrName = "brk"; break; case 1: instrName = "sleep"; break; case 2: instrName = "swi"; break; default: instrName = "???"; state->flow=invalid_instr; break; } } break; /* ARC Extension Library Instructions NOTE: We assume that extension codes are these instrs. */ default: instrName = instruction_name (state, state->_opcode, FIELDC (state->words[0]), & flags); if (!instrName) { instrName = "???"; state->flow = invalid_instr; } if (flags & IGNORE_FIRST_OPD) ignoreFirstOpd = 1; break; } break; case op_BC: instrName = "b"; case op_BLC: if (!instrName) instrName = "bl"; case op_LPC: if (!instrName) instrName = "lp"; case op_JC: if (!instrName) { if (BITS (state->words[0],9,9)) { instrName = "jl"; is_linked = 1; } else { instrName = "j"; is_linked = 0; } } condCodeIsPartOfName = 1; decodingClass = ((state->_opcode == op_JC) ? 4 : 3); state->isBranch = 1; break; case op_ADD: case op_ADC: case op_AND: repeatsOp = (FIELDC (state->words[0]) == FIELDB (state->words[0])); decodingClass = 0; switch (state->_opcode) { case op_ADD: instrName = (repeatsOp ? "asl" : "add"); break; case op_ADC: instrName = (repeatsOp ? "rlc" : "adc"); break; case op_AND: instrName = (repeatsOp ? "mov" : "and"); break; } break; case op_SUB: instrName = "sub"; break; case op_SBC: instrName = "sbc"; break; case op_OR: instrName = "or"; break; case op_BIC: instrName = "bic"; break; case op_XOR: if (state->words[0] == 0x7fffffff) { /* nop encoded as xor -1, -1, -1 */ instrName = "nop"; decodingClass = 9; } else instrName = "xor"; break; default: instrName = instruction_name (state,state->_opcode,0,&flags); /* if (instrName) printf("FLAGS=0x%x\n", flags); */ if (!instrName) { instrName = "???"; state->flow=invalid_instr; } if (flags & IGNORE_FIRST_OPD) ignoreFirstOpd = 1; break; } fieldAisReg = fieldBisReg = fieldCisReg = 1; /* Assume regs for now. */ flag = cond = is_shimm = is_limm = 0; state->nullifyMode = BR_exec_when_no_jump; /* 0 */ signExtend = addrWriteBack = directMem = 0; usesAuxReg = 0; switch (decodingClass) { case 0: CHECK_FIELD_A (); CHECK_FIELD_B (); if (!repeatsOp) CHECK_FIELD_C (); CHECK_FLAG_COND_NULLIFY (); write_instr_name (); if (!ignoreFirstOpd) { WRITE_FORMAT_x (A); WRITE_FORMAT_COMMA_x (B); if (!repeatsOp) WRITE_FORMAT_COMMA_x (C); WRITE_NOP_COMMENT (); my_sprintf (state, state->operandBuffer, formatString, fieldA, fieldB, fieldC); } else { WRITE_FORMAT_x (B); if (!repeatsOp) WRITE_FORMAT_COMMA_x (C); my_sprintf (state, state->operandBuffer, formatString, fieldB, fieldC); } write_comments (); break; case 1: CHECK_FIELD_A (); CHECK_FIELD_B (); CHECK_FLAG_COND_NULLIFY (); write_instr_name (); if (!ignoreFirstOpd) { WRITE_FORMAT_x (A); WRITE_FORMAT_COMMA_x (B); WRITE_NOP_COMMENT (); my_sprintf (state, state->operandBuffer, formatString, fieldA, fieldB); } else { WRITE_FORMAT_x (B); my_sprintf (state, state->operandBuffer, formatString, fieldB); } write_comments (); break; case 2: CHECK_FIELD_B (); CHECK_FLAG_COND_NULLIFY (); flag = 0; /* this is the FLAG instruction -- it's redundant */ write_instr_name (); WRITE_FORMAT_x (B); my_sprintf (state, state->operandBuffer, formatString, fieldB); write_comments (); break; case 3: fieldA = BITS (state->words[0],7,26) << 2; fieldA = (fieldA << 10) >> 10; /* make it signed */ fieldA += addr + 4; CHECK_FLAG_COND_NULLIFY (); flag = 0; write_instr_name (); /* This address could be a label we know. Convert it. */ if (state->_opcode != op_LPC /* LP */) { add_target (fieldA); /* For debugger. */ state->flow = state->_opcode == op_BLC /* BL */ ? direct_call : direct_jump; /* indirect calls are achieved by "lr blink,[status]; lr dest<- func addr; j [dest]" */ } strcat (formatString, "%s"); /* address/label name */ my_sprintf (state, state->operandBuffer, formatString, post_address (state, fieldA)); write_comments (); break; case 4: /* For op_JC -- jump to address specified. Also covers jump and link--bit 9 of the instr. word selects whether linked, thus "is_linked" is set above. */ fieldA = 0; CHECK_FIELD_B (); CHECK_FLAG_COND_NULLIFY (); if (!fieldBisReg) { fieldAisReg = 0; fieldA = (fieldB >> 25) & 0x7F; /* flags */ fieldB = (fieldB & 0xFFFFFF) << 2; state->flow = is_linked ? direct_call : direct_jump; add_target (fieldB); /* screwy JLcc requires .jd mode to execute correctly * but we pretend it is .nd (no delay slot). */ if (is_linked && state->nullifyMode == BR_exec_when_jump) state->nullifyMode = BR_exec_when_no_jump; } else { state->flow = is_linked ? indirect_call : indirect_jump; /* We should also treat this as indirect call if NOT linked * but the preceding instruction was a "lr blink,[status]" * and we have a delay slot with "add blink,blink,2". * For now we can't detect such. */ state->register_for_indirect_jump = fieldB; } write_instr_name (); strcat (formatString, IS_REG (B) ? "[%r]" : "%s"); /* address/label name */ if (fieldA != 0) { fieldAisReg = 0; WRITE_FORMAT_COMMA_x (A); } if (IS_REG (B)) my_sprintf (state, state->operandBuffer, formatString, fieldB, fieldA); else my_sprintf (state, state->operandBuffer, formatString, post_address (state, fieldB), fieldA); write_comments (); break; case 5: /* LD instruction. B and C can be regs, or one (both?) can be limm. */ CHECK_FIELD_A (); CHECK_FIELD_B (); CHECK_FIELD_C (); if (dbg) printf ("5:b reg %d %d c reg %d %d \n", fieldBisReg,fieldB,fieldCisReg,fieldC); state->_offset = 0; state->_ea_present = 1; if (fieldBisReg) state->ea_reg1 = fieldB; else state->_offset += fieldB; if (fieldCisReg) state->ea_reg2 = fieldC; else state->_offset += fieldC; state->_mem_load = 1; directMem = BIT (state->words[0],5); addrWriteBack = BIT (state->words[0],3); signExtend = BIT (state->words[0],0); write_instr_name (); WRITE_FORMAT_x_COMMA_LB(A); if (fieldBisReg || fieldB != 0) WRITE_FORMAT_x_COMMA (B); else fieldB = fieldC; WRITE_FORMAT_x_RB (C); my_sprintf (state, state->operandBuffer, formatString, fieldA, fieldB, fieldC); write_comments (); break; case 6: /* LD instruction. */ CHECK_FIELD_B (); CHECK_FIELD_A (); fieldC = FIELDD (state->words[0]); if (dbg) printf ("6:b reg %d %d c 0x%x \n", fieldBisReg, fieldB, fieldC); state->_ea_present = 1; state->_offset = fieldC; state->_mem_load = 1; if (fieldBisReg) state->ea_reg1 = fieldB; /* field B is either a shimm (same as fieldC) or limm (different!) Say ea is not present, so only one of us will do the name lookup. */ else state->_offset += fieldB, state->_ea_present = 0; directMem = BIT (state->words[0],14); addrWriteBack = BIT (state->words[0],12); signExtend = BIT (state->words[0],9); write_instr_name (); WRITE_FORMAT_x_COMMA_LB (A); if (!fieldBisReg) { fieldB = state->_offset; WRITE_FORMAT_x_RB (B); } else { WRITE_FORMAT_x (B); if (fieldC != 0 && !BIT (state->words[0],13)) { fieldCisReg = 0; WRITE_FORMAT_COMMA_x_RB (C); } else WRITE_FORMAT_RB (); } my_sprintf (state, state->operandBuffer, formatString, fieldA, fieldB, fieldC); write_comments (); break; case 7: /* ST instruction. */ CHECK_FIELD_B(); CHECK_FIELD_C(); fieldA = FIELDD(state->words[0]); /* shimm */ /* [B,A offset] */ if (dbg) printf("7:b reg %d %x off %x\n", fieldBisReg,fieldB,fieldA); state->_ea_present = 1; state->_offset = fieldA; if (fieldBisReg) state->ea_reg1 = fieldB; /* field B is either a shimm (same as fieldA) or limm (different!) Say ea is not present, so only one of us will do the name lookup. (for is_limm we do the name translation here). */ else state->_offset += fieldB, state->_ea_present = 0; directMem = BIT(state->words[0],26); addrWriteBack = BIT(state->words[0],24); write_instr_name(); WRITE_FORMAT_x_COMMA_LB(C); if (!fieldBisReg) { fieldB = state->_offset; WRITE_FORMAT_x_RB(B); } else { WRITE_FORMAT_x(B); if (fieldBisReg && fieldA != 0) { fieldAisReg = 0; WRITE_FORMAT_COMMA_x_RB(A); } else WRITE_FORMAT_RB(); } my_sprintf (state, state->operandBuffer, formatString, fieldC, fieldB, fieldA); write_comments2(fieldA); break; case 8: /* SR instruction */ CHECK_FIELD_B(); CHECK_FIELD_C(); write_instr_name(); WRITE_FORMAT_x_COMMA_LB(C); /* Try to print B as an aux reg if it is not a core reg. */ usesAuxReg = 1; WRITE_FORMAT_x(B); WRITE_FORMAT_RB(); my_sprintf (state, state->operandBuffer, formatString, fieldC, fieldB); write_comments(); break; case 9: write_instr_name(); state->operandBuffer[0] = '\0'; break; case 10: /* LR instruction */ CHECK_FIELD_A(); CHECK_FIELD_B(); write_instr_name(); WRITE_FORMAT_x_COMMA_LB(A); /* Try to print B as an aux reg if it is not a core reg. */ usesAuxReg = 1; WRITE_FORMAT_x(B); WRITE_FORMAT_RB(); my_sprintf (state, state->operandBuffer, formatString, fieldA, fieldB); write_comments(); break; case 11: CHECK_COND(); write_instr_name(); state->operandBuffer[0] = '\0'; break; default: mwerror (state, "Bad decoding class in ARC disassembler"); break; } state->_cond = cond; return state->instructionLen = offset;}/* Returns the name the user specified core extension register. */static const char *_coreRegName(arg, regval) void * arg ATTRIBUTE_UNUSED; int regval;{ return arcExtMap_coreRegName (regval);}/* Returns the name the user specified AUX extension register. */static const char *_auxRegName(void *_this ATTRIBUTE_UNUSED, int regval){ return arcExtMap_auxRegName(regval);}/* Returns the name the user specified condition code name. */static const char *_condCodeName(void *_this ATTRIBUTE_UNUSED, int regval){ return arcExtMap_condCodeName(regval);}/* Returns the name the user specified extension instruction. */static const char *_instName (void *_this ATTRIBUTE_UNUSED, int majop, int minop, int *flags){ return arcExtMap_instName(majop, minop, flags);}/* Decode an instruction returning the size of the instruction in bytes or zero if unrecognized. */static intdecodeInstr (address, info) bfd_vma address; /* Address of this instruction. */ disassemble_info * info;{ int status; bfd_byte buffer[4]; struct arcDisState s; /* ARC Disassembler state */ void *stream = info->stream; /* output stream */ fprintf_ftype func = info->fprintf_func; int bytes; memset (&s, 0, sizeof(struct arcDisState)); /* read first instruction */ status = (*info->read_memory_func) (address, buffer, 4, info); if (status != 0) { (*info->memory_error_func) (status, address, info); return 0; } if (info->endian == BFD_ENDIAN_LITTLE) s.words[0] = bfd_getl32(buffer); else s.words[0] = bfd_getb32(buffer); /* always read second word in case of limm */ /* we ignore the result since last insn may not have a limm */ status = (*info->read_memory_func) (address + 4, buffer, 4, info); if (info->endian == BFD_ENDIAN_LITTLE) s.words[1] = bfd_getl32(buffer); else s.words[1] = bfd_getb32(buffer); s._this = &s; s.coreRegName = _coreRegName; s.auxRegName = _auxRegName; s.condCodeName = _condCodeName; s.instName = _instName; /* disassemble */ bytes = dsmOneArcInst(address, (void *)&s); /* display the disassembly instruction */ (*func) (stream, "%08x ", s.words[0]); (*func) (stream, " "); (*func) (stream, "%-10s ", s.instrBuffer); if (__TRANSLATION_REQUIRED(s)) { bfd_vma addr = s.addresses[s.operandBuffer[1] - '0']; (*info->print_address_func) ((bfd_vma) addr, info); (*func) (stream, "\n"); } else (*func) (stream, "%s",s.operandBuffer); return s.instructionLen;}/* Return the print_insn function to use. Side effect: load (possibly empty) extension section */disassembler_ftypearc_get_disassembler (void *ptr){ if (ptr) build_ARC_extmap (ptr); return decodeInstr;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?