diff --git a/external/capstone/arch/M68K/M68KInstPrinter.c b/external/capstone/arch/M68K/M68KInstPrinter.c index 5cd1640b..25f14400 100644 --- a/external/capstone/arch/M68K/M68KInstPrinter.c +++ b/external/capstone/arch/M68K/M68KInstPrinter.c @@ -15,6 +15,7 @@ #include // DEBUG #include #include +#include #include "M68KInstPrinter.h" @@ -104,7 +105,7 @@ static void printRegbitsRange(char* buffer, uint32_t data, const char* prefix) } } -static void registerBits(SStream* O, const cs_m68k_op* op) +static void registerBits(cs_detail* detail, SStream* O, const cs_m68k_op* op, bool write_reg) { char buffer[128]; unsigned int data = op->register_bits; @@ -120,41 +121,114 @@ static void registerBits(SStream* O, const cs_m68k_op* op) printRegbitsRange(buffer, (data >> 8) & 0xff, "a"); printRegbitsRange(buffer, (data >> 16) & 0xff, "fp"); + RegisterStringInfo* info = NULL; + + if (write_reg) { + int i = detail->regs_write_string_count++; + info = &detail->regs_write_string_info[i]; + } else { + int i = detail->regs_read_string_count++; + info = &detail->regs_read_string_info[i]; + } + + info->type = REGISTER_STRING_INFO_REG_BITS; + info->length = strlen(buffer); + info->offset = O->index; + SStream_concat(O, "%s", buffer); } +static void addStringInfo(cs_detail* detail, SStream* O, int adjust_offset, bool is_write, uint8_t length) +{ + RegisterStringInfo* info = NULL; + + if (is_write) { + int i = detail->regs_write_string_count++; + info = &detail->regs_write_string_info[i]; + } else { + int i = detail->regs_read_string_count++; + info = &detail->regs_read_string_info[i]; + } + + info->type = REGISTER_STRING_INFO_REGISTER; + info->length = length; + info->offset = O->index + adjust_offset; +} + static void registerPair(SStream* O, const cs_m68k_op* op) { - SStream_concat(O, "%s:%s", s_reg_names[op->reg_pair.reg_0], - s_reg_names[op->reg_pair.reg_1]); + SStream_concat(O, "%s:%s", s_reg_names[op->reg_pair.reg_0], s_reg_names[op->reg_pair.reg_1]); } -static void printAddressingMode(SStream* O, unsigned int pc, const cs_m68k* inst, const cs_m68k_op* op) +static void printAddressingMode(cs_detail* detail, SStream* O, unsigned int pc, const cs_m68k* inst, const cs_m68k_op* op, bool is_write) { switch (op->address_mode) { case M68K_AM_NONE: switch (op->type) { case M68K_OP_REG_BITS: - registerBits(O, op); + registerBits(detail, O, op, is_write); break; case M68K_OP_REG_PAIR: + //registerPair(detail, O, op, is_write); registerPair(O, op); break; case M68K_OP_REG: SStream_concat(O, "%s", s_reg_names[op->reg]); + addStringInfo(detail, O, 0, is_write, strlen(s_reg_names[op->reg])); break; default: break; } break; - case M68K_AM_REG_DIRECT_DATA: SStream_concat(O, "d%d", (op->reg - M68K_REG_D0)); break; - case M68K_AM_REG_DIRECT_ADDR: SStream_concat(O, "a%d", (op->reg - M68K_REG_A0)); break; - case M68K_AM_REGI_ADDR: SStream_concat(O, "(a%d)", (op->reg - M68K_REG_A0)); break; - case M68K_AM_REGI_ADDR_POST_INC: SStream_concat(O, "(a%d)+", (op->reg - M68K_REG_A0)); break; - case M68K_AM_REGI_ADDR_PRE_DEC: SStream_concat(O, "-(a%d)", (op->reg - M68K_REG_A0)); break; - case M68K_AM_REGI_ADDR_DISP: SStream_concat(O, "%s$%x(a%d)", op->mem.disp < 0 ? "-" : "", abs(op->mem.disp), (op->mem.base_reg - M68K_REG_A0)); break; - case M68K_AM_PCI_DISP: SStream_concat(O, "$%x(pc)", pc + 2 + op->mem.disp); break; + case M68K_AM_REG_DIRECT_DATA: + { + addStringInfo(detail, O, 0, is_write, 2); + SStream_concat(O, "d%d", (op->reg - M68K_REG_D0)); + break; + } + + case M68K_AM_REG_DIRECT_ADDR: + { + addStringInfo(detail, O, 0, is_write, 2); + SStream_concat(O, "a%d", (op->reg - M68K_REG_A0)); + break; + } + + case M68K_AM_REGI_ADDR: + { + addStringInfo(detail, O, 1, is_write, 2); + SStream_concat(O, "(a%d)", (op->reg - M68K_REG_A0)); + break; + } + + case M68K_AM_REGI_ADDR_POST_INC: + { + addStringInfo(detail, O, 1, true, 2); + SStream_concat(O, "(a%d)+", (op->reg - M68K_REG_A0)); + break; + } + + case M68K_AM_REGI_ADDR_PRE_DEC: + { + addStringInfo(detail, O, 2, true, 2); + SStream_concat(O, "-(a%d)", (op->reg - M68K_REG_A0)); + break; + } + + case M68K_AM_REGI_ADDR_DISP: + { + SStream_concat(O, "%s$%x(a%d)", op->mem.disp < 0 ? "-" : "", abs(op->mem.disp), (op->mem.base_reg - M68K_REG_A0)); + addStringInfo(detail, O, -2, false, 2); + break; + } + + case M68K_AM_PCI_DISP: + { + SStream_concat(O, "$%x(pc)", pc + 2 + op->mem.disp); + break; + } + case M68K_AM_ABSOLUTE_DATA_SHORT: SStream_concat(O, "$%x.w", op->imm); break; case M68K_AM_ABSOLUTE_DATA_LONG: SStream_concat(O, "$%x.l", op->imm); break; case M68K_AM_IMMEDIATE: @@ -176,11 +250,26 @@ static void printAddressingMode(SStream* O, unsigned int pc, const cs_m68k* inst SStream_concat(O, "#$%x", op->imm); break; case M68K_AM_PCI_INDEX_8_BIT_DISP: - SStream_concat(O, "$%x(pc,%s%s.%c)", pc + 2 + op->mem.disp, s_spacing, getRegName(op->mem.index_reg), op->mem.index_size ? 'l' : 'w'); + { + SStream_concat(O, "$%x(pc,%s.%c)", + pc + 2 + op->mem.disp, + getRegName(op->mem.index_reg), + op->mem.index_size ? 'l' : 'w'); + addStringInfo(detail, O, -3, false, 2); break; + } case M68K_AM_AREGI_INDEX_8_BIT_DISP: - SStream_concat(O, "%s$%x(%s,%s%s.%c)", op->mem.disp < 0 ? "-" : "", abs(op->mem.disp), getRegName(op->mem.base_reg), s_spacing, getRegName(op->mem.index_reg), op->mem.index_size ? 'l' : 'w'); + { + SStream_concat(O, "%s$%x(%s,%s.%c)", + op->mem.disp < 0 ? "-" : "", + abs(op->mem.disp), + getRegName(op->mem.base_reg), + getRegName(op->mem.index_reg), + op->mem.index_size ? 'l' : 'w'); + addStringInfo(detail, O, -5, false, 2); + addStringInfo(detail, O, -3, false, 2); break; + } case M68K_AM_PCI_INDEX_BASE_DISP: case M68K_AM_AREGI_INDEX_BASE_DISP: @@ -197,7 +286,12 @@ static void printAddressingMode(SStream* O, unsigned int pc, const cs_m68k* inst SStream_concat(O, "pc,%s.%c", getRegName(op->mem.index_reg), op->mem.index_size ? 'l' : 'w'); } else { if (op->mem.base_reg != M68K_REG_INVALID) + { + addStringInfo(detail, O, 0, false, 2); SStream_concat(O, "a%d,%s", op->mem.base_reg - M68K_REG_A0, s_spacing); + } + + addStringInfo(detail, O, 0, false, 2); SStream_concat(O, "%s.%c", getRegName(op->mem.index_reg), op->mem.index_size ? 'l' : 'w'); } @@ -224,9 +318,15 @@ static void printAddressingMode(SStream* O, unsigned int pc, const cs_m68k* inst if (op->mem.base_reg != M68K_REG_INVALID) { if (op->mem.in_disp > 0) - SStream_concat(O, ",%s%s", s_spacing, getRegName(op->mem.base_reg)); + { + addStringInfo(detail, O, 1, false, 2); + SStream_concat(O, ",%s", getRegName(op->mem.base_reg)); + } else + { + addStringInfo(detail, O, 0, false, 2); SStream_concat(O, "%s", getRegName(op->mem.base_reg)); + } } if (op->address_mode == M68K_AM_MEMI_POST_INDEX || op->address_mode == M68K_AM_PC_MEMI_POST_INDEX) @@ -325,8 +425,8 @@ void M68K_printInst(MCInst* MI, SStream* O, void* PrinterInfo) if (MI->Opcode == M68K_INS_CAS2) { int reg_value_0, reg_value_1; - printAddressingMode(O, info->pc, ext, &ext->operands[0]); SStream_concat0(O, ","); - printAddressingMode(O, info->pc, ext, &ext->operands[1]); SStream_concat0(O, ","); + printAddressingMode(detail, O, info->pc, ext, &ext->operands[0], false); SStream_concat0(O, ","); + printAddressingMode(detail, O, info->pc, ext, &ext->operands[1], true); SStream_concat0(O, ","); reg_value_0 = ext->operands[2].register_bits >> 4; reg_value_1 = ext->operands[2].register_bits & 0xf; SStream_concat(O, "(%s):(%s)", s_reg_names[M68K_REG_D0 + reg_value_0], s_reg_names[M68K_REG_D0 + reg_value_1]); @@ -334,7 +434,8 @@ void M68K_printInst(MCInst* MI, SStream* O, void* PrinterInfo) } for (i = 0; i < ext->op_count; ++i) { - printAddressingMode(O, info->pc, ext, &ext->operands[i]); + bool is_write = i == ext->op_count - 1; + printAddressingMode(detail, O, info->pc, ext, &ext->operands[i], is_write); if ((i + 1) != ext->op_count) SStream_concat(O, ",%s", s_spacing); } diff --git a/external/capstone/include/capstone/capstone.h b/external/capstone/include/capstone/capstone.h index a7313754..f8df19ac 100644 --- a/external/capstone/include/capstone/capstone.h +++ b/external/capstone/include/capstone/capstone.h @@ -377,18 +377,31 @@ typedef struct cs_opt_skipdata { #define MAX_IMPL_R_REGS 20 #define MAX_NUM_GROUPS 8 +#define REGISTER_STRING_INFO_REGISTER 0 +#define REGISTER_STRING_INFO_REG_BITS 1 + +typedef struct RegisterStringInfo { + uint16_t offset; + uint8_t length; + uint8_t type; +} RegisterStringInfo; + /// NOTE: All information in cs_detail is only available when CS_OPT_DETAIL = CS_OPT_ON /// Initialized as memset(., 0, offsetof(cs_detail, ARCH)+sizeof(cs_ARCH)) /// by ARCH_getInstruction in arch/ARCH/ARCHDisassembler.c /// if cs_detail changes, in particular if a field is added after the union, /// then update arch/ARCH/ARCHDisassembler.c accordingly typedef struct cs_detail { - uint16_t regs_read - [MAX_IMPL_R_REGS]; ///< list of implicit registers read by this insn - uint8_t regs_read_count; ///< number of implicit registers read by this insn + RegisterStringInfo regs_read_string_info[MAX_IMPL_R_REGS]; + uint8_t regs_read_string_count; - uint16_t regs_write - [MAX_IMPL_W_REGS]; ///< list of implicit registers modified by this insn + RegisterStringInfo regs_write_string_info[MAX_IMPL_W_REGS]; + uint8_t regs_write_string_count; + + uint16_t regs_read[MAX_IMPL_R_REGS]; ///< list of implicit registers read by this insn + uint8_t regs_read_count; ///< number of implicit registers read by this insn + + uint16_t regs_write[MAX_IMPL_W_REGS]; ///< list of implicit registers modified by this insn uint8_t regs_write_count; ///< number of implicit registers modified by this insn uint8_t groups[MAX_NUM_GROUPS]; ///< list of group this instruction belong to diff --git a/src/debugger/disassembly_view.cpp b/src/debugger/disassembly_view.cpp index 73d82864..bb89cad5 100644 --- a/src/debugger/disassembly_view.cpp +++ b/src/debugger/disassembly_view.cpp @@ -40,6 +40,44 @@ static void draw_disassembly(DisassemblyView* self) { cs_insn* insn = nullptr; size_t count = cs_disasm(self->capstone, pc_addr - offset, count_bytes, start_disasm, 0, &insn); + for (size_t j = 0; j < count; j++) { + cs_detail* detail = insn[j].detail; + + printf("--------------------------------------------------------\n"); + + printf("%08llxx %s %s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str); + printf(" read offsets registers: "); + + for (int i = 0; i < detail->regs_read_string_count; i++) { + RegisterStringInfo* reg = &detail->regs_read_string_info[i]; + printf(" %d %d %d |", reg->offset, reg->length, reg->type); + } + + printf("\n"); + printf(" write offsets registers:"); + + for (int i = 0; i < detail->regs_write_string_count; i++) { + RegisterStringInfo* reg = &detail->regs_write_string_info[i]; + printf(" %d %d %d | \n", reg->offset, reg->length, reg->type); + } + + printf("\n"); + printf(" read registers: "); + + for (int i = 0; i < detail->regs_read_count; i++) { + printf(" %d |", detail->regs_read[i]); + } + + printf("\n"); + printf(" write registers: "); + + for (int i = 0; i < detail->regs_write_count; i++) { + printf(" %d |", detail->regs_write[i]); + } + + printf("\n"); + } + int max_instruction_width = 20; ImGuiTableFlags flags = ImGuiTableFlags_Resizable diff --git a/src/quaesar.cpp b/src/quaesar.cpp index faf47648..3fa0d521 100644 --- a/src/quaesar.cpp +++ b/src/quaesar.cpp @@ -65,8 +65,9 @@ int main(int argc, char** argv) { currprefs.cpu_cycle_exact = 1; currprefs.cpu_memory_cycle_exact = 1; currprefs.blitter_cycle_exact = 1; - currprefs.turbo_emulation = 0; + currprefs.turbo_emulation = 1; currprefs.sound_stereo_separation = 0; + currprefs.uaeboard = 1; strcpy(currprefs.romfile, options.kickstart.c_str());