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.
This commit is contained in:
@@ -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,
|
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;
|
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:
|
case UC_ARM64_REG_PC:
|
||||||
CHECK_REG_TYPE(uint64_t);
|
CHECK_REG_TYPE(uint64_t);
|
||||||
env->pc = *(uint64_t *)value;
|
env->pc = *(uint64_t *)value;
|
||||||
|
*setpc = 1;
|
||||||
break;
|
break;
|
||||||
case UC_ARM64_REG_SP:
|
case UC_ARM64_REG_SP:
|
||||||
CHECK_REG_TYPE(uint64_t);
|
CHECK_REG_TYPE(uint64_t);
|
||||||
@@ -397,17 +398,15 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
static uc_err reg_read_batch(CPUARMState *env, unsigned int *regs,
|
||||||
size_t *sizes, int count)
|
void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUARMState *env = &(ARM_CPU(uc->cpu)->env);
|
|
||||||
int i;
|
int i;
|
||||||
uc_err err;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
void *value = vals[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) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -416,26 +415,46 @@ int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
|||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arm64_reg_write(struct uc_struct *uc, unsigned int *regs,
|
static uc_err reg_write_batch(CPUARMState *env, unsigned int *regs,
|
||||||
const void *const *vals, size_t *sizes, int count)
|
const void *const *vals, size_t *sizes, int count,
|
||||||
|
int *setpc)
|
||||||
{
|
{
|
||||||
CPUARMState *env = &(ARM_CPU(uc->cpu)->env);
|
|
||||||
int i;
|
int i;
|
||||||
uc_err err;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
const void *value = vals[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) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (regid == UC_ARM64_REG_PC) {
|
}
|
||||||
|
|
||||||
|
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
|
// force to quit execution and flush TB
|
||||||
uc->quit_request = true;
|
uc->quit_request = true;
|
||||||
break_translation_loop(uc);
|
break_translation_loop(uc);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
}
|
}
|
||||||
@@ -450,19 +469,7 @@ int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
CPUARMState *env = (CPUARMState *)ctx->data;
|
CPUARMState *env = (CPUARMState *)ctx->data;
|
||||||
int i;
|
return reg_read_batch(env, regs, vals, sizes, count);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_VISIBILITY
|
DEFAULT_VISIBILITY
|
||||||
@@ -475,19 +482,8 @@ int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
CPUARMState *env = (CPUARMState *)ctx->data;
|
CPUARMState *env = (CPUARMState *)ctx->data;
|
||||||
int i;
|
int setpc = 0;
|
||||||
uc_err err;
|
return reg_write_batch(env, regs, vals, sizes, count, &setpc);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int arm64_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
static int arm64_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
||||||
|
|||||||
@@ -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,
|
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;
|
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->thumb = (*(uint32_t *)value & 1);
|
||||||
env->uc->thumb = (*(uint32_t *)value & 1);
|
env->uc->thumb = (*(uint32_t *)value & 1);
|
||||||
env->regs[15] = (*(uint32_t *)value & ~1);
|
env->regs[15] = (*(uint32_t *)value & ~1);
|
||||||
|
*setpc = 1;
|
||||||
break;
|
break;
|
||||||
// case UC_ARM_REG_C1_C0_2:
|
// case UC_ARM_REG_C1_C0_2:
|
||||||
// env->cp15.c1_coproc = *(int32_t *)value;
|
// 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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
static uc_err reg_read_batch(CPUARMState *env, unsigned int *regs,
|
||||||
size_t *sizes, int count)
|
void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUARMState *env = &(ARM_CPU(uc->cpu)->env);
|
|
||||||
int i;
|
int i;
|
||||||
uc_err err;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
void *value = vals[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;
|
|
||||||
}
|
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -572,26 +568,46 @@ int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
|||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arm_reg_write(struct uc_struct *uc, unsigned int *regs,
|
static uc_err reg_write_batch(CPUARMState *env, unsigned int *regs,
|
||||||
const void *const *vals, size_t *sizes, int count)
|
const void *const *vals, size_t *sizes, int count,
|
||||||
|
int *setpc)
|
||||||
{
|
{
|
||||||
CPUArchState *env = &(ARM_CPU(uc->cpu)->env);
|
|
||||||
int i;
|
int i;
|
||||||
uc_err err;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
const void *value = vals[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) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (regid == UC_ARM_REG_R15) {
|
}
|
||||||
|
|
||||||
|
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
|
// force to quit execution and flush TB
|
||||||
uc->quit_request = true;
|
uc->quit_request = true;
|
||||||
break_translation_loop(uc);
|
break_translation_loop(uc);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return UC_ERR_OK;
|
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)
|
void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUARMState *env = (CPUARMState *)ctx->data;
|
CPUARMState *env = (CPUARMState *)ctx->data;
|
||||||
int i;
|
return reg_read_batch(env, regs, vals, sizes, count);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_VISIBILITY
|
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)
|
const void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUARMState *env = (CPUARMState *)ctx->data;
|
CPUARMState *env = (CPUARMState *)ctx->data;
|
||||||
int i;
|
int setpc = 0;
|
||||||
uc_err err;
|
return reg_write_batch(env, regs, vals, sizes, count, &setpc);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool arm_stop_interrupt(struct uc_struct *uc, int intno)
|
static bool arm_stop_interrupt(struct uc_struct *uc, int intno)
|
||||||
|
|||||||
@@ -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,
|
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;
|
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:
|
case UC_X86_REG_EIP:
|
||||||
CHECK_REG_TYPE(uint32_t);
|
CHECK_REG_TYPE(uint32_t);
|
||||||
env->eip = *(uint32_t *)value;
|
env->eip = *(uint32_t *)value;
|
||||||
|
*setpc = 1;
|
||||||
break;
|
break;
|
||||||
case UC_X86_REG_IP:
|
case UC_X86_REG_IP:
|
||||||
CHECK_REG_TYPE(uint16_t);
|
CHECK_REG_TYPE(uint16_t);
|
||||||
env->eip = *(uint16_t *)value;
|
env->eip = *(uint16_t *)value;
|
||||||
|
*setpc = 1;
|
||||||
break;
|
break;
|
||||||
case UC_X86_REG_CS:
|
case UC_X86_REG_CS:
|
||||||
CHECK_REG_TYPE(uint16_t);
|
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:
|
case UC_X86_REG_RIP:
|
||||||
CHECK_REG_TYPE(uint64_t);
|
CHECK_REG_TYPE(uint64_t);
|
||||||
env->eip = *(uint64_t *)value;
|
env->eip = *(uint64_t *)value;
|
||||||
|
*setpc = 1;
|
||||||
break;
|
break;
|
||||||
case UC_X86_REG_EIP:
|
case UC_X86_REG_EIP:
|
||||||
CHECK_REG_TYPE(uint32_t);
|
CHECK_REG_TYPE(uint32_t);
|
||||||
env->eip = *(uint32_t *)value;
|
env->eip = *(uint32_t *)value;
|
||||||
|
*setpc = 1;
|
||||||
break;
|
break;
|
||||||
case UC_X86_REG_IP:
|
case UC_X86_REG_IP:
|
||||||
CHECK_REG_TYPE(uint16_t);
|
CHECK_REG_TYPE(uint16_t);
|
||||||
WRITE_WORD(env->eip, *(uint16_t *)value);
|
WRITE_WORD(env->eip, *(uint16_t *)value);
|
||||||
|
*setpc = 1;
|
||||||
break;
|
break;
|
||||||
case UC_X86_REG_CS:
|
case UC_X86_REG_CS:
|
||||||
CHECK_REG_TYPE(uint16_t);
|
CHECK_REG_TYPE(uint16_t);
|
||||||
@@ -1801,17 +1806,17 @@ static uc_err reg_write(CPUX86State *env, unsigned int regid, const void *value,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
static uc_err reg_read_batch(CPUX86State *env, unsigned int *regs,
|
||||||
size_t *sizes, int count)
|
void *const *vals, size_t *sizes, int count,
|
||||||
|
int mode)
|
||||||
{
|
{
|
||||||
CPUX86State *env = &(X86_CPU(uc->cpu)->env);
|
|
||||||
int i;
|
int i;
|
||||||
uc_err err;
|
uc_err err;
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
void *value = vals[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) {
|
if (err) {
|
||||||
return 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;
|
return UC_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x86_reg_write(struct uc_struct *uc, unsigned int *regs,
|
static uc_err reg_write_batch(CPUX86State *env, unsigned int *regs,
|
||||||
const void *const *vals, size_t *sizes, int count)
|
const void *const *vals, size_t *sizes, int count,
|
||||||
|
int mode, int *setpc)
|
||||||
{
|
{
|
||||||
CPUX86State *env = &(X86_CPU(uc->cpu)->env);
|
|
||||||
int i;
|
int i;
|
||||||
uc_err err;
|
uc_err err;
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
const void *value = vals[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) {
|
if (err) {
|
||||||
return 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
|
return UC_ERR_OK;
|
||||||
case UC_MODE_64:
|
}
|
||||||
switch (regid) {
|
|
||||||
default:
|
int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||||
break;
|
size_t *sizes, int count)
|
||||||
case UC_X86_REG_RIP:
|
{
|
||||||
case UC_X86_REG_EIP:
|
CPUX86State *env = &(X86_CPU(uc->cpu)->env);
|
||||||
case UC_X86_REG_IP:
|
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
|
// force to quit execution and flush TB
|
||||||
uc->quit_request = true;
|
uc->quit_request = true;
|
||||||
break_translation_loop(uc);
|
break_translation_loop(uc);
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return UC_ERR_OK;
|
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)
|
void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUX86State *env = (CPUX86State *)ctx->data;
|
CPUX86State *env = (CPUX86State *)ctx->data;
|
||||||
int i;
|
return reg_read_batch(env, regs, vals, sizes, count, ctx->mode);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_VISIBILITY
|
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)
|
const void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUX86State *env = (CPUX86State *)ctx->data;
|
CPUX86State *env = (CPUX86State *)ctx->data;
|
||||||
int i;
|
int setpc = 0;
|
||||||
uc_err err;
|
return reg_write_batch(env, regs, vals, sizes, count, ctx->mode, &setpc);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool x86_stop_interrupt(struct uc_struct *uc, int intno)
|
static bool x86_stop_interrupt(struct uc_struct *uc, int intno)
|
||||||
|
|||||||
@@ -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,
|
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;
|
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:
|
case UC_M68K_REG_PC:
|
||||||
CHECK_REG_TYPE(uint32_t);
|
CHECK_REG_TYPE(uint32_t);
|
||||||
env->pc = *(uint32_t *)value;
|
env->pc = *(uint32_t *)value;
|
||||||
|
*setpc = 1;
|
||||||
break;
|
break;
|
||||||
case UC_M68K_REG_SR:
|
case UC_M68K_REG_SR:
|
||||||
CHECK_REG_TYPE(uint32_t);
|
CHECK_REG_TYPE(uint32_t);
|
||||||
@@ -107,17 +108,15 @@ static uc_err reg_write(CPUM68KState *env, unsigned int regid,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
static uc_err reg_read_batch(CPUM68KState *env, unsigned int *regs,
|
||||||
size_t *sizes, int count)
|
void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUM68KState *env = &(M68K_CPU(uc->cpu)->env);
|
|
||||||
int i;
|
int i;
|
||||||
uc_err err;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
void *value = vals[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) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -126,26 +125,46 @@ int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
|||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int m68k_reg_write(struct uc_struct *uc, unsigned int *regs,
|
static uc_err reg_write_batch(CPUM68KState *env, unsigned int *regs,
|
||||||
const void *const *vals, size_t *sizes, int count)
|
const void *const *vals, size_t *sizes, int count,
|
||||||
|
int *setpc)
|
||||||
{
|
{
|
||||||
CPUM68KState *env = &(M68K_CPU(uc->cpu)->env);
|
|
||||||
int i;
|
int i;
|
||||||
uc_err err;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
const void *value = vals[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) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (regid == UC_M68K_REG_PC) {
|
}
|
||||||
|
|
||||||
|
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
|
// force to quit execution and flush TB
|
||||||
uc->quit_request = true;
|
uc->quit_request = true;
|
||||||
break_translation_loop(uc);
|
break_translation_loop(uc);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return UC_ERR_OK;
|
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)
|
void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUM68KState *env = (CPUM68KState *)ctx->data;
|
CPUM68KState *env = (CPUM68KState *)ctx->data;
|
||||||
int i;
|
return reg_read_batch(env, regs, vals, sizes, count);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_VISIBILITY
|
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)
|
const void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUM68KState *env = (CPUM68KState *)ctx->data;
|
CPUM68KState *env = (CPUM68KState *)ctx->data;
|
||||||
int i;
|
int setpc = 0;
|
||||||
uc_err err;
|
return reg_write_batch(env, regs, vals, sizes, count, &setpc);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int m68k_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
static int m68k_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
||||||
|
|||||||
@@ -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,
|
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;
|
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:
|
case UC_MIPS_REG_PC:
|
||||||
CHECK_REG_TYPE(mipsreg_t);
|
CHECK_REG_TYPE(mipsreg_t);
|
||||||
env->active_tc.PC = *(mipsreg_t *)value;
|
env->active_tc.PC = *(mipsreg_t *)value;
|
||||||
|
*setpc = 1;
|
||||||
break;
|
break;
|
||||||
case UC_MIPS_REG_CP0_CONFIG3:
|
case UC_MIPS_REG_CP0_CONFIG3:
|
||||||
CHECK_REG_TYPE(mipsreg_t);
|
CHECK_REG_TYPE(mipsreg_t);
|
||||||
@@ -147,17 +148,15 @@ static uc_err reg_write(CPUMIPSState *env, unsigned int regid,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
static uc_err reg_read_batch(CPUMIPSState *env, unsigned int *regs,
|
||||||
size_t *sizes, int count)
|
void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUMIPSState *env = &(MIPS_CPU(uc->cpu)->env);
|
|
||||||
int i;
|
int i;
|
||||||
uc_err err;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
void *value = vals[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) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -166,26 +165,46 @@ int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
|||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mips_reg_write(struct uc_struct *uc, unsigned int *regs,
|
static uc_err reg_write_batch(CPUMIPSState *env, unsigned int *regs,
|
||||||
const void *const *vals, size_t *sizes, int count)
|
const void *const *vals, size_t *sizes, int count,
|
||||||
|
int *setpc)
|
||||||
{
|
{
|
||||||
CPUMIPSState *env = &(MIPS_CPU(uc->cpu)->env);
|
|
||||||
int i;
|
int i;
|
||||||
uc_err err;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
const void *value = vals[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) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (regid == UC_MIPS_REG_PC) {
|
}
|
||||||
|
|
||||||
|
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
|
// force to quit execution and flush TB
|
||||||
uc->quit_request = true;
|
uc->quit_request = true;
|
||||||
break_translation_loop(uc);
|
break_translation_loop(uc);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
}
|
}
|
||||||
@@ -210,19 +229,7 @@ int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
CPUMIPSState *env = (CPUMIPSState *)ctx->data;
|
CPUMIPSState *env = (CPUMIPSState *)ctx->data;
|
||||||
int i;
|
return reg_read_batch(env, regs, vals, sizes, count);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_VISIBILITY
|
DEFAULT_VISIBILITY
|
||||||
@@ -246,19 +253,8 @@ int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
CPUMIPSState *env = (CPUMIPSState *)ctx->data;
|
CPUMIPSState *env = (CPUMIPSState *)ctx->data;
|
||||||
int i;
|
int setpc = 0;
|
||||||
uc_err err;
|
return reg_write_batch(env, regs, vals, sizes, count, &setpc);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mips_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
static int mips_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
||||||
|
|||||||
@@ -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,
|
static uc_err reg_write(CPUPPCState *env, unsigned int regid, const void *value,
|
||||||
size_t *size)
|
size_t *size, int *setpc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
uc_err ret = UC_ERR_ARG;
|
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:
|
case UC_PPC_REG_PC:
|
||||||
CHECK_REG_TYPE(ppcreg_t);
|
CHECK_REG_TYPE(ppcreg_t);
|
||||||
env->nip = *(ppcreg_t *)value;
|
env->nip = *(ppcreg_t *)value;
|
||||||
|
*setpc = 1;
|
||||||
break;
|
break;
|
||||||
case UC_PPC_REG_CR: {
|
case UC_PPC_REG_CR: {
|
||||||
CHECK_REG_TYPE(uint32_t);
|
CHECK_REG_TYPE(uint32_t);
|
||||||
@@ -263,17 +264,15 @@ static uc_err reg_write(CPUPPCState *env, unsigned int regid, const void *value,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
static uc_err reg_read_batch(CPUPPCState *env, unsigned int *regs,
|
||||||
size_t *sizes, int count)
|
void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUPPCState *env = &(POWERPC_CPU(uc->cpu)->env);
|
|
||||||
int i;
|
int i;
|
||||||
uc_err err;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
void *value = vals[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) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -282,26 +281,46 @@ int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
|||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ppc_reg_write(struct uc_struct *uc, unsigned int *regs,
|
static uc_err reg_write_batch(CPUPPCState *env, unsigned int *regs,
|
||||||
const void *const *vals, size_t *sizes, int count)
|
const void *const *vals, size_t *sizes, int count,
|
||||||
|
int *setpc)
|
||||||
{
|
{
|
||||||
CPUPPCState *env = &(POWERPC_CPU(uc->cpu)->env);
|
|
||||||
int i;
|
int i;
|
||||||
uc_err err;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
const void *value = vals[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) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (regid == UC_PPC_REG_PC) {
|
}
|
||||||
|
|
||||||
|
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
|
// force to quit execution and flush TB
|
||||||
uc->quit_request = true;
|
uc->quit_request = true;
|
||||||
break_translation_loop(uc);
|
break_translation_loop(uc);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
}
|
}
|
||||||
@@ -316,19 +335,7 @@ int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
CPUPPCState *env = (CPUPPCState *)ctx->data;
|
CPUPPCState *env = (CPUPPCState *)ctx->data;
|
||||||
int i;
|
return reg_read_batch(env, regs, vals, sizes, count);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_VISIBILITY
|
DEFAULT_VISIBILITY
|
||||||
@@ -341,19 +348,8 @@ int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
CPUPPCState *env = (CPUPPCState *)ctx->data;
|
CPUPPCState *env = (CPUPPCState *)ctx->data;
|
||||||
int i;
|
int setpc = 0;
|
||||||
uc_err err;
|
return reg_write_batch(env, regs, vals, sizes, count, &setpc);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerPCCPU *cpu_ppc_init(struct uc_struct *uc);
|
PowerPCCPU *cpu_ppc_init(struct uc_struct *uc);
|
||||||
|
|||||||
@@ -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,
|
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;
|
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);
|
CHECK_REG_TYPE(uint32_t);
|
||||||
env->pc = *(uint32_t *)value;
|
env->pc = *(uint32_t *)value;
|
||||||
#endif
|
#endif
|
||||||
|
*setpc = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,17 +175,15 @@ static uc_err reg_write(CPURISCVState *env, unsigned int regid,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
static uc_err reg_read_batch(CPURISCVState *env, unsigned int *regs,
|
||||||
size_t *sizes, int count)
|
void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPURISCVState *env = &(RISCV_CPU(uc->cpu)->env);
|
|
||||||
int i;
|
int i;
|
||||||
uc_err err;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
void *value = vals[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) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -193,26 +192,46 @@ int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
|||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int riscv_reg_write(struct uc_struct *uc, unsigned int *regs,
|
static uc_err reg_write_batch(CPURISCVState *env, unsigned int *regs,
|
||||||
const void *const *vals, size_t *sizes, int count)
|
const void *const *vals, size_t *sizes, int count,
|
||||||
|
int *setpc)
|
||||||
{
|
{
|
||||||
CPURISCVState *env = &(RISCV_CPU(uc->cpu)->env);
|
|
||||||
int i;
|
int i;
|
||||||
uc_err err;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
const void *value = vals[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) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (regid == UC_RISCV_REG_PC) {
|
}
|
||||||
|
|
||||||
|
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
|
// force to quit execution and flush TB
|
||||||
uc->quit_request = true;
|
uc->quit_request = true;
|
||||||
break_translation_loop(uc);
|
break_translation_loop(uc);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
}
|
}
|
||||||
@@ -228,19 +247,7 @@ int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
CPURISCVState *env = (CPURISCVState *)ctx->data;
|
CPURISCVState *env = (CPURISCVState *)ctx->data;
|
||||||
int i;
|
return reg_read_batch(env, regs, vals, sizes, count);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_VISIBILITY
|
DEFAULT_VISIBILITY
|
||||||
@@ -254,19 +261,8 @@ int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
CPURISCVState *env = (CPURISCVState *)ctx->data;
|
CPURISCVState *env = (CPURISCVState *)ctx->data;
|
||||||
int i;
|
int setpc = 0;
|
||||||
uc_err err;
|
return reg_write_batch(env, regs, vals, sizes, count, &setpc);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool riscv_stop_interrupt(struct uc_struct *uc, int intno)
|
static bool riscv_stop_interrupt(struct uc_struct *uc, int intno)
|
||||||
|
|||||||
@@ -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,
|
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;
|
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:
|
case UC_S390X_REG_PC:
|
||||||
CHECK_REG_TYPE(uint64_t);
|
CHECK_REG_TYPE(uint64_t);
|
||||||
env->psw.addr = *(uint64_t *)value;
|
env->psw.addr = *(uint64_t *)value;
|
||||||
|
*setpc = 1;
|
||||||
break;
|
break;
|
||||||
case UC_S390X_REG_PSWM:
|
case UC_S390X_REG_PSWM:
|
||||||
CHECK_REG_TYPE(uint64_t);
|
CHECK_REG_TYPE(uint64_t);
|
||||||
@@ -111,18 +112,34 @@ static uc_err reg_write(CPUS390XState *env, unsigned int regid,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_VISIBILITY
|
static uc_err reg_read_batch(CPUS390XState *env, unsigned int *regs,
|
||||||
int s390_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
void *const *vals, size_t *sizes, int count)
|
||||||
size_t *sizes, int count)
|
|
||||||
{
|
{
|
||||||
CPUS390XState *env = &(S390_CPU(uc->cpu)->env);
|
|
||||||
int i;
|
int i;
|
||||||
uc_err err;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
void *value = vals[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) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -131,27 +148,29 @@ int s390_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
|||||||
return UC_ERR_OK;
|
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
|
DEFAULT_VISIBILITY
|
||||||
int s390_reg_write(struct uc_struct *uc, unsigned int *regs,
|
int s390_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||||
const void *const *vals, size_t *sizes, int count)
|
const void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUS390XState *env = &(S390_CPU(uc->cpu)->env);
|
CPUS390XState *env = &(S390_CPU(uc->cpu)->env);
|
||||||
int i;
|
int setpc = 0;
|
||||||
uc_err err;
|
uc_err err = reg_write_batch(env, regs, vals, sizes, count, &setpc);
|
||||||
|
|
||||||
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) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (regid == UC_S390X_REG_PC) {
|
if (setpc) {
|
||||||
// force to quit execution and flush TB
|
// force to quit execution and flush TB
|
||||||
uc->quit_request = true;
|
uc->quit_request = true;
|
||||||
break_translation_loop(uc);
|
break_translation_loop(uc);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return UC_ERR_OK;
|
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)
|
void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUS390XState *env = (CPUS390XState *)ctx->data;
|
CPUS390XState *env = (CPUS390XState *)ctx->data;
|
||||||
int i;
|
return reg_read_batch(env, regs, vals, sizes, count);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_VISIBILITY
|
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)
|
const void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUS390XState *env = (CPUS390XState *)ctx->data;
|
CPUS390XState *env = (CPUS390XState *)ctx->data;
|
||||||
int i;
|
int setpc = 0;
|
||||||
uc_err err;
|
return reg_write_batch(env, regs, vals, sizes, count, &setpc);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int s390_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
static int s390_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
||||||
|
|||||||
@@ -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,
|
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;
|
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);
|
CHECK_REG_TYPE(uint32_t);
|
||||||
env->pc = *(uint32_t *)value;
|
env->pc = *(uint32_t *)value;
|
||||||
env->npc = *(uint32_t *)value + 4;
|
env->npc = *(uint32_t *)value + 4;
|
||||||
|
*setpc = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,17 +124,15 @@ static uc_err reg_write(CPUSPARCState *env, unsigned int regid,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
static uc_err reg_read_batch(CPUSPARCState *env, unsigned int *regs,
|
||||||
size_t *sizes, int count)
|
void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env);
|
|
||||||
int i;
|
int i;
|
||||||
uc_err err;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
void *value = vals[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) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -142,26 +141,46 @@ int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
|||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs,
|
static uc_err reg_write_batch(CPUSPARCState *env, unsigned int *regs,
|
||||||
const void *const *vals, size_t *sizes, int count)
|
const void *const *vals, size_t *sizes, int count,
|
||||||
|
int *setpc)
|
||||||
{
|
{
|
||||||
CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env);
|
|
||||||
int i;
|
int i;
|
||||||
uc_err err;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
const void *value = vals[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) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (regid == UC_SPARC_REG_PC) {
|
}
|
||||||
|
|
||||||
|
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
|
// force to quit execution and flush TB
|
||||||
uc->quit_request = true;
|
uc->quit_request = true;
|
||||||
break_translation_loop(uc);
|
break_translation_loop(uc);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return UC_ERR_OK;
|
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)
|
void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUSPARCState *env = (CPUSPARCState *)ctx->data;
|
CPUSPARCState *env = (CPUSPARCState *)ctx->data;
|
||||||
int i;
|
return reg_read_batch(env, regs, vals, sizes, count);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_VISIBILITY
|
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)
|
const void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUSPARCState *env = (CPUSPARCState *)ctx->data;
|
CPUSPARCState *env = (CPUSPARCState *)ctx->data;
|
||||||
int i;
|
int setpc = 0;
|
||||||
uc_err err;
|
return reg_write_batch(env, regs, vals, sizes, count, &setpc);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sparc_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
static int sparc_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ static uc_err reg_read(CPUSPARCState *env, unsigned int regid, void *value, size
|
|||||||
return ret;
|
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;
|
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);
|
CHECK_REG_TYPE(uint64_t);
|
||||||
env->pc = *(uint64_t *)value;
|
env->pc = *(uint64_t *)value;
|
||||||
env->npc = *(uint64_t *)value + 4;
|
env->npc = *(uint64_t *)value + 4;
|
||||||
|
*setpc = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,16 +145,14 @@ static uc_err reg_write(CPUSPARCState *env, unsigned int regid, const void *valu
|
|||||||
return ret;
|
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;
|
int i;
|
||||||
uc_err err;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
void *value = vals[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) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -162,25 +161,41 @@ int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
|||||||
return UC_ERR_OK;
|
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;
|
int i;
|
||||||
uc_err err;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
const void *value = vals[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) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (regid == UC_SPARC_REG_PC) {
|
}
|
||||||
|
|
||||||
|
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
|
// force to quit execution and flush TB
|
||||||
uc->quit_request = true;
|
uc->quit_request = true;
|
||||||
break_translation_loop(uc);
|
break_translation_loop(uc);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return UC_ERR_OK;
|
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)
|
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;
|
CPUSPARCState *env = (CPUSPARCState *)ctx->data;
|
||||||
int i;
|
return reg_read_batch(env, regs, vals, sizes, count);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_VISIBILITY
|
DEFAULT_VISIBILITY
|
||||||
int sparc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, const void *const *vals, size_t *sizes, int count)
|
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;
|
CPUSPARCState *env = (CPUSPARCState *)ctx->data;
|
||||||
int i;
|
int setpc = 0;
|
||||||
uc_err err;
|
return reg_write_batch(env, regs, vals, sizes, count, &setpc);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sparc_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
static int sparc_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
||||||
|
|||||||
@@ -139,46 +139,8 @@ static uc_err reg_read(CPUTriCoreState *env, unsigned int regid, void *value,
|
|||||||
return ret;
|
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,
|
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;
|
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:
|
case UC_TRICORE_REG_PC:
|
||||||
CHECK_REG_TYPE(uint32_t);
|
CHECK_REG_TYPE(uint32_t);
|
||||||
env->PC = *(uint32_t *)value;
|
env->PC = *(uint32_t *)value;
|
||||||
|
*setpc = 1;
|
||||||
break;
|
break;
|
||||||
case UC_TRICORE_REG_PCXI:
|
case UC_TRICORE_REG_PCXI:
|
||||||
CHECK_REG_TYPE(uint32_t);
|
CHECK_REG_TYPE(uint32_t);
|
||||||
@@ -277,47 +240,80 @@ static uc_err reg_write(CPUTriCoreState *env, unsigned int regid,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tricore_reg_write(struct uc_struct *uc, unsigned int *regs,
|
static uc_err reg_read_batch(CPUTriCoreState *env, unsigned int *regs,
|
||||||
const void *const *vals, size_t *sizes, int count)
|
void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUTriCoreState *env = &(TRICORE_CPU(uc->cpu)->env);
|
|
||||||
int i;
|
int i;
|
||||||
uc_err err;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
const void *value = vals[i];
|
void *value = vals[i];
|
||||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
uc_err err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||||
if (err) {
|
if (err) {
|
||||||
return 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;
|
return UC_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uc_err reg_write_batch(CPUTriCoreState *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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
int tricore_context_reg_write(struct uc_context *uc, unsigned int *regs,
|
||||||
const void *const *vals, size_t *sizes, int count)
|
const void *const *vals, size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
CPUTriCoreState *env = (CPUTriCoreState *)uc->data;
|
CPUTriCoreState *env = (CPUTriCoreState *)uc->data;
|
||||||
int i;
|
int setpc = 0;
|
||||||
uc_err err;
|
return reg_write_batch(env, regs, vals, sizes, count, &setpc);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tricore_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
static int tricore_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
||||||
|
|||||||
@@ -130,8 +130,8 @@ static inline void uc_common_init(struct uc_struct* uc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_REG_TYPE(type) do { \
|
#define CHECK_REG_TYPE(type) do { \
|
||||||
if (size) { \
|
if (unlikely(size)) { \
|
||||||
if (*size < sizeof(type)) { \
|
if (unlikely(*size < sizeof(type))) { \
|
||||||
return UC_ERR_NOMEM; \
|
return UC_ERR_NOMEM; \
|
||||||
} \
|
} \
|
||||||
*size = sizeof(type); \
|
*size = sizeof(type); \
|
||||||
|
|||||||
43
uc.c
43
uc.c
@@ -82,6 +82,18 @@ unsigned int uc_version(unsigned int *major, unsigned int *minor)
|
|||||||
UC_API_EXTRA;
|
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
|
UNICORN_EXPORT
|
||||||
uc_err uc_errno(uc_engine *uc)
|
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->errnum = UC_ERR_OK;
|
||||||
uc->arch = arch;
|
uc->arch = arch;
|
||||||
uc->mode = mode;
|
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) };
|
// uc->ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list.blocks) };
|
||||||
QLIST_INIT(&uc->ram_list.blocks);
|
QLIST_INIT(&uc->ram_list.blocks);
|
||||||
@@ -507,13 +521,16 @@ uc_err uc_close(uc_engine *uc)
|
|||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
uc_err uc_reg_read_batch(uc_engine *uc, int *ids, void **vals, int count)
|
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
|
UNICORN_EXPORT
|
||||||
uc_err uc_reg_write_batch(uc_engine *uc, int *ids, void *const *vals, int count)
|
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
|
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)
|
size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
UC_INIT(uc);
|
UC_INIT(uc);
|
||||||
|
|
||||||
if (uc->reg_read) {
|
|
||||||
return uc->reg_read(uc, (unsigned int *)ids, vals, sizes, count);
|
return uc->reg_read(uc, (unsigned int *)ids, vals, sizes, count);
|
||||||
} else {
|
|
||||||
return UC_ERR_HANDLE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UNICORN_EXPORT
|
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)
|
size_t *sizes, int count)
|
||||||
{
|
{
|
||||||
UC_INIT(uc);
|
UC_INIT(uc);
|
||||||
|
|
||||||
if (uc->reg_write) {
|
|
||||||
return uc->reg_write(uc, (unsigned int *)ids, vals, sizes, count);
|
return uc->reg_write(uc, (unsigned int *)ids, vals, sizes, count);
|
||||||
} else {
|
|
||||||
return UC_ERR_HANDLE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
uc_err uc_reg_read(uc_engine *uc, int regid, void *value)
|
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
|
UNICORN_EXPORT
|
||||||
uc_err uc_reg_write(uc_engine *uc, int regid, const void *value)
|
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
|
UNICORN_EXPORT
|
||||||
uc_err uc_reg_read2(uc_engine *uc, int regid, void *value, size_t *size)
|
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
|
UNICORN_EXPORT
|
||||||
uc_err uc_reg_write2(uc_engine *uc, int regid, const void *value, size_t *size)
|
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
|
// check if a memory area is mapped
|
||||||
|
|||||||
Reference in New Issue
Block a user