Implement uc_reg_{read,write}{,_batch}2 APIs.

These APIs take size parameters, which can be used to properly bounds-check the
inputs and outputs for various registers. Additionally, all backends now throw
UC_ERR_ARG if the input register numbers are invalid.

Completes #1831.
This commit is contained in:
Robert Xiao
2023-05-11 12:43:15 -07:00
parent d7a806c026
commit 4055a5ab10
24 changed files with 1523 additions and 1032 deletions

View File

@@ -63,15 +63,16 @@ typedef uc_err (*query_t)(struct uc_struct *uc, uc_query_type type,
size_t *result);
// return 0 on success, -1 on failure
typedef int (*reg_read_t)(struct uc_struct *uc, unsigned int *regs, void **vals,
int count);
typedef int (*reg_read_t)(struct uc_struct *uc, unsigned int *regs,
void *const *vals, size_t *sizes, int count);
typedef int (*reg_write_t)(struct uc_struct *uc, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes, int count);
typedef int (*context_reg_read_t)(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
void *const *vals, size_t *sizes, int count);
typedef int (*context_reg_write_t)(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes,
int count);
typedef struct {
context_reg_read_t context_reg_read;
context_reg_write_t context_reg_write;

View File

@@ -779,10 +779,9 @@ const char *uc_strerror(uc_err code);
@uc: handle returned by uc_open()
@regid: register ID that is to be modified.
@value: pointer to the value that will set to register @regid
@value: pointer to the value that will be written to register @regid
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
for detailed error).
@return UC_ERR_OK on success; UC_ERR_ARG if register number or value is invalid
*/
UNICORN_EXPORT
uc_err uc_reg_write(uc_engine *uc, int regid, const void *value);
@@ -794,22 +793,49 @@ uc_err uc_reg_write(uc_engine *uc, int regid, const void *value);
@regid: register ID that is to be retrieved.
@value: pointer to a variable storing the register value.
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
for detailed error).
@return UC_ERR_OK on success; UC_ERR_ARG if register number or value is invalid
*/
UNICORN_EXPORT
uc_err uc_reg_read(uc_engine *uc, int regid, void *value);
/*
Write to register.
@uc: handle returned by uc_open()
@regid: register ID that is to be modified.
@value: pointer to the value that will be written to register @regid
@size: size of value being written; on return, size of value written
@return UC_ERR_OK on success; UC_ERR_ARG if register number or value is
invalid; UC_ERR_NOMEM if value is not large enough.
*/
UNICORN_EXPORT
uc_err uc_reg_write2(uc_engine *uc, int regid, const void *value, size_t *size);
/*
Read register value.
@uc: handle returned by uc_open()
@regid: register ID that is to be retrieved.
@value: pointer to a variable storing the register value.
@size: size of value buffer; on return, size of value read
@return UC_ERR_OK on success; UC_ERR_ARG if register number or value is
invalid; UC_ERR_NOMEM if value is not large enough.
*/
UNICORN_EXPORT
uc_err uc_reg_read2(uc_engine *uc, int regid, void *value, size_t *size);
/*
Write multiple register values.
@uc: handle returned by uc_open()
@rges: array of register IDs to store
@value: pointer to array of register values
@regs: array of register IDs to store
@vals: array of pointers to register values
@count: length of both *regs and *vals
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
for detailed error).
@return UC_ERR_OK on success; UC_ERR_ARG if some register number or value is
invalid
*/
UNICORN_EXPORT
uc_err uc_reg_write_batch(uc_engine *uc, int *regs, void *const *vals,
@@ -819,16 +845,49 @@ uc_err uc_reg_write_batch(uc_engine *uc, int *regs, void *const *vals,
Read multiple register values.
@uc: handle returned by uc_open()
@rges: array of register IDs to retrieve
@value: pointer to array of values to hold registers
@regs: array of register IDs to retrieve
@vals: array of pointers to register values
@count: length of both *regs and *vals
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
for detailed error).
@return UC_ERR_OK on success; UC_ERR_ARG if some register number or value is
invalid
*/
UNICORN_EXPORT
uc_err uc_reg_read_batch(uc_engine *uc, int *regs, void **vals, int count);
/*
Write multiple register values.
@uc: handle returned by uc_open()
@regs: array of register IDs to store
@value: array of pointers to register values
@sizes: array of sizes of each value; on return, sizes of each stored register
@count: length of *regs, *vals and *sizes
@return UC_ERR_OK on success; UC_ERR_ARG if some register number or value is
invalid; UC_ERR_NOMEM if some value is not large enough.
*/
UNICORN_EXPORT
uc_err uc_reg_write_batch2(uc_engine *uc, int *regs, const void *const *vals,
size_t *sizes, int count);
/*
Read multiple register values.
@uc: handle returned by uc_open()
@regs: array of register IDs to retrieve
@value: pointer to array of values to hold registers
@sizes: array of sizes of each value; on return, sizes of each retrieved
register
@count: length of *regs, *vals and *sizes
@return UC_ERR_OK on success; UC_ERR_ARG if some register number or value is
invalid; UC_ERR_NOMEM if some value is not large enough.
*/
UNICORN_EXPORT
uc_err uc_reg_read_batch2(uc_engine *uc, int *regs, void *const *vals,
size_t *sizes, int count);
/*
Write to a range of bytes in memory.
@@ -1131,10 +1190,9 @@ uc_err uc_context_save(uc_engine *uc, uc_context *context);
@ctx: handle returned by uc_context_alloc()
@regid: register ID that is to be modified.
@value: pointer to the value that will set to register @regid
@value: pointer to the value that will be written to register @regid
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
for detailed error).
@return UC_ERR_OK on success; UC_ERR_ARG if register number or value is invalid
*/
UNICORN_EXPORT
uc_err uc_context_reg_write(uc_context *ctx, int regid, const void *value);
@@ -1146,12 +1204,41 @@ uc_err uc_context_reg_write(uc_context *ctx, int regid, const void *value);
@regid: register ID that is to be retrieved.
@value: pointer to a variable storing the register value.
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
for detailed error).
@return UC_ERR_OK on success; UC_ERR_ARG if register number or value is invalid
*/
UNICORN_EXPORT
uc_err uc_context_reg_read(uc_context *ctx, int regid, void *value);
/*
Write value to a register of a context.
@ctx: handle returned by uc_context_alloc()
@regid: register ID that is to be modified.
@value: pointer to the value that will be written to register @regid
@size: size of value being written; on return, size of value written
@return UC_ERR_OK on success; UC_ERR_ARG if register number or value is
invalid; UC_ERR_NOMEM if value is not large enough.
*/
UNICORN_EXPORT
uc_err uc_context_reg_write2(uc_context *ctx, int regid, const void *value,
size_t *size);
/*
Read register value from a context.
@ctx: handle returned by uc_context_alloc()
@regid: register ID that is to be retrieved.
@value: pointer to a variable storing the register value.
@size: size of value buffer; on return, size of value read
@return UC_ERR_OK on success; UC_ERR_ARG if register number or value is
invalid; UC_ERR_NOMEM if value is not large enough.
*/
UNICORN_EXPORT
uc_err uc_context_reg_read2(uc_context *ctx, int regid, void *value,
size_t *size);
/*
Write multiple register values to registers of a context.
@@ -1182,6 +1269,40 @@ UNICORN_EXPORT
uc_err uc_context_reg_read_batch(uc_context *ctx, int *regs, void **vals,
int count);
/*
Write multiple register values to registers of a context.
@ctx: handle returned by uc_context_alloc()
@regs: array of register IDs to store
@value: array of pointers to register values
@sizes: array of sizes of each value; on return, sizes of each stored register
@count: length of *regs, *vals and *sizes
@return UC_ERR_OK on success; UC_ERR_ARG if some register number or value is
invalid; UC_ERR_NOMEM if some value is not large enough.
*/
UNICORN_EXPORT
uc_err uc_context_reg_write_batch2(uc_context *ctx, int *regs,
const void *const *vals, size_t *sizes,
int count);
/*
Read multiple register values from a context.
@ctx: handle returned by uc_context_alloc()
@regs: array of register IDs to retrieve
@value: pointer to array of values to hold registers
@sizes: array of sizes of each value; on return, sizes of each retrieved
register
@count: length of *regs, *vals and *sizes
@return UC_ERR_OK on success; UC_ERR_ARG if some register number or value is
invalid; UC_ERR_NOMEM if some value is not large enough.
*/
UNICORN_EXPORT
uc_err uc_context_reg_read_batch2(uc_context *ctx, int *regs, void *const *vals,
size_t *sizes, int count);
/*
Restore the current CPU context from a saved copy.
This API should be used to roll the CPU context back to a previous

View File

@@ -5,23 +5,23 @@
#define UC_QEMU_TARGET_ARM_H
// functions to read & write registers
int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count);
int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count);
int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count);
int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count);
int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
size_t *sizes, int count);
int arm_reg_write(struct uc_struct *uc, unsigned int *regs,
const void *const *vals, size_t *sizes, int count);
int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
size_t *sizes, int count);
int arm64_reg_write(struct uc_struct *uc, unsigned int *regs,
const void *const *vals, size_t *sizes, int count);
int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
void *const *vals, size_t *sizes, int count);
int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes, int count);
int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
void *const *vals, size_t *sizes, int count);
int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes, int count);
void arm_reg_reset(struct uc_struct *uc);
void arm64_reg_reset(struct uc_struct *uc);

View File

@@ -138,97 +138,127 @@ static uc_err write_cp_reg(CPUARMState *env, uc_arm64_cp_reg *cp)
return UC_ERR_OK;
}
static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value)
static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value,
size_t *size)
{
uc_err ret = UC_ERR_OK;
uc_err ret = UC_ERR_ARG;
if (regid >= UC_ARM64_REG_V0 && regid <= UC_ARM64_REG_V31) {
regid += UC_ARM64_REG_Q0 - UC_ARM64_REG_V0;
}
if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28) {
*(int64_t *)value = env->xregs[regid - UC_ARM64_REG_X0];
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->xregs[regid - UC_ARM64_REG_X0];
} else if (regid >= UC_ARM64_REG_W0 && regid <= UC_ARM64_REG_W30) {
*(int32_t *)value = READ_DWORD(env->xregs[regid - UC_ARM64_REG_W0]);
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = READ_DWORD(env->xregs[regid - UC_ARM64_REG_W0]);
} else if (regid >= UC_ARM64_REG_Q0 && regid <= UC_ARM64_REG_Q31) { // FIXME
CHECK_REG_TYPE(float64[2]);
float64 *dst = (float64 *)value;
uint32_t reg_index = regid - UC_ARM64_REG_Q0;
dst[0] = env->vfp.zregs[reg_index].d[0];
dst[1] = env->vfp.zregs[reg_index].d[1];
} else if (regid >= UC_ARM64_REG_D0 && regid <= UC_ARM64_REG_D31) {
CHECK_REG_TYPE(float64);
*(float64 *)value = env->vfp.zregs[regid - UC_ARM64_REG_D0].d[0];
} else if (regid >= UC_ARM64_REG_S0 && regid <= UC_ARM64_REG_S31) {
CHECK_REG_TYPE(int32_t);
*(int32_t *)value =
READ_DWORD(env->vfp.zregs[regid - UC_ARM64_REG_S0].d[0]);
} else if (regid >= UC_ARM64_REG_H0 && regid <= UC_ARM64_REG_H31) {
CHECK_REG_TYPE(int16_t);
*(int16_t *)value =
READ_WORD(env->vfp.zregs[regid - UC_ARM64_REG_H0].d[0]);
} else if (regid >= UC_ARM64_REG_B0 && regid <= UC_ARM64_REG_B31) {
CHECK_REG_TYPE(int8_t);
*(int8_t *)value =
READ_BYTE_L(env->vfp.zregs[regid - UC_ARM64_REG_B0].d[0]);
} else if (regid >= UC_ARM64_REG_ELR_EL0 && regid <= UC_ARM64_REG_ELR_EL3) {
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->elr_el[regid - UC_ARM64_REG_ELR_EL0];
} else if (regid >= UC_ARM64_REG_SP_EL0 && regid <= UC_ARM64_REG_SP_EL3) {
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->sp_el[regid - UC_ARM64_REG_SP_EL0];
} else if (regid >= UC_ARM64_REG_ESR_EL0 && regid <= UC_ARM64_REG_ESR_EL3) {
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->cp15.esr_el[regid - UC_ARM64_REG_ESR_EL0];
} else if (regid >= UC_ARM64_REG_FAR_EL0 && regid <= UC_ARM64_REG_FAR_EL3) {
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->cp15.far_el[regid - UC_ARM64_REG_FAR_EL0];
} else if (regid >= UC_ARM64_REG_VBAR_EL0 &&
regid <= UC_ARM64_REG_VBAR_EL3) {
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->cp15.vbar_el[regid - UC_ARM64_REG_VBAR_EL0];
} else {
switch (regid) {
default:
break;
case UC_ARM64_REG_CPACR_EL1:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->cp15.cpacr_el1;
break;
case UC_ARM64_REG_TPIDR_EL0:
*(int64_t *)value = env->cp15.tpidr_el[0];
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->cp15.tpidr_el[0];
break;
case UC_ARM64_REG_TPIDRRO_EL0:
*(int64_t *)value = env->cp15.tpidrro_el[0];
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->cp15.tpidrro_el[0];
break;
case UC_ARM64_REG_TPIDR_EL1:
*(int64_t *)value = env->cp15.tpidr_el[1];
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->cp15.tpidr_el[1];
break;
case UC_ARM64_REG_X29:
*(int64_t *)value = env->xregs[29];
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->xregs[29];
break;
case UC_ARM64_REG_X30:
*(int64_t *)value = env->xregs[30];
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->xregs[30];
break;
case UC_ARM64_REG_PC:
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->pc;
break;
case UC_ARM64_REG_SP:
*(int64_t *)value = env->xregs[31];
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->xregs[31];
break;
case UC_ARM64_REG_NZCV:
*(int32_t *)value = cpsr_read(env) & CPSR_NZCV;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = cpsr_read(env) & CPSR_NZCV;
break;
case UC_ARM64_REG_PSTATE:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = pstate_read(env);
break;
case UC_ARM64_REG_TTBR0_EL1:
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->cp15.ttbr0_el[1];
break;
case UC_ARM64_REG_TTBR1_EL1:
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->cp15.ttbr1_el[1];
break;
case UC_ARM64_REG_PAR_EL1:
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->cp15.par_el[1];
break;
case UC_ARM64_REG_MAIR_EL1:
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->cp15.mair_el[1];
break;
case UC_ARM64_REG_CP_REG:
CHECK_REG_TYPE(uc_arm64_cp_reg);
ret = read_cp_reg(env, (uc_arm64_cp_reg *)value);
break;
case UC_ARM64_REG_FPCR:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = vfp_get_fpcr(env);
break;
case UC_ARM64_REG_FPSR:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = vfp_get_fpsr(env);
break;
}
@@ -237,98 +267,128 @@ static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value)
return ret;
}
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)
{
uc_err ret = UC_ERR_OK;
uc_err ret = UC_ERR_ARG;
if (regid >= UC_ARM64_REG_V0 && regid <= UC_ARM64_REG_V31) {
regid += UC_ARM64_REG_Q0 - UC_ARM64_REG_V0;
}
if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28) {
CHECK_REG_TYPE(uint64_t);
env->xregs[regid - UC_ARM64_REG_X0] = *(uint64_t *)value;
} else if (regid >= UC_ARM64_REG_W0 && regid <= UC_ARM64_REG_W30) {
CHECK_REG_TYPE(uint32_t);
WRITE_DWORD(env->xregs[regid - UC_ARM64_REG_W0], *(uint32_t *)value);
} else if (regid >= UC_ARM64_REG_Q0 && regid <= UC_ARM64_REG_Q31) {
CHECK_REG_TYPE(float64[2]);
float64 *src = (float64 *)value;
uint32_t reg_index = regid - UC_ARM64_REG_Q0;
env->vfp.zregs[reg_index].d[0] = src[0];
env->vfp.zregs[reg_index].d[1] = src[1];
} else if (regid >= UC_ARM64_REG_D0 && regid <= UC_ARM64_REG_D31) {
CHECK_REG_TYPE(float64);
env->vfp.zregs[regid - UC_ARM64_REG_D0].d[0] = *(float64 *)value;
} else if (regid >= UC_ARM64_REG_S0 && regid <= UC_ARM64_REG_S31) {
CHECK_REG_TYPE(int32_t);
WRITE_DWORD(env->vfp.zregs[regid - UC_ARM64_REG_S0].d[0],
*(int32_t *)value);
} else if (regid >= UC_ARM64_REG_H0 && regid <= UC_ARM64_REG_H31) {
CHECK_REG_TYPE(int16_t);
WRITE_WORD(env->vfp.zregs[regid - UC_ARM64_REG_H0].d[0],
*(int16_t *)value);
} else if (regid >= UC_ARM64_REG_B0 && regid <= UC_ARM64_REG_B31) {
CHECK_REG_TYPE(int8_t);
WRITE_BYTE_L(env->vfp.zregs[regid - UC_ARM64_REG_B0].d[0],
*(int8_t *)value);
} else if (regid >= UC_ARM64_REG_ELR_EL0 && regid <= UC_ARM64_REG_ELR_EL3) {
CHECK_REG_TYPE(uint64_t);
env->elr_el[regid - UC_ARM64_REG_ELR_EL0] = *(uint64_t *)value;
} else if (regid >= UC_ARM64_REG_SP_EL0 && regid <= UC_ARM64_REG_SP_EL3) {
CHECK_REG_TYPE(uint64_t);
env->sp_el[regid - UC_ARM64_REG_SP_EL0] = *(uint64_t *)value;
} else if (regid >= UC_ARM64_REG_ESR_EL0 && regid <= UC_ARM64_REG_ESR_EL3) {
CHECK_REG_TYPE(uint64_t);
env->cp15.esr_el[regid - UC_ARM64_REG_ESR_EL0] = *(uint64_t *)value;
} else if (regid >= UC_ARM64_REG_FAR_EL0 && regid <= UC_ARM64_REG_FAR_EL3) {
CHECK_REG_TYPE(uint64_t);
env->cp15.far_el[regid - UC_ARM64_REG_FAR_EL0] = *(uint64_t *)value;
} else if (regid >= UC_ARM64_REG_VBAR_EL0 &&
regid <= UC_ARM64_REG_VBAR_EL3) {
CHECK_REG_TYPE(uint64_t);
env->cp15.vbar_el[regid - UC_ARM64_REG_VBAR_EL0] = *(uint64_t *)value;
} else {
switch (regid) {
default:
break;
case UC_ARM64_REG_CPACR_EL1:
CHECK_REG_TYPE(uint32_t);
env->cp15.cpacr_el1 = *(uint32_t *)value;
break;
case UC_ARM64_REG_TPIDR_EL0:
CHECK_REG_TYPE(uint64_t);
env->cp15.tpidr_el[0] = *(uint64_t *)value;
break;
case UC_ARM64_REG_TPIDRRO_EL0:
CHECK_REG_TYPE(uint64_t);
env->cp15.tpidrro_el[0] = *(uint64_t *)value;
break;
case UC_ARM64_REG_TPIDR_EL1:
CHECK_REG_TYPE(uint64_t);
env->cp15.tpidr_el[1] = *(uint64_t *)value;
break;
case UC_ARM64_REG_X29:
CHECK_REG_TYPE(uint64_t);
env->xregs[29] = *(uint64_t *)value;
break;
case UC_ARM64_REG_X30:
CHECK_REG_TYPE(uint64_t);
env->xregs[30] = *(uint64_t *)value;
break;
case UC_ARM64_REG_PC:
CHECK_REG_TYPE(uint64_t);
env->pc = *(uint64_t *)value;
break;
case UC_ARM64_REG_SP:
CHECK_REG_TYPE(uint64_t);
env->xregs[31] = *(uint64_t *)value;
break;
case UC_ARM64_REG_NZCV:
CHECK_REG_TYPE(uint32_t);
cpsr_write(env, *(uint32_t *)value, CPSR_NZCV, CPSRWriteRaw);
break;
case UC_ARM64_REG_PSTATE:
CHECK_REG_TYPE(uint32_t);
pstate_write(env, *(uint32_t *)value);
break;
case UC_ARM64_REG_TTBR0_EL1:
CHECK_REG_TYPE(uint64_t);
env->cp15.ttbr0_el[1] = *(uint64_t *)value;
break;
case UC_ARM64_REG_TTBR1_EL1:
CHECK_REG_TYPE(uint64_t);
env->cp15.ttbr1_el[1] = *(uint64_t *)value;
break;
case UC_ARM64_REG_PAR_EL1:
CHECK_REG_TYPE(uint64_t);
env->cp15.par_el[1] = *(uint64_t *)value;
break;
case UC_ARM64_REG_MAIR_EL1:
CHECK_REG_TYPE(uint64_t);
env->cp15.mair_el[1] = *(uint64_t *)value;
break;
case UC_ARM64_REG_CP_REG:
CHECK_REG_TYPE(uc_arm64_cp_reg);
ret = write_cp_reg(env, (uc_arm64_cp_reg *)value);
arm_rebuild_hflags(env);
break;
case UC_ARM64_REG_FPCR:
CHECK_REG_TYPE(uint32_t);
vfp_set_fpcr(env, *(uint32_t *)value);
break;
case UC_ARM64_REG_FPSR:
CHECK_REG_TYPE(uint32_t);
vfp_set_fpsr(env, *(uint32_t *)value);
break;
}
@@ -337,8 +397,8 @@ 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 **vals,
int count)
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);
int i;
@@ -347,7 +407,7 @@ int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
void *value = vals[i];
err = reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
@@ -356,8 +416,8 @@ int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
return UC_ERR_OK;
}
int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int 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 i;
@@ -366,7 +426,7 @@ int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
const void *value = vals[i];
err = reg_write(env, regid, value);
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
@@ -383,10 +443,10 @@ int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
DEFAULT_VISIBILITY
#ifdef TARGET_WORDS_BIGENDIAN
int arm64eb_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
void *const *vals, size_t *sizes, int count)
#else
int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
void *const *vals, size_t *sizes, int count)
#endif
{
CPUARMState *env = (CPUARMState *)ctx->data;
@@ -396,22 +456,22 @@ int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
void *value = vals[i];
err = reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
DEFAULT_VISIBILITY
#ifdef TARGET_WORDS_BIGENDIAN
int arm64eb_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
const void *const *vals, size_t *sizes, int count)
#else
int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
const void *const *vals, size_t *sizes, int count)
#endif
{
CPUARMState *env = (CPUARMState *)ctx->data;
@@ -421,13 +481,13 @@ int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
const void *value = vals[i];
err = reg_write(env, regid, value);
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
static int arm64_cpus_init(struct uc_struct *uc, const char *cpu_model)

View File

@@ -206,20 +206,25 @@ static uc_err write_cp_reg(CPUARMState *env, uc_arm_cp_reg *cp)
return UC_ERR_OK;
}
static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value)
static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value,
size_t *size)
{
uc_err ret = UC_ERR_OK;
uc_err ret = UC_ERR_ARG;
if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) {
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->regs[regid - UC_ARM_REG_R0];
} else if (regid >= UC_ARM_REG_Q0 && regid <= UC_ARM_REG_Q15) {
CHECK_REG_TYPE(uint64_t[2]);
uint32_t reg_index = regid - UC_ARM_REG_Q0;
*(uint64_t *)value = env->vfp.zregs[reg_index].d[0];
*(((uint64_t *)value) + 1) = env->vfp.zregs[reg_index].d[1];
} else if (regid >= UC_ARM_REG_D0 && regid <= UC_ARM_REG_D31) {
CHECK_REG_TYPE(uint64_t);
uint32_t reg_index = regid - UC_ARM_REG_D0;
*(uint64_t *)value = env->vfp.zregs[reg_index / 2].d[reg_index & 1];
} else if (regid >= UC_ARM_REG_S0 && regid <= UC_ARM_REG_S31) {
CHECK_REG_TYPE(uint32_t);
uint32_t reg_index = regid - UC_ARM_REG_S0;
uint64_t reg_value = env->vfp.zregs[reg_index / 4].d[reg_index % 4 / 2];
@@ -232,88 +237,115 @@ static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value)
switch (regid) {
case UC_ARM_REG_APSR:
if (arm_feature(env, ARM_FEATURE_M)) {
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = v7m_mrs_xpsr(env, 0);
} else {
CHECK_REG_TYPE(int32_t);
*(int32_t *)value =
cpsr_read(env) & (CPSR_NZCV | CPSR_Q | CPSR_GE);
}
break;
case UC_ARM_REG_APSR_NZCV:
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = cpsr_read(env) & CPSR_NZCV;
break;
case UC_ARM_REG_CPSR:
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = cpsr_read(env);
break;
case UC_ARM_REG_SPSR:
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = env->spsr;
break;
// case UC_ARM_REG_SP:
case UC_ARM_REG_R13:
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = env->regs[13];
break;
// case UC_ARM_REG_LR:
case UC_ARM_REG_R14:
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = env->regs[14];
break;
// case UC_ARM_REG_PC:
case UC_ARM_REG_R15:
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = env->regs[15];
break;
case UC_ARM_REG_C1_C0_2:
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = env->cp15.cpacr_el1;
break;
case UC_ARM_REG_C13_C0_3:
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = env->cp15.tpidrro_el[0];
break;
case UC_ARM_REG_FPEXC:
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = env->vfp.xregs[ARM_VFP_FPEXC];
break;
case UC_ARM_REG_FPSCR:
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = vfp_get_fpscr(env);
break;
case UC_ARM_REG_FPSID:
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = env->vfp.xregs[ARM_VFP_FPSID];
break;
case UC_ARM_REG_IPSR:
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = v7m_mrs_xpsr(env, 5);
break;
case UC_ARM_REG_MSP:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = helper_v7m_mrs(env, 8);
break;
case UC_ARM_REG_PSP:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = helper_v7m_mrs(env, 9);
break;
case UC_ARM_REG_IAPSR:
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = v7m_mrs_xpsr(env, 1);
break;
case UC_ARM_REG_EAPSR:
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = v7m_mrs_xpsr(env, 2);
break;
case UC_ARM_REG_XPSR:
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = v7m_mrs_xpsr(env, 3);
break;
case UC_ARM_REG_EPSR:
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = v7m_mrs_xpsr(env, 6);
break;
case UC_ARM_REG_IEPSR:
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = v7m_mrs_xpsr(env, 7);
break;
case UC_ARM_REG_PRIMASK:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = helper_v7m_mrs(env, 16);
break;
case UC_ARM_REG_BASEPRI:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = helper_v7m_mrs(env, 17);
break;
case UC_ARM_REG_BASEPRI_MAX:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = helper_v7m_mrs(env, 18);
break;
case UC_ARM_REG_FAULTMASK:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = helper_v7m_mrs(env, 19);
break;
case UC_ARM_REG_CONTROL:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = helper_v7m_mrs(env, 20);
break;
case UC_ARM_REG_CP_REG:
CHECK_REG_TYPE(uc_arm_cp_reg);
ret = read_cp_reg(env, (uc_arm_cp_reg *)value);
break;
}
@@ -322,20 +354,25 @@ static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value)
return ret;
}
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)
{
uc_err ret = UC_ERR_OK;
uc_err ret = UC_ERR_ARG;
if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) {
CHECK_REG_TYPE(uint32_t);
env->regs[regid - UC_ARM_REG_R0] = *(uint32_t *)value;
} else if (regid >= UC_ARM_REG_Q0 && regid <= UC_ARM_REG_Q15) {
CHECK_REG_TYPE(uint64_t[2]);
uint32_t reg_index = regid - UC_ARM_REG_Q0;
env->vfp.zregs[reg_index].d[0] = *(uint64_t *)value;
env->vfp.zregs[reg_index].d[1] = *(((uint64_t *)value) + 1);
} else if (regid >= UC_ARM_REG_D0 && regid <= UC_ARM_REG_D31) {
CHECK_REG_TYPE(uint64_t);
uint32_t reg_index = regid - UC_ARM_REG_D0;
env->vfp.zregs[reg_index / 2].d[reg_index & 1] = *(uint64_t *)value;
} else if (regid >= UC_ARM_REG_S0 && regid <= UC_ARM_REG_S31) {
CHECK_REG_TYPE(uint32_t);
uint32_t reg_index = regid - UC_ARM_REG_S0;
uint64_t *p_reg_value =
&env->vfp.zregs[reg_index / 4].d[reg_index % 4 / 2];
@@ -350,6 +387,7 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value)
} else {
switch (regid) {
case UC_ARM_REG_APSR:
CHECK_REG_TYPE(uint32_t);
if (!arm_feature(env, ARM_FEATURE_M)) {
cpsr_write(env, *(uint32_t *)value,
(CPSR_NZCV | CPSR_Q | CPSR_GE), CPSRWriteByUnicorn);
@@ -360,26 +398,32 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value)
}
break;
case UC_ARM_REG_APSR_NZCV:
CHECK_REG_TYPE(uint32_t);
cpsr_write(env, *(uint32_t *)value, CPSR_NZCV, CPSRWriteByUnicorn);
arm_rebuild_hflags(env);
break;
case UC_ARM_REG_CPSR:
CHECK_REG_TYPE(uint32_t);
cpsr_write(env, *(uint32_t *)value, ~0, CPSRWriteByUnicorn);
arm_rebuild_hflags(env);
break;
case UC_ARM_REG_SPSR:
CHECK_REG_TYPE(uint32_t);
env->spsr = *(uint32_t *)value;
break;
// case UC_ARM_REG_SP:
case UC_ARM_REG_R13:
CHECK_REG_TYPE(uint32_t);
env->regs[13] = *(uint32_t *)value;
break;
// case UC_ARM_REG_LR:
case UC_ARM_REG_R14:
CHECK_REG_TYPE(uint32_t);
env->regs[14] = *(uint32_t *)value;
break;
// case UC_ARM_REG_PC:
case UC_ARM_REG_R15:
CHECK_REG_TYPE(uint32_t);
env->pc = (*(uint32_t *)value & ~1);
env->thumb = (*(uint32_t *)value & 1);
env->uc->thumb = (*(uint32_t *)value & 1);
@@ -390,87 +434,114 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value)
// break;
case UC_ARM_REG_C13_C0_3:
CHECK_REG_TYPE(int32_t);
env->cp15.tpidrro_el[0] = *(int32_t *)value;
break;
case UC_ARM_REG_FPEXC:
CHECK_REG_TYPE(int32_t);
env->vfp.xregs[ARM_VFP_FPEXC] = *(int32_t *)value;
break;
case UC_ARM_REG_FPSCR:
CHECK_REG_TYPE(int32_t);
vfp_set_fpscr(env, *(int32_t *)value);
break;
case UC_ARM_REG_FPSID:
CHECK_REG_TYPE(int32_t);
env->vfp.xregs[ARM_VFP_FPSID] = *(int32_t *)value;
break;
case UC_ARM_REG_IPSR:
CHECK_REG_TYPE(uint32_t);
v7m_msr_xpsr(env, 0b1000, 5, *(uint32_t *)value);
break;
case UC_ARM_REG_MSP:
CHECK_REG_TYPE(uint32_t);
helper_v7m_msr(env, 8, *(uint32_t *)value);
break;
case UC_ARM_REG_PSP:
CHECK_REG_TYPE(uint32_t);
helper_v7m_msr(env, 9, *(uint32_t *)value);
break;
case UC_ARM_REG_CONTROL:
CHECK_REG_TYPE(uint32_t);
helper_v7m_msr(env, 20, *(uint32_t *)value);
break;
case UC_ARM_REG_EPSR:
CHECK_REG_TYPE(uint32_t);
v7m_msr_xpsr(env, 0b1000, 6, *(uint32_t *)value);
break;
case UC_ARM_REG_IEPSR:
CHECK_REG_TYPE(uint32_t);
v7m_msr_xpsr(env, 0b1000, 7, *(uint32_t *)value);
break;
case UC_ARM_REG_PRIMASK:
CHECK_REG_TYPE(uint32_t);
helper_v7m_msr(env, 16, *(uint32_t *)value);
break;
case UC_ARM_REG_BASEPRI:
CHECK_REG_TYPE(uint32_t);
helper_v7m_msr(env, 17, *(uint32_t *)value);
break;
case UC_ARM_REG_BASEPRI_MAX:
CHECK_REG_TYPE(uint32_t);
helper_v7m_msr(env, 18, *(uint32_t *)value);
break;
case UC_ARM_REG_FAULTMASK:
CHECK_REG_TYPE(uint32_t);
helper_v7m_msr(env, 19, *(uint32_t *)value);
break;
case UC_ARM_REG_APSR_NZCVQ:
CHECK_REG_TYPE(uint32_t);
v7m_msr_xpsr(env, 0b1000, 0, *(uint32_t *)value);
break;
case UC_ARM_REG_APSR_G:
CHECK_REG_TYPE(uint32_t);
v7m_msr_xpsr(env, 0b0100, 0, *(uint32_t *)value);
break;
case UC_ARM_REG_APSR_NZCVQG:
CHECK_REG_TYPE(uint32_t);
v7m_msr_xpsr(env, 0b1100, 0, *(uint32_t *)value);
break;
case UC_ARM_REG_IAPSR:
case UC_ARM_REG_IAPSR_NZCVQ:
CHECK_REG_TYPE(uint32_t);
v7m_msr_xpsr(env, 0b1000, 1, *(uint32_t *)value);
break;
case UC_ARM_REG_IAPSR_G:
CHECK_REG_TYPE(uint32_t);
v7m_msr_xpsr(env, 0b0100, 1, *(uint32_t *)value);
break;
case UC_ARM_REG_IAPSR_NZCVQG:
CHECK_REG_TYPE(uint32_t);
v7m_msr_xpsr(env, 0b1100, 1, *(uint32_t *)value);
break;
case UC_ARM_REG_EAPSR:
case UC_ARM_REG_EAPSR_NZCVQ:
CHECK_REG_TYPE(uint32_t);
v7m_msr_xpsr(env, 0b1000, 2, *(uint32_t *)value);
break;
case UC_ARM_REG_EAPSR_G:
CHECK_REG_TYPE(uint32_t);
v7m_msr_xpsr(env, 0b0100, 2, *(uint32_t *)value);
break;
case UC_ARM_REG_EAPSR_NZCVQG:
CHECK_REG_TYPE(uint32_t);
v7m_msr_xpsr(env, 0b1100, 2, *(uint32_t *)value);
break;
case UC_ARM_REG_XPSR:
case UC_ARM_REG_XPSR_NZCVQ:
CHECK_REG_TYPE(uint32_t);
v7m_msr_xpsr(env, 0b1000, 3, *(uint32_t *)value);
break;
case UC_ARM_REG_XPSR_G:
CHECK_REG_TYPE(uint32_t);
v7m_msr_xpsr(env, 0b0100, 3, *(uint32_t *)value);
break;
case UC_ARM_REG_XPSR_NZCVQG:
CHECK_REG_TYPE(uint32_t);
v7m_msr_xpsr(env, 0b1100, 3, *(uint32_t *)value);
break;
case UC_ARM_REG_CP_REG:
CHECK_REG_TYPE(uc_arm_cp_reg);
ret = write_cp_reg(env, (uc_arm_cp_reg *)value);
break;
}
@@ -479,8 +550,8 @@ 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 **vals,
int count)
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);
int i;
@@ -489,17 +560,20 @@ int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
void *value = vals[i];
err = reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int 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 i;
@@ -508,7 +582,7 @@ int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
const void *value = vals[i];
err = reg_write(env, regid, value);
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
@@ -519,12 +593,12 @@ int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
}
}
return 0;
return UC_ERR_OK;
}
DEFAULT_VISIBILITY
int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
void *const *vals, size_t *sizes, int count)
{
CPUARMState *env = (CPUARMState *)ctx->data;
int i;
@@ -533,18 +607,21 @@ int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs,
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
void *value = vals[i];
err = reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
DEFAULT_VISIBILITY
int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
const void *const *vals, size_t *sizes, int count)
{
CPUARMState *env = (CPUARMState *)ctx->data;
int i;
@@ -553,13 +630,13 @@ int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs,
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
const void *value = vals[i];
err = reg_write(env, regid, value);
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
static bool arm_stop_interrupt(struct uc_struct *uc, int intno)

File diff suppressed because it is too large Load Diff

View File

@@ -6,14 +6,14 @@
#define UC_QEMU_TARGET_I386_H
// functions to read & write registers
int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count);
int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count);
int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
size_t *sizes, int count);
int x86_reg_write(struct uc_struct *uc, unsigned int *regs,
const void *const *vals, size_t *sizes, int count);
int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
void *const *vals, size_t *sizes, int count);
int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes, int count);
void x86_reg_reset(struct uc_struct *uc);

View File

@@ -49,71 +49,97 @@ void m68k_reg_reset(struct uc_struct *uc)
env->pc = 0;
}
static void reg_read(CPUM68KState *env, unsigned int regid, void *value)
static uc_err reg_read(CPUM68KState *env, unsigned int regid, void *value,
size_t *size)
{
if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7)
*(int32_t *)value = env->aregs[regid - UC_M68K_REG_A0];
else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7)
*(int32_t *)value = env->dregs[regid - UC_M68K_REG_D0];
else {
uc_err ret = UC_ERR_ARG;
if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7) {
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->aregs[regid - UC_M68K_REG_A0];
} else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7) {
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->dregs[regid - UC_M68K_REG_D0];
} else {
switch (regid) {
default:
break;
case UC_M68K_REG_PC:
*(int32_t *)value = env->pc;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->pc;
break;
case UC_M68K_REG_SR:
*(int32_t *)value = env->sr;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->sr;
break;
}
}
return ret;
}
static void reg_write(CPUM68KState *env, unsigned int regid, const void *value)
static uc_err reg_write(CPUM68KState *env, unsigned int regid,
const void *value, size_t *size)
{
if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7)
uc_err ret = UC_ERR_ARG;
if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7) {
CHECK_REG_TYPE(uint32_t);
env->aregs[regid - UC_M68K_REG_A0] = *(uint32_t *)value;
else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7)
} else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7) {
CHECK_REG_TYPE(uint32_t);
env->dregs[regid - UC_M68K_REG_D0] = *(uint32_t *)value;
else {
} else {
switch (regid) {
default:
break;
case UC_M68K_REG_PC:
CHECK_REG_TYPE(uint32_t);
env->pc = *(uint32_t *)value;
break;
case UC_M68K_REG_SR:
CHECK_REG_TYPE(uint32_t);
cpu_m68k_set_sr(env, *(uint32_t *)value);
break;
}
}
return ret;
}
int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count)
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);
int i;
uc_err err;
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
void *value = vals[i];
reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int 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 i;
uc_err err;
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
const void *value = vals[i];
reg_write(env, regid, value);
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
if (regid == UC_M68K_REG_PC) {
// force to quit execution and flush TB
uc->quit_request = true;
@@ -121,39 +147,47 @@ int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
}
}
return 0;
return UC_ERR_OK;
}
DEFAULT_VISIBILITY
int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
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];
reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
DEFAULT_VISIBILITY
int m68k_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
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];
reg_write(env, regid, value);
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
static int m68k_cpus_init(struct uc_struct *uc, const char *cpu_model)

View File

@@ -5,14 +5,14 @@
#define UC_QEMU_TARGET_M68K_H
// functions to read & write registers
int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count);
int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count);
int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
size_t *sizes, int count);
int m68k_reg_write(struct uc_struct *uc, unsigned int *regs,
const void *const *vals, size_t *sizes, int count);
int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
void *const *vals, size_t *sizes, int count);
int m68k_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes, int count);
void m68k_reg_reset(struct uc_struct *uc);

View File

@@ -59,99 +59,127 @@ void mips_reg_reset(struct uc_struct *uc)
env->active_tc.PC = 0;
}
static void reg_read(CPUMIPSState *env, unsigned int regid, void *value)
static uc_err reg_read(CPUMIPSState *env, unsigned int regid, void *value,
size_t *size)
{
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31)
uc_err ret = UC_ERR_ARG;
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31) {
CHECK_REG_TYPE(mipsreg_t);
*(mipsreg_t *)value = env->active_tc.gpr[regid - UC_MIPS_REG_0];
else {
} else {
switch (regid) {
default:
break;
case UC_MIPS_REG_HI:
CHECK_REG_TYPE(mipsreg_t);
*(mipsreg_t *)value = env->active_tc.HI[0];
break;
case UC_MIPS_REG_LO:
CHECK_REG_TYPE(mipsreg_t);
*(mipsreg_t *)value = env->active_tc.LO[0];
break;
case UC_MIPS_REG_PC:
CHECK_REG_TYPE(mipsreg_t);
*(mipsreg_t *)value = env->active_tc.PC;
break;
case UC_MIPS_REG_CP0_CONFIG3:
CHECK_REG_TYPE(mipsreg_t);
*(mipsreg_t *)value = env->CP0_Config3;
break;
case UC_MIPS_REG_CP0_STATUS:
CHECK_REG_TYPE(mipsreg_t);
*(mipsreg_t *)value = env->CP0_Status;
break;
case UC_MIPS_REG_CP0_USERLOCAL:
CHECK_REG_TYPE(mipsreg_t);
*(mipsreg_t *)value = env->active_tc.CP0_UserLocal;
break;
}
}
return;
return ret;
}
static void reg_write(CPUMIPSState *env, unsigned int regid, const void *value)
static uc_err reg_write(CPUMIPSState *env, unsigned int regid,
const void *value, size_t *size)
{
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31)
uc_err ret = UC_ERR_ARG;
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31) {
CHECK_REG_TYPE(mipsreg_t);
env->active_tc.gpr[regid - UC_MIPS_REG_0] = *(mipsreg_t *)value;
else {
} else {
switch (regid) {
default:
break;
case UC_MIPS_REG_HI:
CHECK_REG_TYPE(mipsreg_t);
env->active_tc.HI[0] = *(mipsreg_t *)value;
break;
case UC_MIPS_REG_LO:
CHECK_REG_TYPE(mipsreg_t);
env->active_tc.LO[0] = *(mipsreg_t *)value;
break;
case UC_MIPS_REG_PC:
CHECK_REG_TYPE(mipsreg_t);
env->active_tc.PC = *(mipsreg_t *)value;
break;
case UC_MIPS_REG_CP0_CONFIG3:
CHECK_REG_TYPE(mipsreg_t);
env->CP0_Config3 = *(mipsreg_t *)value;
break;
case UC_MIPS_REG_CP0_STATUS:
// TODO: ALL CP0 REGS
// https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00090-2B-MIPS32PRA-AFP-06.02.pdf
// https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00582-2B-microMIPS32-AFP-05.04.pdf
CHECK_REG_TYPE(mipsreg_t);
env->CP0_Status = *(mipsreg_t *)value;
compute_hflags(env);
break;
case UC_MIPS_REG_CP0_USERLOCAL:
CHECK_REG_TYPE(mipsreg_t);
env->active_tc.CP0_UserLocal = *(mipsreg_t *)value;
break;
}
}
return;
return ret;
}
int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count)
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);
int i;
uc_err err;
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
void *value = vals[i];
reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int 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 i;
uc_err err;
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
const void *value = vals[i];
reg_write(env, regid, value);
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
if (regid == UC_MIPS_REG_PC) {
// force to quit execution and flush TB
uc->quit_request = true;
@@ -159,69 +187,78 @@ int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
}
}
return 0;
return UC_ERR_OK;
}
DEFAULT_VISIBILITY
#ifdef TARGET_MIPS64
#ifdef TARGET_WORDS_BIGENDIAN
int mips64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
void *const *vals, size_t *sizes, int count)
#else
int mips64el_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
void *const *vals, size_t *sizes, int count)
#endif
#else // if TARGET_MIPS
#ifdef TARGET_WORDS_BIGENDIAN
int mips_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
void *const *vals, size_t *sizes, int count)
#else
int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
void *const *vals, size_t *sizes, int count)
#endif
#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];
reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
DEFAULT_VISIBILITY
#ifdef TARGET_MIPS64
#ifdef TARGET_WORDS_BIGENDIAN
int mips64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
const void *const *vals, size_t *sizes, int count)
#else
int mips64el_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
const void *const *vals, size_t *sizes,
int count)
#endif
#else // if TARGET_MIPS
#ifdef TARGET_WORDS_BIGENDIAN
int mips_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
const void *const *vals, size_t *sizes, int count)
#else
int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
const void *const *vals, size_t *sizes, int count)
#endif
#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];
reg_write(env, regid, value);
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
static int mips_cpus_init(struct uc_struct *uc, const char *cpu_model)

View File

@@ -5,27 +5,28 @@
#define UC_QEMU_TARGET_MIPS_H
// functions to read & write registers
int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count);
int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count);
int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
size_t *sizes, int count);
int mips_reg_write(struct uc_struct *uc, unsigned int *regs,
const void *const *vals, size_t *sizes, int count);
int mips_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
void *const *vals, size_t *sizes, int count);
int mips_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes, int count);
int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
void *const *vals, size_t *sizes, int count);
int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes, int count);
int mips64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
void *const *vals, size_t *sizes, int count);
int mips64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes, int count);
int mips64el_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
void *const *vals, size_t *sizes, int count);
int mips64el_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes,
int count);
void mips_reg_reset(struct uc_struct *uc);

View File

@@ -146,64 +146,31 @@ void ppc_reg_reset(struct uc_struct *uc)
}
// http://www.csit-sun.pub.ro/~cpop/Documentatie_SMP/Motorola_PowerPC/PowerPc/GenInfo/pemch2.pdf
static void reg_read(CPUPPCState *env, unsigned int regid, void *value)
static uc_err reg_read(CPUPPCState *env, unsigned int regid, void *value,
size_t *size)
{
uint32_t val;
uc_err ret = UC_ERR_ARG;
if (regid >= UC_PPC_REG_0 && regid <= UC_PPC_REG_31)
if (regid >= UC_PPC_REG_0 && regid <= UC_PPC_REG_31) {
CHECK_REG_TYPE(ppcreg_t);
*(ppcreg_t *)value = env->gpr[regid - UC_PPC_REG_0];
else {
} else if (regid >= UC_PPC_REG_FPR0 && regid <= UC_PPC_REG_FPR31) {
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->vsr[regid - UC_PPC_REG_FPR0].VsrD(0);
} else if (regid >= UC_PPC_REG_CR0 && regid <= UC_PPC_REG_CR7) {
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->crf[regid - UC_PPC_REG_CR0];
} else {
switch (regid) {
default:
break;
case UC_PPC_REG_PC:
CHECK_REG_TYPE(ppcreg_t);
*(ppcreg_t *)value = env->nip;
break;
case UC_PPC_REG_FPR0:
case UC_PPC_REG_FPR1:
case UC_PPC_REG_FPR2:
case UC_PPC_REG_FPR3:
case UC_PPC_REG_FPR4:
case UC_PPC_REG_FPR5:
case UC_PPC_REG_FPR6:
case UC_PPC_REG_FPR7:
case UC_PPC_REG_FPR8:
case UC_PPC_REG_FPR9:
case UC_PPC_REG_FPR10:
case UC_PPC_REG_FPR11:
case UC_PPC_REG_FPR12:
case UC_PPC_REG_FPR13:
case UC_PPC_REG_FPR14:
case UC_PPC_REG_FPR15:
case UC_PPC_REG_FPR16:
case UC_PPC_REG_FPR17:
case UC_PPC_REG_FPR18:
case UC_PPC_REG_FPR19:
case UC_PPC_REG_FPR20:
case UC_PPC_REG_FPR21:
case UC_PPC_REG_FPR22:
case UC_PPC_REG_FPR23:
case UC_PPC_REG_FPR24:
case UC_PPC_REG_FPR25:
case UC_PPC_REG_FPR26:
case UC_PPC_REG_FPR27:
case UC_PPC_REG_FPR28:
case UC_PPC_REG_FPR29:
case UC_PPC_REG_FPR30:
case UC_PPC_REG_FPR31:
*(uint64_t *)value = env->vsr[regid - UC_PPC_REG_FPR0].VsrD(0);
break;
case UC_PPC_REG_CR0:
case UC_PPC_REG_CR1:
case UC_PPC_REG_CR2:
case UC_PPC_REG_CR3:
case UC_PPC_REG_CR4:
case UC_PPC_REG_CR5:
case UC_PPC_REG_CR6:
case UC_PPC_REG_CR7:
*(uint32_t *)value = env->crf[regid - UC_PPC_REG_CR0];
break;
case UC_PPC_REG_CR:
case UC_PPC_REG_CR: {
CHECK_REG_TYPE(uint32_t);
uint32_t val;
val = 0;
for (int i = 0; i < 8; i++) {
val <<= 4;
@@ -211,138 +178,124 @@ static void reg_read(CPUPPCState *env, unsigned int regid, void *value)
}
*(uint32_t *)value = val;
break;
}
case UC_PPC_REG_LR:
CHECK_REG_TYPE(ppcreg_t);
*(ppcreg_t *)value = env->lr;
break;
case UC_PPC_REG_CTR:
CHECK_REG_TYPE(ppcreg_t);
*(ppcreg_t *)value = env->ctr;
break;
case UC_PPC_REG_MSR:
CHECK_REG_TYPE(ppcreg_t);
*(ppcreg_t *)value = env->msr;
break;
case UC_PPC_REG_XER:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->xer;
break;
case UC_PPC_REG_FPSCR:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->fpscr;
break;
}
}
return;
return ret;
}
static void 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)
{
uint32_t val;
int i;
uc_err ret = UC_ERR_ARG;
if (regid >= UC_PPC_REG_0 && regid <= UC_PPC_REG_31)
if (regid >= UC_PPC_REG_0 && regid <= UC_PPC_REG_31) {
CHECK_REG_TYPE(ppcreg_t);
env->gpr[regid - UC_PPC_REG_0] = *(ppcreg_t *)value;
else {
} else if (regid >= UC_PPC_REG_FPR0 && regid <= UC_PPC_REG_FPR31) {
CHECK_REG_TYPE(uint64_t);
env->vsr[regid - UC_PPC_REG_FPR0].VsrD(0) = *(uint64_t *)value;
} else if (regid >= UC_PPC_REG_CR0 && regid <= UC_PPC_REG_CR7) {
CHECK_REG_TYPE(uint32_t);
env->crf[regid - UC_PPC_REG_CR0] = (*(uint32_t *)value) & 0b1111;
} else {
switch (regid) {
default:
break;
case UC_PPC_REG_PC:
CHECK_REG_TYPE(ppcreg_t);
env->nip = *(ppcreg_t *)value;
break;
case UC_PPC_REG_FPR0:
case UC_PPC_REG_FPR1:
case UC_PPC_REG_FPR2:
case UC_PPC_REG_FPR3:
case UC_PPC_REG_FPR4:
case UC_PPC_REG_FPR5:
case UC_PPC_REG_FPR6:
case UC_PPC_REG_FPR7:
case UC_PPC_REG_FPR8:
case UC_PPC_REG_FPR9:
case UC_PPC_REG_FPR10:
case UC_PPC_REG_FPR11:
case UC_PPC_REG_FPR12:
case UC_PPC_REG_FPR13:
case UC_PPC_REG_FPR14:
case UC_PPC_REG_FPR15:
case UC_PPC_REG_FPR16:
case UC_PPC_REG_FPR17:
case UC_PPC_REG_FPR18:
case UC_PPC_REG_FPR19:
case UC_PPC_REG_FPR20:
case UC_PPC_REG_FPR21:
case UC_PPC_REG_FPR22:
case UC_PPC_REG_FPR23:
case UC_PPC_REG_FPR24:
case UC_PPC_REG_FPR25:
case UC_PPC_REG_FPR26:
case UC_PPC_REG_FPR27:
case UC_PPC_REG_FPR28:
case UC_PPC_REG_FPR29:
case UC_PPC_REG_FPR30:
case UC_PPC_REG_FPR31:
env->vsr[regid - UC_PPC_REG_FPR0].VsrD(0) = *(uint64_t *)value;
break;
case UC_PPC_REG_CR0:
case UC_PPC_REG_CR1:
case UC_PPC_REG_CR2:
case UC_PPC_REG_CR3:
case UC_PPC_REG_CR4:
case UC_PPC_REG_CR5:
case UC_PPC_REG_CR6:
case UC_PPC_REG_CR7:
env->crf[regid - UC_PPC_REG_CR0] = (*(uint32_t *)value) & 0b1111;
break;
case UC_PPC_REG_CR:
val = *(uint32_t *)value;
case UC_PPC_REG_CR: {
CHECK_REG_TYPE(uint32_t);
uint32_t val = *(uint32_t *)value;
for (i = 7; i >= 0; i--) {
env->crf[i] = val & 0b1111;
val >>= 4;
}
break;
}
case UC_PPC_REG_LR:
CHECK_REG_TYPE(ppcreg_t);
env->lr = *(ppcreg_t *)value;
break;
case UC_PPC_REG_CTR:
CHECK_REG_TYPE(ppcreg_t);
env->ctr = *(ppcreg_t *)value;
break;
case UC_PPC_REG_MSR:
CHECK_REG_TYPE(ppcreg_t);
uc_ppc_store_msr(env, *(ppcreg_t *)value, 0);
break;
case UC_PPC_REG_XER:
CHECK_REG_TYPE(uint32_t);
env->xer = *(uint32_t *)value;
break;
case UC_PPC_REG_FPSCR:
CHECK_REG_TYPE(uint32_t);
store_fpscr(env, *(uint32_t *)value, 0xffffffff);
break;
}
}
return;
return ret;
}
int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count)
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);
int i;
uc_err err;
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
void *value = vals[i];
reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int 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 i;
uc_err err;
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
const void *value = vals[i];
reg_write(env, regid, value);
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
if (regid == UC_PPC_REG_PC) {
// force to quit execution and flush TB
uc->quit_request = true;
@@ -350,49 +303,57 @@ int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
}
}
return 0;
return UC_ERR_OK;
}
DEFAULT_VISIBILITY
#ifdef TARGET_PPC64
int ppc64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
void *const *vals, size_t *sizes, int count)
#else
int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
void *const *vals, size_t *sizes, int count)
#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];
reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
DEFAULT_VISIBILITY
#ifdef TARGET_PPC64
int ppc64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
const void *const *vals, size_t *sizes, int count)
#else
int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
const void *const *vals, size_t *sizes, int count)
#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];
reg_write(env, regid, value);
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
PowerPCCPU *cpu_ppc_init(struct uc_struct *uc);

View File

@@ -5,19 +5,19 @@
#define UC_QEMU_TARGET_PPC_H
// functions to read & write registers
int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count);
int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count);
int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
size_t *sizes, int count);
int ppc_reg_write(struct uc_struct *uc, unsigned int *regs,
const void *const *vals, size_t *sizes, int count);
int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
void *const *vals, size_t *sizes, int count);
int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes, int count);
int ppc64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
void *const *vals, size_t *sizes, int count);
int ppc64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes, int count);
void ppc_reg_reset(struct uc_struct *uc);

View File

@@ -44,6 +44,7 @@ static int csrno_map[] = {
CSR_HIP, CSR_HTINST, CSR_HGATP, CSR_HTIMEDELTA,
CSR_HTIMEDELTAH,
};
#define csrno_count (sizeof(csrno_map) / sizeof(int))
RISCVCPU *cpu_riscv_init(struct uc_struct *uc);
@@ -78,485 +79,134 @@ static void riscv_release(void *ctx)
void riscv_reg_reset(struct uc_struct *uc) {}
static void reg_read(CPURISCVState *env, unsigned int regid, void *value)
static uc_err reg_read(CPURISCVState *env, unsigned int regid, void *value,
size_t *size)
{
switch (regid) {
case UC_RISCV_REG_X0:
case UC_RISCV_REG_X1:
case UC_RISCV_REG_X2:
case UC_RISCV_REG_X3:
case UC_RISCV_REG_X4:
case UC_RISCV_REG_X5:
case UC_RISCV_REG_X6:
case UC_RISCV_REG_X7:
case UC_RISCV_REG_X8:
case UC_RISCV_REG_X9:
case UC_RISCV_REG_X10:
case UC_RISCV_REG_X11:
case UC_RISCV_REG_X12:
case UC_RISCV_REG_X13:
case UC_RISCV_REG_X14:
case UC_RISCV_REG_X15:
case UC_RISCV_REG_X16:
case UC_RISCV_REG_X17:
case UC_RISCV_REG_X18:
case UC_RISCV_REG_X19:
case UC_RISCV_REG_X20:
case UC_RISCV_REG_X21:
case UC_RISCV_REG_X22:
case UC_RISCV_REG_X23:
case UC_RISCV_REG_X24:
case UC_RISCV_REG_X25:
case UC_RISCV_REG_X26:
case UC_RISCV_REG_X27:
case UC_RISCV_REG_X28:
case UC_RISCV_REG_X29:
case UC_RISCV_REG_X30:
case UC_RISCV_REG_X31:
#ifdef TARGET_RISCV64
*(int64_t *)value = env->gpr[regid - UC_RISCV_REG_X0];
#else
*(int32_t *)value = env->gpr[regid - UC_RISCV_REG_X0];
#endif
break;
case UC_RISCV_REG_PC:
#ifdef TARGET_RISCV64
*(int64_t *)value = env->pc;
#else
*(int32_t *)value = env->pc;
#endif
break;
uc_err ret = UC_ERR_ARG;
case UC_RISCV_REG_F0: // "ft0"
case UC_RISCV_REG_F1: // "ft1"
case UC_RISCV_REG_F2: // "ft2"
case UC_RISCV_REG_F3: // "ft3"
case UC_RISCV_REG_F4: // "ft4"
case UC_RISCV_REG_F5: // "ft5"
case UC_RISCV_REG_F6: // "ft6"
case UC_RISCV_REG_F7: // "ft7"
case UC_RISCV_REG_F8: // "fs0"
case UC_RISCV_REG_F9: // "fs1"
case UC_RISCV_REG_F10: // "fa0"
case UC_RISCV_REG_F11: // "fa1"
case UC_RISCV_REG_F12: // "fa2"
case UC_RISCV_REG_F13: // "fa3"
case UC_RISCV_REG_F14: // "fa4"
case UC_RISCV_REG_F15: // "fa5"
case UC_RISCV_REG_F16: // "fa6"
case UC_RISCV_REG_F17: // "fa7"
case UC_RISCV_REG_F18: // "fs2"
case UC_RISCV_REG_F19: // "fs3"
case UC_RISCV_REG_F20: // "fs4"
case UC_RISCV_REG_F21: // "fs5"
case UC_RISCV_REG_F22: // "fs6"
case UC_RISCV_REG_F23: // "fs7"
case UC_RISCV_REG_F24: // "fs8"
case UC_RISCV_REG_F25: // "fs9"
case UC_RISCV_REG_F26: // "fs10"
case UC_RISCV_REG_F27: // "fs11"
case UC_RISCV_REG_F28: // "ft8"
case UC_RISCV_REG_F29: // "ft9"
case UC_RISCV_REG_F30: // "ft10"
case UC_RISCV_REG_F31: // "ft11"
if (regid >= UC_RISCV_REG_X0 && regid <= UC_RISCV_REG_X31) {
#ifdef TARGET_RISCV64
*(int64_t *)value = env->fpr[regid - UC_RISCV_REG_F0];
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->gpr[regid - UC_RISCV_REG_X0];
#else
*(int32_t *)value = env->fpr[regid - UC_RISCV_REG_F0];
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->gpr[regid - UC_RISCV_REG_X0];
#endif
break;
case UC_RISCV_REG_USTATUS:
case UC_RISCV_REG_UIE:
case UC_RISCV_REG_UTVEC:
case UC_RISCV_REG_USCRATCH:
case UC_RISCV_REG_UEPC:
case UC_RISCV_REG_UCAUSE:
case UC_RISCV_REG_UTVAL:
case UC_RISCV_REG_UIP:
case UC_RISCV_REG_FFLAGS:
case UC_RISCV_REG_FRM:
case UC_RISCV_REG_FCSR:
case UC_RISCV_REG_CYCLE:
case UC_RISCV_REG_TIME:
case UC_RISCV_REG_INSTRET:
case UC_RISCV_REG_HPMCOUNTER3:
case UC_RISCV_REG_HPMCOUNTER4:
case UC_RISCV_REG_HPMCOUNTER5:
case UC_RISCV_REG_HPMCOUNTER6:
case UC_RISCV_REG_HPMCOUNTER7:
case UC_RISCV_REG_HPMCOUNTER8:
case UC_RISCV_REG_HPMCOUNTER9:
case UC_RISCV_REG_HPMCOUNTER10:
case UC_RISCV_REG_HPMCOUNTER11:
case UC_RISCV_REG_HPMCOUNTER12:
case UC_RISCV_REG_HPMCOUNTER13:
case UC_RISCV_REG_HPMCOUNTER14:
case UC_RISCV_REG_HPMCOUNTER15:
case UC_RISCV_REG_HPMCOUNTER16:
case UC_RISCV_REG_HPMCOUNTER17:
case UC_RISCV_REG_HPMCOUNTER18:
case UC_RISCV_REG_HPMCOUNTER19:
case UC_RISCV_REG_HPMCOUNTER20:
case UC_RISCV_REG_HPMCOUNTER21:
case UC_RISCV_REG_HPMCOUNTER22:
case UC_RISCV_REG_HPMCOUNTER23:
case UC_RISCV_REG_HPMCOUNTER24:
case UC_RISCV_REG_HPMCOUNTER25:
case UC_RISCV_REG_HPMCOUNTER26:
case UC_RISCV_REG_HPMCOUNTER27:
case UC_RISCV_REG_HPMCOUNTER28:
case UC_RISCV_REG_HPMCOUNTER29:
case UC_RISCV_REG_HPMCOUNTER30:
case UC_RISCV_REG_HPMCOUNTER31:
case UC_RISCV_REG_CYCLEH:
case UC_RISCV_REG_TIMEH:
case UC_RISCV_REG_INSTRETH:
case UC_RISCV_REG_HPMCOUNTER3H:
case UC_RISCV_REG_HPMCOUNTER4H:
case UC_RISCV_REG_HPMCOUNTER5H:
case UC_RISCV_REG_HPMCOUNTER6H:
case UC_RISCV_REG_HPMCOUNTER7H:
case UC_RISCV_REG_HPMCOUNTER8H:
case UC_RISCV_REG_HPMCOUNTER9H:
case UC_RISCV_REG_HPMCOUNTER10H:
case UC_RISCV_REG_HPMCOUNTER11H:
case UC_RISCV_REG_HPMCOUNTER12H:
case UC_RISCV_REG_HPMCOUNTER13H:
case UC_RISCV_REG_HPMCOUNTER14H:
case UC_RISCV_REG_HPMCOUNTER15H:
case UC_RISCV_REG_HPMCOUNTER16H:
case UC_RISCV_REG_HPMCOUNTER17H:
case UC_RISCV_REG_HPMCOUNTER18H:
case UC_RISCV_REG_HPMCOUNTER19H:
case UC_RISCV_REG_HPMCOUNTER20H:
case UC_RISCV_REG_HPMCOUNTER21H:
case UC_RISCV_REG_HPMCOUNTER22H:
case UC_RISCV_REG_HPMCOUNTER23H:
case UC_RISCV_REG_HPMCOUNTER24H:
case UC_RISCV_REG_HPMCOUNTER25H:
case UC_RISCV_REG_HPMCOUNTER26H:
case UC_RISCV_REG_HPMCOUNTER27H:
case UC_RISCV_REG_HPMCOUNTER28H:
case UC_RISCV_REG_HPMCOUNTER29H:
case UC_RISCV_REG_HPMCOUNTER30H:
case UC_RISCV_REG_HPMCOUNTER31H:
case UC_RISCV_REG_MCYCLE:
case UC_RISCV_REG_MINSTRET:
case UC_RISCV_REG_MCYCLEH:
case UC_RISCV_REG_MINSTRETH:
case UC_RISCV_REG_MVENDORID:
case UC_RISCV_REG_MARCHID:
case UC_RISCV_REG_MIMPID:
case UC_RISCV_REG_MHARTID:
case UC_RISCV_REG_MSTATUS:
case UC_RISCV_REG_MISA:
case UC_RISCV_REG_MEDELEG:
case UC_RISCV_REG_MIDELEG:
case UC_RISCV_REG_MIE:
case UC_RISCV_REG_MTVEC:
case UC_RISCV_REG_MCOUNTEREN:
case UC_RISCV_REG_MSTATUSH:
case UC_RISCV_REG_MUCOUNTEREN:
case UC_RISCV_REG_MSCOUNTEREN:
case UC_RISCV_REG_MHCOUNTEREN:
case UC_RISCV_REG_MSCRATCH:
case UC_RISCV_REG_MEPC:
case UC_RISCV_REG_MCAUSE:
case UC_RISCV_REG_MTVAL:
case UC_RISCV_REG_MIP:
case UC_RISCV_REG_MBADADDR:
case UC_RISCV_REG_SSTATUS:
case UC_RISCV_REG_SEDELEG:
case UC_RISCV_REG_SIDELEG:
case UC_RISCV_REG_SIE:
case UC_RISCV_REG_STVEC:
case UC_RISCV_REG_SCOUNTEREN:
case UC_RISCV_REG_SSCRATCH:
case UC_RISCV_REG_SEPC:
case UC_RISCV_REG_SCAUSE:
case UC_RISCV_REG_STVAL:
case UC_RISCV_REG_SIP:
case UC_RISCV_REG_SBADADDR:
case UC_RISCV_REG_SPTBR:
case UC_RISCV_REG_SATP:
case UC_RISCV_REG_HSTATUS:
case UC_RISCV_REG_HEDELEG:
case UC_RISCV_REG_HIDELEG:
case UC_RISCV_REG_HIE:
case UC_RISCV_REG_HCOUNTEREN:
case UC_RISCV_REG_HTVAL:
case UC_RISCV_REG_HIP:
case UC_RISCV_REG_HTINST:
case UC_RISCV_REG_HGATP:
case UC_RISCV_REG_HTIMEDELTA:
case UC_RISCV_REG_HTIMEDELTAH: {
} else if (regid >= UC_RISCV_REG_F0 &&
regid <= UC_RISCV_REG_F31) { // "ft0".."ft31"
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->fpr[regid - UC_RISCV_REG_F0];
} else if (regid >= UC_RISCV_REG_USTATUS &&
regid < UC_RISCV_REG_USTATUS + csrno_count) {
target_ulong val;
int csrno = csrno_map[regid - UC_RISCV_REG_USTATUS];
riscv_csrrw(env, csrno, &val, -1, 0);
#ifdef TARGET_RISCV64
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = (uint64_t)val;
#else
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = (uint32_t)val;
#endif
break;
}
default:
break;
} else {
switch (regid) {
default:
break;
case UC_RISCV_REG_PC:
#ifdef TARGET_RISCV64
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->pc;
#else
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->pc;
#endif
break;
}
}
return;
return ret;
}
static void reg_write(CPURISCVState *env, unsigned int regid, const void *value)
static uc_err reg_write(CPURISCVState *env, unsigned int regid,
const void *value, size_t *size)
{
switch (regid) {
case UC_RISCV_REG_X0:
case UC_RISCV_REG_X1:
case UC_RISCV_REG_X2:
case UC_RISCV_REG_X3:
case UC_RISCV_REG_X4:
case UC_RISCV_REG_X5:
case UC_RISCV_REG_X6:
case UC_RISCV_REG_X7:
case UC_RISCV_REG_X8:
case UC_RISCV_REG_X9:
case UC_RISCV_REG_X10:
case UC_RISCV_REG_X11:
case UC_RISCV_REG_X12:
case UC_RISCV_REG_X13:
case UC_RISCV_REG_X14:
case UC_RISCV_REG_X15:
case UC_RISCV_REG_X16:
case UC_RISCV_REG_X17:
case UC_RISCV_REG_X18:
case UC_RISCV_REG_X19:
case UC_RISCV_REG_X20:
case UC_RISCV_REG_X21:
case UC_RISCV_REG_X22:
case UC_RISCV_REG_X23:
case UC_RISCV_REG_X24:
case UC_RISCV_REG_X25:
case UC_RISCV_REG_X26:
case UC_RISCV_REG_X27:
case UC_RISCV_REG_X28:
case UC_RISCV_REG_X29:
case UC_RISCV_REG_X30:
case UC_RISCV_REG_X31:
uc_err ret = UC_ERR_ARG;
if (regid >= UC_RISCV_REG_X0 && regid <= UC_RISCV_REG_X31) {
#ifdef TARGET_RISCV64
CHECK_REG_TYPE(uint64_t);
env->gpr[regid - UC_RISCV_REG_X0] = *(uint64_t *)value;
#else
CHECK_REG_TYPE(uint32_t);
env->gpr[regid - UC_RISCV_REG_X0] = *(uint32_t *)value;
#endif
break;
case UC_RISCV_REG_PC:
#ifdef TARGET_RISCV64
env->pc = *(uint64_t *)value;
#else
env->pc = *(uint32_t *)value;
#endif
break;
case UC_RISCV_REG_F0: // "ft0"
case UC_RISCV_REG_F1: // "ft1"
case UC_RISCV_REG_F2: // "ft2"
case UC_RISCV_REG_F3: // "ft3"
case UC_RISCV_REG_F4: // "ft4"
case UC_RISCV_REG_F5: // "ft5"
case UC_RISCV_REG_F6: // "ft6"
case UC_RISCV_REG_F7: // "ft7"
case UC_RISCV_REG_F8: // "fs0"
case UC_RISCV_REG_F9: // "fs1"
case UC_RISCV_REG_F10: // "fa0"
case UC_RISCV_REG_F11: // "fa1"
case UC_RISCV_REG_F12: // "fa2"
case UC_RISCV_REG_F13: // "fa3"
case UC_RISCV_REG_F14: // "fa4"
case UC_RISCV_REG_F15: // "fa5"
case UC_RISCV_REG_F16: // "fa6"
case UC_RISCV_REG_F17: // "fa7"
case UC_RISCV_REG_F18: // "fs2"
case UC_RISCV_REG_F19: // "fs3"
case UC_RISCV_REG_F20: // "fs4"
case UC_RISCV_REG_F21: // "fs5"
case UC_RISCV_REG_F22: // "fs6"
case UC_RISCV_REG_F23: // "fs7"
case UC_RISCV_REG_F24: // "fs8"
case UC_RISCV_REG_F25: // "fs9"
case UC_RISCV_REG_F26: // "fs10"
case UC_RISCV_REG_F27: // "fs11"
case UC_RISCV_REG_F28: // "ft8"
case UC_RISCV_REG_F29: // "ft9"
case UC_RISCV_REG_F30: // "ft10"
case UC_RISCV_REG_F31: // "ft11"
#ifdef TARGET_RISCV64
} else if (regid >= UC_RISCV_REG_F0 &&
regid <= UC_RISCV_REG_F31) { // "ft0".."ft31"
CHECK_REG_TYPE(uint64_t);
env->fpr[regid - UC_RISCV_REG_F0] = *(uint64_t *)value;
#else
env->fpr[regid - UC_RISCV_REG_F0] = *(uint32_t *)value;
#endif
break;
case UC_RISCV_REG_USTATUS:
case UC_RISCV_REG_UIE:
case UC_RISCV_REG_UTVEC:
case UC_RISCV_REG_USCRATCH:
case UC_RISCV_REG_UEPC:
case UC_RISCV_REG_UCAUSE:
case UC_RISCV_REG_UTVAL:
case UC_RISCV_REG_UIP:
case UC_RISCV_REG_FFLAGS:
case UC_RISCV_REG_FRM:
case UC_RISCV_REG_FCSR:
case UC_RISCV_REG_CYCLE:
case UC_RISCV_REG_TIME:
case UC_RISCV_REG_INSTRET:
case UC_RISCV_REG_HPMCOUNTER3:
case UC_RISCV_REG_HPMCOUNTER4:
case UC_RISCV_REG_HPMCOUNTER5:
case UC_RISCV_REG_HPMCOUNTER6:
case UC_RISCV_REG_HPMCOUNTER7:
case UC_RISCV_REG_HPMCOUNTER8:
case UC_RISCV_REG_HPMCOUNTER9:
case UC_RISCV_REG_HPMCOUNTER10:
case UC_RISCV_REG_HPMCOUNTER11:
case UC_RISCV_REG_HPMCOUNTER12:
case UC_RISCV_REG_HPMCOUNTER13:
case UC_RISCV_REG_HPMCOUNTER14:
case UC_RISCV_REG_HPMCOUNTER15:
case UC_RISCV_REG_HPMCOUNTER16:
case UC_RISCV_REG_HPMCOUNTER17:
case UC_RISCV_REG_HPMCOUNTER18:
case UC_RISCV_REG_HPMCOUNTER19:
case UC_RISCV_REG_HPMCOUNTER20:
case UC_RISCV_REG_HPMCOUNTER21:
case UC_RISCV_REG_HPMCOUNTER22:
case UC_RISCV_REG_HPMCOUNTER23:
case UC_RISCV_REG_HPMCOUNTER24:
case UC_RISCV_REG_HPMCOUNTER25:
case UC_RISCV_REG_HPMCOUNTER26:
case UC_RISCV_REG_HPMCOUNTER27:
case UC_RISCV_REG_HPMCOUNTER28:
case UC_RISCV_REG_HPMCOUNTER29:
case UC_RISCV_REG_HPMCOUNTER30:
case UC_RISCV_REG_HPMCOUNTER31:
case UC_RISCV_REG_CYCLEH:
case UC_RISCV_REG_TIMEH:
case UC_RISCV_REG_INSTRETH:
case UC_RISCV_REG_HPMCOUNTER3H:
case UC_RISCV_REG_HPMCOUNTER4H:
case UC_RISCV_REG_HPMCOUNTER5H:
case UC_RISCV_REG_HPMCOUNTER6H:
case UC_RISCV_REG_HPMCOUNTER7H:
case UC_RISCV_REG_HPMCOUNTER8H:
case UC_RISCV_REG_HPMCOUNTER9H:
case UC_RISCV_REG_HPMCOUNTER10H:
case UC_RISCV_REG_HPMCOUNTER11H:
case UC_RISCV_REG_HPMCOUNTER12H:
case UC_RISCV_REG_HPMCOUNTER13H:
case UC_RISCV_REG_HPMCOUNTER14H:
case UC_RISCV_REG_HPMCOUNTER15H:
case UC_RISCV_REG_HPMCOUNTER16H:
case UC_RISCV_REG_HPMCOUNTER17H:
case UC_RISCV_REG_HPMCOUNTER18H:
case UC_RISCV_REG_HPMCOUNTER19H:
case UC_RISCV_REG_HPMCOUNTER20H:
case UC_RISCV_REG_HPMCOUNTER21H:
case UC_RISCV_REG_HPMCOUNTER22H:
case UC_RISCV_REG_HPMCOUNTER23H:
case UC_RISCV_REG_HPMCOUNTER24H:
case UC_RISCV_REG_HPMCOUNTER25H:
case UC_RISCV_REG_HPMCOUNTER26H:
case UC_RISCV_REG_HPMCOUNTER27H:
case UC_RISCV_REG_HPMCOUNTER28H:
case UC_RISCV_REG_HPMCOUNTER29H:
case UC_RISCV_REG_HPMCOUNTER30H:
case UC_RISCV_REG_HPMCOUNTER31H:
case UC_RISCV_REG_MCYCLE:
case UC_RISCV_REG_MINSTRET:
case UC_RISCV_REG_MCYCLEH:
case UC_RISCV_REG_MINSTRETH:
case UC_RISCV_REG_MVENDORID:
case UC_RISCV_REG_MARCHID:
case UC_RISCV_REG_MIMPID:
case UC_RISCV_REG_MHARTID:
case UC_RISCV_REG_MSTATUS:
case UC_RISCV_REG_MISA:
case UC_RISCV_REG_MEDELEG:
case UC_RISCV_REG_MIDELEG:
case UC_RISCV_REG_MIE:
case UC_RISCV_REG_MTVEC:
case UC_RISCV_REG_MCOUNTEREN:
case UC_RISCV_REG_MSTATUSH:
case UC_RISCV_REG_MUCOUNTEREN:
case UC_RISCV_REG_MSCOUNTEREN:
case UC_RISCV_REG_MHCOUNTEREN:
case UC_RISCV_REG_MSCRATCH:
case UC_RISCV_REG_MEPC:
case UC_RISCV_REG_MCAUSE:
case UC_RISCV_REG_MTVAL:
case UC_RISCV_REG_MIP:
case UC_RISCV_REG_MBADADDR:
case UC_RISCV_REG_SSTATUS:
case UC_RISCV_REG_SEDELEG:
case UC_RISCV_REG_SIDELEG:
case UC_RISCV_REG_SIE:
case UC_RISCV_REG_STVEC:
case UC_RISCV_REG_SCOUNTEREN:
case UC_RISCV_REG_SSCRATCH:
case UC_RISCV_REG_SEPC:
case UC_RISCV_REG_SCAUSE:
case UC_RISCV_REG_STVAL:
case UC_RISCV_REG_SIP:
case UC_RISCV_REG_SBADADDR:
case UC_RISCV_REG_SPTBR:
case UC_RISCV_REG_SATP:
case UC_RISCV_REG_HSTATUS:
case UC_RISCV_REG_HEDELEG:
case UC_RISCV_REG_HIDELEG:
case UC_RISCV_REG_HIE:
case UC_RISCV_REG_HCOUNTEREN:
case UC_RISCV_REG_HTVAL:
case UC_RISCV_REG_HIP:
case UC_RISCV_REG_HTINST:
case UC_RISCV_REG_HGATP:
case UC_RISCV_REG_HTIMEDELTA:
case UC_RISCV_REG_HTIMEDELTAH: {
} else if (regid >= UC_RISCV_REG_USTATUS &&
regid < UC_RISCV_REG_USTATUS + csrno_count) {
target_ulong val;
int csrno = csrno_map[regid - UC_RISCV_REG_USTATUS];
#ifdef TARGET_RISCV64
CHECK_REG_TYPE(uint64_t);
riscv_csrrw(env, csrno, &val, *(uint64_t *)value, -1);
#else
CHECK_REG_TYPE(uint32_t);
riscv_csrrw(env, csrno, &val, *(uint32_t *)value, -1);
#endif
break;
}
default:
break;
} else {
switch (regid) {
default:
break;
case UC_RISCV_REG_PC:
#ifdef TARGET_RISCV64
CHECK_REG_TYPE(uint64_t);
env->pc = *(uint64_t *)value;
#else
CHECK_REG_TYPE(uint32_t);
env->pc = *(uint32_t *)value;
#endif
break;
}
}
return ret;
}
int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count)
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);
int i;
uc_err err;
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
void *value = vals[i];
reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int 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 i;
uc_err err;
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
const void *value = vals[i];
reg_write(env, regid, value);
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
if (regid == UC_RISCV_REG_PC) {
// force to quit execution and flush TB
uc->quit_request = true;
@@ -564,51 +214,59 @@ int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
}
}
return 0;
return UC_ERR_OK;
}
DEFAULT_VISIBILITY
#ifdef TARGET_RISCV32
int riscv32_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
void *const *vals, size_t *sizes, int count)
#else
/* TARGET_RISCV64 */
int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
void *const *vals, size_t *sizes, int count)
#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];
reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
DEFAULT_VISIBILITY
#ifdef TARGET_RISCV32
int riscv32_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
const void *const *vals, size_t *sizes, int count)
#else
/* TARGET_RISCV64 */
int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
const void *const *vals, size_t *sizes, int count)
#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];
reg_write(env, regid, value);
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
static bool riscv_stop_interrupt(struct uc_struct *uc, int intno)

