Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uc hook tcg improve #2011

Merged
merged 4 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions qemu/target/arm/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
#include "uc_priv.h"

#define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
#define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
Expand Down Expand Up @@ -451,9 +452,29 @@ static void gen_sub_carry(TCGContext *tcg_ctx, TCGv_i32 dest, TCGv_i32 t0, TCGv_
tcg_gen_subi_i32(tcg_ctx, dest, dest, 1);
}

static inline void mb_tcg_opcode_cmp_hook(TCGContext *tcg_ctx, TCGv_i64 v0, TCGv_i64 v1, uint32_t size)
{
CPUARMState *cpuarm = (CPUARMState *)(tcg_ctx->cpu->env_ptr);
uint64_t pc = cpuarm->regs[15] + (cpuarm->thumb ? 1 : 0);
uc_engine *uc = tcg_ctx->uc;
if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_TCG_OPCODE, pc)) {
struct hook *hook;
HOOK_FOREACH_VAR_DECLARE;
HOOK_FOREACH(uc, hook, UC_HOOK_TCG_OPCODE) {
if (hook->to_delete)
continue;
if (hook->op == UC_TCG_OP_SUB && (hook->op_flags & UC_TCG_OP_FLAG_CMP)) {
gen_uc_traceopcode(tcg_ctx, hook, v0, v1, size, uc, pc);
}
}
}
}

/* dest = T0 + T1. Compute C, N, V and Z flags */
static void gen_add_CC(TCGContext *tcg_ctx, TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
{
mb_tcg_opcode_cmp_hook(tcg_ctx, (TCGv_i64)t0, (TCGv_i64)t1, 32);

TCGv_i32 tmp = tcg_temp_new_i32(tcg_ctx);
tcg_gen_movi_i32(tcg_ctx, tmp, 0);
tcg_gen_add2_i32(tcg_ctx, tcg_ctx->cpu_NF, tcg_ctx->cpu_CF, t0, tmp, t1, tmp);
Expand Down Expand Up @@ -496,6 +517,8 @@ static void gen_adc_CC(TCGContext *tcg_ctx, TCGv_i32 dest, TCGv_i32 t0, TCGv_i32
/* dest = T0 - T1. Compute C, N, V and Z flags */
static void gen_sub_CC(TCGContext *tcg_ctx, TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
{
mb_tcg_opcode_cmp_hook(tcg_ctx, (TCGv_i64)t0, (TCGv_i64)t1, 32);

TCGv_i32 tmp;
tcg_gen_sub_i32(tcg_ctx, tcg_ctx->cpu_NF, t0, t1);
tcg_gen_mov_i32(tcg_ctx, tcg_ctx->cpu_ZF, tcg_ctx->cpu_NF);
Expand Down
70 changes: 70 additions & 0 deletions tests/unit/test_arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,74 @@ static void test_arm_mem_hook_read_write(void)
OK(uc_close(uc));
}

typedef struct {
uint64_t v0;
uint64_t v1;
uint64_t size;
uint64_t pc;
} _last_cmp_info;

static void _uc_hook_sub_cmp(uc_engine *uc, uint64_t address, uint64_t arg1,
uint64_t arg2, uint32_t size,
_last_cmp_info *user_data)
{
user_data->pc = address;
user_data->size = size;
user_data->v0 = arg1;
user_data->v1 = arg2;
}

static void test_arm_tcg_opcode_cmp(void)
{
uc_engine *uc;
const char code[] = "\x04\x00\x9f\xe5" // ldr r0, [pc, #4]
"\x04\x10\x9f\xe5" // ldr r1, [pc, #4]
"\x01\x00\x50\xe1" // cmp r0, r1
"\x05\x00\x00\x00" // (5)
"\x03\x00\x00\x00" // (3)
;

uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_ARM, code, sizeof(code) - 1,
UC_CPU_ARM_CORTEX_A15);

uc_hook hook;
_last_cmp_info cmp_info = {0};

OK(uc_hook_add(uc, &hook, UC_HOOK_TCG_OPCODE, (void *)_uc_hook_sub_cmp,
(void *)&cmp_info, 1, 0, UC_TCG_OP_SUB, UC_TCG_OP_FLAG_CMP));

OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 3));
TEST_CHECK(cmp_info.v0 == 5 && cmp_info.v1 == 3);
TEST_CHECK(cmp_info.pc == code_start);
TEST_CHECK(cmp_info.size == 32);
}

static void test_arm_thumb_tcg_opcode_cmn(void)
{
uc_engine *uc;
const char code[] = "\x01\x48" // ldr r0, [pc, #4]
"\x02\x49" // ldr r1, [pc, #8]
"\x00\xbf" // nop
"\xc8\x42" // cmn r0, r1
"\x05\x00\x00\x00" // (5)
"\x03\x00\x00\x00" // (3)
;

uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB, code, sizeof(code) - 1,
UC_CPU_ARM_CORTEX_A15);

uc_hook hook;
_last_cmp_info cmp_info = {0};

OK(uc_hook_add(uc, &hook, UC_HOOK_TCG_OPCODE, (void *)_uc_hook_sub_cmp,
(void *)&cmp_info, 1, 0, UC_TCG_OP_SUB, UC_TCG_OP_FLAG_CMP));

OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0, 4));
TEST_CHECK(cmp_info.v0 == 5 && cmp_info.v1 == 3);
TEST_CHECK(cmp_info.pc == (code_start | 1));
TEST_CHECK(cmp_info.size == 32);
}

TEST_LIST = {{"test_arm_nop", test_arm_nop},
{"test_arm_thumb_sub", test_arm_thumb_sub},
{"test_armeb_sub", test_armeb_sub},
Expand All @@ -887,4 +955,6 @@ TEST_LIST = {{"test_arm_nop", test_arm_nop},
{"test_arm_thumb2", test_arm_thumb2},
{"test_armeb_be32_thumb2", test_armeb_be32_thumb2},
{"test_arm_mem_hook_read_write", test_arm_mem_hook_read_write},
{"test_arm_tcg_opcode_cmp", test_arm_tcg_opcode_cmp},
{"test_arm_thumb_tcg_opcode_cmn", test_arm_thumb_tcg_opcode_cmn},
{NULL, NULL}};
Loading