From 4295268e947104a17d64fb5b3e53380f269d7bdd Mon Sep 17 00:00:00 2001 From: wargio <wargio@libero.it> Date: Mon, 26 Jun 2023 22:40:09 +0800 Subject: [PATCH 1/3] Initial working sh4 frame support --- linux-user/sh4/trace_info.h | 6 ++ qobject/block-qdict.c | 2 +- target/sh4/helper.h | 5 ++ target/sh4/meson.build | 4 ++ target/sh4/trace_helper.c | 120 ++++++++++++++++++++++++++++++++++++ target/sh4/translate.c | 27 ++++++++ 6 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 linux-user/sh4/trace_info.h create mode 100644 target/sh4/trace_helper.c diff --git a/linux-user/sh4/trace_info.h b/linux-user/sh4/trace_info.h new file mode 100644 index 0000000000000..e32f8a07f63d1 --- /dev/null +++ b/linux-user/sh4/trace_info.h @@ -0,0 +1,6 @@ +#pragma once + +#include "frame_arch.h" + +const uint64_t frame_arch = frame_arch_sh; +const uint64_t frame_mach = frame_mach_sh4; diff --git a/qobject/block-qdict.c b/qobject/block-qdict.c index b26524429c0dd..699ddd4fe596d 100644 --- a/qobject/block-qdict.c +++ b/qobject/block-qdict.c @@ -222,7 +222,7 @@ void qdict_array_split(QDict *src, QList **dst) *dst = qlist_new(); for (i = 0; i < UINT_MAX; i++) { - QObject *subqobj; + QObject *subqobj = NULL; bool is_subqdict; QDict *subqdict = NULL; char indexstr[32], prefix[32]; diff --git a/target/sh4/helper.h b/target/sh4/helper.h index 8d792f6b5538d..d2d517cf68f7d 100644 --- a/target/sh4/helper.h +++ b/target/sh4/helper.h @@ -41,3 +41,8 @@ DEF_HELPER_FLAGS_2(ftrc_FT, TCG_CALL_NO_WG, i32, env, f32) DEF_HELPER_FLAGS_2(ftrc_DT, TCG_CALL_NO_WG, i32, env, f64) DEF_HELPER_3(fipr, void, env, i32, i32) DEF_HELPER_2(ftrv, void, env, i32) + +#ifdef HAS_TRACEWRAP +DEF_HELPER_1(trace_newframe, void, i32) +DEF_HELPER_2(trace_endframe, void, env, i32) +#endif /* HAS_TRACEWRAP */ diff --git a/target/sh4/meson.build b/target/sh4/meson.build index 56a57576da76b..1f02c289a01d8 100644 --- a/target/sh4/meson.build +++ b/target/sh4/meson.build @@ -7,6 +7,10 @@ sh4_ss.add(files( 'translate.c', )) +if get_option('tracewrap') + sh4_ss.add(files('trace_helper.c')) +endif + sh4_softmmu_ss = ss.source_set() sh4_softmmu_ss.add(files('monitor.c')) diff --git a/target/sh4/trace_helper.c b/target/sh4/trace_helper.c new file mode 100644 index 0000000000000..71dad011acd8d --- /dev/null +++ b/target/sh4/trace_helper.c @@ -0,0 +1,120 @@ +#include "tracewrap.h" +#include "cpu.h" +#include "qemu/log.h" +#include "exec/helper-proto.h" +#include "exec/memop.h" + +const char *regs[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r0b", "r1b", "r2b", "r3b", "r4b", "r5b", "r6b", "r7b", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "sr", + "gbr", "ssr", "spc", "sgr", "dbr", "vbr", "mach", "macl", "pr" +}; +static const int reg_max = sizeof(regs) / sizeof(regs[0]); + +void HELPER(trace_newframe)(target_ulong pc) +{ + qemu_trace_newframe(pc, 0); +} + +void HELPER(trace_endframe)(CPUSH4State *env, target_ulong old_pc) +{ + qemu_trace_endframe(env, old_pc, 32); +} + +/* +OperandInfo * load_store_reg(uint32_t reg, uint32_t val, int ls) +{ + RegOperand * ro = g_new(RegOperand,1); + reg_operand__init(ro); + ro->name = g_strdup(reg < reg_max ? regs[reg] : "UNKNOWN"); + + OperandInfoSpecific *ois = g_new(OperandInfoSpecific,1); + operand_info_specific__init(ois); + ois->reg_operand = ro; + OperandUsage *ou = g_new(OperandUsage,1); + operand_usage__init(ou); + if (ls == 0) + { + ou->read = 1; + } else { + ou->written = 1; + } + OperandInfo *oi = g_new(OperandInfo,1); + operand_info__init(oi); + oi->bit_length = 0; + oi->operand_info_specific = ois; + oi->operand_usage = ou; + oi->value.len = 4; + oi->value.data = g_malloc(oi->value.len); + memcpy(oi->value.data, &val, 4); + return oi; +} + +void HELPER(trace_load_reg)(uint32_t reg, uint32_t val) +{ + qemu_log("This register (r%d) was read. Value 0x%x\n", reg, val); + + //r0 always reads 0 + OperandInfo *oi = load_store_reg(reg, (reg != 0) ? val : 0, 0); + + qemu_trace_add_operand(oi, 0x1); +} + +void HELPER(trace_store_reg)(uint32_t reg, uint32_t val) +{ + qemu_log("This register (r%d) was written. Value: 0x%x\n", reg, val); + + OperandInfo *oi = load_store_reg(reg, val, 1); + + qemu_trace_add_operand(oi, 0x2); +} + +// TODO: signature has changed, see arm +OperandInfo * load_store_mem(uint32_t addr, uint32_t val, int ls, int len) { + MemOperand * mo = g_new(MemOperand,1); + mem_operand__init(mo); + + mo->address = addr; + + OperandInfoSpecific *ois = g_new(OperandInfoSpecific,1); + operand_info_specific__init(ois); + ois->mem_operand = mo; + + OperandUsage *ou = g_new(OperandUsage,1); + operand_usage__init(ou); + if (ls == 0) { + ou->read = 1; + } else { + ou->written = 1; + } + OperandInfo *oi = g_new(OperandInfo,1); + operand_info__init(oi); + oi->bit_length = len*8; + oi->operand_info_specific = ois; + oi->operand_usage = ou; + oi->value.len = len; + oi->value.data = g_malloc(oi->value.len); + memcpy(oi->value.data, &val, len); + + return oi; +} + +void HELPER(trace_ld)(CPUMIPSState *env, uint32_t val, uint32_t addr) +{ + qemu_log("This was a read 0x%x addr:0x%x value:0x%x\n", env->active_tc.PC, addr, val); + + OperandInfo *oi = load_store_mem(addr, val, 0, 4); + + qemu_trace_add_operand(oi, 0x1); +} + +void HELPER(trace_st)(CPUMIPSState *env, uint32_t val, uint32_t addr) +{ + qemu_log("This was a store 0x%x addr:0x%x value:0x%x\n", env->active_tc.PC, addr, val); + + OperandInfo *oi = load_store_mem(addr, val, 1, 4); + + qemu_trace_add_operand(oi, 0x2); +} +*/ \ No newline at end of file diff --git a/target/sh4/translate.c b/target/sh4/translate.c index ce5d674a520e7..36942a7a68c2d 100644 --- a/target/sh4/translate.c +++ b/target/sh4/translate.c @@ -2285,6 +2285,24 @@ static void sh4_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) tcg_gen_insn_start(ctx->base.pc_next, ctx->envflags); } +#ifdef HAS_TRACEWRAP +static inline void gen_trace_newframe(uint32_t pc) +{ + TCGv_i32 tmp0 = tcg_temp_new_i32(); + tcg_gen_movi_i32(tmp0, pc); + gen_helper_trace_newframe(tmp0); + tcg_temp_free_i32(tmp0); +} + +static inline void gen_trace_endframe(uint32_t pc) +{ + TCGv_i32 tmp0 = tcg_temp_new_i32(); + tcg_gen_movi_i32(tmp0, pc); + gen_helper_trace_endframe(cpu_env, tmp0); + tcg_temp_free_i32(tmp0); +} +#endif /* HAS_TRACEWRAP */ + static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { CPUSH4State *env = cs->env_ptr; @@ -2303,9 +2321,18 @@ static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) } #endif +#ifdef HAS_TRACEWRAP + gen_trace_newframe(ctx->base.pc_next); +#endif + ctx->opcode = translator_lduw(env, &ctx->base, ctx->base.pc_next); decode_opc(ctx); ctx->base.pc_next += 2; + +#ifdef HAS_TRACEWRAP + gen_trace_endframe(ctx->base.pc_next); +#endif + } static void sh4_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) From 9018d02d7cb0e6142d8b91b3156f1f3792831315 Mon Sep 17 00:00:00 2001 From: wargio <wargio@libero.it> Date: Mon, 26 Jun 2023 22:48:30 +0800 Subject: [PATCH 2/3] Fixed trace --- target/sh4/helper.h | 4 ++++ target/sh4/trace_helper.c | 40 +++++++++++++++++++-------------------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/target/sh4/helper.h b/target/sh4/helper.h index d2d517cf68f7d..2ed3a5bcfcc69 100644 --- a/target/sh4/helper.h +++ b/target/sh4/helper.h @@ -45,4 +45,8 @@ DEF_HELPER_2(ftrv, void, env, i32) #ifdef HAS_TRACEWRAP DEF_HELPER_1(trace_newframe, void, i32) DEF_HELPER_2(trace_endframe, void, env, i32) +DEF_HELPER_2(trace_load_reg, void, i32, i32) +DEF_HELPER_2(trace_store_reg, void, i32, i32) +DEF_HELPER_3(trace_ld, void, env, i32, i32) +DEF_HELPER_3(trace_st, void, env, i32, i32) #endif /* HAS_TRACEWRAP */ diff --git a/target/sh4/trace_helper.c b/target/sh4/trace_helper.c index 71dad011acd8d..0e6f3c872dcc5 100644 --- a/target/sh4/trace_helper.c +++ b/target/sh4/trace_helper.c @@ -22,7 +22,6 @@ void HELPER(trace_endframe)(CPUSH4State *env, target_ulong old_pc) qemu_trace_endframe(env, old_pc, 32); } -/* OperandInfo * load_store_reg(uint32_t reg, uint32_t val, int ls) { RegOperand * ro = g_new(RegOperand,1); @@ -53,7 +52,7 @@ OperandInfo * load_store_reg(uint32_t reg, uint32_t val, int ls) void HELPER(trace_load_reg)(uint32_t reg, uint32_t val) { - qemu_log("This register (r%d) was read. Value 0x%x\n", reg, val); + // qemu_log("This register (r%d) was read. Value 0x%x\n", reg, val); //r0 always reads 0 OperandInfo *oi = load_store_reg(reg, (reg != 0) ? val : 0, 0); @@ -63,58 +62,59 @@ void HELPER(trace_load_reg)(uint32_t reg, uint32_t val) void HELPER(trace_store_reg)(uint32_t reg, uint32_t val) { - qemu_log("This register (r%d) was written. Value: 0x%x\n", reg, val); + // qemu_log("This register (r%d) was written. Value: 0x%x\n", reg, val); OperandInfo *oi = load_store_reg(reg, val, 1); qemu_trace_add_operand(oi, 0x2); } -// TODO: signature has changed, see arm -OperandInfo * load_store_mem(uint32_t addr, uint32_t val, int ls, int len) { - MemOperand * mo = g_new(MemOperand,1); +OperandInfo *load_store_mem(uint64_t addr, int ls, const void *data, size_t data_size) { + MemOperand * mo = g_new(MemOperand, 1); mem_operand__init(mo); mo->address = addr; - OperandInfoSpecific *ois = g_new(OperandInfoSpecific,1); + OperandInfoSpecific *ois = g_new(OperandInfoSpecific, 1); operand_info_specific__init(ois); ois->mem_operand = mo; - OperandUsage *ou = g_new(OperandUsage,1); + OperandUsage *ou = g_new(OperandUsage, 1); operand_usage__init(ou); if (ls == 0) { ou->read = 1; } else { ou->written = 1; } - OperandInfo *oi = g_new(OperandInfo,1); + OperandInfo *oi = g_new(OperandInfo, 1); operand_info__init(oi); - oi->bit_length = len*8; + oi->bit_length = data_size * 8; oi->operand_info_specific = ois; oi->operand_usage = ou; - oi->value.len = len; + oi->value.len = data_size; oi->value.data = g_malloc(oi->value.len); - memcpy(oi->value.data, &val, len); - + #ifdef BSWAP_NEEDED + memcpy_rev(oi->value.data, data, data_size); + #else + memcpy(oi->value.data, data, data_size); + #endif return oi; } -void HELPER(trace_ld)(CPUMIPSState *env, uint32_t val, uint32_t addr) +void HELPER(trace_ld)(CPUSH4State *env, uint32_t val, uint32_t addr) { - qemu_log("This was a read 0x%x addr:0x%x value:0x%x\n", env->active_tc.PC, addr, val); + // qemu_log("This was a read 0x%x addr:0x%x value:0x%x\n", env->active_tc.PC, addr, val); - OperandInfo *oi = load_store_mem(addr, val, 0, 4); + OperandInfo *oi = load_store_mem(addr, 0, val, 4); qemu_trace_add_operand(oi, 0x1); } -void HELPER(trace_st)(CPUMIPSState *env, uint32_t val, uint32_t addr) +void HELPER(trace_st)(CPUSH4State *env, uint32_t val, uint32_t addr) { - qemu_log("This was a store 0x%x addr:0x%x value:0x%x\n", env->active_tc.PC, addr, val); + // qemu_log("This was a store 0x%x addr:0x%x value:0x%x\n", env->active_tc.PC, addr, val); - OperandInfo *oi = load_store_mem(addr, val, 1, 4); + OperandInfo *oi = load_store_mem(addr, 1, val, 4); qemu_trace_add_operand(oi, 0x2); } -*/ \ No newline at end of file From 55cca7a8d322f025475f12b82cf0df26d57c9a94 Mon Sep 17 00:00:00 2001 From: wargio <wargio@libero.it> Date: Thu, 29 Jun 2023 11:19:14 +0800 Subject: [PATCH 3/3] Trying to make things work --- target/sh4/helper.h | 4 +- target/sh4/trace_helper.c | 21 ++++----- target/sh4/translate.c | 95 +++++++++++++++++++++++++++++---------- 3 files changed, 83 insertions(+), 37 deletions(-) diff --git a/target/sh4/helper.h b/target/sh4/helper.h index 2ed3a5bcfcc69..cb274a0c38e3c 100644 --- a/target/sh4/helper.h +++ b/target/sh4/helper.h @@ -47,6 +47,6 @@ DEF_HELPER_1(trace_newframe, void, i32) DEF_HELPER_2(trace_endframe, void, env, i32) DEF_HELPER_2(trace_load_reg, void, i32, i32) DEF_HELPER_2(trace_store_reg, void, i32, i32) -DEF_HELPER_3(trace_ld, void, env, i32, i32) -DEF_HELPER_3(trace_st, void, env, i32, i32) +DEF_HELPER_3(trace_load_mem, void, i32, i32, i32) +DEF_HELPER_3(trace_store_mem, void, i32, i32, i32) #endif /* HAS_TRACEWRAP */ diff --git a/target/sh4/trace_helper.c b/target/sh4/trace_helper.c index 0e6f3c872dcc5..a619bc926ddc0 100644 --- a/target/sh4/trace_helper.c +++ b/target/sh4/trace_helper.c @@ -3,6 +3,7 @@ #include "qemu/log.h" #include "exec/helper-proto.h" #include "exec/memop.h" +#include "qemu/log.h" const char *regs[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", @@ -52,7 +53,7 @@ OperandInfo * load_store_reg(uint32_t reg, uint32_t val, int ls) void HELPER(trace_load_reg)(uint32_t reg, uint32_t val) { - // qemu_log("This register (r%d) was read. Value 0x%x\n", reg, val); + qemu_log("This register (r%d) was read. Value 0x%x\n", reg, val); //r0 always reads 0 OperandInfo *oi = load_store_reg(reg, (reg != 0) ? val : 0, 0); @@ -62,7 +63,7 @@ void HELPER(trace_load_reg)(uint32_t reg, uint32_t val) void HELPER(trace_store_reg)(uint32_t reg, uint32_t val) { - // qemu_log("This register (r%d) was written. Value: 0x%x\n", reg, val); + qemu_log("This register (r%d) was written. Value: 0x%x\n", reg, val); OperandInfo *oi = load_store_reg(reg, val, 1); @@ -101,20 +102,16 @@ OperandInfo *load_store_mem(uint64_t addr, int ls, const void *data, size_t data return oi; } -void HELPER(trace_ld)(CPUSH4State *env, uint32_t val, uint32_t addr) +void HELPER(trace_load_mem)(uint32_t addr, uint32_t val, uint32_t op) { - // qemu_log("This was a read 0x%x addr:0x%x value:0x%x\n", env->active_tc.PC, addr, val); - - OperandInfo *oi = load_store_mem(addr, 0, val, 4); - + qemu_log("LOAD at 0x%lx size: %d data: 0x%lx\n", (unsigned long) addr, memop_size(op), (unsigned long) val); + OperandInfo *oi = load_store_mem(addr, 0, &val, memop_size(op)); qemu_trace_add_operand(oi, 0x1); } -void HELPER(trace_st)(CPUSH4State *env, uint32_t val, uint32_t addr) +void HELPER(trace_store_mem)(uint32_t addr, uint32_t val, uint32_t op) { - // qemu_log("This was a store 0x%x addr:0x%x value:0x%x\n", env->active_tc.PC, addr, val); - - OperandInfo *oi = load_store_mem(addr, 1, val, 4); - + qemu_log("STORE at 0x%lx size: %d data: 0x%lx\n", (unsigned long) addr, memop_size(op), (unsigned long) val); + OperandInfo *oi = load_store_mem(addr, 1, &val, memop_size(op)); qemu_trace_add_operand(oi, 0x2); } diff --git a/target/sh4/translate.c b/target/sh4/translate.c index 36942a7a68c2d..0aff9da2172e6 100644 --- a/target/sh4/translate.c +++ b/target/sh4/translate.c @@ -185,6 +185,66 @@ void superh_cpu_dump_state(CPUState *cs, FILE *f, int flags) } } +#ifdef HAS_TRACEWRAP +static void gen_trace_load_reg(uint32_t reg, TCGv var) +{ + TCGv_i32 t = tcg_const_i32(reg); + gen_helper_trace_load_reg(t, var); + tcg_temp_free_i32(t); +} + +static void gen_trace_store_reg(uint32_t reg, TCGv var) +{ + TCGv_i32 t = tcg_const_i32(reg); + gen_helper_trace_store_reg(t, var); + tcg_temp_free_i32(t); +} + +static inline void gen_trace_newframe(uint32_t pc) +{ + TCGv_i32 tmp0 = tcg_temp_new_i32(); + tcg_gen_movi_i32(tmp0, pc); + gen_helper_trace_newframe(tmp0); + tcg_temp_free_i32(tmp0); +} + +static inline void gen_trace_endframe(uint32_t pc) +{ + TCGv_i32 tmp0 = tcg_temp_new_i32(); + tcg_gen_movi_i32(tmp0, pc); + gen_helper_trace_endframe(cpu_env, tmp0); + tcg_temp_free_i32(tmp0); +} +#endif /* HAS_TRACEWRAP */ + +static inline void log_load_gpr(uint32_t rx, TCGv var) { + #ifdef HAS_TRACEWRAP + gen_trace_load_reg(rx, var); + #endif +} + +static inline void log_store_gpr(uint32_t rx, TCGv var) { + #ifdef HAS_TRACEWRAP + gen_trace_store_reg(rx, var); + #endif +} + +static inline void log_load_mem(TCGv addr, TCGv val, MemOp op) { + #ifdef HAS_TRACEWRAP + TCGv_i32 o = tcg_const_i32(op); + gen_helper_trace_load_mem(addr, val, o); + tcg_temp_free_i32(o); + #endif +} + +static inline void log_store_mem(TCGv addr, TCGv val, MemOp op) { + #ifdef HAS_TRACEWRAP + TCGv_i32 o = tcg_const_i32(op); + gen_helper_trace_store_mem(addr, val, o); + tcg_temp_free_i32(o); + #endif +} + static void gen_read_sr(TCGv dst) { TCGv t0 = tcg_temp_new(); @@ -238,6 +298,9 @@ static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) tcg_gen_goto_tb(n); tcg_gen_movi_i32(cpu_pc, dest); tcg_gen_exit_tb(ctx->base.tb, n); + #ifdef HAS_TRACEWRAP + gen_trace_endframe(dest); + #endif } else { tcg_gen_movi_i32(cpu_pc, dest); if (use_exit_tb(ctx)) { @@ -529,8 +592,9 @@ static void _decode_opc(DisasContext * ctx) return; case 0xd000: /* mov.l @(disp,PC),Rn */ { - TCGv addr = tcg_const_i32((ctx->base.pc_next + 4 + B7_0 * 4) & ~3); - tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL); + TCGv addr = tcg_const_i32((ctx->base.pc_next + 4 + B7_0 * 4) & ~3); + tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL); + log_load_mem(addr, REG(B11_8), MO_TESL); tcg_temp_free(addr); } return; @@ -552,7 +616,7 @@ static void _decode_opc(DisasContext * ctx) switch (ctx->opcode & 0xf00f) { case 0x6003: /* mov Rm,Rn */ - tcg_gen_mov_i32(REG(B11_8), REG(B7_4)); + tcg_gen_mov_i32(REG(B11_8), REG(B7_4)); return; case 0x2000: /* mov.b Rm,@Rn */ tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_UB); @@ -659,8 +723,8 @@ static void _decode_opc(DisasContext * ctx) { TCGv addr = tcg_temp_new(); tcg_gen_add_i32(addr, REG(B7_4), REG(0)); - tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL); - tcg_temp_free(addr); + tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL); + tcg_temp_free(addr); } return; case 0x6008: /* swap.b Rm,Rn */ @@ -2285,24 +2349,6 @@ static void sh4_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) tcg_gen_insn_start(ctx->base.pc_next, ctx->envflags); } -#ifdef HAS_TRACEWRAP -static inline void gen_trace_newframe(uint32_t pc) -{ - TCGv_i32 tmp0 = tcg_temp_new_i32(); - tcg_gen_movi_i32(tmp0, pc); - gen_helper_trace_newframe(tmp0); - tcg_temp_free_i32(tmp0); -} - -static inline void gen_trace_endframe(uint32_t pc) -{ - TCGv_i32 tmp0 = tcg_temp_new_i32(); - tcg_gen_movi_i32(tmp0, pc); - gen_helper_trace_endframe(cpu_env, tmp0); - tcg_temp_free_i32(tmp0); -} -#endif /* HAS_TRACEWRAP */ - static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { CPUSH4State *env = cs->env_ptr; @@ -2353,6 +2399,9 @@ static void sh4_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) case DISAS_TOO_MANY: gen_save_cpu_state(ctx, false); gen_goto_tb(ctx, 0, ctx->base.pc_next); + #ifdef HAS_TRACEWRAP + gen_trace_endframe(ctx->base.pc_next); + #endif break; case DISAS_NORETURN: break;