View File

@@ -6,19 +6,21 @@
#define UC_QEMU_TARGET_RISCV_H
// functions to read & write registers
int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count);
int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count);
int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
size_t *sizes, int count);
int riscv_reg_write(struct uc_struct *uc, unsigned int *regs,
const void *const *vals, size_t *sizes, int count);
int riscv32_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
void *const *vals, size_t *sizes, int count);
int riscv32_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes,
int count);
int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
void *const *vals, size_t *sizes, int count);
int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes,
int count);
void riscv_reg_reset(struct uc_struct *uc);

View File

@@ -53,80 +53,99 @@ void s390_reg_reset(struct uc_struct *uc)
env->psw.addr = 0;
}
static void reg_read(CPUS390XState *env, unsigned int regid, void *value)
static uc_err reg_read(CPUS390XState *env, unsigned int regid, void *value,
size_t *size)
{
uc_err ret = UC_ERR_ARG;
if (regid >= UC_S390X_REG_R0 && regid <= UC_S390X_REG_R15) {
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->regs[regid - UC_S390X_REG_R0];
return;
}
if (regid >= UC_S390X_REG_A0 && regid <= UC_S390X_REG_A15) {
} else if (regid >= UC_S390X_REG_A0 && regid <= UC_S390X_REG_A15) {
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->regs[regid - UC_S390X_REG_A0];
return;
} else {
switch (regid) {
default:
break;
case UC_S390X_REG_PC:
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->psw.addr;
break;
case UC_S390X_REG_PSWM:
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = get_psw_mask(env);
break;
}
}
switch (regid) {
default:
break;
case UC_S390X_REG_PC:
*(uint64_t *)value = env->psw.addr;
break;
case UC_S390X_REG_PSWM:
*(uint64_t *)value = get_psw_mask(env);
break;
}
return ret;
}
static void reg_write(CPUS390XState *env, unsigned int regid, const void *value)
static uc_err reg_write(CPUS390XState *env, unsigned int regid,
const void *value, size_t *size)
{
uc_err ret = UC_ERR_ARG;
if (regid >= UC_S390X_REG_R0 && regid <= UC_S390X_REG_R15) {
CHECK_REG_TYPE(uint64_t);
env->regs[regid - UC_S390X_REG_R0] = *(uint64_t *)value;
return;
}
if (regid >= UC_S390X_REG_A0 && regid <= UC_S390X_REG_A15) {
} else if (regid >= UC_S390X_REG_A0 && regid <= UC_S390X_REG_A15) {
CHECK_REG_TYPE(uint32_t);
env->regs[regid - UC_S390X_REG_A0] = *(uint32_t *)value;
return;
}
switch (regid) {
default:
break;
case UC_S390X_REG_PC:
env->psw.addr = *(uint64_t *)value;
break;
case UC_S390X_REG_PSWM:
env->psw.mask = *(uint64_t *)value;
env->cc_op = (env->psw.mask >> 44) & 3;
break;
} else {
switch (regid) {
default:
break;
case UC_S390X_REG_PC:
CHECK_REG_TYPE(uint64_t);
env->psw.addr = *(uint64_t *)value;
break;
case UC_S390X_REG_PSWM:
CHECK_REG_TYPE(uint64_t);
env->psw.mask = *(uint64_t *)value;
env->cc_op = (env->psw.mask >> 44) & 3;
break;
}
}
return ret;
}
static int s390_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count)
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);
int i;
uc_err err;
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
void *value = vals[i];
reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
static int s390_reg_write(struct uc_struct *uc, unsigned int *regs,
void *const *vals, int 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];
reg_write(env, regid, value);
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;
@@ -134,39 +153,47 @@ static int s390_reg_write(struct uc_struct *uc, unsigned int *regs,
}
}
return 0;
return UC_ERR_OK;
}
DEFAULT_VISIBILITY
int s390_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
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];
reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
DEFAULT_VISIBILITY
int s390_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
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];
reg_write(env, regid, value);
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
static int s390_cpus_init(struct uc_struct *uc, const char *cpu_model)

