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); size_t *result);
// return 0 on success, -1 on failure // return 0 on success, -1 on failure
typedef int (*reg_read_t)(struct uc_struct *uc, unsigned int *regs, void **vals, typedef int (*reg_read_t)(struct uc_struct *uc, unsigned int *regs,
int count); void *const *vals, size_t *sizes, int count);
typedef int (*reg_write_t)(struct uc_struct *uc, unsigned int *regs, 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, 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, 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 { typedef struct {
context_reg_read_t context_reg_read; context_reg_read_t context_reg_read;
context_reg_write_t context_reg_write; 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() @uc: handle returned by uc_open()
@regid: register ID that is to be modified. @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 @return UC_ERR_OK on success; UC_ERR_ARG if register number or value is invalid
for detailed error).
*/ */
UNICORN_EXPORT UNICORN_EXPORT
uc_err uc_reg_write(uc_engine *uc, int regid, const void *value); uc_err uc_reg_write(uc_engine *uc, int regid, const void *value);
@@ -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. @regid: register ID that is to be retrieved.
@value: pointer to a variable storing the register value. @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 @return UC_ERR_OK on success; UC_ERR_ARG if register number or value is invalid
for detailed error).
*/ */
UNICORN_EXPORT UNICORN_EXPORT
uc_err uc_reg_read(uc_engine *uc, int regid, void *value); uc_err uc_reg_read(uc_engine *uc, int regid, void *value);
/*
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. Write multiple register values.
@uc: handle returned by uc_open() @uc: handle returned by uc_open()
@rges: array of register IDs to store @regs: array of register IDs to store
@value: pointer to array of register values @vals: array of pointers to register values
@count: length of both *regs and *vals @count: length of both *regs and *vals
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum @return UC_ERR_OK on success; UC_ERR_ARG if some register number or value is
for detailed error). invalid
*/ */
UNICORN_EXPORT UNICORN_EXPORT
uc_err uc_reg_write_batch(uc_engine *uc, int *regs, void *const *vals, 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. Read multiple register values.
@uc: handle returned by uc_open() @uc: handle returned by uc_open()
@rges: array of register IDs to retrieve @regs: array of register IDs to retrieve
@value: pointer to array of values to hold registers @vals: array of pointers to register values
@count: length of both *regs and *vals @count: length of both *regs and *vals
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum @return UC_ERR_OK on success; UC_ERR_ARG if some register number or value is
for detailed error). invalid
*/ */
UNICORN_EXPORT UNICORN_EXPORT
uc_err uc_reg_read_batch(uc_engine *uc, int *regs, void **vals, int count); 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. 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() @ctx: handle returned by uc_context_alloc()
@regid: register ID that is to be modified. @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 @return UC_ERR_OK on success; UC_ERR_ARG if register number or value is invalid
for detailed error).
*/ */
UNICORN_EXPORT UNICORN_EXPORT
uc_err uc_context_reg_write(uc_context *ctx, int regid, const void *value); 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. @regid: register ID that is to be retrieved.
@value: pointer to a variable storing the register value. @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 @return UC_ERR_OK on success; UC_ERR_ARG if register number or value is invalid
for detailed error).
*/ */
UNICORN_EXPORT UNICORN_EXPORT
uc_err uc_context_reg_read(uc_context *ctx, int regid, void *value); 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. 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, uc_err uc_context_reg_read_batch(uc_context *ctx, int *regs, void **vals,
int count); 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. Restore the current CPU context from a saved copy.
This API should be used to roll the CPU context back to a previous 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 #define UC_QEMU_TARGET_ARM_H
// functions to read & write registers // functions to read & write registers
int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count); size_t *sizes, int count);
int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int arm_reg_write(struct uc_struct *uc, unsigned int *regs,
int count); const void *const *vals, size_t *sizes, int count);
int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count); size_t *sizes, int count);
int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int arm64_reg_write(struct uc_struct *uc, unsigned int *regs,
int count); const void *const *vals, size_t *sizes, int count);
int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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, 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, 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, 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 arm_reg_reset(struct uc_struct *uc);
void arm64_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; 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) { if (regid >= UC_ARM64_REG_V0 && regid <= UC_ARM64_REG_V31) {
regid += UC_ARM64_REG_Q0 - UC_ARM64_REG_V0; regid += UC_ARM64_REG_Q0 - UC_ARM64_REG_V0;
} }
if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28) { 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) { } 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 } else if (regid >= UC_ARM64_REG_Q0 && regid <= UC_ARM64_REG_Q31) { // FIXME
CHECK_REG_TYPE(float64[2]);
float64 *dst = (float64 *)value; float64 *dst = (float64 *)value;
uint32_t reg_index = regid - UC_ARM64_REG_Q0; uint32_t reg_index = regid - UC_ARM64_REG_Q0;
dst[0] = env->vfp.zregs[reg_index].d[0]; dst[0] = env->vfp.zregs[reg_index].d[0];
dst[1] = env->vfp.zregs[reg_index].d[1]; dst[1] = env->vfp.zregs[reg_index].d[1];
} else if (regid >= UC_ARM64_REG_D0 && regid <= UC_ARM64_REG_D31) { } 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]; *(float64 *)value = env->vfp.zregs[regid - UC_ARM64_REG_D0].d[0];
} else if (regid >= UC_ARM64_REG_S0 && regid <= UC_ARM64_REG_S31) { } else if (regid >= UC_ARM64_REG_S0 && regid <= UC_ARM64_REG_S31) {
CHECK_REG_TYPE(int32_t);
*(int32_t *)value = *(int32_t *)value =
READ_DWORD(env->vfp.zregs[regid - UC_ARM64_REG_S0].d[0]); READ_DWORD(env->vfp.zregs[regid - UC_ARM64_REG_S0].d[0]);
} else if (regid >= UC_ARM64_REG_H0 && regid <= UC_ARM64_REG_H31) { } else if (regid >= UC_ARM64_REG_H0 && regid <= UC_ARM64_REG_H31) {
CHECK_REG_TYPE(int16_t);
*(int16_t *)value = *(int16_t *)value =
READ_WORD(env->vfp.zregs[regid - UC_ARM64_REG_H0].d[0]); READ_WORD(env->vfp.zregs[regid - UC_ARM64_REG_H0].d[0]);
} else if (regid >= UC_ARM64_REG_B0 && regid <= UC_ARM64_REG_B31) { } else if (regid >= UC_ARM64_REG_B0 && regid <= UC_ARM64_REG_B31) {
CHECK_REG_TYPE(int8_t);
*(int8_t *)value = *(int8_t *)value =
READ_BYTE_L(env->vfp.zregs[regid - UC_ARM64_REG_B0].d[0]); 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) { } 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]; *(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) { } 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]; *(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) { } 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]; *(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) { } 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]; *(uint64_t *)value = env->cp15.far_el[regid - UC_ARM64_REG_FAR_EL0];
} else if (regid >= UC_ARM64_REG_VBAR_EL0 && } else if (regid >= UC_ARM64_REG_VBAR_EL0 &&
regid <= UC_ARM64_REG_VBAR_EL3) { regid <= UC_ARM64_REG_VBAR_EL3) {
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->cp15.vbar_el[regid - UC_ARM64_REG_VBAR_EL0]; *(uint64_t *)value = env->cp15.vbar_el[regid - UC_ARM64_REG_VBAR_EL0];
} else { } else {
switch (regid) { switch (regid) {
default: default:
break; break;
case UC_ARM64_REG_CPACR_EL1: case UC_ARM64_REG_CPACR_EL1:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->cp15.cpacr_el1; *(uint32_t *)value = env->cp15.cpacr_el1;
break; break;
case UC_ARM64_REG_TPIDR_EL0: 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; break;
case UC_ARM64_REG_TPIDRRO_EL0: 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; break;
case UC_ARM64_REG_TPIDR_EL1: 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; break;
case UC_ARM64_REG_X29: case UC_ARM64_REG_X29:
*(int64_t *)value = env->xregs[29]; CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->xregs[29];
break; break;
case UC_ARM64_REG_X30: case UC_ARM64_REG_X30:
*(int64_t *)value = env->xregs[30]; CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->xregs[30];
break; break;
case UC_ARM64_REG_PC: case UC_ARM64_REG_PC:
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->pc; *(uint64_t *)value = env->pc;
break; break;
case UC_ARM64_REG_SP: case UC_ARM64_REG_SP:
*(int64_t *)value = env->xregs[31]; CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->xregs[31];
break; break;
case UC_ARM64_REG_NZCV: 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; break;
case UC_ARM64_REG_PSTATE: case UC_ARM64_REG_PSTATE:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = pstate_read(env); *(uint32_t *)value = pstate_read(env);
break; break;
case UC_ARM64_REG_TTBR0_EL1: case UC_ARM64_REG_TTBR0_EL1:
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->cp15.ttbr0_el[1]; *(uint64_t *)value = env->cp15.ttbr0_el[1];
break; break;
case UC_ARM64_REG_TTBR1_EL1: case UC_ARM64_REG_TTBR1_EL1:
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->cp15.ttbr1_el[1]; *(uint64_t *)value = env->cp15.ttbr1_el[1];
break; break;
case UC_ARM64_REG_PAR_EL1: case UC_ARM64_REG_PAR_EL1:
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->cp15.par_el[1]; *(uint64_t *)value = env->cp15.par_el[1];
break; break;
case UC_ARM64_REG_MAIR_EL1: case UC_ARM64_REG_MAIR_EL1:
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = env->cp15.mair_el[1]; *(uint64_t *)value = env->cp15.mair_el[1];
break; break;
case UC_ARM64_REG_CP_REG: case UC_ARM64_REG_CP_REG:
CHECK_REG_TYPE(uc_arm64_cp_reg);
ret = read_cp_reg(env, (uc_arm64_cp_reg *)value); ret = read_cp_reg(env, (uc_arm64_cp_reg *)value);
break; break;
case UC_ARM64_REG_FPCR: case UC_ARM64_REG_FPCR:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = vfp_get_fpcr(env); *(uint32_t *)value = vfp_get_fpcr(env);
break; break;
case UC_ARM64_REG_FPSR: case UC_ARM64_REG_FPSR:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = vfp_get_fpsr(env); *(uint32_t *)value = vfp_get_fpsr(env);
break; break;
} }
@@ -237,98 +267,128 @@ static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value)
return ret; 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) { if (regid >= UC_ARM64_REG_V0 && regid <= UC_ARM64_REG_V31) {
regid += UC_ARM64_REG_Q0 - UC_ARM64_REG_V0; regid += UC_ARM64_REG_Q0 - UC_ARM64_REG_V0;
} }
if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28) { 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; env->xregs[regid - UC_ARM64_REG_X0] = *(uint64_t *)value;
} else if (regid >= UC_ARM64_REG_W0 && regid <= UC_ARM64_REG_W30) { } 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); WRITE_DWORD(env->xregs[regid - UC_ARM64_REG_W0], *(uint32_t *)value);
} else if (regid >= UC_ARM64_REG_Q0 && regid <= UC_ARM64_REG_Q31) { } else if (regid >= UC_ARM64_REG_Q0 && regid <= UC_ARM64_REG_Q31) {
CHECK_REG_TYPE(float64[2]);
float64 *src = (float64 *)value; float64 *src = (float64 *)value;
uint32_t reg_index = regid - UC_ARM64_REG_Q0; uint32_t reg_index = regid - UC_ARM64_REG_Q0;
env->vfp.zregs[reg_index].d[0] = src[0]; env->vfp.zregs[reg_index].d[0] = src[0];
env->vfp.zregs[reg_index].d[1] = src[1]; env->vfp.zregs[reg_index].d[1] = src[1];
} else if (regid >= UC_ARM64_REG_D0 && regid <= UC_ARM64_REG_D31) { } 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; env->vfp.zregs[regid - UC_ARM64_REG_D0].d[0] = *(float64 *)value;
} else if (regid >= UC_ARM64_REG_S0 && regid <= UC_ARM64_REG_S31) { } 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], WRITE_DWORD(env->vfp.zregs[regid - UC_ARM64_REG_S0].d[0],
*(int32_t *)value); *(int32_t *)value);
} else if (regid >= UC_ARM64_REG_H0 && regid <= UC_ARM64_REG_H31) { } 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], WRITE_WORD(env->vfp.zregs[regid - UC_ARM64_REG_H0].d[0],
*(int16_t *)value); *(int16_t *)value);
} else if (regid >= UC_ARM64_REG_B0 && regid <= UC_ARM64_REG_B31) { } 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], WRITE_BYTE_L(env->vfp.zregs[regid - UC_ARM64_REG_B0].d[0],
*(int8_t *)value); *(int8_t *)value);
} else if (regid >= UC_ARM64_REG_ELR_EL0 && regid <= UC_ARM64_REG_ELR_EL3) { } 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; 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) { } 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; 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) { } 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; 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) { } 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; env->cp15.far_el[regid - UC_ARM64_REG_FAR_EL0] = *(uint64_t *)value;
} else if (regid >= UC_ARM64_REG_VBAR_EL0 && } else if (regid >= UC_ARM64_REG_VBAR_EL0 &&
regid <= UC_ARM64_REG_VBAR_EL3) { regid <= UC_ARM64_REG_VBAR_EL3) {
CHECK_REG_TYPE(uint64_t);
env->cp15.vbar_el[regid - UC_ARM64_REG_VBAR_EL0] = *(uint64_t *)value; env->cp15.vbar_el[regid - UC_ARM64_REG_VBAR_EL0] = *(uint64_t *)value;
} else { } else {
switch (regid) { switch (regid) {
default: default:
break; break;
case UC_ARM64_REG_CPACR_EL1: case UC_ARM64_REG_CPACR_EL1:
CHECK_REG_TYPE(uint32_t);
env->cp15.cpacr_el1 = *(uint32_t *)value; env->cp15.cpacr_el1 = *(uint32_t *)value;
break; break;
case UC_ARM64_REG_TPIDR_EL0: case UC_ARM64_REG_TPIDR_EL0:
CHECK_REG_TYPE(uint64_t);
env->cp15.tpidr_el[0] = *(uint64_t *)value; env->cp15.tpidr_el[0] = *(uint64_t *)value;
break; break;
case UC_ARM64_REG_TPIDRRO_EL0: case UC_ARM64_REG_TPIDRRO_EL0:
CHECK_REG_TYPE(uint64_t);
env->cp15.tpidrro_el[0] = *(uint64_t *)value; env->cp15.tpidrro_el[0] = *(uint64_t *)value;
break; break;
case UC_ARM64_REG_TPIDR_EL1: case UC_ARM64_REG_TPIDR_EL1:
CHECK_REG_TYPE(uint64_t);
env->cp15.tpidr_el[1] = *(uint64_t *)value; env->cp15.tpidr_el[1] = *(uint64_t *)value;
break; break;
case UC_ARM64_REG_X29: case UC_ARM64_REG_X29:
CHECK_REG_TYPE(uint64_t);
env->xregs[29] = *(uint64_t *)value; env->xregs[29] = *(uint64_t *)value;
break; break;
case UC_ARM64_REG_X30: case UC_ARM64_REG_X30:
CHECK_REG_TYPE(uint64_t);
env->xregs[30] = *(uint64_t *)value; env->xregs[30] = *(uint64_t *)value;
break; break;
case UC_ARM64_REG_PC: case UC_ARM64_REG_PC:
CHECK_REG_TYPE(uint64_t);
env->pc = *(uint64_t *)value; env->pc = *(uint64_t *)value;
break; break;
case UC_ARM64_REG_SP: case UC_ARM64_REG_SP:
CHECK_REG_TYPE(uint64_t);
env->xregs[31] = *(uint64_t *)value; env->xregs[31] = *(uint64_t *)value;
break; break;
case UC_ARM64_REG_NZCV: case UC_ARM64_REG_NZCV:
CHECK_REG_TYPE(uint32_t);
cpsr_write(env, *(uint32_t *)value, CPSR_NZCV, CPSRWriteRaw); cpsr_write(env, *(uint32_t *)value, CPSR_NZCV, CPSRWriteRaw);
break; break;
case UC_ARM64_REG_PSTATE: case UC_ARM64_REG_PSTATE:
CHECK_REG_TYPE(uint32_t);
pstate_write(env, *(uint32_t *)value); pstate_write(env, *(uint32_t *)value);
break; break;
case UC_ARM64_REG_TTBR0_EL1: case UC_ARM64_REG_TTBR0_EL1:
CHECK_REG_TYPE(uint64_t);
env->cp15.ttbr0_el[1] = *(uint64_t *)value; env->cp15.ttbr0_el[1] = *(uint64_t *)value;
break; break;
case UC_ARM64_REG_TTBR1_EL1: case UC_ARM64_REG_TTBR1_EL1:
CHECK_REG_TYPE(uint64_t);
env->cp15.ttbr1_el[1] = *(uint64_t *)value; env->cp15.ttbr1_el[1] = *(uint64_t *)value;
break; break;
case UC_ARM64_REG_PAR_EL1: case UC_ARM64_REG_PAR_EL1:
CHECK_REG_TYPE(uint64_t);
env->cp15.par_el[1] = *(uint64_t *)value; env->cp15.par_el[1] = *(uint64_t *)value;
break; break;
case UC_ARM64_REG_MAIR_EL1: case UC_ARM64_REG_MAIR_EL1:
CHECK_REG_TYPE(uint64_t);
env->cp15.mair_el[1] = *(uint64_t *)value; env->cp15.mair_el[1] = *(uint64_t *)value;
break; break;
case UC_ARM64_REG_CP_REG: case UC_ARM64_REG_CP_REG:
CHECK_REG_TYPE(uc_arm64_cp_reg);
ret = write_cp_reg(env, (uc_arm64_cp_reg *)value); ret = write_cp_reg(env, (uc_arm64_cp_reg *)value);
arm_rebuild_hflags(env); arm_rebuild_hflags(env);
break; break;
case UC_ARM64_REG_FPCR: case UC_ARM64_REG_FPCR:
CHECK_REG_TYPE(uint32_t);
vfp_set_fpcr(env, *(uint32_t *)value); vfp_set_fpcr(env, *(uint32_t *)value);
break; break;
case UC_ARM64_REG_FPSR: case UC_ARM64_REG_FPSR:
CHECK_REG_TYPE(uint32_t);
vfp_set_fpsr(env, *(uint32_t *)value); vfp_set_fpsr(env, *(uint32_t *)value);
break; break;
} }
@@ -337,8 +397,8 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value)
return ret; return ret;
} }
int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count) size_t *sizes, int count)
{ {
CPUARMState *env = &(ARM_CPU(uc->cpu)->env); CPUARMState *env = &(ARM_CPU(uc->cpu)->env);
int i; 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++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[i]; void *value = vals[i];
err = reg_read(env, regid, value); err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) { if (err) {
return err; return err;
} }
@@ -356,8 +416,8 @@ int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
return UC_ERR_OK; return UC_ERR_OK;
} }
int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int arm64_reg_write(struct uc_struct *uc, unsigned int *regs,
int count) const void *const *vals, size_t *sizes, int count)
{ {
CPUARMState *env = &(ARM_CPU(uc->cpu)->env); CPUARMState *env = &(ARM_CPU(uc->cpu)->env);
int i; 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++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
const void *value = vals[i]; const void *value = vals[i];
err = reg_write(env, regid, value); err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) { if (err) {
return err; return err;
} }
@@ -383,10 +443,10 @@ int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
DEFAULT_VISIBILITY DEFAULT_VISIBILITY
#ifdef TARGET_WORDS_BIGENDIAN #ifdef TARGET_WORDS_BIGENDIAN
int arm64eb_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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 #else
int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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 #endif
{ {
CPUARMState *env = (CPUARMState *)ctx->data; 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++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[i]; void *value = vals[i];
err = reg_read(env, regid, value); err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
if (err) { if (err) {
return err; return err;
} }
} }
return 0; return UC_ERR_OK;
} }
DEFAULT_VISIBILITY DEFAULT_VISIBILITY
#ifdef TARGET_WORDS_BIGENDIAN #ifdef TARGET_WORDS_BIGENDIAN
int arm64eb_context_reg_write(struct uc_context *ctx, unsigned int *regs, 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 #else
int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs, 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 #endif
{ {
CPUARMState *env = (CPUARMState *)ctx->data; 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++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
const void *value = vals[i]; const void *value = vals[i];
err = reg_write(env, regid, value); err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
if (err) { if (err) {
return err; return err;
} }
} }
return 0; return UC_ERR_OK;
} }
static int arm64_cpus_init(struct uc_struct *uc, const char *cpu_model) static int arm64_cpus_init(struct uc_struct *uc, const char *cpu_model)

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -6,14 +6,14 @@
#define UC_QEMU_TARGET_I386_H #define UC_QEMU_TARGET_I386_H
// functions to read & write registers // functions to read & write registers
int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count); size_t *sizes, int count);
int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int x86_reg_write(struct uc_struct *uc, unsigned int *regs,
int count); const void *const *vals, size_t *sizes, int count);
int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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, 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); 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; 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) uc_err ret = UC_ERR_ARG;
*(int32_t *)value = env->aregs[regid - UC_M68K_REG_A0];
else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7) if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7) {
*(int32_t *)value = env->dregs[regid - UC_M68K_REG_D0]; CHECK_REG_TYPE(uint32_t);
else { *(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) { switch (regid) {
default: default:
break; break;
case UC_M68K_REG_PC: case UC_M68K_REG_PC:
*(int32_t *)value = env->pc; CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->pc;
break; break;
case UC_M68K_REG_SR: case UC_M68K_REG_SR:
*(int32_t *)value = env->sr; CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->sr;
break; 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; 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; env->dregs[regid - UC_M68K_REG_D0] = *(uint32_t *)value;
else { } else {
switch (regid) { switch (regid) {
default: default:
break; break;
case UC_M68K_REG_PC: case UC_M68K_REG_PC:
CHECK_REG_TYPE(uint32_t);
env->pc = *(uint32_t *)value; env->pc = *(uint32_t *)value;
break; break;
case UC_M68K_REG_SR: case UC_M68K_REG_SR:
CHECK_REG_TYPE(uint32_t);
cpu_m68k_set_sr(env, *(uint32_t *)value); cpu_m68k_set_sr(env, *(uint32_t *)value);
break; break;
} }
} }
return ret;
} }
int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count) size_t *sizes, int count)
{ {
CPUM68KState *env = &(M68K_CPU(uc->cpu)->env); CPUM68KState *env = &(M68K_CPU(uc->cpu)->env);
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[i]; void *value = vals[i];
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 m68k_reg_write(struct uc_struct *uc, unsigned int *regs,
int count) const void *const *vals, size_t *sizes, int count)
{ {
CPUM68KState *env = &(M68K_CPU(uc->cpu)->env); CPUM68KState *env = &(M68K_CPU(uc->cpu)->env);
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
const void *value = vals[i]; const void *value = vals[i];
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) { if (regid == UC_M68K_REG_PC) {
// force to quit execution and flush TB // force to quit execution and flush TB
uc->quit_request = true; 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 DEFAULT_VISIBILITY
int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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; CPUM68KState *env = (CPUM68KState *)ctx->data;
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[i]; void *value = vals[i];
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 DEFAULT_VISIBILITY
int m68k_context_reg_write(struct uc_context *ctx, unsigned int *regs, 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; CPUM68KState *env = (CPUM68KState *)ctx->data;
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
const void *value = vals[i]; const void *value = vals[i];
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) 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 #define UC_QEMU_TARGET_M68K_H
// functions to read & write registers // functions to read & write registers
int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count); size_t *sizes, int count);
int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int m68k_reg_write(struct uc_struct *uc, unsigned int *regs,
int count); const void *const *vals, size_t *sizes, int count);
int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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, 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); 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; 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]; *(mipsreg_t *)value = env->active_tc.gpr[regid - UC_MIPS_REG_0];
else { } else {
switch (regid) { switch (regid) {
default: default:
break; break;
case UC_MIPS_REG_HI: case UC_MIPS_REG_HI:
CHECK_REG_TYPE(mipsreg_t);
*(mipsreg_t *)value = env->active_tc.HI[0]; *(mipsreg_t *)value = env->active_tc.HI[0];
break; break;
case UC_MIPS_REG_LO: case UC_MIPS_REG_LO:
CHECK_REG_TYPE(mipsreg_t);
*(mipsreg_t *)value = env->active_tc.LO[0]; *(mipsreg_t *)value = env->active_tc.LO[0];
break; break;
case UC_MIPS_REG_PC: case UC_MIPS_REG_PC:
CHECK_REG_TYPE(mipsreg_t);
*(mipsreg_t *)value = env->active_tc.PC; *(mipsreg_t *)value = env->active_tc.PC;
break; break;
case UC_MIPS_REG_CP0_CONFIG3: case UC_MIPS_REG_CP0_CONFIG3:
CHECK_REG_TYPE(mipsreg_t);
*(mipsreg_t *)value = env->CP0_Config3; *(mipsreg_t *)value = env->CP0_Config3;
break; break;
case UC_MIPS_REG_CP0_STATUS: case UC_MIPS_REG_CP0_STATUS:
CHECK_REG_TYPE(mipsreg_t);
*(mipsreg_t *)value = env->CP0_Status; *(mipsreg_t *)value = env->CP0_Status;
break; break;
case UC_MIPS_REG_CP0_USERLOCAL: case UC_MIPS_REG_CP0_USERLOCAL:
CHECK_REG_TYPE(mipsreg_t);
*(mipsreg_t *)value = env->active_tc.CP0_UserLocal; *(mipsreg_t *)value = env->active_tc.CP0_UserLocal;
break; 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; env->active_tc.gpr[regid - UC_MIPS_REG_0] = *(mipsreg_t *)value;
else { } else {
switch (regid) { switch (regid) {
default: default:
break; break;
case UC_MIPS_REG_HI: case UC_MIPS_REG_HI:
CHECK_REG_TYPE(mipsreg_t);
env->active_tc.HI[0] = *(mipsreg_t *)value; env->active_tc.HI[0] = *(mipsreg_t *)value;
break; break;
case UC_MIPS_REG_LO: case UC_MIPS_REG_LO:
CHECK_REG_TYPE(mipsreg_t);
env->active_tc.LO[0] = *(mipsreg_t *)value; env->active_tc.LO[0] = *(mipsreg_t *)value;
break; break;
case UC_MIPS_REG_PC: case UC_MIPS_REG_PC:
CHECK_REG_TYPE(mipsreg_t);
env->active_tc.PC = *(mipsreg_t *)value; env->active_tc.PC = *(mipsreg_t *)value;
break; break;
case UC_MIPS_REG_CP0_CONFIG3: case UC_MIPS_REG_CP0_CONFIG3:
CHECK_REG_TYPE(mipsreg_t);
env->CP0_Config3 = *(mipsreg_t *)value; env->CP0_Config3 = *(mipsreg_t *)value;
break; break;
case UC_MIPS_REG_CP0_STATUS: case UC_MIPS_REG_CP0_STATUS:
// TODO: ALL CP0 REGS // 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/MD00090-2B-MIPS32PRA-AFP-06.02.pdf
// https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00582-2B-microMIPS32-AFP-05.04.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; env->CP0_Status = *(mipsreg_t *)value;
compute_hflags(env); compute_hflags(env);
break; break;
case UC_MIPS_REG_CP0_USERLOCAL: case UC_MIPS_REG_CP0_USERLOCAL:
CHECK_REG_TYPE(mipsreg_t);
env->active_tc.CP0_UserLocal = *(mipsreg_t *)value; env->active_tc.CP0_UserLocal = *(mipsreg_t *)value;
break; break;
} }
} }
return; return ret;
} }
int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count) size_t *sizes, int count)
{ {
CPUMIPSState *env = &(MIPS_CPU(uc->cpu)->env); CPUMIPSState *env = &(MIPS_CPU(uc->cpu)->env);
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[i]; void *value = vals[i];
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 mips_reg_write(struct uc_struct *uc, unsigned int *regs,
int count) const void *const *vals, size_t *sizes, int count)
{ {
CPUMIPSState *env = &(MIPS_CPU(uc->cpu)->env); CPUMIPSState *env = &(MIPS_CPU(uc->cpu)->env);
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
const void *value = vals[i]; const void *value = vals[i];
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) { if (regid == UC_MIPS_REG_PC) {
// force to quit execution and flush TB // force to quit execution and flush TB
uc->quit_request = true; 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 DEFAULT_VISIBILITY
#ifdef TARGET_MIPS64 #ifdef TARGET_MIPS64
#ifdef TARGET_WORDS_BIGENDIAN #ifdef TARGET_WORDS_BIGENDIAN
int mips64_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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 #else
int mips64el_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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 #endif
#else // if TARGET_MIPS #else // if TARGET_MIPS
#ifdef TARGET_WORDS_BIGENDIAN #ifdef TARGET_WORDS_BIGENDIAN
int mips_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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 #else
int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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
#endif #endif
{ {
CPUMIPSState *env = (CPUMIPSState *)ctx->data; CPUMIPSState *env = (CPUMIPSState *)ctx->data;
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[i]; void *value = vals[i];
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 DEFAULT_VISIBILITY
#ifdef TARGET_MIPS64 #ifdef TARGET_MIPS64
#ifdef TARGET_WORDS_BIGENDIAN #ifdef TARGET_WORDS_BIGENDIAN
int mips64_context_reg_write(struct uc_context *ctx, unsigned int *regs, 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 #else
int mips64el_context_reg_write(struct uc_context *ctx, unsigned int *regs, 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 #endif
#else // if TARGET_MIPS #else // if TARGET_MIPS
#ifdef TARGET_WORDS_BIGENDIAN #ifdef TARGET_WORDS_BIGENDIAN
int mips_context_reg_write(struct uc_context *ctx, unsigned int *regs, 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 #else
int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs, 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
#endif #endif
{ {
CPUMIPSState *env = (CPUMIPSState *)ctx->data; CPUMIPSState *env = (CPUMIPSState *)ctx->data;
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
const void *value = vals[i]; const void *value = vals[i];
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) 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 #define UC_QEMU_TARGET_MIPS_H
// functions to read & write registers // functions to read & write registers
int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count); size_t *sizes, int count);
int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int mips_reg_write(struct uc_struct *uc, unsigned int *regs,
int count); const void *const *vals, size_t *sizes, int count);
int mips_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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, 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, 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, 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, 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, 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, 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, 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); 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 // 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]; *(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) { switch (regid) {
default: default:
break; break;
case UC_PPC_REG_PC: case UC_PPC_REG_PC:
CHECK_REG_TYPE(ppcreg_t);
*(ppcreg_t *)value = env->nip; *(ppcreg_t *)value = env->nip;
break; break;
case UC_PPC_REG_FPR0: case UC_PPC_REG_CR: {
case UC_PPC_REG_FPR1: CHECK_REG_TYPE(uint32_t);
case UC_PPC_REG_FPR2: uint32_t val;
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:
val = 0; val = 0;
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
val <<= 4; val <<= 4;
@@ -211,138 +178,124 @@ static void reg_read(CPUPPCState *env, unsigned int regid, void *value)
} }
*(uint32_t *)value = val; *(uint32_t *)value = val;
break; break;
}
case UC_PPC_REG_LR: case UC_PPC_REG_LR:
CHECK_REG_TYPE(ppcreg_t);
*(ppcreg_t *)value = env->lr; *(ppcreg_t *)value = env->lr;
break; break;
case UC_PPC_REG_CTR: case UC_PPC_REG_CTR:
CHECK_REG_TYPE(ppcreg_t);
*(ppcreg_t *)value = env->ctr; *(ppcreg_t *)value = env->ctr;
break; break;
case UC_PPC_REG_MSR: case UC_PPC_REG_MSR:
CHECK_REG_TYPE(ppcreg_t);
*(ppcreg_t *)value = env->msr; *(ppcreg_t *)value = env->msr;
break; break;
case UC_PPC_REG_XER: case UC_PPC_REG_XER:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->xer; *(uint32_t *)value = env->xer;
break; break;
case UC_PPC_REG_FPSCR: case UC_PPC_REG_FPSCR:
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->fpscr; *(uint32_t *)value = env->fpscr;
break; 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; 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; 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) { switch (regid) {
default: default:
break; break;
case UC_PPC_REG_PC: case UC_PPC_REG_PC:
CHECK_REG_TYPE(ppcreg_t);
env->nip = *(ppcreg_t *)value; env->nip = *(ppcreg_t *)value;
break; break;
case UC_PPC_REG_FPR0: case UC_PPC_REG_CR: {
case UC_PPC_REG_FPR1: CHECK_REG_TYPE(uint32_t);
case UC_PPC_REG_FPR2: uint32_t val = *(uint32_t *)value;
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;
for (i = 7; i >= 0; i--) { for (i = 7; i >= 0; i--) {
env->crf[i] = val & 0b1111; env->crf[i] = val & 0b1111;
val >>= 4; val >>= 4;
} }
break; break;
}
case UC_PPC_REG_LR: case UC_PPC_REG_LR:
CHECK_REG_TYPE(ppcreg_t);
env->lr = *(ppcreg_t *)value; env->lr = *(ppcreg_t *)value;
break; break;
case UC_PPC_REG_CTR: case UC_PPC_REG_CTR:
CHECK_REG_TYPE(ppcreg_t);
env->ctr = *(ppcreg_t *)value; env->ctr = *(ppcreg_t *)value;
break; break;
case UC_PPC_REG_MSR: case UC_PPC_REG_MSR:
CHECK_REG_TYPE(ppcreg_t);
uc_ppc_store_msr(env, *(ppcreg_t *)value, 0); uc_ppc_store_msr(env, *(ppcreg_t *)value, 0);
break; break;
case UC_PPC_REG_XER: case UC_PPC_REG_XER:
CHECK_REG_TYPE(uint32_t);
env->xer = *(uint32_t *)value; env->xer = *(uint32_t *)value;
break; break;
case UC_PPC_REG_FPSCR: case UC_PPC_REG_FPSCR:
CHECK_REG_TYPE(uint32_t);
store_fpscr(env, *(uint32_t *)value, 0xffffffff); store_fpscr(env, *(uint32_t *)value, 0xffffffff);
break; break;
} }
} }
return; return ret;
} }
int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count) size_t *sizes, int count)
{ {
CPUPPCState *env = &(POWERPC_CPU(uc->cpu)->env); CPUPPCState *env = &(POWERPC_CPU(uc->cpu)->env);
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[i]; void *value = vals[i];
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 ppc_reg_write(struct uc_struct *uc, unsigned int *regs,
int count) const void *const *vals, size_t *sizes, int count)
{ {
CPUPPCState *env = &(POWERPC_CPU(uc->cpu)->env); CPUPPCState *env = &(POWERPC_CPU(uc->cpu)->env);
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
const void *value = vals[i]; const void *value = vals[i];
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) { if (regid == UC_PPC_REG_PC) {
// force to quit execution and flush TB // force to quit execution and flush TB
uc->quit_request = true; 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 DEFAULT_VISIBILITY
#ifdef TARGET_PPC64 #ifdef TARGET_PPC64
int ppc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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 #else
int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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 #endif
{ {
CPUPPCState *env = (CPUPPCState *)ctx->data; CPUPPCState *env = (CPUPPCState *)ctx->data;
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[i]; void *value = vals[i];
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 DEFAULT_VISIBILITY
#ifdef TARGET_PPC64 #ifdef TARGET_PPC64
int ppc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, 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 #else
int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs, 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 #endif
{ {
CPUPPCState *env = (CPUPPCState *)ctx->data; CPUPPCState *env = (CPUPPCState *)ctx->data;
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
const void *value = vals[i]; const void *value = vals[i];
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); PowerPCCPU *cpu_ppc_init(struct uc_struct *uc);

View File

@@ -5,19 +5,19 @@
#define UC_QEMU_TARGET_PPC_H #define UC_QEMU_TARGET_PPC_H
// functions to read & write registers // functions to read & write registers
int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count); size_t *sizes, int count);
int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int ppc_reg_write(struct uc_struct *uc, unsigned int *regs,
int count); const void *const *vals, size_t *sizes, int count);
int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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, 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, 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, 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); 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_HIP, CSR_HTINST, CSR_HGATP, CSR_HTIMEDELTA,
CSR_HTIMEDELTAH, CSR_HTIMEDELTAH,
}; };
#define csrno_count (sizeof(csrno_map) / sizeof(int))
RISCVCPU *cpu_riscv_init(struct uc_struct *uc); 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) {} 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) { uc_err ret = UC_ERR_ARG;
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;
case UC_RISCV_REG_F0: // "ft0" if (regid >= UC_RISCV_REG_X0 && regid <= UC_RISCV_REG_X31) {
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 #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 #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 #endif
break; } else if (regid >= UC_RISCV_REG_F0 &&
case UC_RISCV_REG_USTATUS: regid <= UC_RISCV_REG_F31) { // "ft0".."ft31"
case UC_RISCV_REG_UIE: CHECK_REG_TYPE(uint64_t);
case UC_RISCV_REG_UTVEC: *(uint64_t *)value = env->fpr[regid - UC_RISCV_REG_F0];
case UC_RISCV_REG_USCRATCH: } else if (regid >= UC_RISCV_REG_USTATUS &&
case UC_RISCV_REG_UEPC: regid < UC_RISCV_REG_USTATUS + csrno_count) {
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: {
target_ulong val; target_ulong val;
int csrno = csrno_map[regid - UC_RISCV_REG_USTATUS]; int csrno = csrno_map[regid - UC_RISCV_REG_USTATUS];
riscv_csrrw(env, csrno, &val, -1, 0); riscv_csrrw(env, csrno, &val, -1, 0);
#ifdef TARGET_RISCV64 #ifdef TARGET_RISCV64
CHECK_REG_TYPE(uint64_t);
*(uint64_t *)value = (uint64_t)val; *(uint64_t *)value = (uint64_t)val;
#else #else
CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = (uint32_t)val; *(uint32_t *)value = (uint32_t)val;
#endif #endif
break; } else {
} switch (regid) {
default: default:
break; 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) { uc_err ret = UC_ERR_ARG;
case UC_RISCV_REG_X0:
case UC_RISCV_REG_X1: if (regid >= UC_RISCV_REG_X0 && regid <= UC_RISCV_REG_X31) {
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 #ifdef TARGET_RISCV64
CHECK_REG_TYPE(uint64_t);
env->gpr[regid - UC_RISCV_REG_X0] = *(uint64_t *)value; env->gpr[regid - UC_RISCV_REG_X0] = *(uint64_t *)value;
#else #else
CHECK_REG_TYPE(uint32_t);
env->gpr[regid - UC_RISCV_REG_X0] = *(uint32_t *)value; env->gpr[regid - UC_RISCV_REG_X0] = *(uint32_t *)value;
#endif #endif
break; } else if (regid >= UC_RISCV_REG_F0 &&
case UC_RISCV_REG_PC: regid <= UC_RISCV_REG_F31) { // "ft0".."ft31"
#ifdef TARGET_RISCV64 CHECK_REG_TYPE(uint64_t);
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
env->fpr[regid - UC_RISCV_REG_F0] = *(uint64_t *)value; env->fpr[regid - UC_RISCV_REG_F0] = *(uint64_t *)value;
#else } else if (regid >= UC_RISCV_REG_USTATUS &&
env->fpr[regid - UC_RISCV_REG_F0] = *(uint32_t *)value; regid < UC_RISCV_REG_USTATUS + csrno_count) {
#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: {
target_ulong val; target_ulong val;
int csrno = csrno_map[regid - UC_RISCV_REG_USTATUS]; int csrno = csrno_map[regid - UC_RISCV_REG_USTATUS];
#ifdef TARGET_RISCV64 #ifdef TARGET_RISCV64
CHECK_REG_TYPE(uint64_t);
riscv_csrrw(env, csrno, &val, *(uint64_t *)value, -1); riscv_csrrw(env, csrno, &val, *(uint64_t *)value, -1);
#else #else
CHECK_REG_TYPE(uint32_t);
riscv_csrrw(env, csrno, &val, *(uint32_t *)value, -1); riscv_csrrw(env, csrno, &val, *(uint32_t *)value, -1);
#endif #endif
break; } else {
} switch (regid) {
default: default:
break; 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 riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count) size_t *sizes, int count)
{ {
CPURISCVState *env = &(RISCV_CPU(uc->cpu)->env); CPURISCVState *env = &(RISCV_CPU(uc->cpu)->env);
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[i]; void *value = vals[i];
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 riscv_reg_write(struct uc_struct *uc, unsigned int *regs,
int count) const void *const *vals, size_t *sizes, int count)
{ {
CPURISCVState *env = &(RISCV_CPU(uc->cpu)->env); CPURISCVState *env = &(RISCV_CPU(uc->cpu)->env);
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
const void *value = vals[i]; const void *value = vals[i];
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) { if (regid == UC_RISCV_REG_PC) {
// force to quit execution and flush TB // force to quit execution and flush TB
uc->quit_request = true; 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 DEFAULT_VISIBILITY
#ifdef TARGET_RISCV32 #ifdef TARGET_RISCV32
int riscv32_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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 #else
/* TARGET_RISCV64 */ /* TARGET_RISCV64 */
int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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 #endif
{ {
CPURISCVState *env = (CPURISCVState *)ctx->data; CPURISCVState *env = (CPURISCVState *)ctx->data;
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[i]; void *value = vals[i];
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 DEFAULT_VISIBILITY
#ifdef TARGET_RISCV32 #ifdef TARGET_RISCV32
int riscv32_context_reg_write(struct uc_context *ctx, unsigned int *regs, 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 #else
/* TARGET_RISCV64 */ /* TARGET_RISCV64 */
int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs, 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 #endif
{ {
CPURISCVState *env = (CPURISCVState *)ctx->data; CPURISCVState *env = (CPURISCVState *)ctx->data;
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
const void *value = vals[i]; const void *value = vals[i];
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) static bool riscv_stop_interrupt(struct uc_struct *uc, int intno)

View File

@@ -6,19 +6,21 @@
#define UC_QEMU_TARGET_RISCV_H #define UC_QEMU_TARGET_RISCV_H
// functions to read & write registers // functions to read & write registers
int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count); size_t *sizes, int count);
int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int riscv_reg_write(struct uc_struct *uc, unsigned int *regs,
int count); const void *const *vals, size_t *sizes, int count);
int riscv32_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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, 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, 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, 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); 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; 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) { 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]; *(uint64_t *)value = env->regs[regid - UC_S390X_REG_R0];
return; } else if (regid >= UC_S390X_REG_A0 && regid <= UC_S390X_REG_A15) {
} CHECK_REG_TYPE(uint32_t);
if (regid >= UC_S390X_REG_A0 && regid <= UC_S390X_REG_A15) {
*(uint32_t *)value = env->regs[regid - UC_S390X_REG_A0]; *(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) { return ret;
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;
}
} }
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) { 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; env->regs[regid - UC_S390X_REG_R0] = *(uint64_t *)value;
return; } else if (regid >= UC_S390X_REG_A0 && regid <= UC_S390X_REG_A15) {
} CHECK_REG_TYPE(uint32_t);
if (regid >= UC_S390X_REG_A0 && regid <= UC_S390X_REG_A15) {
env->regs[regid - UC_S390X_REG_A0] = *(uint32_t *)value; env->regs[regid - UC_S390X_REG_A0] = *(uint32_t *)value;
return; } else {
} switch (regid) {
default:
switch (regid) { break;
default: case UC_S390X_REG_PC:
break; CHECK_REG_TYPE(uint64_t);
case UC_S390X_REG_PC: env->psw.addr = *(uint64_t *)value;
env->psw.addr = *(uint64_t *)value; break;
break; case UC_S390X_REG_PSWM:
case UC_S390X_REG_PSWM: CHECK_REG_TYPE(uint64_t);
env->psw.mask = *(uint64_t *)value; env->psw.mask = *(uint64_t *)value;
env->cc_op = (env->psw.mask >> 44) & 3; env->cc_op = (env->psw.mask >> 44) & 3;
break; break;
}
} }
return ret;
} }
static int s390_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, DEFAULT_VISIBILITY
int count) 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); CPUS390XState *env = &(S390_CPU(uc->cpu)->env);
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[i]; void *value = vals[i];
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, DEFAULT_VISIBILITY
void *const *vals, int count) 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); CPUS390XState *env = &(S390_CPU(uc->cpu)->env);
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
const void *value = vals[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) { if (regid == UC_S390X_REG_PC) {
// force to quit execution and flush TB // force to quit execution and flush TB
uc->quit_request = true; 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 DEFAULT_VISIBILITY
int s390_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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; CPUS390XState *env = (CPUS390XState *)ctx->data;
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[i]; void *value = vals[i];
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 DEFAULT_VISIBILITY
int s390_context_reg_write(struct uc_context *ctx, unsigned int *regs, 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; CPUS390XState *env = (CPUS390XState *)ctx->data;
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
const void *value = vals[i]; const void *value = vals[i];
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) 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 #define UC_QEMU_TARGET_S390X_H
// functions to read & write registers // functions to read & write registers
// int s390_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int int s390_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
// count); int s390_reg_write(struct uc_struct *uc, unsigned int *regs, void size_t *sizes, int count);
// *const *vals, 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, 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, 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); 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; 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) uc_err ret = UC_ERR_ARG;
*(int32_t *)value = env->gregs[regid - UC_SPARC_REG_G0];
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7) {
*(int32_t *)value = env->regwptr[regid - UC_SPARC_REG_O0]; CHECK_REG_TYPE(uint32_t);
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) *(uint32_t *)value = env->gregs[regid - UC_SPARC_REG_G0];
*(int32_t *)value = env->regwptr[8 + regid - UC_SPARC_REG_L0]; } else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) {
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) CHECK_REG_TYPE(uint32_t);
*(int32_t *)value = env->regwptr[16 + regid - UC_SPARC_REG_I0]; *(uint32_t *)value = env->regwptr[regid - UC_SPARC_REG_O0];
else { } 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) { switch (regid) {
default: default:
break; break;
case UC_SPARC_REG_PC: case UC_SPARC_REG_PC:
*(int32_t *)value = env->pc; CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->pc;
break; 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; 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; 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; 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; env->regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint32_t *)value;
else { } else {
switch (regid) { switch (regid) {
default: default:
break; break;
case UC_SPARC_REG_PC: case UC_SPARC_REG_PC:
CHECK_REG_TYPE(uint32_t);
env->pc = *(uint32_t *)value; env->pc = *(uint32_t *)value;
env->npc = *(uint32_t *)value + 4; env->npc = *(uint32_t *)value + 4;
break; break;
} }
} }
return; return ret;
} }
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count) size_t *sizes, int count)
{ {
CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env); CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env);
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[i]; void *value = vals[i];
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 sparc_reg_write(struct uc_struct *uc, unsigned int *regs,
int count) const void *const *vals, size_t *sizes, int count)
{ {
CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env); CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env);
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
const void *value = vals[i]; const void *value = vals[i];
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) { if (regid == UC_SPARC_REG_PC) {
// force to quit execution and flush TB // force to quit execution and flush TB
uc->quit_request = true; uc->quit_request = true;
uc_emu_stop(uc); break_translation_loop(uc);
break;
} }
} }
return 0; return UC_ERR_OK;
} }
DEFAULT_VISIBILITY DEFAULT_VISIBILITY
int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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; CPUSPARCState *env = (CPUSPARCState *)ctx->data;
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[i]; void *value = vals[i];
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 DEFAULT_VISIBILITY
int sparc_context_reg_write(struct uc_context *ctx, unsigned int *regs, 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; CPUSPARCState *env = (CPUSPARCState *)ctx->data;
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
const void *value = vals[i]; const void *value = vals[i];
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) 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 #define UC_QEMU_TARGET_SPARC_H
// functions to read & write registers // functions to read & write registers
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
int count); size_t *sizes, int count);
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int sparc_reg_write(struct uc_struct *uc, unsigned int *regs,
int count); const void *const *vals, size_t *sizes, int count);
int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs, 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, 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, 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, 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); 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; 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) uc_err ret = UC_ERR_ARG;
*(int64_t *)value = env->gregs[regid - UC_SPARC_REG_G0];
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7) {
*(int64_t *)value = env->regwptr[regid - UC_SPARC_REG_O0]; CHECK_REG_TYPE(uint64_t);
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) *(uint64_t *)value = env->gregs[regid - UC_SPARC_REG_G0];
*(int64_t *)value = env->regwptr[8 + regid - UC_SPARC_REG_L0]; } else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) {
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) CHECK_REG_TYPE(uint64_t);
*(int64_t *)value = env->regwptr[16 + regid - UC_SPARC_REG_I0]; *(uint64_t *)value = env->regwptr[regid - UC_SPARC_REG_O0];
else { } 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) { switch(regid) {
default: break; default:
case UC_SPARC_REG_PC: break;
*(int64_t *)value = env->pc; case UC_SPARC_REG_PC:
break; 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; 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; 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; 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; env->regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint64_t *)value;
else { } else {
switch(regid) { switch(regid) {
default: break; default:
case UC_SPARC_REG_PC: break;
env->pc = *(uint64_t *)value; case UC_SPARC_REG_PC:
env->npc = *(uint64_t *)value + 4; CHECK_REG_TYPE(uint64_t);
break; 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); CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env);
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[i]; void *value = vals[i];
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); CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env);
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
const void *value = vals[i]; const void *value = vals[i];
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 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; CPUSPARCState *env = (CPUSPARCState *)ctx->data;
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[i]; void *value = vals[i];
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 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; CPUSPARCState *env = (CPUSPARCState *)ctx->data;
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
const void *value = vals[i]; const void *value = vals[i];
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) 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; 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) uc_err ret = UC_ERR_ARG;
*(int32_t *)value = env->gpr_a[regid - UC_TRICORE_REG_A0];
if (regid >= UC_TRICORE_REG_A12 && regid <= UC_TRICORE_REG_A15) if (regid >= UC_TRICORE_REG_A0 && regid <= UC_TRICORE_REG_A9) {
*(int32_t *)value = env->gpr_a[regid - UC_TRICORE_REG_A0]; CHECK_REG_TYPE(uint32_t);
else if (regid >= UC_TRICORE_REG_D0 && regid <= UC_TRICORE_REG_D15) *(uint32_t *)value = env->gpr_a[regid - UC_TRICORE_REG_A0];
*(int32_t *)value = env->gpr_d[regid - UC_TRICORE_REG_D0]; } else if (regid >= UC_TRICORE_REG_A12 && regid <= UC_TRICORE_REG_A15) {
else { 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) { switch (regid) {
// case UC_TRICORE_REG_SP: // case UC_TRICORE_REG_SP:
case UC_TRICORE_REG_A10: 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; break;
// case UC_TRICORE_REG_LR: // case UC_TRICORE_REG_LR:
case UC_TRICORE_REG_A11: 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; break;
case UC_TRICORE_REG_PC: case UC_TRICORE_REG_PC:
*(int32_t *)value = env->PC; CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->PC;
break; break;
case UC_TRICORE_REG_PCXI: case UC_TRICORE_REG_PCXI:
*(int32_t *)value = env->PCXI; CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->PCXI;
break; break;
case UC_TRICORE_REG_PSW: case UC_TRICORE_REG_PSW:
*(int32_t *)value = env->PSW; CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->PSW;
break; break;
case UC_TRICORE_REG_PSW_USB_C: 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; break;
case UC_TRICORE_REG_PSW_USB_V: 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; break;
case UC_TRICORE_REG_PSW_USB_SV: 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; break;
case UC_TRICORE_REG_PSW_USB_AV: 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; break;
case UC_TRICORE_REG_PSW_USB_SAV: 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; break;
case UC_TRICORE_REG_SYSCON: case UC_TRICORE_REG_SYSCON:
*(int32_t *)value = env->SYSCON; CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->SYSCON;
break; break;
case UC_TRICORE_REG_CPU_ID: case UC_TRICORE_REG_CPU_ID:
*(int32_t *)value = env->CPU_ID; CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->CPU_ID;
break; break;
case UC_TRICORE_REG_BIV: case UC_TRICORE_REG_BIV:
*(int32_t *)value = env->BIV; CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->BIV;
break; break;
case UC_TRICORE_REG_BTV: case UC_TRICORE_REG_BTV:
*(int32_t *)value = env->BTV; CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->BTV;
break; break;
case UC_TRICORE_REG_ISP: case UC_TRICORE_REG_ISP:
*(int32_t *)value = env->ISP; CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->ISP;
break; break;
case UC_TRICORE_REG_ICR: case UC_TRICORE_REG_ICR:
*(int32_t *)value = env->ICR; CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->ICR;
break; break;
case UC_TRICORE_REG_FCX: case UC_TRICORE_REG_FCX:
*(int32_t *)value = env->FCX; CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->FCX;
break; break;
case UC_TRICORE_REG_LCX: case UC_TRICORE_REG_LCX:
*(int32_t *)value = env->LCX; CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->LCX;
break; break;
case UC_TRICORE_REG_COMPAT: case UC_TRICORE_REG_COMPAT:
*(int32_t *)value = env->COMPAT; CHECK_REG_TYPE(uint32_t);
*(uint32_t *)value = env->COMPAT;
break; break;
} }
} }
return ret;
} }
int tricore_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int tricore_reg_read(struct uc_struct *uc, unsigned int *regs,
int count) void *const *vals, size_t *sizes, int count)
{ {
CPUTriCoreState *env = &(TRICORE_CPU(uc->cpu)->env); CPUTriCoreState *env = &(TRICORE_CPU(uc->cpu)->env);
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[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, 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; CPUTriCoreState *env = (CPUTriCoreState *)uc->data;
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[i]; void *value = vals[i];
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, static uc_err reg_write(CPUTriCoreState *env, unsigned int regid,
const void *value) const void *value, size_t *size)
{ {
if (regid >= UC_TRICORE_REG_A0 && regid <= UC_TRICORE_REG_A9) uc_err ret = UC_ERR_ARG;
env->gpr_a[regid - UC_TRICORE_REG_A0] = *(int32_t *)value;
if (regid >= UC_TRICORE_REG_A12 && regid <= UC_TRICORE_REG_A15) if (regid >= UC_TRICORE_REG_A0 && regid <= UC_TRICORE_REG_A9) {
env->gpr_a[regid - UC_TRICORE_REG_A0] = *(int32_t *)value; CHECK_REG_TYPE(uint32_t);
else if (regid >= UC_TRICORE_REG_D0 && regid <= UC_TRICORE_REG_D15) env->gpr_a[regid - UC_TRICORE_REG_A0] = *(uint32_t *)value;
env->gpr_d[regid - UC_TRICORE_REG_D0] = *(int32_t *)value; } else if (regid >= UC_TRICORE_REG_A12 && regid <= UC_TRICORE_REG_A15) {
else { 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) { switch (regid) {
// case UC_TRICORE_REG_SP: // case UC_TRICORE_REG_SP:
case UC_TRICORE_REG_A10: 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; break;
// case UC_TRICORE_REG_LR: // case UC_TRICORE_REG_LR:
case UC_TRICORE_REG_A11: 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; break;
case UC_TRICORE_REG_PC: case UC_TRICORE_REG_PC:
env->PC = *(int32_t *)value; CHECK_REG_TYPE(uint32_t);
env->PC = *(uint32_t *)value;
break; break;
case UC_TRICORE_REG_PCXI: case UC_TRICORE_REG_PCXI:
env->PCXI = *(int32_t *)value; CHECK_REG_TYPE(uint32_t);
env->PCXI = *(uint32_t *)value;
break; break;
case UC_TRICORE_REG_PSW: case UC_TRICORE_REG_PSW:
env->PSW = *(int32_t *)value; CHECK_REG_TYPE(uint32_t);
env->PSW = *(uint32_t *)value;
break; break;
case UC_TRICORE_REG_PSW_USB_C: 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; break;
case UC_TRICORE_REG_PSW_USB_V: 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; break;
case UC_TRICORE_REG_PSW_USB_SV: 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; break;
case UC_TRICORE_REG_PSW_USB_AV: 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; break;
case UC_TRICORE_REG_PSW_USB_SAV: 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; break;
case UC_TRICORE_REG_SYSCON: case UC_TRICORE_REG_SYSCON:
env->SYSCON = *(int32_t *)value; CHECK_REG_TYPE(uint32_t);
env->SYSCON = *(uint32_t *)value;
break; break;
case UC_TRICORE_REG_CPU_ID: case UC_TRICORE_REG_CPU_ID:
env->CPU_ID = *(int32_t *)value; CHECK_REG_TYPE(uint32_t);
env->CPU_ID = *(uint32_t *)value;
break; break;
case UC_TRICORE_REG_BIV: case UC_TRICORE_REG_BIV:
env->BIV = *(int32_t *)value; CHECK_REG_TYPE(uint32_t);
env->BIV = *(uint32_t *)value;
break; break;
case UC_TRICORE_REG_BTV: case UC_TRICORE_REG_BTV:
env->BTV = *(int32_t *)value; CHECK_REG_TYPE(uint32_t);
env->BTV = *(uint32_t *)value;
break; break;
case UC_TRICORE_REG_ISP: case UC_TRICORE_REG_ISP:
env->ISP = *(int32_t *)value; CHECK_REG_TYPE(uint32_t);
env->ISP = *(uint32_t *)value;
break; break;
case UC_TRICORE_REG_ICR: case UC_TRICORE_REG_ICR:
env->ICR = *(int32_t *)value; CHECK_REG_TYPE(uint32_t);
env->ICR = *(uint32_t *)value;
break; break;
case UC_TRICORE_REG_FCX: case UC_TRICORE_REG_FCX:
env->FCX = *(int32_t *)value; CHECK_REG_TYPE(uint32_t);
env->FCX = *(uint32_t *)value;
break; break;
case UC_TRICORE_REG_LCX: case UC_TRICORE_REG_LCX:
env->LCX = *(int32_t *)value; CHECK_REG_TYPE(uint32_t);
env->LCX = *(uint32_t *)value;
break; break;
case UC_TRICORE_REG_COMPAT: case UC_TRICORE_REG_COMPAT:
env->COMPAT = *(int32_t *)value; CHECK_REG_TYPE(uint32_t);
env->COMPAT = *(uint32_t *)value;
break; break;
} }
} }
return ret;
} }
int tricore_reg_write(struct uc_struct *uc, unsigned int *regs, 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); CPUTriCoreState *env = &(TRICORE_CPU(uc->cpu)->env);
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
void *value = vals[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_TRICORE_REG_PC) { if (regid == UC_TRICORE_REG_PC) {
// force to quit execution and flush TB // force to quit execution and flush TB
uc->quit_request = true; 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, 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; CPUTriCoreState *env = (CPUTriCoreState *)uc->data;
int i; int i;
uc_err err;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
unsigned int regid = regs[i]; unsigned int regid = regs[i];
const void *value = vals[i]; const void *value = vals[i];
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) 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 #define UC_QEMU_TARGET_TRICORE_H
// functions to read & write registers // functions to read & write registers
int tricore_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int tricore_reg_read(struct uc_struct *uc, unsigned int *regs,
int count); void *const *vals, size_t *sizes, int count);
int tricore_reg_write(struct uc_struct *uc, unsigned int *regs, 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, 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, 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); 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) if (!uc->release)
uc->release = release_common; 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 #endif

