X86 : Improved instruction dumping
This commit is contained in:
parent
9487ec09a7
commit
fc3f0161bf
|
@ -2547,33 +2547,73 @@ char *Distorm_OpcodeString(const int opcode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void output_value(std::stringstream &output, int nibbles, uint32_t value)
|
||||||
|
{
|
||||||
|
if (value < 0xA)
|
||||||
|
output << std::setw(1) << value;
|
||||||
|
else
|
||||||
|
output << std::setfill('0') << std::setw(nibbles) << std::right << value << 'h';
|
||||||
|
}
|
||||||
|
|
||||||
|
void output_value_disp(std::stringstream &output, int nibbles, uint32_t value)
|
||||||
|
{
|
||||||
|
if (value != 0) {
|
||||||
|
if ((int32_t)value < 0) {
|
||||||
|
output << '-';
|
||||||
|
output_value(output, nibbles, -value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
output << '+';
|
||||||
|
output_value(output, nibbles, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EmuX86_DistormLogInstruction(const uint8_t *Eip, _DInst &info)
|
void EmuX86_DistormLogInstruction(const uint8_t *Eip, _DInst &info)
|
||||||
{
|
{
|
||||||
std::stringstream output;
|
std::stringstream output;
|
||||||
output
|
output << "Disassembly : "
|
||||||
//<< std::setfill('0')
|
<< std::setfill('0') << std::setw(8) << std::right << std::hex << std::uppercase << (xbaddr)Eip;
|
||||||
<< std::setw(8) << std::hex
|
for (int b = 0; b < MAX(7, info.size); b++) {
|
||||||
<< "Processed instruction : "
|
if (b < info.size)
|
||||||
<< (xbaddr)Eip
|
//output << " " << std::setfill('0') << std::setw(2) << std::right << std::hex << ((uint8_t)0+Eip[b]); // add 2 hex nibbles, not chars
|
||||||
// << " "
|
output << " " << std::setw(2) << ((uint8_t)0+Eip[b]); // add 2 hex nibbles, not chars
|
||||||
// << std::setw(8) << *((uint8_t*)info.addr)
|
else
|
||||||
<< " "
|
output << " ";
|
||||||
<< Distorm_OpcodeString(info.opcode)
|
}
|
||||||
;
|
|
||||||
|
|
||||||
|
output << " " << std::setfill(' ') << std::left << std::setw(11) << Distorm_OpcodeString(info.opcode);
|
||||||
for (int o = 0; o < 4 && info.ops[o].type != O_NONE; o++) {
|
for (int o = 0; o < 4 && info.ops[o].type != O_NONE; o++) {
|
||||||
output << ((o == 0) ? " " : ",");
|
// Convert size in bits to (hexadecimal) nibble count
|
||||||
//output << std::setw(info.ops[o].size / 4); // Convert size in bits to (hexadecimal) nibble count
|
int nr_nibbles = info.ops[o].size / 4;
|
||||||
|
std::string size_str;
|
||||||
|
output << std::setfill(' ') << std::setw(1) << std::right << ((o == 0) ? " " : ",");
|
||||||
|
switch (info.ops[o].size) {
|
||||||
|
case 8: size_str = "byte ptr "; break;
|
||||||
|
case 16: size_str = "word ptr "; break;
|
||||||
|
case 32: size_str = "dword ptr "; break;
|
||||||
|
default: nr_nibbles = 8; size_str = ""; break;
|
||||||
|
}
|
||||||
switch (info.ops[o].type) {
|
switch (info.ops[o].type) {
|
||||||
case O_REG: output << Distorm_RegStrings[info.ops[o].index]; break;
|
case O_REG: output << Distorm_RegStrings[info.ops[o].index]; break;
|
||||||
case O_IMM: output << info.imm.dword; break;
|
case O_IMM: output_value(output, nr_nibbles, info.imm.dword); break;
|
||||||
case O_IMM1: output << info.imm.ex.i1; break;
|
case O_IMM1: output_value(output, nr_nibbles, info.imm.ex.i1); break;
|
||||||
case O_IMM2: output << info.imm.ex.i2; break;
|
case O_IMM2: output_value(output, nr_nibbles, info.imm.ex.i2); break;
|
||||||
case O_DISP: output << "dword ptr ds:[" << info.disp << "]"; break;
|
case O_DISP: output << size_str << "ds:[";
|
||||||
case O_SMEM: output << "dword ptr [" << Distorm_RegStrings[info.ops[o].index] << "+" << info.disp << "]"; break;
|
output_value(output, nr_nibbles, info.disp);
|
||||||
case O_MEM: output << "[" << Distorm_RegStrings[info.ops[o].index] << "*?]"; break; // TODO O_MEM : complex memory dereference (optional fields : s / i / b / disp).
|
output << "]"; break;
|
||||||
case O_PC: output << (xbaddr)Eip + INSTRUCTION_GET_TARGET(&info); break;
|
case O_SMEM: output << size_str << "[" << Distorm_RegStrings[info.ops[o].index];
|
||||||
case O_PTR: output << "+" << info.imm.ptr.seg << "/" << info.imm.ptr.off; break;
|
output_value_disp(output, nr_nibbles, info.disp);
|
||||||
|
output << "]"; break;
|
||||||
|
case O_MEM: output << size_str << "[" << Distorm_RegStrings[info.base] << "+" << Distorm_RegStrings[info.ops[o].index];
|
||||||
|
if (info.scale >= 2) {
|
||||||
|
output << "*"; output_value(output, 1, info.scale);
|
||||||
|
}
|
||||||
|
output_value_disp(output, nr_nibbles, info.disp);
|
||||||
|
output << "]"; break;
|
||||||
|
case O_PC: output_value(output, 8, (xbaddr)Eip + (xbaddr)INSTRUCTION_GET_TARGET(&info)); break;
|
||||||
|
case O_PTR: output << "+" << std::setfill('0') << info.imm.ptr.seg << "/";
|
||||||
|
output_value(output, nr_nibbles, info.imm.ptr.off); break;
|
||||||
default: output << "?"; break;
|
default: output << "?"; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2794,6 +2834,9 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e)
|
||||||
if (EmuX86_Opcode_LEA(e, info)) break;
|
if (EmuX86_Opcode_LEA(e, info)) break;
|
||||||
goto opcode_error;
|
goto opcode_error;
|
||||||
}
|
}
|
||||||
|
case I_LEAVE:
|
||||||
|
// LEAVE often precedes RET - end of a code block
|
||||||
|
return true;
|
||||||
case I_LFENCE: { // = 4287 : Serializes load operations.
|
case I_LFENCE: { // = 4287 : Serializes load operations.
|
||||||
__asm { lfence }; // emulate as-is (doesn't cause exceptions)
|
__asm { lfence }; // emulate as-is (doesn't cause exceptions)
|
||||||
break;
|
break;
|
||||||
|
@ -2942,7 +2985,7 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e)
|
||||||
if (EmuX86_Opcode_XOR(e, info)) break;
|
if (EmuX86_Opcode_XOR(e, info)) break;
|
||||||
goto opcode_error;
|
goto opcode_error;
|
||||||
default:
|
default:
|
||||||
EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "Unhandled instruction : %u", info.opcode);
|
EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "Unhandled instruction : %s (%u)", Distorm_OpcodeString(info.opcode), info.opcode);
|
||||||
// Fail if the first hit instruction couldn't be emulated,
|
// Fail if the first hit instruction couldn't be emulated,
|
||||||
// but let host CPU execute following (unhandled) instructions :
|
// but let host CPU execute following (unhandled) instructions :
|
||||||
return (StartingEip != e->ContextRecord->Eip);
|
return (StartingEip != e->ContextRecord->Eip);
|
||||||
|
|
|
@ -164,11 +164,11 @@ static void update_irq(NV2AState *d)
|
||||||
#include "EmuNV2A_DEBUG.cpp"
|
#include "EmuNV2A_DEBUG.cpp"
|
||||||
|
|
||||||
|
|
||||||
#define DEBUG_READ32(DEV) DBG_PRINTF_EX(CXBXR_MODULE::X86, "Rd32 NV2A " #DEV "(0x%08X) = 0x%08X [Handled %s]\n", addr, result, DebugNV_##DEV##(addr))
|
#define DEBUG_READ32(DEV) DBG_PRINTF("Rd32 NV2A " #DEV "(0x%08X) = 0x%08X [Handled %s]\n", addr, result, DebugNV_##DEV##(addr))
|
||||||
#define DEBUG_READ32_UNHANDLED(DEV) { DBG_PRINTF_EX(CXBXR_MODULE::X86, "Rd32 NV2A " #DEV "(0x%08X) = 0x%08X [Unhandled %s]\n", addr, result, DebugNV_##DEV##(addr)); return result; }
|
#define DEBUG_READ32_UNHANDLED(DEV) { DBG_PRINTF("Rd32 NV2A " #DEV "(0x%08X) = 0x%08X [Unhandled %s]\n", addr, result, DebugNV_##DEV##(addr)); return result; }
|
||||||
|
|
||||||
#define DEBUG_WRITE32(DEV) DBG_PRINTF_EX(CXBXR_MODULE::X86, "Wr32 NV2A " #DEV "(0x%08X, 0x%08X) [Handled %s]\n", addr, value, DebugNV_##DEV##(addr))
|
#define DEBUG_WRITE32(DEV) DBG_PRINTF("Wr32 NV2A " #DEV "(0x%08X, 0x%08X) [Handled %s]\n", addr, value, DebugNV_##DEV##(addr))
|
||||||
#define DEBUG_WRITE32_UNHANDLED(DEV) { DBG_PRINTF_EX(CXBXR_MODULE::X86, "Wr32 NV2A " #DEV "(0x%08X, 0x%08X) [Unhandled %s]\n", addr, value, DebugNV_##DEV##(addr)); return; }
|
#define DEBUG_WRITE32_UNHANDLED(DEV) { DBG_PRINTF("Wr32 NV2A " #DEV "(0x%08X, 0x%08X) [Unhandled %s]\n", addr, value, DebugNV_##DEV##(addr)); return; }
|
||||||
|
|
||||||
#define DEVICE_READ32(DEV) uint32_t EmuNV2A_##DEV##_Read32(NV2AState *d, xbaddr addr)
|
#define DEVICE_READ32(DEV) uint32_t EmuNV2A_##DEV##_Read32(NV2AState *d, xbaddr addr)
|
||||||
#define DEVICE_READ32_SWITCH() uint32_t result = 0; switch (addr)
|
#define DEVICE_READ32_SWITCH() uint32_t result = 0; switch (addr)
|
||||||
|
|
Loading…
Reference in New Issue