View File

@@ -5,13 +5,14 @@
#define UC_QEMU_TARGET_S390X_H
// functions to read & write registers
// int s390_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int
// count); int s390_reg_write(struct uc_struct *uc, unsigned int *regs, void
// *const *vals, int count);
int s390_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
size_t *sizes, int count);
int s390_reg_write(struct uc_struct *uc, unsigned int *regs,
const void *const *vals, size_t *sizes, int count);
int s390_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
void *const *vals, size_t *sizes, int count);
int s390_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes, int count);
void s390_reg_reset(struct uc_struct *uc);

View File

@@ -61,119 +61,149 @@ void sparc_reg_reset(struct uc_struct *uc)
env->regwptr = env->regbase;
}
static void reg_read(CPUSPARCState *env, unsigned int regid, void *value)
static uc_err reg_read(CPUSPARCState *env, unsigned int regid, void *value,
size_t *size)
{
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
*(int32_t *)value = env->gregs[regid - UC_SPARC_REG_G0];
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
*(int32_t *)value = env->regwptr[regid - UC_SPARC_REG_O0];
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
*(int32_t *)value = env->regwptr[8 + regid - UC_SPARC_REG_L0];
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
*(int32_t *)value = env->regwptr[16 + regid - UC_SPARC_REG_I0];
else {
uc_err ret = UC_ERR_ARG;
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7) {
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->gregs[regid - UC_SPARC_REG_G0];
} else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) {
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->regwptr[regid - UC_SPARC_REG_O0];
} else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) {
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->regwptr[8 + regid - UC_SPARC_REG_L0];
} else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) {
*(uint32_t *)value = env->regwptr[16 + regid - UC_SPARC_REG_I0];
} else {
switch (regid) {
default:
break;
case UC_SPARC_REG_PC:
*(int32_t *)value = env->pc;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->pc;
break;
}
}
return;
return ret;
}
static void reg_write(CPUSPARCState *env, unsigned int regid, const void *value)
static uc_err reg_write(CPUSPARCState *env, unsigned int regid,
const void *value, size_t *size)
{
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
uc_err ret = UC_ERR_ARG;
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7) {
CHECK_REG_TYPE(uint32_t);
env->gregs[regid - UC_SPARC_REG_G0] = *(uint32_t *)value;
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
} else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) {
CHECK_REG_TYPE(uint32_t);
env->regwptr[regid - UC_SPARC_REG_O0] = *(uint32_t *)value;
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
} else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) {
CHECK_REG_TYPE(uint32_t);
env->regwptr[8 + regid - UC_SPARC_REG_L0] = *(uint32_t *)value;
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
} else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) {
CHECK_REG_TYPE(uint32_t);
env->regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint32_t *)value;
else {
} else {
switch (regid) {
default:
break;
case UC_SPARC_REG_PC:
CHECK_REG_TYPE(uint32_t);
env->pc = *(uint32_t *)value;
env->npc = *(uint32_t *)value + 4;
break;
}
}
return;
return ret;
}
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count)
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);
int i;
uc_err err;
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
void *value = vals[i];
reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int 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 i;
uc_err err;
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
const void *value = vals[i];
reg_write(env, regid, value);
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
if (regid == UC_SPARC_REG_PC) {
// force to quit execution and flush TB
uc->quit_request = true;
uc_emu_stop(uc);
break;
break_translation_loop(uc);
}
}
return 0;
return UC_ERR_OK;
}
DEFAULT_VISIBILITY
int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count)
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];
reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
DEFAULT_VISIBILITY
int sparc_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count)
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];
reg_write(env, regid, value);
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
static int sparc_cpus_init(struct uc_struct *uc, const char *cpu_model)