108
uc.c
View File

@@ -507,47 +507,63 @@ uc_err uc_close(uc_engine *uc)
UNICORN_EXPORT UNICORN_EXPORT
uc_err uc_reg_read_batch(uc_engine *uc, int *ids, void **vals, int count) uc_err uc_reg_read_batch(uc_engine *uc, int *ids, void **vals, int count)
{ {
int ret = UC_ERR_OK; return uc_reg_read_batch2(uc, ids, vals, NULL, count);
UC_INIT(uc);
if (uc->reg_read) {
ret = uc->reg_read(uc, (unsigned int *)ids, vals, count);
} else {
return UC_ERR_HANDLE;
}
return ret;
} }
UNICORN_EXPORT UNICORN_EXPORT
uc_err uc_reg_write_batch(uc_engine *uc, int *ids, void *const *vals, int count) uc_err uc_reg_write_batch(uc_engine *uc, int *ids, void *const *vals, int count)
{ {
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); UC_INIT(uc);
if (uc->reg_write) { if (uc->reg_read) {
ret = uc->reg_write(uc, (unsigned int *)ids, vals, count); return uc->reg_read(uc, (unsigned int *)ids, vals, sizes, count);
} else { } else {
return UC_ERR_HANDLE; 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 UNICORN_EXPORT
uc_err uc_reg_read(uc_engine *uc, int regid, void *value) uc_err uc_reg_read(uc_engine *uc, int regid, void *value)
{ {
UC_INIT(uc); return uc_reg_read_batch2(uc, &regid, &value, NULL, 1);
return uc_reg_read_batch(uc, &regid, &value, 1);
} }
UNICORN_EXPORT UNICORN_EXPORT
uc_err uc_reg_write(uc_engine *uc, int regid, const void *value) uc_err uc_reg_write(uc_engine *uc, int regid, const void *value)
{ {
UC_INIT(uc); return uc_reg_write_batch2(uc, &regid, &value, NULL, 1);
return uc_reg_write_batch(uc, &regid, (void *const *)&value, 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 // check if a memory area is mapped
@@ -1869,13 +1885,42 @@ uc_err uc_context_save(uc_engine *uc, uc_context *context)
UNICORN_EXPORT UNICORN_EXPORT
uc_err uc_context_reg_write(uc_context *ctx, int regid, const void *value) 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 UNICORN_EXPORT
uc_err uc_context_reg_read(uc_context *ctx, int regid, void *value) 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. // 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 UNICORN_EXPORT
uc_err uc_context_reg_write_batch(uc_context *ctx, int *ids, void *const *vals, uc_err uc_context_reg_write_batch2(uc_context *ctx, int *ids,
int count) const void *const *vals, size_t *sizes,
int count)
{ {
int ret = UC_ERR_OK;
context_reg_rw_t rw; context_reg_rw_t rw;
find_context_reg_rw_function(ctx->arch, ctx->mode, &rw); find_context_reg_rw_function(ctx->arch, ctx->mode, &rw);
if (rw.context_reg_write) { 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 { } else {
return UC_ERR_HANDLE; return UC_ERR_HANDLE;
} }
return ret;
} }
UNICORN_EXPORT UNICORN_EXPORT
uc_err uc_context_reg_read_batch(uc_context *ctx, int *ids, void **vals, uc_err uc_context_reg_read_batch2(uc_context *ctx, int *ids, void *const *vals,
int count) size_t *sizes, int count)
{ {
int ret = UC_ERR_OK;
context_reg_rw_t rw; context_reg_rw_t rw;
find_context_reg_rw_function(ctx->arch, ctx->mode, &rw); find_context_reg_rw_function(ctx->arch, ctx->mode, &rw);
if (rw.context_reg_read) { 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 { } else {
return UC_ERR_HANDLE; return UC_ERR_HANDLE;
} }
return ret;
} }
UNICORN_EXPORT UNICORN_EXPORT