From 466e16c46ebe35eb17b31e3de82649641428f2c9 Mon Sep 17 00:00:00 2001 From: Anthony Pesch Date: Sat, 7 Oct 2017 20:32:46 -0400 Subject: [PATCH] only raise illegal instruction exception for 0xfffd --- src/guest/sh4/sh4.c | 41 +++++++++++++++++++++++++++-- src/guest/sh4/sh4.h | 1 + src/jit/frontend/sh4/sh4_frontend.c | 2 +- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/guest/sh4/sh4.c b/src/guest/sh4/sh4.c index 3ce8c295..fadea4e3 100644 --- a/src/guest/sh4/sh4.c +++ b/src/guest/sh4/sh4.c @@ -66,20 +66,35 @@ static uint32_t sh4_reg_read(struct sh4 *sh4, uint32_t addr, uint32_t data_mask) { uint32_t offset = SH4_REG_OFFSET(addr); reg_read_cb read = sh4_cb[offset].read; + + uint32_t data; if (read) { - return read(sh4->dc); + data = read(sh4->dc); + } else { + data = sh4->reg[offset]; } - return sh4->reg[offset]; + + if (sh4->log_reg_access) { + LOG_INFO("sh4_reg_read addr=0x%08x data=0x%x", addr, data); + } + + return data; } static void sh4_reg_write(struct sh4 *sh4, uint32_t addr, uint32_t data, uint32_t data_mask) { uint32_t offset = SH4_REG_OFFSET(addr); reg_write_cb write = sh4_cb[offset].write; + + if (sh4->log_reg_access) { + LOG_INFO("sh4_reg_write addr=0x%08x data=0x%x", addr, data & data_mask); + } + if (write) { write(sh4->dc, data); return; } + sh4->reg[offset] = data; } @@ -157,6 +172,24 @@ static void sh4_compile_code(struct sh4 *sh4, uint32_t addr) { } static void sh4_invalid_instr(struct sh4 *sh4) { + uint32_t pc = sh4->ctx.pc; + uint16_t data = as_read16(sh4->memory_if->space, pc); + struct jit_opdef *def = sh4_get_opdef(data); + + /* op may be valid if the delay slot raised this */ + if (def->op != SH4_OP_INVALID) { + data = as_read16(sh4->memory_if->space, pc + 2); + def = sh4_get_opdef(data); + } + + /* TODO write tests to confirm if any other instructions generate illegal + instruction exceptions */ + if (data != 0xfffd) { + return; + } + + CHECK_EQ(def->op, SH4_OP_INVALID); + sh4_exception(sh4, SH4_EXC_ILLINSTR); } @@ -298,6 +331,10 @@ void sh4_debug_menu(struct sh4 *sh4) { } } + if (igMenuItem("log reg access", NULL, sh4->log_reg_access, 1)) { + sh4->log_reg_access = !sh4->log_reg_access; + } + igEndMenu(); } diff --git a/src/guest/sh4/sh4.h b/src/guest/sh4/sh4.h index 62ba3710..046da3e6 100644 --- a/src/guest/sh4/sh4.h +++ b/src/guest/sh4/sh4.h @@ -62,6 +62,7 @@ struct sh4 { struct jit_backend *backend; /* dbg */ + int log_reg_access; struct list breakpoints; /* intc */ diff --git a/src/jit/frontend/sh4/sh4_frontend.c b/src/jit/frontend/sh4/sh4_frontend.c index 7fe5ee3e..342b5495 100644 --- a/src/jit/frontend/sh4/sh4_frontend.c +++ b/src/jit/frontend/sh4/sh4_frontend.c @@ -58,7 +58,7 @@ static int sh4_frontend_is_idle_loop(struct sh4_frontend *frontend, if (def->flags & SH4_FLAG_DELAYED) { uint32_t delay_addr = begin_addr + offset; - uint32_t delay_data = guest->r16(guest->space, delay_addr); + uint16_t delay_data = guest->r16(guest->space, delay_addr); struct jit_opdef *delay_def = sh4_get_opdef(delay_data); offset += 2;