View File

@@ -5,19 +5,20 @@
#define UC_QEMU_TARGET_SPARC_H
// functions to read & write registers
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count);
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count);
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
size_t *sizes, int count);
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs,
const void *const *vals, size_t *sizes, int count);
int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
void *const *vals, size_t *sizes, int count);
int sparc_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes, int count);
int sparc64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
void **vals, int count);
void *const *vals, size_t *sizes, int count);
int sparc64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes,
int count);
void sparc_reg_reset(struct uc_struct *uc);

View File

@@ -83,103 +83,144 @@ void sparc_reg_reset(struct uc_struct *uc)
env->regwptr = env->regbase;
}
static void reg_read(CPUSPARCState *env, unsigned int regid, void *value)
static uc_err reg_read(CPUSPARCState *env, unsigned int regid, void *value, size_t *size)
{
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
*(int64_t *)value = env->gregs[regid - UC_SPARC_REG_G0];
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
*(int64_t *)value = env->regwptr[regid - UC_SPARC_REG_O0];
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
*(int64_t *)value = env->regwptr[8 + regid - UC_SPARC_REG_L0];
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
*(int64_t *)value = env->regwptr[16 + regid - UC_SPARC_REG_I0];
else {
uc_err ret = UC_ERR_ARG;
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7) {
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->gregs[regid - UC_SPARC_REG_G0];
} else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) {
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->regwptr[regid - UC_SPARC_REG_O0];
} else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) {
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->regwptr[8 + regid - UC_SPARC_REG_L0];
} else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) {
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->regwptr[16 + regid - UC_SPARC_REG_I0];
} else {
switch(regid) {
default: break;
case UC_SPARC_REG_PC:
*(int64_t *)value = env->pc;
break;
default:
break;
case UC_SPARC_REG_PC:
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->pc;
break;
}
}
return ret;
}
static void reg_write(CPUSPARCState *env, unsigned int regid, const void *value)
static uc_err reg_write(CPUSPARCState *env, unsigned int regid, const void *value, size_t *size)
{
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
uc_err ret = UC_ERR_ARG;
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7) {
CHECK_REG_TYPE(uint64_t);
env->gregs[regid - UC_SPARC_REG_G0] = *(uint64_t *)value;
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
} else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) {
CHECK_REG_TYPE(uint64_t);
env->regwptr[regid - UC_SPARC_REG_O0] = *(uint64_t *)value;
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
} else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) {
CHECK_REG_TYPE(uint64_t);
env->regwptr[8 + regid - UC_SPARC_REG_L0] = *(uint64_t *)value;
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
} else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) {
CHECK_REG_TYPE(uint64_t);
env->regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint64_t *)value;
else {
} else {
switch(regid) {
default: break;
case UC_SPARC_REG_PC:
env->pc = *(uint64_t *)value;
env->npc = *(uint64_t *)value + 4;
break;
default:
break;
case UC_SPARC_REG_PC:
CHECK_REG_TYPE(uint64_t);
env->pc = *(uint64_t *)value;
env->npc = *(uint64_t *)value + 4;
break;
}
}
return ret;
}
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count)
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);
int i;
uc_err err;
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
void *value = vals[i];
reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, int 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 i;
uc_err err;
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
const void *value = vals[i];
reg_write(env, regid, value);
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
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 0;
return UC_ERR_OK;
}
DEFAULT_VISIBILITY
int sparc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, 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;
int i;
uc_err err;
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
void *value = vals[i];
reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
DEFAULT_VISIBILITY
int sparc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, 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;
int i;
uc_err err;
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
const void *value = vals[i];
reg_write(env, regid, value);
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
static int sparc_cpus_init(struct uc_struct *uc, const char *cpu_model)

