From 074566cf697bfa38b3c9dd283c52ef4e4549c208 Mon Sep 17 00:00:00 2001 From: Robert Xiao Date: Thu, 11 May 2023 20:08:27 -0700 Subject: [PATCH] Slight refactoring to reduce code duplication. This also comes with a performance bump due to inlining of reg_read/reg_write (as they're only called once now) and the unlikely() on CHECK_REG_TYPE. --- qemu/target/arm/unicorn_aarch64.c | 80 +++++++++++----------- qemu/target/arm/unicorn_arm.c | 86 +++++++++++------------- qemu/target/i386/unicorn.c | 107 ++++++++++++------------------ qemu/target/m68k/unicorn.c | 80 +++++++++++----------- qemu/target/mips/unicorn.c | 80 +++++++++++----------- qemu/target/ppc/unicorn.c | 80 +++++++++++----------- qemu/target/riscv/unicorn.c | 80 +++++++++++----------- qemu/target/s390x/unicorn.c | 92 ++++++++++++------------- qemu/target/sparc/unicorn.c | 80 +++++++++++----------- qemu/target/sparc/unicorn64.c | 72 +++++++++----------- qemu/target/tricore/unicorn.c | 106 ++++++++++++++--------------- qemu/unicorn_common.h | 16 ++--- uc.c | 47 ++++++++----- 13 files changed, 473 insertions(+), 533 deletions(-) diff --git a/qemu/target/arm/unicorn_aarch64.c b/qemu/target/arm/unicorn_aarch64.c index f8d4446d..06320819 100644 --- a/qemu/target/arm/unicorn_aarch64.c +++ b/qemu/target/arm/unicorn_aarch64.c @@ -268,7 +268,7 @@ static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value, } static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value, - size_t *size) + size_t *size, int *setpc) { uc_err ret = UC_ERR_ARG; @@ -349,6 +349,7 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value, case UC_ARM64_REG_PC: CHECK_REG_TYPE(uint64_t); env->pc = *(uint64_t *)value; + *setpc = 1; break; case UC_ARM64_REG_SP: CHECK_REG_TYPE(uint64_t); @@ -397,17 +398,15 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value, return ret; } -int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, - size_t *sizes, int count) +static uc_err reg_read_batch(CPUARMState *env, unsigned int *regs, + void *const *vals, size_t *sizes, int count) { - CPUARMState *env = &(ARM_CPU(uc->cpu)->env); int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); + uc_err err = reg_read(env, regid, value, sizes ? sizes + i : NULL); if (err) { return err; } @@ -416,25 +415,45 @@ int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, return UC_ERR_OK; } -int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, - const void *const *vals, size_t *sizes, int count) +static uc_err reg_write_batch(CPUARMState *env, unsigned int *regs, + const void *const *vals, size_t *sizes, int count, + int *setpc) { - CPUARMState *env = &(ARM_CPU(uc->cpu)->env); int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); + uc_err err = + reg_write(env, regid, value, sizes ? sizes + i : NULL, setpc); if (err) { return err; } - if (regid == UC_ARM64_REG_PC) { - // force to quit execution and flush TB - uc->quit_request = true; - break_translation_loop(uc); - } + } + + return UC_ERR_OK; +} + +int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, + size_t *sizes, int count) +{ + CPUARMState *env = &(ARM_CPU(uc->cpu)->env); + return reg_read_batch(env, regs, vals, sizes, count); +} + +int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, + const void *const *vals, size_t *sizes, int count) +{ + CPUARMState *env = &(ARM_CPU(uc->cpu)->env); + int setpc = 0; + uc_err err = reg_write_batch(env, regs, vals, sizes, count, &setpc); + if (err) { + return err; + } + if (setpc) { + // force to quit execution and flush TB + uc->quit_request = true; + break_translation_loop(uc); } return UC_ERR_OK; @@ -450,19 +469,7 @@ int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs, #endif { CPUARMState *env = (CPUARMState *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; + return reg_read_batch(env, regs, vals, sizes, count); } DEFAULT_VISIBILITY @@ -475,19 +482,8 @@ int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs, #endif { CPUARMState *env = (CPUARMState *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; + int setpc = 0; + return reg_write_batch(env, regs, vals, sizes, count, &setpc); } static int arm64_cpus_init(struct uc_struct *uc, const char *cpu_model) diff --git a/qemu/target/arm/unicorn_arm.c b/qemu/target/arm/unicorn_arm.c index 3fc9704f..3582532e 100644 --- a/qemu/target/arm/unicorn_arm.c +++ b/qemu/target/arm/unicorn_arm.c @@ -355,7 +355,7 @@ static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value, } static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value, - size_t *size) + size_t *size, int *setpc) { uc_err ret = UC_ERR_ARG; @@ -428,6 +428,7 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value, env->thumb = (*(uint32_t *)value & 1); env->uc->thumb = (*(uint32_t *)value & 1); env->regs[15] = (*(uint32_t *)value & ~1); + *setpc = 1; break; // case UC_ARM_REG_C1_C0_2: // env->cp15.c1_coproc = *(int32_t *)value; @@ -550,20 +551,15 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value, return ret; } -int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, - size_t *sizes, int count) +static uc_err reg_read_batch(CPUARMState *env, unsigned int *regs, + void *const *vals, size_t *sizes, int count) { - CPUARMState *env = &(ARM_CPU(uc->cpu)->env); int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } + uc_err err = reg_read(env, regid, value, sizes ? sizes + i : NULL); if (err) { return err; } @@ -572,25 +568,45 @@ int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, return UC_ERR_OK; } -int arm_reg_write(struct uc_struct *uc, unsigned int *regs, - const void *const *vals, size_t *sizes, int count) +static uc_err reg_write_batch(CPUARMState *env, unsigned int *regs, + const void *const *vals, size_t *sizes, int count, + int *setpc) { - CPUArchState *env = &(ARM_CPU(uc->cpu)->env); int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); + uc_err err = + reg_write(env, regid, value, sizes ? sizes + i : NULL, setpc); if (err) { return err; } - if (regid == UC_ARM_REG_R15) { - // force to quit execution and flush TB - uc->quit_request = true; - break_translation_loop(uc); - } + } + + return UC_ERR_OK; +} + +int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, + size_t *sizes, int count) +{ + CPUARMState *env = &(ARM_CPU(uc->cpu)->env); + return reg_read_batch(env, regs, vals, sizes, count); +} + +int arm_reg_write(struct uc_struct *uc, unsigned int *regs, + const void *const *vals, size_t *sizes, int count) +{ + CPUArchState *env = &(ARM_CPU(uc->cpu)->env); + int setpc = 0; + uc_err err = reg_write_batch(env, regs, vals, sizes, count, &setpc); + if (err) { + return err; + } + if (setpc) { + // force to quit execution and flush TB + uc->quit_request = true; + break_translation_loop(uc); } return UC_ERR_OK; @@ -601,22 +617,7 @@ int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs, void *const *vals, size_t *sizes, int count) { CPUARMState *env = (CPUARMState *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - if (err) { - return err; - } - } - - return UC_ERR_OK; + return reg_read_batch(env, regs, vals, sizes, count); } DEFAULT_VISIBILITY @@ -624,19 +625,8 @@ int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs, const void *const *vals, size_t *sizes, int count) { CPUARMState *env = (CPUARMState *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; + int setpc = 0; + return reg_write_batch(env, regs, vals, sizes, count, &setpc); } static bool arm_stop_interrupt(struct uc_struct *uc, int intno) diff --git a/qemu/target/i386/unicorn.c b/qemu/target/i386/unicorn.c index 24d85754..6da03f2a 100644 --- a/qemu/target/i386/unicorn.c +++ b/qemu/target/i386/unicorn.c @@ -990,7 +990,7 @@ static uc_err reg_read(CPUX86State *env, unsigned int regid, void *value, } static uc_err reg_write(CPUX86State *env, unsigned int regid, const void *value, - size_t *size, uc_mode mode) + size_t *size, uc_mode mode, int *setpc) { uc_err ret = UC_ERR_ARG; @@ -1279,10 +1279,12 @@ static uc_err reg_write(CPUX86State *env, unsigned int regid, const void *value, case UC_X86_REG_EIP: CHECK_REG_TYPE(uint32_t); env->eip = *(uint32_t *)value; + *setpc = 1; break; case UC_X86_REG_IP: CHECK_REG_TYPE(uint16_t); env->eip = *(uint16_t *)value; + *setpc = 1; break; case UC_X86_REG_CS: CHECK_REG_TYPE(uint16_t); @@ -1569,14 +1571,17 @@ static uc_err reg_write(CPUX86State *env, unsigned int regid, const void *value, case UC_X86_REG_RIP: CHECK_REG_TYPE(uint64_t); env->eip = *(uint64_t *)value; + *setpc = 1; break; case UC_X86_REG_EIP: CHECK_REG_TYPE(uint32_t); env->eip = *(uint32_t *)value; + *setpc = 1; break; case UC_X86_REG_IP: CHECK_REG_TYPE(uint16_t); WRITE_WORD(env->eip, *(uint16_t *)value); + *setpc = 1; break; case UC_X86_REG_CS: CHECK_REG_TYPE(uint16_t); @@ -1801,17 +1806,17 @@ static uc_err reg_write(CPUX86State *env, unsigned int regid, const void *value, return ret; } -int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, - size_t *sizes, int count) +static uc_err reg_read_batch(CPUX86State *env, unsigned int *regs, + void *const *vals, size_t *sizes, int count, + int mode) { - CPUX86State *env = &(X86_CPU(uc->cpu)->env); int i; uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL, uc->mode); + err = reg_read(env, regid, value, sizes ? sizes + i : NULL, mode); if (err) { return err; } @@ -1820,50 +1825,47 @@ int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, return UC_ERR_OK; } -int x86_reg_write(struct uc_struct *uc, unsigned int *regs, - const void *const *vals, size_t *sizes, int count) +static uc_err reg_write_batch(CPUX86State *env, unsigned int *regs, + const void *const *vals, size_t *sizes, int count, + int mode, int *setpc) { - CPUX86State *env = &(X86_CPU(uc->cpu)->env); int i; uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL, uc->mode); + err = + reg_write(env, regid, value, sizes ? sizes + i : NULL, mode, setpc); if (err) { return err; } - switch (uc->mode) { - default: - break; - case UC_MODE_32: - switch (regid) { - default: - break; - case UC_X86_REG_EIP: - case UC_X86_REG_IP: - // force to quit execution and flush TB - uc->quit_request = true; - break_translation_loop(uc); - break; - } + } -#ifdef TARGET_X86_64 - case UC_MODE_64: - switch (regid) { - default: - break; - case UC_X86_REG_RIP: - case UC_X86_REG_EIP: - case UC_X86_REG_IP: - // force to quit execution and flush TB - uc->quit_request = true; - break_translation_loop(uc); - break; - } -#endif - } + return UC_ERR_OK; +} + +int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, + size_t *sizes, int count) +{ + CPUX86State *env = &(X86_CPU(uc->cpu)->env); + return reg_read_batch(env, regs, vals, sizes, count, uc->mode); +} + +int x86_reg_write(struct uc_struct *uc, unsigned int *regs, + const void *const *vals, size_t *sizes, int count) +{ + CPUX86State *env = &(X86_CPU(uc->cpu)->env); + int setpc = 0; + uc_err err = + reg_write_batch(env, regs, vals, sizes, count, uc->mode, &setpc); + if (err) { + return err; + } + if (setpc) { + // force to quit execution and flush TB + uc->quit_request = true; + break_translation_loop(uc); } return UC_ERR_OK; @@ -1874,19 +1876,7 @@ int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs, void *const *vals, size_t *sizes, int count) { CPUX86State *env = (CPUX86State *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL, ctx->mode); - if (err) { - return err; - } - } - - return UC_ERR_OK; + return reg_read_batch(env, regs, vals, sizes, count, ctx->mode); } DEFAULT_VISIBILITY @@ -1894,19 +1884,8 @@ int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs, const void *const *vals, size_t *sizes, int count) { CPUX86State *env = (CPUX86State *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL, ctx->mode); - if (err) { - return err; - } - } - - return UC_ERR_OK; + int setpc = 0; + return reg_write_batch(env, regs, vals, sizes, count, ctx->mode, &setpc); } static bool x86_stop_interrupt(struct uc_struct *uc, int intno) diff --git a/qemu/target/m68k/unicorn.c b/qemu/target/m68k/unicorn.c index 414a94ce..93bc7170 100644 --- a/qemu/target/m68k/unicorn.c +++ b/qemu/target/m68k/unicorn.c @@ -79,7 +79,7 @@ static uc_err reg_read(CPUM68KState *env, unsigned int regid, void *value, } static uc_err reg_write(CPUM68KState *env, unsigned int regid, - const void *value, size_t *size) + const void *value, size_t *size, int *setpc) { uc_err ret = UC_ERR_ARG; @@ -96,6 +96,7 @@ static uc_err reg_write(CPUM68KState *env, unsigned int regid, case UC_M68K_REG_PC: CHECK_REG_TYPE(uint32_t); env->pc = *(uint32_t *)value; + *setpc = 1; break; case UC_M68K_REG_SR: CHECK_REG_TYPE(uint32_t); @@ -107,17 +108,15 @@ static uc_err reg_write(CPUM68KState *env, unsigned int regid, return ret; } -int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, - size_t *sizes, int count) +static uc_err reg_read_batch(CPUM68KState *env, unsigned int *regs, + void *const *vals, size_t *sizes, int count) { - CPUM68KState *env = &(M68K_CPU(uc->cpu)->env); int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); + uc_err err = reg_read(env, regid, value, sizes ? sizes + i : NULL); if (err) { return err; } @@ -126,25 +125,45 @@ int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, return UC_ERR_OK; } -int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, - const void *const *vals, size_t *sizes, int count) +static uc_err reg_write_batch(CPUM68KState *env, unsigned int *regs, + const void *const *vals, size_t *sizes, int count, + int *setpc) { - CPUM68KState *env = &(M68K_CPU(uc->cpu)->env); int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); + uc_err err = + reg_write(env, regid, value, sizes ? sizes + i : NULL, setpc); if (err) { return err; } - if (regid == UC_M68K_REG_PC) { - // force to quit execution and flush TB - uc->quit_request = true; - break_translation_loop(uc); - } + } + + return UC_ERR_OK; +} + +int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, + size_t *sizes, int count) +{ + CPUM68KState *env = &(M68K_CPU(uc->cpu)->env); + return reg_read_batch(env, regs, vals, sizes, count); +} + +int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, + const void *const *vals, size_t *sizes, int count) +{ + CPUM68KState *env = &(M68K_CPU(uc->cpu)->env); + int setpc = 0; + uc_err err = reg_write_batch(env, regs, vals, sizes, count, &setpc); + if (err) { + return err; + } + if (setpc) { + // force to quit execution and flush TB + uc->quit_request = true; + break_translation_loop(uc); } return UC_ERR_OK; @@ -155,19 +174,7 @@ int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs, void *const *vals, size_t *sizes, int count) { CPUM68KState *env = (CPUM68KState *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; + return reg_read_batch(env, regs, vals, sizes, count); } DEFAULT_VISIBILITY @@ -175,19 +182,8 @@ int m68k_context_reg_write(struct uc_context *ctx, unsigned int *regs, const void *const *vals, size_t *sizes, int count) { CPUM68KState *env = (CPUM68KState *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; + int setpc = 0; + return reg_write_batch(env, regs, vals, sizes, count, &setpc); } static int m68k_cpus_init(struct uc_struct *uc, const char *cpu_model) diff --git a/qemu/target/mips/unicorn.c b/qemu/target/mips/unicorn.c index 786e014d..4edb7d33 100644 --- a/qemu/target/mips/unicorn.c +++ b/qemu/target/mips/unicorn.c @@ -102,7 +102,7 @@ static uc_err reg_read(CPUMIPSState *env, unsigned int regid, void *value, } static uc_err reg_write(CPUMIPSState *env, unsigned int regid, - const void *value, size_t *size) + const void *value, size_t *size, int *setpc) { uc_err ret = UC_ERR_ARG; @@ -124,6 +124,7 @@ static uc_err reg_write(CPUMIPSState *env, unsigned int regid, case UC_MIPS_REG_PC: CHECK_REG_TYPE(mipsreg_t); env->active_tc.PC = *(mipsreg_t *)value; + *setpc = 1; break; case UC_MIPS_REG_CP0_CONFIG3: CHECK_REG_TYPE(mipsreg_t); @@ -147,17 +148,15 @@ static uc_err reg_write(CPUMIPSState *env, unsigned int regid, return ret; } -int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, - size_t *sizes, int count) +static uc_err reg_read_batch(CPUMIPSState *env, unsigned int *regs, + void *const *vals, size_t *sizes, int count) { - CPUMIPSState *env = &(MIPS_CPU(uc->cpu)->env); int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); + uc_err err = reg_read(env, regid, value, sizes ? sizes + i : NULL); if (err) { return err; } @@ -166,25 +165,45 @@ int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, return UC_ERR_OK; } -int mips_reg_write(struct uc_struct *uc, unsigned int *regs, - const void *const *vals, size_t *sizes, int count) +static uc_err reg_write_batch(CPUMIPSState *env, unsigned int *regs, + const void *const *vals, size_t *sizes, int count, + int *setpc) { - CPUMIPSState *env = &(MIPS_CPU(uc->cpu)->env); int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); + uc_err err = + reg_write(env, regid, value, sizes ? sizes + i : NULL, setpc); if (err) { return err; } - if (regid == UC_MIPS_REG_PC) { - // force to quit execution and flush TB - uc->quit_request = true; - break_translation_loop(uc); - } + } + + return UC_ERR_OK; +} + +int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, + size_t *sizes, int count) +{ + CPUMIPSState *env = &(MIPS_CPU(uc->cpu)->env); + return reg_read_batch(env, regs, vals, sizes, count); +} + +int mips_reg_write(struct uc_struct *uc, unsigned int *regs, + const void *const *vals, size_t *sizes, int count) +{ + CPUMIPSState *env = &(MIPS_CPU(uc->cpu)->env); + int setpc = 0; + uc_err err = reg_write_batch(env, regs, vals, sizes, count, &setpc); + if (err) { + return err; + } + if (setpc) { + // force to quit execution and flush TB + uc->quit_request = true; + break_translation_loop(uc); } return UC_ERR_OK; @@ -210,19 +229,7 @@ int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs, #endif { CPUMIPSState *env = (CPUMIPSState *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; + return reg_read_batch(env, regs, vals, sizes, count); } DEFAULT_VISIBILITY @@ -246,19 +253,8 @@ int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs, #endif { CPUMIPSState *env = (CPUMIPSState *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; + int setpc = 0; + return reg_write_batch(env, regs, vals, sizes, count, &setpc); } static int mips_cpus_init(struct uc_struct *uc, const char *cpu_model) diff --git a/qemu/target/ppc/unicorn.c b/qemu/target/ppc/unicorn.c index b0f02ce2..edda420b 100644 --- a/qemu/target/ppc/unicorn.c +++ b/qemu/target/ppc/unicorn.c @@ -206,7 +206,7 @@ static uc_err reg_read(CPUPPCState *env, unsigned int regid, void *value, } static uc_err reg_write(CPUPPCState *env, unsigned int regid, const void *value, - size_t *size) + size_t *size, int *setpc) { int i; uc_err ret = UC_ERR_ARG; @@ -227,6 +227,7 @@ static uc_err reg_write(CPUPPCState *env, unsigned int regid, const void *value, case UC_PPC_REG_PC: CHECK_REG_TYPE(ppcreg_t); env->nip = *(ppcreg_t *)value; + *setpc = 1; break; case UC_PPC_REG_CR: { CHECK_REG_TYPE(uint32_t); @@ -263,17 +264,15 @@ static uc_err reg_write(CPUPPCState *env, unsigned int regid, const void *value, return ret; } -int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, - size_t *sizes, int count) +static uc_err reg_read_batch(CPUPPCState *env, unsigned int *regs, + void *const *vals, size_t *sizes, int count) { - CPUPPCState *env = &(POWERPC_CPU(uc->cpu)->env); int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); + uc_err err = reg_read(env, regid, value, sizes ? sizes + i : NULL); if (err) { return err; } @@ -282,25 +281,45 @@ int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, return UC_ERR_OK; } -int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, - const void *const *vals, size_t *sizes, int count) +static uc_err reg_write_batch(CPUPPCState *env, unsigned int *regs, + const void *const *vals, size_t *sizes, int count, + int *setpc) { - CPUPPCState *env = &(POWERPC_CPU(uc->cpu)->env); int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); + uc_err err = + reg_write(env, regid, value, sizes ? sizes + i : NULL, setpc); if (err) { return err; } - if (regid == UC_PPC_REG_PC) { - // force to quit execution and flush TB - uc->quit_request = true; - break_translation_loop(uc); - } + } + + return UC_ERR_OK; +} + +int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, + size_t *sizes, int count) +{ + CPUPPCState *env = &(POWERPC_CPU(uc->cpu)->env); + return reg_read_batch(env, regs, vals, sizes, count); +} + +int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, + const void *const *vals, size_t *sizes, int count) +{ + CPUPPCState *env = &(POWERPC_CPU(uc->cpu)->env); + int setpc = 0; + uc_err err = reg_write_batch(env, regs, vals, sizes, count, &setpc); + if (err) { + return err; + } + if (setpc) { + // force to quit execution and flush TB + uc->quit_request = true; + break_translation_loop(uc); } return UC_ERR_OK; @@ -316,19 +335,7 @@ int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs, #endif { CPUPPCState *env = (CPUPPCState *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; + return reg_read_batch(env, regs, vals, sizes, count); } DEFAULT_VISIBILITY @@ -341,19 +348,8 @@ int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs, #endif { CPUPPCState *env = (CPUPPCState *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; + int setpc = 0; + return reg_write_batch(env, regs, vals, sizes, count, &setpc); } PowerPCCPU *cpu_ppc_init(struct uc_struct *uc); diff --git a/qemu/target/riscv/unicorn.c b/qemu/target/riscv/unicorn.c index 846d2c17..86ab8746 100644 --- a/qemu/target/riscv/unicorn.c +++ b/qemu/target/riscv/unicorn.c @@ -128,7 +128,7 @@ static uc_err reg_read(CPURISCVState *env, unsigned int regid, void *value, } static uc_err reg_write(CPURISCVState *env, unsigned int regid, - const void *value, size_t *size) + const void *value, size_t *size, int *setpc) { uc_err ret = UC_ERR_ARG; @@ -167,6 +167,7 @@ static uc_err reg_write(CPURISCVState *env, unsigned int regid, CHECK_REG_TYPE(uint32_t); env->pc = *(uint32_t *)value; #endif + *setpc = 1; break; } } @@ -174,17 +175,15 @@ static uc_err reg_write(CPURISCVState *env, unsigned int regid, return ret; } -int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, - size_t *sizes, int count) +static uc_err reg_read_batch(CPURISCVState *env, unsigned int *regs, + void *const *vals, size_t *sizes, int count) { - CPURISCVState *env = &(RISCV_CPU(uc->cpu)->env); int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); + uc_err err = reg_read(env, regid, value, sizes ? sizes + i : NULL); if (err) { return err; } @@ -193,25 +192,45 @@ int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, return UC_ERR_OK; } -int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, - const void *const *vals, size_t *sizes, int count) +static uc_err reg_write_batch(CPURISCVState *env, unsigned int *regs, + const void *const *vals, size_t *sizes, int count, + int *setpc) { - CPURISCVState *env = &(RISCV_CPU(uc->cpu)->env); int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); + uc_err err = + reg_write(env, regid, value, sizes ? sizes + i : NULL, setpc); if (err) { return err; } - if (regid == UC_RISCV_REG_PC) { - // force to quit execution and flush TB - uc->quit_request = true; - break_translation_loop(uc); - } + } + + return UC_ERR_OK; +} + +int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, + size_t *sizes, int count) +{ + CPURISCVState *env = &(RISCV_CPU(uc->cpu)->env); + return reg_read_batch(env, regs, vals, sizes, count); +} + +int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, + const void *const *vals, size_t *sizes, int count) +{ + CPURISCVState *env = &(RISCV_CPU(uc->cpu)->env); + int setpc = 0; + uc_err err = reg_write_batch(env, regs, vals, sizes, count, &setpc); + if (err) { + return err; + } + if (setpc) { + // force to quit execution and flush TB + uc->quit_request = true; + break_translation_loop(uc); } return UC_ERR_OK; @@ -228,19 +247,7 @@ int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs, #endif { CPURISCVState *env = (CPURISCVState *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; + return reg_read_batch(env, regs, vals, sizes, count); } DEFAULT_VISIBILITY @@ -254,19 +261,8 @@ int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs, #endif { CPURISCVState *env = (CPURISCVState *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; + int setpc = 0; + return reg_write_batch(env, regs, vals, sizes, count, &setpc); } static bool riscv_stop_interrupt(struct uc_struct *uc, int intno) diff --git a/qemu/target/s390x/unicorn.c b/qemu/target/s390x/unicorn.c index f2e54d02..9d4ac0b0 100644 --- a/qemu/target/s390x/unicorn.c +++ b/qemu/target/s390x/unicorn.c @@ -83,7 +83,7 @@ static uc_err reg_read(CPUS390XState *env, unsigned int regid, void *value, } static uc_err reg_write(CPUS390XState *env, unsigned int regid, - const void *value, size_t *size) + const void *value, size_t *size, int *setpc) { uc_err ret = UC_ERR_ARG; @@ -100,6 +100,7 @@ static uc_err reg_write(CPUS390XState *env, unsigned int regid, case UC_S390X_REG_PC: CHECK_REG_TYPE(uint64_t); env->psw.addr = *(uint64_t *)value; + *setpc = 1; break; case UC_S390X_REG_PSWM: CHECK_REG_TYPE(uint64_t); @@ -111,18 +112,34 @@ static uc_err reg_write(CPUS390XState *env, unsigned int regid, return ret; } -DEFAULT_VISIBILITY -int s390_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, - size_t *sizes, int count) +static uc_err reg_read_batch(CPUS390XState *env, unsigned int *regs, + void *const *vals, size_t *sizes, int count) { - CPUS390XState *env = &(S390_CPU(uc->cpu)->env); int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); + uc_err err = reg_read(env, regid, value, sizes ? sizes + i : NULL); + if (err) { + return err; + } + } + + return UC_ERR_OK; +} + +static uc_err reg_write_batch(CPUS390XState *env, unsigned int *regs, + const void *const *vals, size_t *sizes, int count, + int *setpc) +{ + int i; + + for (i = 0; i < count; i++) { + unsigned int regid = regs[i]; + const void *value = vals[i]; + uc_err err = + reg_write(env, regid, value, sizes ? sizes + i : NULL, setpc); if (err) { return err; } @@ -131,26 +148,28 @@ int s390_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, return UC_ERR_OK; } +DEFAULT_VISIBILITY +int s390_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, + size_t *sizes, int count) +{ + CPUS390XState *env = &(S390_CPU(uc->cpu)->env); + return reg_read_batch(env, regs, vals, sizes, count); +} + DEFAULT_VISIBILITY int s390_reg_write(struct uc_struct *uc, unsigned int *regs, const void *const *vals, size_t *sizes, int count) { CPUS390XState *env = &(S390_CPU(uc->cpu)->env); - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - if (regid == UC_S390X_REG_PC) { - // force to quit execution and flush TB - uc->quit_request = true; - break_translation_loop(uc); - } + int setpc = 0; + uc_err err = reg_write_batch(env, regs, vals, sizes, count, &setpc); + if (err) { + return err; + } + if (setpc) { + // force to quit execution and flush TB + uc->quit_request = true; + break_translation_loop(uc); } return UC_ERR_OK; @@ -161,19 +180,7 @@ int s390_context_reg_read(struct uc_context *ctx, unsigned int *regs, void *const *vals, size_t *sizes, int count) { CPUS390XState *env = (CPUS390XState *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; + return reg_read_batch(env, regs, vals, sizes, count); } DEFAULT_VISIBILITY @@ -181,19 +188,8 @@ int s390_context_reg_write(struct uc_context *ctx, unsigned int *regs, const void *const *vals, size_t *sizes, int count) { CPUS390XState *env = (CPUS390XState *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; + int setpc = 0; + return reg_write_batch(env, regs, vals, sizes, count, &setpc); } static int s390_cpus_init(struct uc_struct *uc, const char *cpu_model) diff --git a/qemu/target/sparc/unicorn.c b/qemu/target/sparc/unicorn.c index d000b7de..030d3b12 100644 --- a/qemu/target/sparc/unicorn.c +++ b/qemu/target/sparc/unicorn.c @@ -92,7 +92,7 @@ static uc_err reg_read(CPUSPARCState *env, unsigned int regid, void *value, } static uc_err reg_write(CPUSPARCState *env, unsigned int regid, - const void *value, size_t *size) + const void *value, size_t *size, int *setpc) { uc_err ret = UC_ERR_ARG; @@ -116,6 +116,7 @@ static uc_err reg_write(CPUSPARCState *env, unsigned int regid, CHECK_REG_TYPE(uint32_t); env->pc = *(uint32_t *)value; env->npc = *(uint32_t *)value + 4; + *setpc = 1; break; } } @@ -123,17 +124,15 @@ static uc_err reg_write(CPUSPARCState *env, unsigned int regid, return ret; } -int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, - size_t *sizes, int count) +static uc_err reg_read_batch(CPUSPARCState *env, unsigned int *regs, + void *const *vals, size_t *sizes, int count) { - CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env); int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); + uc_err err = reg_read(env, regid, value, sizes ? sizes + i : NULL); if (err) { return err; } @@ -142,25 +141,45 @@ int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, return UC_ERR_OK; } -int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, - const void *const *vals, size_t *sizes, int count) +static uc_err reg_write_batch(CPUSPARCState *env, unsigned int *regs, + const void *const *vals, size_t *sizes, int count, + int *setpc) { - CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env); int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); + uc_err err = + reg_write(env, regid, value, sizes ? sizes + i : NULL, setpc); if (err) { return err; } - if (regid == UC_SPARC_REG_PC) { - // force to quit execution and flush TB - uc->quit_request = true; - break_translation_loop(uc); - } + } + + return UC_ERR_OK; +} + +int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, + size_t *sizes, int count) +{ + CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env); + return reg_read_batch(env, regs, vals, sizes, count); +} + +int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, + const void *const *vals, size_t *sizes, int count) +{ + CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env); + int setpc = 0; + uc_err err = reg_write_batch(env, regs, vals, sizes, count, &setpc); + if (err) { + return err; + } + if (setpc) { + // force to quit execution and flush TB + uc->quit_request = true; + break_translation_loop(uc); } return UC_ERR_OK; @@ -171,19 +190,7 @@ int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void *const *vals, size_t *sizes, int count) { CPUSPARCState *env = (CPUSPARCState *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; + return reg_read_batch(env, regs, vals, sizes, count); } DEFAULT_VISIBILITY @@ -191,19 +198,8 @@ int sparc_context_reg_write(struct uc_context *ctx, unsigned int *regs, const void *const *vals, size_t *sizes, int count) { CPUSPARCState *env = (CPUSPARCState *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; + int setpc = 0; + return reg_write_batch(env, regs, vals, sizes, count, &setpc); } static int sparc_cpus_init(struct uc_struct *uc, const char *cpu_model) diff --git a/qemu/target/sparc/unicorn64.c b/qemu/target/sparc/unicorn64.c index f477ea06..6c7bfae9 100644 --- a/qemu/target/sparc/unicorn64.c +++ b/qemu/target/sparc/unicorn64.c @@ -113,7 +113,7 @@ static uc_err reg_read(CPUSPARCState *env, unsigned int regid, void *value, size return ret; } -static uc_err reg_write(CPUSPARCState *env, unsigned int regid, const void *value, size_t *size) +static uc_err reg_write(CPUSPARCState *env, unsigned int regid, const void *value, size_t *size, int *setpc) { uc_err ret = UC_ERR_ARG; @@ -137,6 +137,7 @@ static uc_err reg_write(CPUSPARCState *env, unsigned int regid, const void *valu CHECK_REG_TYPE(uint64_t); env->pc = *(uint64_t *)value; env->npc = *(uint64_t *)value + 4; + *setpc = 1; break; } } @@ -144,16 +145,14 @@ static uc_err reg_write(CPUSPARCState *env, unsigned int regid, const void *valu return ret; } -int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, size_t *sizes, int count) +static uc_err reg_read_batch(CPUSPARCState *env, unsigned int *regs, void *const *vals, size_t *sizes, int count) { - CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env); int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); + uc_err err = reg_read(env, regid, value, sizes ? sizes + i : NULL); if (err) { return err; } @@ -162,24 +161,40 @@ int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, return UC_ERR_OK; } -int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, const void* const* vals, size_t *sizes, int count) +static uc_err reg_write_batch(CPUSPARCState *env, unsigned int *regs, const void* const* vals, size_t *sizes, int count, int *setpc) { - CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env); int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); + uc_err err = reg_write(env, regid, value, sizes ? sizes + i : NULL, setpc); if (err) { return err; } - if (regid == UC_SPARC_REG_PC) { - // force to quit execution and flush TB - uc->quit_request = true; - break_translation_loop(uc); - } + } + + return UC_ERR_OK; +} + +int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, size_t *sizes, int count) +{ + CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env); + return reg_read_batch(env, regs, vals, sizes, count); +} + +int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, const void* const* vals, size_t *sizes, int count) +{ + CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env); + int setpc = 0; + uc_err err = reg_write_batch(env, regs, vals, sizes, count, &setpc); + if (err) { + return err; + } + if (setpc) { + // force to quit execution and flush TB + uc->quit_request = true; + break_translation_loop(uc); } return UC_ERR_OK; @@ -189,38 +204,15 @@ DEFAULT_VISIBILITY int sparc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void *const *vals, size_t *sizes, int count) { CPUSPARCState *env = (CPUSPARCState *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; + return reg_read_batch(env, regs, vals, sizes, count); } DEFAULT_VISIBILITY int sparc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, const void *const *vals, size_t *sizes, int count) { CPUSPARCState *env = (CPUSPARCState *)ctx->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; + int setpc = 0; + return reg_write_batch(env, regs, vals, sizes, count, &setpc); } static int sparc_cpus_init(struct uc_struct *uc, const char *cpu_model) diff --git a/qemu/target/tricore/unicorn.c b/qemu/target/tricore/unicorn.c index 155cff15..3d35846b 100644 --- a/qemu/target/tricore/unicorn.c +++ b/qemu/target/tricore/unicorn.c @@ -139,46 +139,8 @@ static uc_err reg_read(CPUTriCoreState *env, unsigned int regid, void *value, return ret; } -int tricore_reg_read(struct uc_struct *uc, unsigned int *regs, - void *const *vals, size_t *sizes, int count) -{ - CPUTriCoreState *env = &(TRICORE_CPU(uc->cpu)->env); - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; -} - -int tricore_context_reg_read(struct uc_context *uc, unsigned int *regs, - void *const *vals, size_t *sizes, int count) -{ - CPUTriCoreState *env = (CPUTriCoreState *)uc->data; - int i; - uc_err err; - - for (i = 0; i < count; i++) { - unsigned int regid = regs[i]; - void *value = vals[i]; - err = reg_read(env, regid, value, sizes ? sizes + i : NULL); - if (err) { - return err; - } - } - - return UC_ERR_OK; -} - static uc_err reg_write(CPUTriCoreState *env, unsigned int regid, - const void *value, size_t *size) + const void *value, size_t *size, int *setpc) { uc_err ret = UC_ERR_ARG; @@ -206,6 +168,7 @@ static uc_err reg_write(CPUTriCoreState *env, unsigned int regid, case UC_TRICORE_REG_PC: CHECK_REG_TYPE(uint32_t); env->PC = *(uint32_t *)value; + *setpc = 1; break; case UC_TRICORE_REG_PCXI: CHECK_REG_TYPE(uint32_t); @@ -277,41 +240,34 @@ static uc_err reg_write(CPUTriCoreState *env, unsigned int regid, return ret; } -int tricore_reg_write(struct uc_struct *uc, unsigned int *regs, - const void *const *vals, size_t *sizes, int count) +static uc_err reg_read_batch(CPUTriCoreState *env, unsigned int *regs, + void *const *vals, size_t *sizes, int count) { - CPUTriCoreState *env = &(TRICORE_CPU(uc->cpu)->env); int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; - const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); + void *value = vals[i]; + uc_err err = reg_read(env, regid, value, sizes ? sizes + i : NULL); if (err) { return err; } - if (regid == UC_TRICORE_REG_PC) { - // force to quit execution and flush TB - uc->quit_request = true; - break_translation_loop(uc); - } } return UC_ERR_OK; } -int tricore_context_reg_write(struct uc_context *uc, unsigned int *regs, - const void *const *vals, size_t *sizes, int count) +static uc_err reg_write_batch(CPUTriCoreState *env, unsigned int *regs, + const void *const *vals, size_t *sizes, int count, + int *setpc) { - CPUTriCoreState *env = (CPUTriCoreState *)uc->data; int i; - uc_err err; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; const void *value = vals[i]; - err = reg_write(env, regid, value, sizes ? sizes + i : NULL); + uc_err err = + reg_write(env, regid, value, sizes ? sizes + i : NULL, setpc); if (err) { return err; } @@ -320,6 +276,46 @@ int tricore_context_reg_write(struct uc_context *uc, unsigned int *regs, return UC_ERR_OK; } +int tricore_reg_read(struct uc_struct *uc, unsigned int *regs, + void *const *vals, size_t *sizes, int count) +{ + CPUTriCoreState *env = &(TRICORE_CPU(uc->cpu)->env); + return reg_read_batch(env, regs, vals, sizes, count); +} + +int tricore_reg_write(struct uc_struct *uc, unsigned int *regs, + const void *const *vals, size_t *sizes, int count) +{ + CPUTriCoreState *env = &(TRICORE_CPU(uc->cpu)->env); + int setpc = 0; + uc_err err = reg_write_batch(env, regs, vals, sizes, count, &setpc); + if (err) { + return err; + } + if (setpc) { + // force to quit execution and flush TB + uc->quit_request = true; + break_translation_loop(uc); + } + + return UC_ERR_OK; +} + +int tricore_context_reg_read(struct uc_context *uc, unsigned int *regs, + void *const *vals, size_t *sizes, int count) +{ + CPUTriCoreState *env = (CPUTriCoreState *)uc->data; + return reg_read_batch(env, regs, vals, sizes, count); +} + +int tricore_context_reg_write(struct uc_context *uc, unsigned int *regs, + const void *const *vals, size_t *sizes, int count) +{ + CPUTriCoreState *env = (CPUTriCoreState *)uc->data; + int setpc = 0; + return reg_write_batch(env, regs, vals, sizes, count, &setpc); +} + static int tricore_cpus_init(struct uc_struct *uc, const char *cpu_model) { TriCoreCPU *cpu; diff --git a/qemu/unicorn_common.h b/qemu/unicorn_common.h index b5cb5610..3059eb74 100644 --- a/qemu/unicorn_common.h +++ b/qemu/unicorn_common.h @@ -129,14 +129,14 @@ static inline void uc_common_init(struct uc_struct* uc) uc->release = release_common; } -#define CHECK_REG_TYPE(type) do { \ - if (size) { \ - if (*size < sizeof(type)) { \ - return UC_ERR_NOMEM; \ - } \ - *size = sizeof(type); \ - } \ - ret = UC_ERR_OK; \ +#define CHECK_REG_TYPE(type) do { \ + if (unlikely(size)) { \ + if (unlikely(*size < sizeof(type))) { \ + return UC_ERR_NOMEM; \ + } \ + *size = sizeof(type); \ + } \ + ret = UC_ERR_OK; \ } while(0) #endif diff --git a/uc.c b/uc.c index 1152f3ee..0581c408 100644 --- a/uc.c +++ b/uc.c @@ -82,6 +82,18 @@ unsigned int uc_version(unsigned int *major, unsigned int *minor) UC_API_EXTRA; } +static int default_reg_read(struct uc_struct *uc, unsigned int *regs, + void *const *vals, size_t *sizes, int count) +{ + return UC_ERR_HANDLE; +} + +static int default_reg_write(struct uc_struct *uc, unsigned int *regs, + const void *const *vals, size_t *sizes, int count) +{ + return UC_ERR_HANDLE; +} + UNICORN_EXPORT uc_err uc_errno(uc_engine *uc) { @@ -264,6 +276,8 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) uc->errnum = UC_ERR_OK; uc->arch = arch; uc->mode = mode; + uc->reg_read = default_reg_read; + uc->reg_write = default_reg_write; // uc->ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list.blocks) }; QLIST_INIT(&uc->ram_list.blocks); @@ -507,13 +521,16 @@ uc_err uc_close(uc_engine *uc) UNICORN_EXPORT uc_err uc_reg_read_batch(uc_engine *uc, int *ids, void **vals, int count) { - return uc_reg_read_batch2(uc, ids, vals, NULL, count); + UC_INIT(uc); + return uc->reg_read(uc, (unsigned int *)ids, vals, NULL, count); } UNICORN_EXPORT uc_err uc_reg_write_batch(uc_engine *uc, int *ids, void *const *vals, int count) { - return uc_reg_write_batch2(uc, ids, (const void *const *)vals, NULL, count); + UC_INIT(uc); + return uc->reg_write(uc, (unsigned int *)ids, (const void *const *)vals, + NULL, count); } UNICORN_EXPORT @@ -521,12 +538,7 @@ uc_err uc_reg_read_batch2(uc_engine *uc, int *ids, void *const *vals, size_t *sizes, int count) { UC_INIT(uc); - - if (uc->reg_read) { - return uc->reg_read(uc, (unsigned int *)ids, vals, sizes, count); - } else { - return UC_ERR_HANDLE; - } + return uc->reg_read(uc, (unsigned int *)ids, vals, sizes, count); } UNICORN_EXPORT @@ -534,36 +546,35 @@ uc_err uc_reg_write_batch2(uc_engine *uc, int *ids, const void *const *vals, size_t *sizes, int count) { UC_INIT(uc); - - if (uc->reg_write) { - return uc->reg_write(uc, (unsigned int *)ids, vals, sizes, count); - } else { - return UC_ERR_HANDLE; - } + return uc->reg_write(uc, (unsigned int *)ids, vals, sizes, count); } UNICORN_EXPORT uc_err uc_reg_read(uc_engine *uc, int regid, void *value) { - return uc_reg_read_batch2(uc, ®id, &value, NULL, 1); + UC_INIT(uc); + return uc->reg_read(uc, (unsigned int *)®id, &value, NULL, 1); } UNICORN_EXPORT uc_err uc_reg_write(uc_engine *uc, int regid, const void *value) { - return uc_reg_write_batch2(uc, ®id, &value, NULL, 1); + UC_INIT(uc); + return uc->reg_write(uc, (unsigned int *)®id, &value, NULL, 1); } UNICORN_EXPORT uc_err uc_reg_read2(uc_engine *uc, int regid, void *value, size_t *size) { - return uc_reg_read_batch2(uc, ®id, &value, size, 1); + UC_INIT(uc); + return uc->reg_read(uc, (unsigned int *)®id, &value, size, 1); } UNICORN_EXPORT uc_err uc_reg_write2(uc_engine *uc, int regid, const void *value, size_t *size) { - return uc_reg_write_batch2(uc, ®id, &value, size, 1); + UC_INIT(uc); + return uc->reg_write(uc, (unsigned int *)®id, &value, size, 1); } // check if a memory area is mapped