From aaf2c49015866a681f0d93f6e77513d6e4385eec Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Mon, 6 Jun 2016 17:55:05 +0200 Subject: [PATCH] [M68K] Implemented regs read/write lists --- arch/M68K/M68KDisassembler.c | 133 +++++++++++++++++++++++++++++++++++ arch/M68K/M68KDisassembler.h | 4 ++ arch/M68K/M68KInstPrinter.c | 20 ++++-- bindings/python/test_m68k.py | 11 ++- tests/test_m68k.c | 26 +++++-- 5 files changed, 185 insertions(+), 9 deletions(-) diff --git a/arch/M68K/M68KDisassembler.c b/arch/M68K/M68KDisassembler.c index 45206080..605c46e8 100644 --- a/arch/M68K/M68KDisassembler.c +++ b/arch/M68K/M68KDisassembler.c @@ -3833,6 +3833,135 @@ static int instruction_is_valid(m68k_info *info, const unsigned int word_check) return 1; } +static int exists_reg_list(uint16_t *regs, uint8_t count, m68k_reg reg) +{ + uint8_t i; + + for (i = 0; i < count; ++i) { + if (regs[i] == (uint16_t)reg) + return 1; + } + + return 0; +} + +static void add_reg_to_rw_list(m68k_info *info, m68k_reg reg, int write) +{ + if (reg == M68K_REG_INVALID) + return; + + if (write) + { + if (exists_reg_list(info->regs_write, info->regs_write_count, reg)) + return; + + info->regs_write[info->regs_write_count++] = (uint16_t)reg; + } + else + { + if (exists_reg_list(info->regs_read, info->regs_read_count, reg)) + return; + + info->regs_read[info->regs_read_count++] = (uint16_t)reg; + } +} + +static void update_am_reg_list(m68k_info *info, cs_m68k_op *op, int write) +{ + switch (op->address_mode) { + case M68K_AM_REG_DIRECT_ADDR: + case M68K_AM_REG_DIRECT_DATA: + add_reg_to_rw_list(info, op->reg, write); + break; + + case M68K_AM_REGI_ADDR_POST_INC: + case M68K_AM_REGI_ADDR_PRE_DEC: + add_reg_to_rw_list(info, op->reg, 1); + break; + + case M68K_AM_REGI_ADDR: + case M68K_AM_REGI_ADDR_DISP: + add_reg_to_rw_list(info, op->reg, 0); + break; + + case M68K_AM_AREGI_INDEX_8_BIT_DISP: + case M68K_AM_AREGI_INDEX_BASE_DISP: + case M68K_AM_MEMI_POST_INDEX: + case M68K_AM_MEMI_PRE_INDEX: + case M68K_AM_PCI_INDEX_8_BIT_DISP: + case M68K_AM_PCI_INDEX_BASE_DISP: + case M68K_AM_PC_MEMI_PRE_INDEX: + case M68K_AM_PC_MEMI_POST_INDEX: + add_reg_to_rw_list(info, op->mem.index_reg, 0); + add_reg_to_rw_list(info, op->mem.base_reg, 0); + break; + + // no register(s) in the other addressing modes + default: + break; + } +} + +static void update_bits_range(m68k_info *info, m68k_reg reg_start, uint8_t bits, int write) +{ + int i; + + for (i = 0; i < 8; ++i) { + if (bits & (1 << i)) { + add_reg_to_rw_list(info, reg_start + i, write); + } + } +} + +static void update_reg_list_regbits(m68k_info *info, cs_m68k_op *op, int write) +{ + uint32_t bits = op->register_bits; + update_bits_range(info, M68K_REG_D0, bits & 0xff, write); + update_bits_range(info, M68K_REG_A0, (bits >> 8) & 0xff, write); + update_bits_range(info, M68K_REG_FP0, (bits >> 16) & 0xff, write); +} + +static void update_op_reg_list(m68k_info *info, cs_m68k_op *op, int write) +{ + switch ((int)op->type) { + case M68K_OP_REG: + add_reg_to_rw_list(info, op->reg, write); + break; + + case M68K_OP_MEM: + update_am_reg_list(info, op, write); + break; + + case M68K_OP_REG_BITS: + update_reg_list_regbits(info, op, write); + break; + + case M68K_OP_REG_PAIR: + add_reg_to_rw_list(info, M68K_REG_D0 + op->reg_pair.reg_0, write); + add_reg_to_rw_list(info, M68K_REG_D0 + op->reg_pair.reg_1, write); + break; + } +} + +static void build_regs_read_write_counts(m68k_info *info) +{ + int i; + + if (!info->extension.op_count) + return; + + if (info->extension.op_count == 1) { + update_op_reg_list(info, &info->extension.operands[0], 1); + } else { + // first operand is always read + update_op_reg_list(info, &info->extension.operands[0], 0); + + // remaning write + for (i = 1; i < info->extension.op_count; ++i) + update_op_reg_list(info, &info->extension.operands[i], 1); + } +} + static void m68k_setup_internals(m68k_info* info, MCInst* inst, unsigned int pc, unsigned int cpu_type) { info->inst = inst; @@ -3913,6 +4042,8 @@ bool M68K_getInstruction(csh ud, const uint8_t* code, size_t code_len, MCInst* i m68k_info *info = (m68k_info*)handle->printer_info; info->groups_count = 0; + info->regs_read_count = 0; + info->regs_write_count = 0; info->code = code; info->code_len = code_len; info->baseAddress = address; @@ -3936,6 +4067,8 @@ bool M68K_getInstruction(csh ud, const uint8_t* code, size_t code_len, MCInst* i return false; } + build_regs_read_write_counts(info); + #ifdef M68K_DEBUG SStream_Init(&ss); M68K_printInst(instr, &ss, info); diff --git a/arch/M68K/M68KDisassembler.h b/arch/M68K/M68KDisassembler.h index c5f797c8..7f715f69 100644 --- a/arch/M68K/M68KDisassembler.h +++ b/arch/M68K/M68KDisassembler.h @@ -17,6 +17,10 @@ typedef struct m68k_info { unsigned int type; unsigned int address_mask; /* Address mask to simulate address lines */ cs_m68k extension; + uint16_t regs_read[12]; // 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[20]; // list of implicit registers modified by this insn + uint8_t regs_write_count; // number of implicit registers modified by this insn uint8_t groups[8]; uint8_t groups_count; } m68k_info; diff --git a/arch/M68K/M68KInstPrinter.c b/arch/M68K/M68KInstPrinter.c index 91baeec9..76e81080 100644 --- a/arch/M68K/M68KInstPrinter.c +++ b/arch/M68K/M68KInstPrinter.c @@ -233,6 +233,9 @@ void printAddressingMode(SStream* O, const cs_m68k* inst, const cs_m68k_op* op) } #endif +#define m68k_sizeof_array(array) (int)(sizeof(array)/sizeof(array[0])) +#define m68k_min(a, b) (a < b) ? a : b + void M68K_printInst(MCInst* MI, SStream* O, void* PrinterInfo) { #ifndef CAPSTONE_DIET @@ -243,11 +246,20 @@ void M68K_printInst(MCInst* MI, SStream* O, void* PrinterInfo) detail = MI->flat_insn->detail; if (detail) { + int regs_read_count = m68k_min(m68k_sizeof_array(detail->regs_read), info->regs_read_count); + int regs_write_count = m68k_min(m68k_sizeof_array(detail->regs_write), info->regs_write_count); + int groups_count = m68k_min(m68k_sizeof_array(detail->groups), info->groups_count); + memcpy(&detail->m68k, ext, sizeof(cs_m68k)); - memcpy(&detail->groups, &info->groups, info->groups_count); - detail->groups_count = info->groups_count; - detail->regs_read_count = 0; - detail->regs_write_count = 0; + + memcpy(&detail->regs_read, &info->regs_read, regs_read_count * sizeof(uint16_t)); + detail->regs_read_count = regs_read_count; + + memcpy(&detail->regs_write, &info->regs_write, regs_write_count * sizeof(uint16_t)); + detail->regs_write_count = regs_write_count; + + memcpy(&detail->groups, &info->groups, groups_count); + detail->groups_count = groups_count; } if (MI->Opcode == M68K_INS_INVALID) { diff --git a/bindings/python/test_m68k.py b/bindings/python/test_m68k.py index 4f6e3dfe..8400311a 100755 --- a/bindings/python/test_m68k.py +++ b/bindings/python/test_m68k.py @@ -6,7 +6,7 @@ from capstone import * from capstone.m68k import * from xprint import to_hex, to_x -M68K_CODE = b"\xd4\x40\x87\x5a\x4e\x71\x02\xb4\xc0\xde\xc0\xde\x5c\x00\x1d\x80\x71\x12\x01\x23\xf2\x3c\x44\x22\x40\x49\x0e\x56\x54\xc5\xf2\x3c\x44\x00\x44\x7a\x00\x00\xf2\x00\x0a\x28\x4E\xB9\x00\x00\x00\x12\x4E\x75" +M68K_CODE = b"\x4c\x00\x54\x04\x48\xe7\xe0\x30\x4c\xdf\x0c\x07\xd4\x40\x87\x5a\x4e\x71\x02\xb4\xc0\xde\xc0\xde\x5c\x00\x1d\x80\x71\x12\x01\x23\xf2\x3c\x44\x22\x40\x49\x0e\x56\x54\xc5\xf2\x3c\x44\x00\x44\x7a\x00\x00\xf2\x00\x0a\x28\x4e\xb9\x00\x00\x00\x12\x4e\x75" all_tests = ( (CS_ARCH_M68K, CS_MODE_BIG_ENDIAN | CS_MODE_M68K_040, M68K_CODE, "M68K"), @@ -42,11 +42,20 @@ s_addressing_modes = { 18: "Immidate value", } +def print_read_write_regs(insn): + for m in insn.regs_read: + print("\treading from reg: %s" % insn.reg_name(m)) + + for m in insn.regs_write: + print("\twriting to reg: %s" % insn.reg_name(m)) + def print_insn_detail(insn): if len(insn.operands) > 0: print("\top_count: %u" % (len(insn.operands))) print("\tgroups_count: %u" % len(insn.groups)) + print_read_write_regs(insn) + for i, op in enumerate(insn.operands): if op.type == M68K_OP_REG: print("\t\toperands[%u].type: REG = %s" % (i, insn.reg_name(op.reg))) diff --git a/tests/test_m68k.c b/tests/test_m68k.c index 46e73e03..ff60ac03 100644 --- a/tests/test_m68k.c +++ b/tests/test_m68k.c @@ -58,6 +58,25 @@ const char* s_addressing_modes[] = { "Immidate value", }; +static void print_read_write_regs(cs_detail* detail) +{ + int i; + + for (i = 0; i < detail->regs_read_count; ++i) + { + uint16_t reg_id = detail->regs_read[i]; + const char* reg_name = cs_reg_name(handle, reg_id); + printf("\treading from reg: %s\n", reg_name); + } + + for (i = 0; i < detail->regs_write_count; ++i) + { + uint16_t reg_id = detail->regs_write[i]; + const char* reg_name = cs_reg_name(handle, reg_id); + printf("\twriting to reg: %s\n", reg_name); + } +} + static void print_insn_detail(cs_insn *ins) { cs_m68k* m68k; @@ -73,6 +92,8 @@ static void print_insn_detail(cs_insn *ins) if (m68k->op_count) printf("\top_count: %u\n", m68k->op_count); + print_read_write_regs(detail); + printf("\tgroups_count: %u\n", detail->groups_count); for (i = 0; i < m68k->op_count; i++) { @@ -119,12 +140,9 @@ static void print_insn_detail(cs_insn *ins) printf("\n"); } -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - static void test() { -#define M68K_CODE "\xd4\x40\x87\x5a\x4e\x71\x02\xb4\xc0\xde\xc0\xde\x5c\x00\x1d\x80\x71\x12\x01\x23\xf2\x3c\x44\x22\x40\x49\x0e\x56\x54\xc5\xf2\x3c\x44\x00\x44\x7a\x00\x00\xf2\x00\x0a\x28\x4E\xB9\x00\x00\x00\x12\x4E\x75" - +#define M68K_CODE "\x4C\x00\x54\x04\x48\xe7\xe0\x30\x4C\xDF\x0C\x07\xd4\x40\x87\x5a\x4e\x71\x02\xb4\xc0\xde\xc0\xde\x5c\x00\x1d\x80\x71\x12\x01\x23\xf2\x3c\x44\x22\x40\x49\x0e\x56\x54\xc5\xf2\x3c\x44\x00\x44\x7a\x00\x00\xf2\x00\x0a\x28\x4E\xB9\x00\x00\x00\x12\x4E\x75" struct platform platforms[] = { { CS_ARCH_M68K,