View File

@@ -39,193 +39,258 @@ void tricore_reg_reset(struct uc_struct *uc)
env->PC = 0;
}
static void reg_read(CPUTriCoreState *env, unsigned int regid, void *value)
static uc_err reg_read(CPUTriCoreState *env, unsigned int regid, void *value,
size_t *size)
{
if (regid >= UC_TRICORE_REG_A0 && regid <= UC_TRICORE_REG_A9)
*(int32_t *)value = env->gpr_a[regid - UC_TRICORE_REG_A0];
if (regid >= UC_TRICORE_REG_A12 && regid <= UC_TRICORE_REG_A15)
*(int32_t *)value = env->gpr_a[regid - UC_TRICORE_REG_A0];
else if (regid >= UC_TRICORE_REG_D0 && regid <= UC_TRICORE_REG_D15)
*(int32_t *)value = env->gpr_d[regid - UC_TRICORE_REG_D0];
else {
uc_err ret = UC_ERR_ARG;
if (regid >= UC_TRICORE_REG_A0 && regid <= UC_TRICORE_REG_A9) {
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->gpr_a[regid - UC_TRICORE_REG_A0];
} else if (regid >= UC_TRICORE_REG_A12 && regid <= UC_TRICORE_REG_A15) {
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->gpr_a[regid - UC_TRICORE_REG_A0];
} else if (regid >= UC_TRICORE_REG_D0 && regid <= UC_TRICORE_REG_D15) {
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->gpr_d[regid - UC_TRICORE_REG_D0];
} else {
switch (regid) {
// case UC_TRICORE_REG_SP:
case UC_TRICORE_REG_A10:
*(int32_t *)value = env->gpr_a[10];
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->gpr_a[10];
break;
// case UC_TRICORE_REG_LR:
case UC_TRICORE_REG_A11:
*(int32_t *)value = env->gpr_a[11];
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->gpr_a[11];
break;
case UC_TRICORE_REG_PC:
*(int32_t *)value = env->PC;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->PC;
break;
case UC_TRICORE_REG_PCXI:
*(int32_t *)value = env->PCXI;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->PCXI;
break;
case UC_TRICORE_REG_PSW:
*(int32_t *)value = env->PSW;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->PSW;
break;
case UC_TRICORE_REG_PSW_USB_C:
*(int32_t *)value = env->PSW_USB_C;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->PSW_USB_C;
break;
case UC_TRICORE_REG_PSW_USB_V:
*(int32_t *)value = env->PSW_USB_V;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->PSW_USB_V;
break;
case UC_TRICORE_REG_PSW_USB_SV:
*(int32_t *)value = env->PSW_USB_SV;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->PSW_USB_SV;
break;
case UC_TRICORE_REG_PSW_USB_AV:
*(int32_t *)value = env->PSW_USB_AV;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->PSW_USB_AV;
break;
case UC_TRICORE_REG_PSW_USB_SAV:
*(int32_t *)value = env->PSW_USB_SAV;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->PSW_USB_SAV;
break;
case UC_TRICORE_REG_SYSCON:
*(int32_t *)value = env->SYSCON;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->SYSCON;
break;
case UC_TRICORE_REG_CPU_ID:
*(int32_t *)value = env->CPU_ID;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->CPU_ID;
break;
case UC_TRICORE_REG_BIV:
*(int32_t *)value = env->BIV;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->BIV;
break;
case UC_TRICORE_REG_BTV:
*(int32_t *)value = env->BTV;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->BTV;
break;
case UC_TRICORE_REG_ISP:
*(int32_t *)value = env->ISP;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->ISP;
break;
case UC_TRICORE_REG_ICR:
*(int32_t *)value = env->ICR;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->ICR;
break;
case UC_TRICORE_REG_FCX:
*(int32_t *)value = env->FCX;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->FCX;
break;
case UC_TRICORE_REG_LCX:
*(int32_t *)value = env->LCX;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->LCX;
break;
case UC_TRICORE_REG_COMPAT:
*(int32_t *)value = env->COMPAT;
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->COMPAT;
break;
}
}
return ret;
}
int tricore_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count)
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];
reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
int tricore_context_reg_read(struct uc_context *uc, unsigned int *regs,
void **vals, int count)
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];
reg_read(env, regid, value);
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
static void reg_write(CPUTriCoreState *env, unsigned int regid,
const void *value)
static uc_err reg_write(CPUTriCoreState *env, unsigned int regid,
const void *value, size_t *size)
{
if (regid >= UC_TRICORE_REG_A0 && regid <= UC_TRICORE_REG_A9)
env->gpr_a[regid - UC_TRICORE_REG_A0] = *(int32_t *)value;
if (regid >= UC_TRICORE_REG_A12 && regid <= UC_TRICORE_REG_A15)
env->gpr_a[regid - UC_TRICORE_REG_A0] = *(int32_t *)value;
else if (regid >= UC_TRICORE_REG_D0 && regid <= UC_TRICORE_REG_D15)
env->gpr_d[regid - UC_TRICORE_REG_D0] = *(int32_t *)value;
else {
uc_err ret = UC_ERR_ARG;
if (regid >= UC_TRICORE_REG_A0 && regid <= UC_TRICORE_REG_A9) {
CHECK_REG_TYPE(uint32_t);
env->gpr_a[regid - UC_TRICORE_REG_A0] = *(uint32_t *)value;
} else if (regid >= UC_TRICORE_REG_A12 && regid <= UC_TRICORE_REG_A15) {
CHECK_REG_TYPE(uint32_t);
env->gpr_a[regid - UC_TRICORE_REG_A0] = *(uint32_t *)value;
} else if (regid >= UC_TRICORE_REG_D0 && regid <= UC_TRICORE_REG_D15) {
CHECK_REG_TYPE(uint32_t);
env->gpr_d[regid - UC_TRICORE_REG_D0] = *(uint32_t *)value;
} else {
switch (regid) {
// case UC_TRICORE_REG_SP:
case UC_TRICORE_REG_A10:
env->gpr_a[10] = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->gpr_a[10] = *(uint32_t *)value;
break;
// case UC_TRICORE_REG_LR:
case UC_TRICORE_REG_A11:
env->gpr_a[11] = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->gpr_a[11] = *(uint32_t *)value;
break;
case UC_TRICORE_REG_PC:
env->PC = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->PC = *(uint32_t *)value;
break;
case UC_TRICORE_REG_PCXI:
env->PCXI = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->PCXI = *(uint32_t *)value;
break;
case UC_TRICORE_REG_PSW:
env->PSW = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->PSW = *(uint32_t *)value;
break;
case UC_TRICORE_REG_PSW_USB_C:
env->PSW_USB_C = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->PSW_USB_C = *(uint32_t *)value;
break;
case UC_TRICORE_REG_PSW_USB_V:
env->PSW_USB_V = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->PSW_USB_V = *(uint32_t *)value;
break;
case UC_TRICORE_REG_PSW_USB_SV:
env->PSW_USB_SV = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->PSW_USB_SV = *(uint32_t *)value;
break;
case UC_TRICORE_REG_PSW_USB_AV:
env->PSW_USB_AV = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->PSW_USB_AV = *(uint32_t *)value;
break;
case UC_TRICORE_REG_PSW_USB_SAV:
env->PSW_USB_SAV = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->PSW_USB_SAV = *(uint32_t *)value;
break;
case UC_TRICORE_REG_SYSCON:
env->SYSCON = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->SYSCON = *(uint32_t *)value;
break;
case UC_TRICORE_REG_CPU_ID:
env->CPU_ID = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->CPU_ID = *(uint32_t *)value;
break;
case UC_TRICORE_REG_BIV:
env->BIV = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->BIV = *(uint32_t *)value;
break;
case UC_TRICORE_REG_BTV:
env->BTV = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->BTV = *(uint32_t *)value;
break;
case UC_TRICORE_REG_ISP:
env->ISP = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->ISP = *(uint32_t *)value;
break;
case UC_TRICORE_REG_ICR:
env->ICR = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->ICR = *(uint32_t *)value;
break;
case UC_TRICORE_REG_FCX:
env->FCX = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->FCX = *(uint32_t *)value;
break;
case UC_TRICORE_REG_LCX:
env->LCX = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->LCX = *(uint32_t *)value;
break;
case UC_TRICORE_REG_COMPAT:
env->COMPAT = *(int32_t *)value;
CHECK_REG_TYPE(uint32_t);
env->COMPAT = *(uint32_t *)value;
break;
}
}
return ret;
}
int tricore_reg_write(struct uc_struct *uc, unsigned int *regs,
void *const *vals, int count)
const 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];
reg_write(env, regid, value);
const void *value = vals[i];
err = reg_write(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;
@@ -233,22 +298,26 @@ int tricore_reg_write(struct uc_struct *uc, unsigned int *regs,
}
}
return 0;
return UC_ERR_OK;
}
int tricore_context_reg_write(struct uc_context *uc, unsigned int *regs,
void *const *vals, int count)
const 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];
const void *value = vals[i];
reg_write(env, regid, value);
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) {
return err;
}
}
return 0;
return UC_ERR_OK;
}
static int tricore_cpus_init(struct uc_struct *uc, const char *cpu_model)

View File

@@ -10,15 +10,16 @@
#define UC_QEMU_TARGET_TRICORE_H
// functions to read & write registers
int tricore_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
int count);
int tricore_reg_read(struct uc_struct *uc, unsigned int *regs,
void *const *vals, size_t *sizes, int count);
int tricore_reg_write(struct uc_struct *uc, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes, int count);
int tricore_context_reg_read(struct uc_context *uc, unsigned int *regs,
void **vals, int count);
void *const *vals, size_t *sizes, int count);
int tricore_context_reg_write(struct uc_context *uc, unsigned int *regs,
void *const *vals, int count);
const void *const *vals, size_t *sizes,
int count);
void tricore_reg_reset(struct uc_struct *uc);

View File

@@ -128,4 +128,15 @@ static inline void uc_common_init(struct uc_struct* uc)
if (!uc->release)
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; \
} while(0)
#endif

108
uc.c
View File

@@ -507,47 +507,63 @@ uc_err uc_close(uc_engine *uc)
UNICORN_EXPORT
uc_err uc_reg_read_batch(uc_engine *uc, int *ids, void **vals, int count)
{
int ret = UC_ERR_OK;
UC_INIT(uc);
if (uc->reg_read) {
ret = uc->reg_read(uc, (unsigned int *)ids, vals, count);
} else {
return UC_ERR_HANDLE;
}
return ret;
return uc_reg_read_batch2(uc, ids, vals, NULL, count);
}
UNICORN_EXPORT
uc_err uc_reg_write_batch(uc_engine *uc, int *ids, void *const *vals, int count)
{
int ret = UC_ERR_OK;
return uc_reg_write_batch2(uc, ids, (const void *const *)vals, NULL, count);
}
UNICORN_EXPORT
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_write) {
ret = uc->reg_write(uc, (unsigned int *)ids, vals, count);
if (uc->reg_read) {
return uc->reg_read(uc, (unsigned int *)ids, vals, sizes, count);
} else {
return UC_ERR_HANDLE;
}
}
return ret;
UNICORN_EXPORT
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;
}
}
UNICORN_EXPORT
uc_err uc_reg_read(uc_engine *uc, int regid, void *value)
{
UC_INIT(uc);
return uc_reg_read_batch(uc, &regid, &value, 1);
return uc_reg_read_batch2(uc, &regid, &value, NULL, 1);
}
UNICORN_EXPORT
uc_err uc_reg_write(uc_engine *uc, int regid, const void *value)
{
UC_INIT(uc);
return uc_reg_write_batch(uc, &regid, (void *const *)&value, 1);
return uc_reg_write_batch2(uc, &regid, &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, &regid, &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, &regid, &value, size, 1);
}
// check if a memory area is mapped
@@ -1869,13 +1885,42 @@ uc_err uc_context_save(uc_engine *uc, uc_context *context)
UNICORN_EXPORT
uc_err uc_context_reg_write(uc_context *ctx, int regid, const void *value)
{
return uc_context_reg_write_batch(ctx, &regid, (void *const *)&value, 1);
return uc_context_reg_write_batch2(ctx, &regid, &value, NULL, 1);
}
UNICORN_EXPORT
uc_err uc_context_reg_read(uc_context *ctx, int regid, void *value)
{
return uc_context_reg_read_batch(ctx, &regid, &value, 1);
return uc_context_reg_read_batch2(ctx, &regid, &value, NULL, 1);
}
UNICORN_EXPORT
uc_err uc_context_reg_write2(uc_context *ctx, int regid, const void *value,
size_t *size)
{
return uc_context_reg_write_batch2(ctx, &regid, &value, size, 1);
}
UNICORN_EXPORT
uc_err uc_context_reg_read2(uc_context *ctx, int regid, void *value,
size_t *size)
{
return uc_context_reg_read_batch2(ctx, &regid, &value, size, 1);
}
UNICORN_EXPORT
uc_err uc_context_reg_write_batch(uc_context *ctx, int *ids, void *const *vals,
int count)
{
return uc_context_reg_write_batch2(ctx, ids, (const void *const *)vals,
NULL, count);
}
UNICORN_EXPORT
uc_err uc_context_reg_read_batch(uc_context *ctx, int *ids, void **vals,
int count)
{
return uc_context_reg_read_batch2(ctx, ids, vals, NULL, count);
}
// Keep in mind that we don't a uc_engine when r/w the registers of a context.
@@ -1997,37 +2042,34 @@ static void find_context_reg_rw_function(uc_arch arch, uc_mode mode,
}
UNICORN_EXPORT
uc_err uc_context_reg_write_batch(uc_context *ctx, int *ids, void *const *vals,
int count)
uc_err uc_context_reg_write_batch2(uc_context *ctx, int *ids,
const void *const *vals, size_t *sizes,
int count)
{
int ret = UC_ERR_OK;
context_reg_rw_t rw;
find_context_reg_rw_function(ctx->arch, ctx->mode, &rw);
if (rw.context_reg_write) {
ret = rw.context_reg_write(ctx, (unsigned int *)ids, vals, count);
return rw.context_reg_write(ctx, (unsigned int *)ids, vals, sizes,
count);
} else {
return UC_ERR_HANDLE;
}
return ret;
}
UNICORN_EXPORT
uc_err uc_context_reg_read_batch(uc_context *ctx, int *ids, void **vals,
int count)
uc_err uc_context_reg_read_batch2(uc_context *ctx, int *ids, void *const *vals,
size_t *sizes, int count)
{
int ret = UC_ERR_OK;
context_reg_rw_t rw;
find_context_reg_rw_function(ctx->arch, ctx->mode, &rw);
if (rw.context_reg_read) {
ret = rw.context_reg_read(ctx, (unsigned int *)ids, vals, count);
return rw.context_reg_read(ctx, (unsigned int *)ids, vals, sizes,
count);
} else {
return UC_ERR_HANDLE;
}
return ret;
}
UNICORN_EXPORT