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:
@@ -63,15 +63,16 @@ typedef uc_err (*query_t)(struct uc_struct *uc, uc_query_type type,
|
||||
size_t *result);
|
||||
|
||||
// return 0 on success, -1 on failure
|
||||
typedef int (*reg_read_t)(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count);
|
||||
typedef int (*reg_read_t)(struct uc_struct *uc, unsigned int *regs,
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
typedef int (*reg_write_t)(struct uc_struct *uc, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
|
||||
typedef int (*context_reg_read_t)(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count);
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
typedef int (*context_reg_write_t)(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes,
|
||||
int count);
|
||||
typedef struct {
|
||||
context_reg_read_t context_reg_read;
|
||||
context_reg_write_t context_reg_write;
|
||||
|
||||
@@ -779,10 +779,9 @@ const char *uc_strerror(uc_err code);
|
||||
|
||||
@uc: handle returned by uc_open()
|
||||
@regid: register ID that is to be modified.
|
||||
@value: pointer to the value that will set to register @regid
|
||||
@value: pointer to the value that will be written to register @regid
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
@return UC_ERR_OK on success; UC_ERR_ARG if register number or value is invalid
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_write(uc_engine *uc, int regid, const void *value);
|
||||
@@ -794,22 +793,49 @@ uc_err uc_reg_write(uc_engine *uc, int regid, const void *value);
|
||||
@regid: register ID that is to be retrieved.
|
||||
@value: pointer to a variable storing the register value.
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
@return UC_ERR_OK on success; UC_ERR_ARG if register number or value is invalid
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_read(uc_engine *uc, int regid, void *value);
|
||||
|
||||
/*
|
||||
Write to register.
|
||||
|
||||
@uc: handle returned by uc_open()
|
||||
@regid: register ID that is to be modified.
|
||||
@value: pointer to the value that will be written to register @regid
|
||||
@size: size of value being written; on return, size of value written
|
||||
|
||||
@return UC_ERR_OK on success; UC_ERR_ARG if register number or value is
|
||||
invalid; UC_ERR_NOMEM if value is not large enough.
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_write2(uc_engine *uc, int regid, const void *value, size_t *size);
|
||||
|
||||
/*
|
||||
Read register value.
|
||||
|
||||
@uc: handle returned by uc_open()
|
||||
@regid: register ID that is to be retrieved.
|
||||
@value: pointer to a variable storing the register value.
|
||||
@size: size of value buffer; on return, size of value read
|
||||
|
||||
@return UC_ERR_OK on success; UC_ERR_ARG if register number or value is
|
||||
invalid; UC_ERR_NOMEM if value is not large enough.
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_read2(uc_engine *uc, int regid, void *value, size_t *size);
|
||||
|
||||
/*
|
||||
Write multiple register values.
|
||||
|
||||
@uc: handle returned by uc_open()
|
||||
@rges: array of register IDs to store
|
||||
@value: pointer to array of register values
|
||||
@regs: array of register IDs to store
|
||||
@vals: array of pointers to register values
|
||||
@count: length of both *regs and *vals
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
@return UC_ERR_OK on success; UC_ERR_ARG if some register number or value is
|
||||
invalid
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_write_batch(uc_engine *uc, int *regs, void *const *vals,
|
||||
@@ -819,16 +845,49 @@ uc_err uc_reg_write_batch(uc_engine *uc, int *regs, void *const *vals,
|
||||
Read multiple register values.
|
||||
|
||||
@uc: handle returned by uc_open()
|
||||
@rges: array of register IDs to retrieve
|
||||
@value: pointer to array of values to hold registers
|
||||
@regs: array of register IDs to retrieve
|
||||
@vals: array of pointers to register values
|
||||
@count: length of both *regs and *vals
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
@return UC_ERR_OK on success; UC_ERR_ARG if some register number or value is
|
||||
invalid
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_read_batch(uc_engine *uc, int *regs, void **vals, int count);
|
||||
|
||||
/*
|
||||
Write multiple register values.
|
||||
|
||||
@uc: handle returned by uc_open()
|
||||
@regs: array of register IDs to store
|
||||
@value: array of pointers to register values
|
||||
@sizes: array of sizes of each value; on return, sizes of each stored register
|
||||
@count: length of *regs, *vals and *sizes
|
||||
|
||||
@return UC_ERR_OK on success; UC_ERR_ARG if some register number or value is
|
||||
invalid; UC_ERR_NOMEM if some value is not large enough.
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_write_batch2(uc_engine *uc, int *regs, const void *const *vals,
|
||||
size_t *sizes, int count);
|
||||
|
||||
/*
|
||||
Read multiple register values.
|
||||
|
||||
@uc: handle returned by uc_open()
|
||||
@regs: array of register IDs to retrieve
|
||||
@value: pointer to array of values to hold registers
|
||||
@sizes: array of sizes of each value; on return, sizes of each retrieved
|
||||
register
|
||||
@count: length of *regs, *vals and *sizes
|
||||
|
||||
@return UC_ERR_OK on success; UC_ERR_ARG if some register number or value is
|
||||
invalid; UC_ERR_NOMEM if some value is not large enough.
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_read_batch2(uc_engine *uc, int *regs, void *const *vals,
|
||||
size_t *sizes, int count);
|
||||
|
||||
/*
|
||||
Write to a range of bytes in memory.
|
||||
|
||||
@@ -1131,10 +1190,9 @@ uc_err uc_context_save(uc_engine *uc, uc_context *context);
|
||||
|
||||
@ctx: handle returned by uc_context_alloc()
|
||||
@regid: register ID that is to be modified.
|
||||
@value: pointer to the value that will set to register @regid
|
||||
@value: pointer to the value that will be written to register @regid
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
@return UC_ERR_OK on success; UC_ERR_ARG if register number or value is invalid
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_reg_write(uc_context *ctx, int regid, const void *value);
|
||||
@@ -1146,12 +1204,41 @@ uc_err uc_context_reg_write(uc_context *ctx, int regid, const void *value);
|
||||
@regid: register ID that is to be retrieved.
|
||||
@value: pointer to a variable storing the register value.
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
@return UC_ERR_OK on success; UC_ERR_ARG if register number or value is invalid
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_reg_read(uc_context *ctx, int regid, void *value);
|
||||
|
||||
/*
|
||||
Write value to a register of a context.
|
||||
|
||||
@ctx: handle returned by uc_context_alloc()
|
||||
@regid: register ID that is to be modified.
|
||||
@value: pointer to the value that will be written to register @regid
|
||||
@size: size of value being written; on return, size of value written
|
||||
|
||||
@return UC_ERR_OK on success; UC_ERR_ARG if register number or value is
|
||||
invalid; UC_ERR_NOMEM if value is not large enough.
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_reg_write2(uc_context *ctx, int regid, const void *value,
|
||||
size_t *size);
|
||||
|
||||
/*
|
||||
Read register value from a context.
|
||||
|
||||
@ctx: handle returned by uc_context_alloc()
|
||||
@regid: register ID that is to be retrieved.
|
||||
@value: pointer to a variable storing the register value.
|
||||
@size: size of value buffer; on return, size of value read
|
||||
|
||||
@return UC_ERR_OK on success; UC_ERR_ARG if register number or value is
|
||||
invalid; UC_ERR_NOMEM if value is not large enough.
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_reg_read2(uc_context *ctx, int regid, void *value,
|
||||
size_t *size);
|
||||
|
||||
/*
|
||||
Write multiple register values to registers of a context.
|
||||
|
||||
@@ -1182,6 +1269,40 @@ UNICORN_EXPORT
|
||||
uc_err uc_context_reg_read_batch(uc_context *ctx, int *regs, void **vals,
|
||||
int count);
|
||||
|
||||
/*
|
||||
Write multiple register values to registers of a context.
|
||||
|
||||
@ctx: handle returned by uc_context_alloc()
|
||||
@regs: array of register IDs to store
|
||||
@value: array of pointers to register values
|
||||
@sizes: array of sizes of each value; on return, sizes of each stored register
|
||||
@count: length of *regs, *vals and *sizes
|
||||
|
||||
@return UC_ERR_OK on success; UC_ERR_ARG if some register number or value is
|
||||
invalid; UC_ERR_NOMEM if some value is not large enough.
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_reg_write_batch2(uc_context *ctx, int *regs,
|
||||
const void *const *vals, size_t *sizes,
|
||||
int count);
|
||||
|
||||
/*
|
||||
Read multiple register values from a context.
|
||||
|
||||
@ctx: handle returned by uc_context_alloc()
|
||||
@regs: array of register IDs to retrieve
|
||||
@value: pointer to array of values to hold registers
|
||||
@sizes: array of sizes of each value; on return, sizes of each retrieved
|
||||
register
|
||||
@count: length of *regs, *vals and *sizes
|
||||
|
||||
@return UC_ERR_OK on success; UC_ERR_ARG if some register number or value is
|
||||
invalid; UC_ERR_NOMEM if some value is not large enough.
|
||||
*/
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_reg_read_batch2(uc_context *ctx, int *regs, void *const *vals,
|
||||
size_t *sizes, int count);
|
||||
|
||||
/*
|
||||
Restore the current CPU context from a saved copy.
|
||||
This API should be used to roll the CPU context back to a previous
|
||||
|
||||
@@ -5,23 +5,23 @@
|
||||
#define UC_QEMU_TARGET_ARM_H
|
||||
|
||||
// functions to read & write registers
|
||||
int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count);
|
||||
int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
int count);
|
||||
int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count);
|
||||
int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
int count);
|
||||
int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
size_t *sizes, int count);
|
||||
int arm_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
size_t *sizes, int count);
|
||||
int arm64_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
|
||||
int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count);
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count);
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
|
||||
void arm_reg_reset(struct uc_struct *uc);
|
||||
void arm64_reg_reset(struct uc_struct *uc);
|
||||
|
||||
@@ -138,97 +138,127 @@ static uc_err write_cp_reg(CPUARMState *env, uc_arm64_cp_reg *cp)
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value)
|
||||
static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value,
|
||||
size_t *size)
|
||||
{
|
||||
uc_err ret = UC_ERR_OK;
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_ARM64_REG_V0 && regid <= UC_ARM64_REG_V31) {
|
||||
regid += UC_ARM64_REG_Q0 - UC_ARM64_REG_V0;
|
||||
}
|
||||
if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28) {
|
||||
*(int64_t *)value = env->xregs[regid - UC_ARM64_REG_X0];
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->xregs[regid - UC_ARM64_REG_X0];
|
||||
} else if (regid >= UC_ARM64_REG_W0 && regid <= UC_ARM64_REG_W30) {
|
||||
*(int32_t *)value = READ_DWORD(env->xregs[regid - UC_ARM64_REG_W0]);
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = READ_DWORD(env->xregs[regid - UC_ARM64_REG_W0]);
|
||||
} else if (regid >= UC_ARM64_REG_Q0 && regid <= UC_ARM64_REG_Q31) { // FIXME
|
||||
CHECK_REG_TYPE(float64[2]);
|
||||
float64 *dst = (float64 *)value;
|
||||
uint32_t reg_index = regid - UC_ARM64_REG_Q0;
|
||||
dst[0] = env->vfp.zregs[reg_index].d[0];
|
||||
dst[1] = env->vfp.zregs[reg_index].d[1];
|
||||
} else if (regid >= UC_ARM64_REG_D0 && regid <= UC_ARM64_REG_D31) {
|
||||
CHECK_REG_TYPE(float64);
|
||||
*(float64 *)value = env->vfp.zregs[regid - UC_ARM64_REG_D0].d[0];
|
||||
} else if (regid >= UC_ARM64_REG_S0 && regid <= UC_ARM64_REG_S31) {
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value =
|
||||
READ_DWORD(env->vfp.zregs[regid - UC_ARM64_REG_S0].d[0]);
|
||||
} else if (regid >= UC_ARM64_REG_H0 && regid <= UC_ARM64_REG_H31) {
|
||||
CHECK_REG_TYPE(int16_t);
|
||||
*(int16_t *)value =
|
||||
READ_WORD(env->vfp.zregs[regid - UC_ARM64_REG_H0].d[0]);
|
||||
} else if (regid >= UC_ARM64_REG_B0 && regid <= UC_ARM64_REG_B31) {
|
||||
CHECK_REG_TYPE(int8_t);
|
||||
*(int8_t *)value =
|
||||
READ_BYTE_L(env->vfp.zregs[regid - UC_ARM64_REG_B0].d[0]);
|
||||
} else if (regid >= UC_ARM64_REG_ELR_EL0 && regid <= UC_ARM64_REG_ELR_EL3) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->elr_el[regid - UC_ARM64_REG_ELR_EL0];
|
||||
} else if (regid >= UC_ARM64_REG_SP_EL0 && regid <= UC_ARM64_REG_SP_EL3) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->sp_el[regid - UC_ARM64_REG_SP_EL0];
|
||||
} else if (regid >= UC_ARM64_REG_ESR_EL0 && regid <= UC_ARM64_REG_ESR_EL3) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->cp15.esr_el[regid - UC_ARM64_REG_ESR_EL0];
|
||||
} else if (regid >= UC_ARM64_REG_FAR_EL0 && regid <= UC_ARM64_REG_FAR_EL3) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->cp15.far_el[regid - UC_ARM64_REG_FAR_EL0];
|
||||
} else if (regid >= UC_ARM64_REG_VBAR_EL0 &&
|
||||
regid <= UC_ARM64_REG_VBAR_EL3) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->cp15.vbar_el[regid - UC_ARM64_REG_VBAR_EL0];
|
||||
} else {
|
||||
switch (regid) {
|
||||
default:
|
||||
break;
|
||||
case UC_ARM64_REG_CPACR_EL1:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->cp15.cpacr_el1;
|
||||
break;
|
||||
case UC_ARM64_REG_TPIDR_EL0:
|
||||
*(int64_t *)value = env->cp15.tpidr_el[0];
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->cp15.tpidr_el[0];
|
||||
break;
|
||||
case UC_ARM64_REG_TPIDRRO_EL0:
|
||||
*(int64_t *)value = env->cp15.tpidrro_el[0];
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->cp15.tpidrro_el[0];
|
||||
break;
|
||||
case UC_ARM64_REG_TPIDR_EL1:
|
||||
*(int64_t *)value = env->cp15.tpidr_el[1];
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->cp15.tpidr_el[1];
|
||||
break;
|
||||
case UC_ARM64_REG_X29:
|
||||
*(int64_t *)value = env->xregs[29];
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->xregs[29];
|
||||
break;
|
||||
case UC_ARM64_REG_X30:
|
||||
*(int64_t *)value = env->xregs[30];
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->xregs[30];
|
||||
break;
|
||||
case UC_ARM64_REG_PC:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->pc;
|
||||
break;
|
||||
case UC_ARM64_REG_SP:
|
||||
*(int64_t *)value = env->xregs[31];
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->xregs[31];
|
||||
break;
|
||||
case UC_ARM64_REG_NZCV:
|
||||
*(int32_t *)value = cpsr_read(env) & CPSR_NZCV;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = cpsr_read(env) & CPSR_NZCV;
|
||||
break;
|
||||
case UC_ARM64_REG_PSTATE:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = pstate_read(env);
|
||||
break;
|
||||
case UC_ARM64_REG_TTBR0_EL1:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->cp15.ttbr0_el[1];
|
||||
break;
|
||||
case UC_ARM64_REG_TTBR1_EL1:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->cp15.ttbr1_el[1];
|
||||
break;
|
||||
case UC_ARM64_REG_PAR_EL1:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->cp15.par_el[1];
|
||||
break;
|
||||
case UC_ARM64_REG_MAIR_EL1:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->cp15.mair_el[1];
|
||||
break;
|
||||
case UC_ARM64_REG_CP_REG:
|
||||
CHECK_REG_TYPE(uc_arm64_cp_reg);
|
||||
ret = read_cp_reg(env, (uc_arm64_cp_reg *)value);
|
||||
break;
|
||||
case UC_ARM64_REG_FPCR:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = vfp_get_fpcr(env);
|
||||
break;
|
||||
case UC_ARM64_REG_FPSR:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = vfp_get_fpsr(env);
|
||||
break;
|
||||
}
|
||||
@@ -237,98 +267,128 @@ static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value)
|
||||
static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value,
|
||||
size_t *size)
|
||||
{
|
||||
uc_err ret = UC_ERR_OK;
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_ARM64_REG_V0 && regid <= UC_ARM64_REG_V31) {
|
||||
regid += UC_ARM64_REG_Q0 - UC_ARM64_REG_V0;
|
||||
}
|
||||
if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->xregs[regid - UC_ARM64_REG_X0] = *(uint64_t *)value;
|
||||
} else if (regid >= UC_ARM64_REG_W0 && regid <= UC_ARM64_REG_W30) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
WRITE_DWORD(env->xregs[regid - UC_ARM64_REG_W0], *(uint32_t *)value);
|
||||
} else if (regid >= UC_ARM64_REG_Q0 && regid <= UC_ARM64_REG_Q31) {
|
||||
CHECK_REG_TYPE(float64[2]);
|
||||
float64 *src = (float64 *)value;
|
||||
uint32_t reg_index = regid - UC_ARM64_REG_Q0;
|
||||
env->vfp.zregs[reg_index].d[0] = src[0];
|
||||
env->vfp.zregs[reg_index].d[1] = src[1];
|
||||
} else if (regid >= UC_ARM64_REG_D0 && regid <= UC_ARM64_REG_D31) {
|
||||
CHECK_REG_TYPE(float64);
|
||||
env->vfp.zregs[regid - UC_ARM64_REG_D0].d[0] = *(float64 *)value;
|
||||
} else if (regid >= UC_ARM64_REG_S0 && regid <= UC_ARM64_REG_S31) {
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
WRITE_DWORD(env->vfp.zregs[regid - UC_ARM64_REG_S0].d[0],
|
||||
*(int32_t *)value);
|
||||
} else if (regid >= UC_ARM64_REG_H0 && regid <= UC_ARM64_REG_H31) {
|
||||
CHECK_REG_TYPE(int16_t);
|
||||
WRITE_WORD(env->vfp.zregs[regid - UC_ARM64_REG_H0].d[0],
|
||||
*(int16_t *)value);
|
||||
} else if (regid >= UC_ARM64_REG_B0 && regid <= UC_ARM64_REG_B31) {
|
||||
CHECK_REG_TYPE(int8_t);
|
||||
WRITE_BYTE_L(env->vfp.zregs[regid - UC_ARM64_REG_B0].d[0],
|
||||
*(int8_t *)value);
|
||||
} else if (regid >= UC_ARM64_REG_ELR_EL0 && regid <= UC_ARM64_REG_ELR_EL3) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->elr_el[regid - UC_ARM64_REG_ELR_EL0] = *(uint64_t *)value;
|
||||
} else if (regid >= UC_ARM64_REG_SP_EL0 && regid <= UC_ARM64_REG_SP_EL3) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->sp_el[regid - UC_ARM64_REG_SP_EL0] = *(uint64_t *)value;
|
||||
} else if (regid >= UC_ARM64_REG_ESR_EL0 && regid <= UC_ARM64_REG_ESR_EL3) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->cp15.esr_el[regid - UC_ARM64_REG_ESR_EL0] = *(uint64_t *)value;
|
||||
} else if (regid >= UC_ARM64_REG_FAR_EL0 && regid <= UC_ARM64_REG_FAR_EL3) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->cp15.far_el[regid - UC_ARM64_REG_FAR_EL0] = *(uint64_t *)value;
|
||||
} else if (regid >= UC_ARM64_REG_VBAR_EL0 &&
|
||||
regid <= UC_ARM64_REG_VBAR_EL3) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->cp15.vbar_el[regid - UC_ARM64_REG_VBAR_EL0] = *(uint64_t *)value;
|
||||
} else {
|
||||
switch (regid) {
|
||||
default:
|
||||
break;
|
||||
case UC_ARM64_REG_CPACR_EL1:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->cp15.cpacr_el1 = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_ARM64_REG_TPIDR_EL0:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->cp15.tpidr_el[0] = *(uint64_t *)value;
|
||||
break;
|
||||
case UC_ARM64_REG_TPIDRRO_EL0:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->cp15.tpidrro_el[0] = *(uint64_t *)value;
|
||||
break;
|
||||
case UC_ARM64_REG_TPIDR_EL1:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->cp15.tpidr_el[1] = *(uint64_t *)value;
|
||||
break;
|
||||
case UC_ARM64_REG_X29:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->xregs[29] = *(uint64_t *)value;
|
||||
break;
|
||||
case UC_ARM64_REG_X30:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->xregs[30] = *(uint64_t *)value;
|
||||
break;
|
||||
case UC_ARM64_REG_PC:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->pc = *(uint64_t *)value;
|
||||
break;
|
||||
case UC_ARM64_REG_SP:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->xregs[31] = *(uint64_t *)value;
|
||||
break;
|
||||
case UC_ARM64_REG_NZCV:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
cpsr_write(env, *(uint32_t *)value, CPSR_NZCV, CPSRWriteRaw);
|
||||
break;
|
||||
case UC_ARM64_REG_PSTATE:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
pstate_write(env, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM64_REG_TTBR0_EL1:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->cp15.ttbr0_el[1] = *(uint64_t *)value;
|
||||
break;
|
||||
case UC_ARM64_REG_TTBR1_EL1:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->cp15.ttbr1_el[1] = *(uint64_t *)value;
|
||||
break;
|
||||
case UC_ARM64_REG_PAR_EL1:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->cp15.par_el[1] = *(uint64_t *)value;
|
||||
break;
|
||||
case UC_ARM64_REG_MAIR_EL1:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->cp15.mair_el[1] = *(uint64_t *)value;
|
||||
break;
|
||||
case UC_ARM64_REG_CP_REG:
|
||||
CHECK_REG_TYPE(uc_arm64_cp_reg);
|
||||
ret = write_cp_reg(env, (uc_arm64_cp_reg *)value);
|
||||
arm_rebuild_hflags(env);
|
||||
break;
|
||||
case UC_ARM64_REG_FPCR:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
vfp_set_fpcr(env, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM64_REG_FPSR:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
vfp_set_fpsr(env, *(uint32_t *)value);
|
||||
break;
|
||||
}
|
||||
@@ -337,8 +397,8 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count)
|
||||
int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
size_t *sizes, int count)
|
||||
{
|
||||
CPUARMState *env = &(ARM_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
@@ -347,7 +407,7 @@ int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
err = reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -356,8 +416,8 @@ int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
int count)
|
||||
int arm64_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUARMState *env = &(ARM_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
@@ -366,7 +426,7 @@ int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
err = reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -383,10 +443,10 @@ int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
DEFAULT_VISIBILITY
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
int arm64eb_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count)
|
||||
void *const *vals, size_t *sizes, int count)
|
||||
#else
|
||||
int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count)
|
||||
void *const *vals, size_t *sizes, int count)
|
||||
#endif
|
||||
{
|
||||
CPUARMState *env = (CPUARMState *)ctx->data;
|
||||
@@ -396,22 +456,22 @@ int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
err = reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
int arm64eb_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
#else
|
||||
int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
#endif
|
||||
{
|
||||
CPUARMState *env = (CPUARMState *)ctx->data;
|
||||
@@ -421,13 +481,13 @@ int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
err = reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
static int arm64_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
||||
|
||||
@@ -206,20 +206,25 @@ static uc_err write_cp_reg(CPUARMState *env, uc_arm_cp_reg *cp)
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value)
|
||||
static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value,
|
||||
size_t *size)
|
||||
{
|
||||
uc_err ret = UC_ERR_OK;
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->regs[regid - UC_ARM_REG_R0];
|
||||
} else if (regid >= UC_ARM_REG_Q0 && regid <= UC_ARM_REG_Q15) {
|
||||
CHECK_REG_TYPE(uint64_t[2]);
|
||||
uint32_t reg_index = regid - UC_ARM_REG_Q0;
|
||||
*(uint64_t *)value = env->vfp.zregs[reg_index].d[0];
|
||||
*(((uint64_t *)value) + 1) = env->vfp.zregs[reg_index].d[1];
|
||||
} else if (regid >= UC_ARM_REG_D0 && regid <= UC_ARM_REG_D31) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
uint32_t reg_index = regid - UC_ARM_REG_D0;
|
||||
*(uint64_t *)value = env->vfp.zregs[reg_index / 2].d[reg_index & 1];
|
||||
} else if (regid >= UC_ARM_REG_S0 && regid <= UC_ARM_REG_S31) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
uint32_t reg_index = regid - UC_ARM_REG_S0;
|
||||
uint64_t reg_value = env->vfp.zregs[reg_index / 4].d[reg_index % 4 / 2];
|
||||
|
||||
@@ -232,88 +237,115 @@ static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value)
|
||||
switch (regid) {
|
||||
case UC_ARM_REG_APSR:
|
||||
if (arm_feature(env, ARM_FEATURE_M)) {
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value = v7m_mrs_xpsr(env, 0);
|
||||
} else {
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value =
|
||||
cpsr_read(env) & (CPSR_NZCV | CPSR_Q | CPSR_GE);
|
||||
}
|
||||
break;
|
||||
case UC_ARM_REG_APSR_NZCV:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value = cpsr_read(env) & CPSR_NZCV;
|
||||
break;
|
||||
case UC_ARM_REG_CPSR:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value = cpsr_read(env);
|
||||
break;
|
||||
case UC_ARM_REG_SPSR:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value = env->spsr;
|
||||
break;
|
||||
// case UC_ARM_REG_SP:
|
||||
case UC_ARM_REG_R13:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value = env->regs[13];
|
||||
break;
|
||||
// case UC_ARM_REG_LR:
|
||||
case UC_ARM_REG_R14:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value = env->regs[14];
|
||||
break;
|
||||
// case UC_ARM_REG_PC:
|
||||
case UC_ARM_REG_R15:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value = env->regs[15];
|
||||
break;
|
||||
case UC_ARM_REG_C1_C0_2:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value = env->cp15.cpacr_el1;
|
||||
break;
|
||||
case UC_ARM_REG_C13_C0_3:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value = env->cp15.tpidrro_el[0];
|
||||
break;
|
||||
case UC_ARM_REG_FPEXC:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value = env->vfp.xregs[ARM_VFP_FPEXC];
|
||||
break;
|
||||
case UC_ARM_REG_FPSCR:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value = vfp_get_fpscr(env);
|
||||
break;
|
||||
case UC_ARM_REG_FPSID:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value = env->vfp.xregs[ARM_VFP_FPSID];
|
||||
break;
|
||||
case UC_ARM_REG_IPSR:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value = v7m_mrs_xpsr(env, 5);
|
||||
break;
|
||||
case UC_ARM_REG_MSP:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = helper_v7m_mrs(env, 8);
|
||||
break;
|
||||
case UC_ARM_REG_PSP:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = helper_v7m_mrs(env, 9);
|
||||
break;
|
||||
case UC_ARM_REG_IAPSR:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value = v7m_mrs_xpsr(env, 1);
|
||||
break;
|
||||
case UC_ARM_REG_EAPSR:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value = v7m_mrs_xpsr(env, 2);
|
||||
break;
|
||||
case UC_ARM_REG_XPSR:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value = v7m_mrs_xpsr(env, 3);
|
||||
break;
|
||||
case UC_ARM_REG_EPSR:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value = v7m_mrs_xpsr(env, 6);
|
||||
break;
|
||||
case UC_ARM_REG_IEPSR:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
*(int32_t *)value = v7m_mrs_xpsr(env, 7);
|
||||
break;
|
||||
case UC_ARM_REG_PRIMASK:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = helper_v7m_mrs(env, 16);
|
||||
break;
|
||||
case UC_ARM_REG_BASEPRI:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = helper_v7m_mrs(env, 17);
|
||||
break;
|
||||
case UC_ARM_REG_BASEPRI_MAX:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = helper_v7m_mrs(env, 18);
|
||||
break;
|
||||
case UC_ARM_REG_FAULTMASK:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = helper_v7m_mrs(env, 19);
|
||||
break;
|
||||
case UC_ARM_REG_CONTROL:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = helper_v7m_mrs(env, 20);
|
||||
break;
|
||||
case UC_ARM_REG_CP_REG:
|
||||
CHECK_REG_TYPE(uc_arm_cp_reg);
|
||||
ret = read_cp_reg(env, (uc_arm_cp_reg *)value);
|
||||
break;
|
||||
}
|
||||
@@ -322,20 +354,25 @@ static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value)
|
||||
static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value,
|
||||
size_t *size)
|
||||
{
|
||||
uc_err ret = UC_ERR_OK;
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->regs[regid - UC_ARM_REG_R0] = *(uint32_t *)value;
|
||||
} else if (regid >= UC_ARM_REG_Q0 && regid <= UC_ARM_REG_Q15) {
|
||||
CHECK_REG_TYPE(uint64_t[2]);
|
||||
uint32_t reg_index = regid - UC_ARM_REG_Q0;
|
||||
env->vfp.zregs[reg_index].d[0] = *(uint64_t *)value;
|
||||
env->vfp.zregs[reg_index].d[1] = *(((uint64_t *)value) + 1);
|
||||
} else if (regid >= UC_ARM_REG_D0 && regid <= UC_ARM_REG_D31) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
uint32_t reg_index = regid - UC_ARM_REG_D0;
|
||||
env->vfp.zregs[reg_index / 2].d[reg_index & 1] = *(uint64_t *)value;
|
||||
} else if (regid >= UC_ARM_REG_S0 && regid <= UC_ARM_REG_S31) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
uint32_t reg_index = regid - UC_ARM_REG_S0;
|
||||
uint64_t *p_reg_value =
|
||||
&env->vfp.zregs[reg_index / 4].d[reg_index % 4 / 2];
|
||||
@@ -350,6 +387,7 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value)
|
||||
} else {
|
||||
switch (regid) {
|
||||
case UC_ARM_REG_APSR:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
if (!arm_feature(env, ARM_FEATURE_M)) {
|
||||
cpsr_write(env, *(uint32_t *)value,
|
||||
(CPSR_NZCV | CPSR_Q | CPSR_GE), CPSRWriteByUnicorn);
|
||||
@@ -360,26 +398,32 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value)
|
||||
}
|
||||
break;
|
||||
case UC_ARM_REG_APSR_NZCV:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
cpsr_write(env, *(uint32_t *)value, CPSR_NZCV, CPSRWriteByUnicorn);
|
||||
arm_rebuild_hflags(env);
|
||||
break;
|
||||
case UC_ARM_REG_CPSR:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
cpsr_write(env, *(uint32_t *)value, ~0, CPSRWriteByUnicorn);
|
||||
arm_rebuild_hflags(env);
|
||||
break;
|
||||
case UC_ARM_REG_SPSR:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->spsr = *(uint32_t *)value;
|
||||
break;
|
||||
// case UC_ARM_REG_SP:
|
||||
case UC_ARM_REG_R13:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->regs[13] = *(uint32_t *)value;
|
||||
break;
|
||||
// case UC_ARM_REG_LR:
|
||||
case UC_ARM_REG_R14:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->regs[14] = *(uint32_t *)value;
|
||||
break;
|
||||
// case UC_ARM_REG_PC:
|
||||
case UC_ARM_REG_R15:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->pc = (*(uint32_t *)value & ~1);
|
||||
env->thumb = (*(uint32_t *)value & 1);
|
||||
env->uc->thumb = (*(uint32_t *)value & 1);
|
||||
@@ -390,87 +434,114 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value)
|
||||
// break;
|
||||
|
||||
case UC_ARM_REG_C13_C0_3:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
env->cp15.tpidrro_el[0] = *(int32_t *)value;
|
||||
break;
|
||||
case UC_ARM_REG_FPEXC:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
env->vfp.xregs[ARM_VFP_FPEXC] = *(int32_t *)value;
|
||||
break;
|
||||
case UC_ARM_REG_FPSCR:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
vfp_set_fpscr(env, *(int32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_FPSID:
|
||||
CHECK_REG_TYPE(int32_t);
|
||||
env->vfp.xregs[ARM_VFP_FPSID] = *(int32_t *)value;
|
||||
break;
|
||||
case UC_ARM_REG_IPSR:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
v7m_msr_xpsr(env, 0b1000, 5, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_MSP:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
helper_v7m_msr(env, 8, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_PSP:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
helper_v7m_msr(env, 9, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_CONTROL:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
helper_v7m_msr(env, 20, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_EPSR:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
v7m_msr_xpsr(env, 0b1000, 6, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_IEPSR:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
v7m_msr_xpsr(env, 0b1000, 7, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_PRIMASK:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
helper_v7m_msr(env, 16, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_BASEPRI:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
helper_v7m_msr(env, 17, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_BASEPRI_MAX:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
helper_v7m_msr(env, 18, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_FAULTMASK:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
helper_v7m_msr(env, 19, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_APSR_NZCVQ:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
v7m_msr_xpsr(env, 0b1000, 0, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_APSR_G:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
v7m_msr_xpsr(env, 0b0100, 0, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_APSR_NZCVQG:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
v7m_msr_xpsr(env, 0b1100, 0, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_IAPSR:
|
||||
case UC_ARM_REG_IAPSR_NZCVQ:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
v7m_msr_xpsr(env, 0b1000, 1, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_IAPSR_G:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
v7m_msr_xpsr(env, 0b0100, 1, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_IAPSR_NZCVQG:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
v7m_msr_xpsr(env, 0b1100, 1, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_EAPSR:
|
||||
case UC_ARM_REG_EAPSR_NZCVQ:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
v7m_msr_xpsr(env, 0b1000, 2, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_EAPSR_G:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
v7m_msr_xpsr(env, 0b0100, 2, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_EAPSR_NZCVQG:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
v7m_msr_xpsr(env, 0b1100, 2, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_XPSR:
|
||||
case UC_ARM_REG_XPSR_NZCVQ:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
v7m_msr_xpsr(env, 0b1000, 3, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_XPSR_G:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
v7m_msr_xpsr(env, 0b0100, 3, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_XPSR_NZCVQG:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
v7m_msr_xpsr(env, 0b1100, 3, *(uint32_t *)value);
|
||||
break;
|
||||
case UC_ARM_REG_CP_REG:
|
||||
CHECK_REG_TYPE(uc_arm_cp_reg);
|
||||
ret = write_cp_reg(env, (uc_arm_cp_reg *)value);
|
||||
break;
|
||||
}
|
||||
@@ -479,8 +550,8 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count)
|
||||
int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
size_t *sizes, int count)
|
||||
{
|
||||
CPUARMState *env = &(ARM_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
@@ -489,17 +560,20 @@ int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
err = reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
int count)
|
||||
int arm_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUArchState *env = &(ARM_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
@@ -508,7 +582,7 @@ int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
err = reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -519,12 +593,12 @@ int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count)
|
||||
void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUARMState *env = (CPUARMState *)ctx->data;
|
||||
int i;
|
||||
@@ -533,18 +607,21 @@ int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
err = reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUARMState *env = (CPUARMState *)ctx->data;
|
||||
int i;
|
||||
@@ -553,13 +630,13 @@ int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
err = reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
static bool arm_stop_interrupt(struct uc_struct *uc, int intno)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,14 +6,14 @@
|
||||
#define UC_QEMU_TARGET_I386_H
|
||||
|
||||
// functions to read & write registers
|
||||
int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count);
|
||||
int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
int count);
|
||||
int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
size_t *sizes, int count);
|
||||
int x86_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count);
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
|
||||
void x86_reg_reset(struct uc_struct *uc);
|
||||
|
||||
|
||||
@@ -49,71 +49,97 @@ void m68k_reg_reset(struct uc_struct *uc)
|
||||
env->pc = 0;
|
||||
}
|
||||
|
||||
static void reg_read(CPUM68KState *env, unsigned int regid, void *value)
|
||||
static uc_err reg_read(CPUM68KState *env, unsigned int regid, void *value,
|
||||
size_t *size)
|
||||
{
|
||||
if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7)
|
||||
*(int32_t *)value = env->aregs[regid - UC_M68K_REG_A0];
|
||||
else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7)
|
||||
*(int32_t *)value = env->dregs[regid - UC_M68K_REG_D0];
|
||||
else {
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->aregs[regid - UC_M68K_REG_A0];
|
||||
} else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->dregs[regid - UC_M68K_REG_D0];
|
||||
} else {
|
||||
switch (regid) {
|
||||
default:
|
||||
break;
|
||||
case UC_M68K_REG_PC:
|
||||
*(int32_t *)value = env->pc;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->pc;
|
||||
break;
|
||||
case UC_M68K_REG_SR:
|
||||
*(int32_t *)value = env->sr;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->sr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void reg_write(CPUM68KState *env, unsigned int regid, const void *value)
|
||||
static uc_err reg_write(CPUM68KState *env, unsigned int regid,
|
||||
const void *value, size_t *size)
|
||||
{
|
||||
if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7)
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->aregs[regid - UC_M68K_REG_A0] = *(uint32_t *)value;
|
||||
else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7)
|
||||
} else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->dregs[regid - UC_M68K_REG_D0] = *(uint32_t *)value;
|
||||
else {
|
||||
} else {
|
||||
switch (regid) {
|
||||
default:
|
||||
break;
|
||||
case UC_M68K_REG_PC:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->pc = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_M68K_REG_SR:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
cpu_m68k_set_sr(env, *(uint32_t *)value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count)
|
||||
int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
size_t *sizes, int count)
|
||||
{
|
||||
CPUM68KState *env = &(M68K_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
int count)
|
||||
int m68k_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUM68KState *env = &(M68K_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
if (regid == UC_M68K_REG_PC) {
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
@@ -121,39 +147,47 @@ int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count)
|
||||
void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUM68KState *env = (CPUM68KState *)ctx->data;
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
int m68k_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUM68KState *env = (CPUM68KState *)ctx->data;
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
static int m68k_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
#define UC_QEMU_TARGET_M68K_H
|
||||
|
||||
// functions to read & write registers
|
||||
int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count);
|
||||
int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
int count);
|
||||
int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
size_t *sizes, int count);
|
||||
int m68k_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count);
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
int m68k_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
|
||||
void m68k_reg_reset(struct uc_struct *uc);
|
||||
|
||||
|
||||
@@ -59,99 +59,127 @@ void mips_reg_reset(struct uc_struct *uc)
|
||||
env->active_tc.PC = 0;
|
||||
}
|
||||
|
||||
static void reg_read(CPUMIPSState *env, unsigned int regid, void *value)
|
||||
static uc_err reg_read(CPUMIPSState *env, unsigned int regid, void *value,
|
||||
size_t *size)
|
||||
{
|
||||
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31)
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31) {
|
||||
CHECK_REG_TYPE(mipsreg_t);
|
||||
*(mipsreg_t *)value = env->active_tc.gpr[regid - UC_MIPS_REG_0];
|
||||
else {
|
||||
} else {
|
||||
switch (regid) {
|
||||
default:
|
||||
break;
|
||||
case UC_MIPS_REG_HI:
|
||||
CHECK_REG_TYPE(mipsreg_t);
|
||||
*(mipsreg_t *)value = env->active_tc.HI[0];
|
||||
break;
|
||||
case UC_MIPS_REG_LO:
|
||||
CHECK_REG_TYPE(mipsreg_t);
|
||||
*(mipsreg_t *)value = env->active_tc.LO[0];
|
||||
break;
|
||||
case UC_MIPS_REG_PC:
|
||||
CHECK_REG_TYPE(mipsreg_t);
|
||||
*(mipsreg_t *)value = env->active_tc.PC;
|
||||
break;
|
||||
case UC_MIPS_REG_CP0_CONFIG3:
|
||||
CHECK_REG_TYPE(mipsreg_t);
|
||||
*(mipsreg_t *)value = env->CP0_Config3;
|
||||
break;
|
||||
case UC_MIPS_REG_CP0_STATUS:
|
||||
CHECK_REG_TYPE(mipsreg_t);
|
||||
*(mipsreg_t *)value = env->CP0_Status;
|
||||
break;
|
||||
case UC_MIPS_REG_CP0_USERLOCAL:
|
||||
CHECK_REG_TYPE(mipsreg_t);
|
||||
*(mipsreg_t *)value = env->active_tc.CP0_UserLocal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void reg_write(CPUMIPSState *env, unsigned int regid, const void *value)
|
||||
static uc_err reg_write(CPUMIPSState *env, unsigned int regid,
|
||||
const void *value, size_t *size)
|
||||
{
|
||||
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31)
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31) {
|
||||
CHECK_REG_TYPE(mipsreg_t);
|
||||
env->active_tc.gpr[regid - UC_MIPS_REG_0] = *(mipsreg_t *)value;
|
||||
else {
|
||||
} else {
|
||||
switch (regid) {
|
||||
default:
|
||||
break;
|
||||
case UC_MIPS_REG_HI:
|
||||
CHECK_REG_TYPE(mipsreg_t);
|
||||
env->active_tc.HI[0] = *(mipsreg_t *)value;
|
||||
break;
|
||||
case UC_MIPS_REG_LO:
|
||||
CHECK_REG_TYPE(mipsreg_t);
|
||||
env->active_tc.LO[0] = *(mipsreg_t *)value;
|
||||
break;
|
||||
case UC_MIPS_REG_PC:
|
||||
CHECK_REG_TYPE(mipsreg_t);
|
||||
env->active_tc.PC = *(mipsreg_t *)value;
|
||||
break;
|
||||
case UC_MIPS_REG_CP0_CONFIG3:
|
||||
CHECK_REG_TYPE(mipsreg_t);
|
||||
env->CP0_Config3 = *(mipsreg_t *)value;
|
||||
break;
|
||||
case UC_MIPS_REG_CP0_STATUS:
|
||||
// TODO: ALL CP0 REGS
|
||||
// https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00090-2B-MIPS32PRA-AFP-06.02.pdf
|
||||
// https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00582-2B-microMIPS32-AFP-05.04.pdf
|
||||
CHECK_REG_TYPE(mipsreg_t);
|
||||
env->CP0_Status = *(mipsreg_t *)value;
|
||||
compute_hflags(env);
|
||||
break;
|
||||
case UC_MIPS_REG_CP0_USERLOCAL:
|
||||
CHECK_REG_TYPE(mipsreg_t);
|
||||
env->active_tc.CP0_UserLocal = *(mipsreg_t *)value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count)
|
||||
int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
size_t *sizes, int count)
|
||||
{
|
||||
CPUMIPSState *env = &(MIPS_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
int count)
|
||||
int mips_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUMIPSState *env = &(MIPS_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
if (regid == UC_MIPS_REG_PC) {
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
@@ -159,69 +187,78 @@ int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
#ifdef TARGET_MIPS64
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
int mips64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count)
|
||||
void *const *vals, size_t *sizes, int count)
|
||||
#else
|
||||
int mips64el_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count)
|
||||
void *const *vals, size_t *sizes, int count)
|
||||
#endif
|
||||
#else // if TARGET_MIPS
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
int mips_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count)
|
||||
void *const *vals, size_t *sizes, int count)
|
||||
#else
|
||||
int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count)
|
||||
void *const *vals, size_t *sizes, int count)
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
CPUMIPSState *env = (CPUMIPSState *)ctx->data;
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
#ifdef TARGET_MIPS64
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
int mips64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
#else
|
||||
int mips64el_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
const void *const *vals, size_t *sizes,
|
||||
int count)
|
||||
#endif
|
||||
#else // if TARGET_MIPS
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
int mips_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
#else
|
||||
int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
CPUMIPSState *env = (CPUMIPSState *)ctx->data;
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
static int mips_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
||||
|
||||
@@ -5,27 +5,28 @@
|
||||
#define UC_QEMU_TARGET_MIPS_H
|
||||
|
||||
// functions to read & write registers
|
||||
int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count);
|
||||
int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
int count);
|
||||
int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
size_t *sizes, int count);
|
||||
int mips_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
|
||||
int mips_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count);
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
int mips_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count);
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
int mips64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count);
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
int mips64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
int mips64el_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count);
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
int mips64el_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes,
|
||||
int count);
|
||||
|
||||
void mips_reg_reset(struct uc_struct *uc);
|
||||
|
||||
|
||||
@@ -146,64 +146,31 @@ void ppc_reg_reset(struct uc_struct *uc)
|
||||
}
|
||||
|
||||
// http://www.csit-sun.pub.ro/~cpop/Documentatie_SMP/Motorola_PowerPC/PowerPc/GenInfo/pemch2.pdf
|
||||
static void reg_read(CPUPPCState *env, unsigned int regid, void *value)
|
||||
static uc_err reg_read(CPUPPCState *env, unsigned int regid, void *value,
|
||||
size_t *size)
|
||||
{
|
||||
uint32_t val;
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_PPC_REG_0 && regid <= UC_PPC_REG_31)
|
||||
if (regid >= UC_PPC_REG_0 && regid <= UC_PPC_REG_31) {
|
||||
CHECK_REG_TYPE(ppcreg_t);
|
||||
*(ppcreg_t *)value = env->gpr[regid - UC_PPC_REG_0];
|
||||
else {
|
||||
} else if (regid >= UC_PPC_REG_FPR0 && regid <= UC_PPC_REG_FPR31) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->vsr[regid - UC_PPC_REG_FPR0].VsrD(0);
|
||||
} else if (regid >= UC_PPC_REG_CR0 && regid <= UC_PPC_REG_CR7) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->crf[regid - UC_PPC_REG_CR0];
|
||||
} else {
|
||||
switch (regid) {
|
||||
default:
|
||||
break;
|
||||
case UC_PPC_REG_PC:
|
||||
CHECK_REG_TYPE(ppcreg_t);
|
||||
*(ppcreg_t *)value = env->nip;
|
||||
break;
|
||||
case UC_PPC_REG_FPR0:
|
||||
case UC_PPC_REG_FPR1:
|
||||
case UC_PPC_REG_FPR2:
|
||||
case UC_PPC_REG_FPR3:
|
||||
case UC_PPC_REG_FPR4:
|
||||
case UC_PPC_REG_FPR5:
|
||||
case UC_PPC_REG_FPR6:
|
||||
case UC_PPC_REG_FPR7:
|
||||
case UC_PPC_REG_FPR8:
|
||||
case UC_PPC_REG_FPR9:
|
||||
case UC_PPC_REG_FPR10:
|
||||
case UC_PPC_REG_FPR11:
|
||||
case UC_PPC_REG_FPR12:
|
||||
case UC_PPC_REG_FPR13:
|
||||
case UC_PPC_REG_FPR14:
|
||||
case UC_PPC_REG_FPR15:
|
||||
case UC_PPC_REG_FPR16:
|
||||
case UC_PPC_REG_FPR17:
|
||||
case UC_PPC_REG_FPR18:
|
||||
case UC_PPC_REG_FPR19:
|
||||
case UC_PPC_REG_FPR20:
|
||||
case UC_PPC_REG_FPR21:
|
||||
case UC_PPC_REG_FPR22:
|
||||
case UC_PPC_REG_FPR23:
|
||||
case UC_PPC_REG_FPR24:
|
||||
case UC_PPC_REG_FPR25:
|
||||
case UC_PPC_REG_FPR26:
|
||||
case UC_PPC_REG_FPR27:
|
||||
case UC_PPC_REG_FPR28:
|
||||
case UC_PPC_REG_FPR29:
|
||||
case UC_PPC_REG_FPR30:
|
||||
case UC_PPC_REG_FPR31:
|
||||
*(uint64_t *)value = env->vsr[regid - UC_PPC_REG_FPR0].VsrD(0);
|
||||
break;
|
||||
case UC_PPC_REG_CR0:
|
||||
case UC_PPC_REG_CR1:
|
||||
case UC_PPC_REG_CR2:
|
||||
case UC_PPC_REG_CR3:
|
||||
case UC_PPC_REG_CR4:
|
||||
case UC_PPC_REG_CR5:
|
||||
case UC_PPC_REG_CR6:
|
||||
case UC_PPC_REG_CR7:
|
||||
*(uint32_t *)value = env->crf[regid - UC_PPC_REG_CR0];
|
||||
break;
|
||||
case UC_PPC_REG_CR:
|
||||
case UC_PPC_REG_CR: {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
uint32_t val;
|
||||
val = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
val <<= 4;
|
||||
@@ -211,138 +178,124 @@ static void reg_read(CPUPPCState *env, unsigned int regid, void *value)
|
||||
}
|
||||
*(uint32_t *)value = val;
|
||||
break;
|
||||
}
|
||||
case UC_PPC_REG_LR:
|
||||
CHECK_REG_TYPE(ppcreg_t);
|
||||
*(ppcreg_t *)value = env->lr;
|
||||
break;
|
||||
case UC_PPC_REG_CTR:
|
||||
CHECK_REG_TYPE(ppcreg_t);
|
||||
*(ppcreg_t *)value = env->ctr;
|
||||
break;
|
||||
case UC_PPC_REG_MSR:
|
||||
CHECK_REG_TYPE(ppcreg_t);
|
||||
*(ppcreg_t *)value = env->msr;
|
||||
break;
|
||||
case UC_PPC_REG_XER:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->xer;
|
||||
break;
|
||||
case UC_PPC_REG_FPSCR:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->fpscr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void reg_write(CPUPPCState *env, unsigned int regid, const void *value)
|
||||
static uc_err reg_write(CPUPPCState *env, unsigned int regid, const void *value,
|
||||
size_t *size)
|
||||
{
|
||||
uint32_t val;
|
||||
int i;
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_PPC_REG_0 && regid <= UC_PPC_REG_31)
|
||||
if (regid >= UC_PPC_REG_0 && regid <= UC_PPC_REG_31) {
|
||||
CHECK_REG_TYPE(ppcreg_t);
|
||||
env->gpr[regid - UC_PPC_REG_0] = *(ppcreg_t *)value;
|
||||
else {
|
||||
} else if (regid >= UC_PPC_REG_FPR0 && regid <= UC_PPC_REG_FPR31) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->vsr[regid - UC_PPC_REG_FPR0].VsrD(0) = *(uint64_t *)value;
|
||||
} else if (regid >= UC_PPC_REG_CR0 && regid <= UC_PPC_REG_CR7) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->crf[regid - UC_PPC_REG_CR0] = (*(uint32_t *)value) & 0b1111;
|
||||
} else {
|
||||
switch (regid) {
|
||||
default:
|
||||
break;
|
||||
case UC_PPC_REG_PC:
|
||||
CHECK_REG_TYPE(ppcreg_t);
|
||||
env->nip = *(ppcreg_t *)value;
|
||||
break;
|
||||
case UC_PPC_REG_FPR0:
|
||||
case UC_PPC_REG_FPR1:
|
||||
case UC_PPC_REG_FPR2:
|
||||
case UC_PPC_REG_FPR3:
|
||||
case UC_PPC_REG_FPR4:
|
||||
case UC_PPC_REG_FPR5:
|
||||
case UC_PPC_REG_FPR6:
|
||||
case UC_PPC_REG_FPR7:
|
||||
case UC_PPC_REG_FPR8:
|
||||
case UC_PPC_REG_FPR9:
|
||||
case UC_PPC_REG_FPR10:
|
||||
case UC_PPC_REG_FPR11:
|
||||
case UC_PPC_REG_FPR12:
|
||||
case UC_PPC_REG_FPR13:
|
||||
case UC_PPC_REG_FPR14:
|
||||
case UC_PPC_REG_FPR15:
|
||||
case UC_PPC_REG_FPR16:
|
||||
case UC_PPC_REG_FPR17:
|
||||
case UC_PPC_REG_FPR18:
|
||||
case UC_PPC_REG_FPR19:
|
||||
case UC_PPC_REG_FPR20:
|
||||
case UC_PPC_REG_FPR21:
|
||||
case UC_PPC_REG_FPR22:
|
||||
case UC_PPC_REG_FPR23:
|
||||
case UC_PPC_REG_FPR24:
|
||||
case UC_PPC_REG_FPR25:
|
||||
case UC_PPC_REG_FPR26:
|
||||
case UC_PPC_REG_FPR27:
|
||||
case UC_PPC_REG_FPR28:
|
||||
case UC_PPC_REG_FPR29:
|
||||
case UC_PPC_REG_FPR30:
|
||||
case UC_PPC_REG_FPR31:
|
||||
env->vsr[regid - UC_PPC_REG_FPR0].VsrD(0) = *(uint64_t *)value;
|
||||
break;
|
||||
case UC_PPC_REG_CR0:
|
||||
case UC_PPC_REG_CR1:
|
||||
case UC_PPC_REG_CR2:
|
||||
case UC_PPC_REG_CR3:
|
||||
case UC_PPC_REG_CR4:
|
||||
case UC_PPC_REG_CR5:
|
||||
case UC_PPC_REG_CR6:
|
||||
case UC_PPC_REG_CR7:
|
||||
env->crf[regid - UC_PPC_REG_CR0] = (*(uint32_t *)value) & 0b1111;
|
||||
break;
|
||||
case UC_PPC_REG_CR:
|
||||
val = *(uint32_t *)value;
|
||||
case UC_PPC_REG_CR: {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
uint32_t val = *(uint32_t *)value;
|
||||
for (i = 7; i >= 0; i--) {
|
||||
env->crf[i] = val & 0b1111;
|
||||
val >>= 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UC_PPC_REG_LR:
|
||||
CHECK_REG_TYPE(ppcreg_t);
|
||||
env->lr = *(ppcreg_t *)value;
|
||||
break;
|
||||
case UC_PPC_REG_CTR:
|
||||
CHECK_REG_TYPE(ppcreg_t);
|
||||
env->ctr = *(ppcreg_t *)value;
|
||||
break;
|
||||
case UC_PPC_REG_MSR:
|
||||
CHECK_REG_TYPE(ppcreg_t);
|
||||
uc_ppc_store_msr(env, *(ppcreg_t *)value, 0);
|
||||
break;
|
||||
case UC_PPC_REG_XER:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->xer = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_PPC_REG_FPSCR:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
store_fpscr(env, *(uint32_t *)value, 0xffffffff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count)
|
||||
int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
size_t *sizes, int count)
|
||||
{
|
||||
CPUPPCState *env = &(POWERPC_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
int count)
|
||||
int ppc_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUPPCState *env = &(POWERPC_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
if (regid == UC_PPC_REG_PC) {
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
@@ -350,49 +303,57 @@ int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
#ifdef TARGET_PPC64
|
||||
int ppc64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count)
|
||||
void *const *vals, size_t *sizes, int count)
|
||||
#else
|
||||
int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count)
|
||||
void *const *vals, size_t *sizes, int count)
|
||||
#endif
|
||||
{
|
||||
CPUPPCState *env = (CPUPPCState *)ctx->data;
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
#ifdef TARGET_PPC64
|
||||
int ppc64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
#else
|
||||
int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
#endif
|
||||
{
|
||||
CPUPPCState *env = (CPUPPCState *)ctx->data;
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
PowerPCCPU *cpu_ppc_init(struct uc_struct *uc);
|
||||
|
||||
@@ -5,19 +5,19 @@
|
||||
#define UC_QEMU_TARGET_PPC_H
|
||||
|
||||
// functions to read & write registers
|
||||
int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count);
|
||||
int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
int count);
|
||||
int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
size_t *sizes, int count);
|
||||
int ppc_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
|
||||
int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count);
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
int ppc64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count);
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
int ppc64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
|
||||
void ppc_reg_reset(struct uc_struct *uc);
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ static int csrno_map[] = {
|
||||
CSR_HIP, CSR_HTINST, CSR_HGATP, CSR_HTIMEDELTA,
|
||||
CSR_HTIMEDELTAH,
|
||||
};
|
||||
#define csrno_count (sizeof(csrno_map) / sizeof(int))
|
||||
|
||||
RISCVCPU *cpu_riscv_init(struct uc_struct *uc);
|
||||
|
||||
@@ -78,485 +79,134 @@ static void riscv_release(void *ctx)
|
||||
|
||||
void riscv_reg_reset(struct uc_struct *uc) {}
|
||||
|
||||
static void reg_read(CPURISCVState *env, unsigned int regid, void *value)
|
||||
static uc_err reg_read(CPURISCVState *env, unsigned int regid, void *value,
|
||||
size_t *size)
|
||||
{
|
||||
switch (regid) {
|
||||
case UC_RISCV_REG_X0:
|
||||
case UC_RISCV_REG_X1:
|
||||
case UC_RISCV_REG_X2:
|
||||
case UC_RISCV_REG_X3:
|
||||
case UC_RISCV_REG_X4:
|
||||
case UC_RISCV_REG_X5:
|
||||
case UC_RISCV_REG_X6:
|
||||
case UC_RISCV_REG_X7:
|
||||
case UC_RISCV_REG_X8:
|
||||
case UC_RISCV_REG_X9:
|
||||
case UC_RISCV_REG_X10:
|
||||
case UC_RISCV_REG_X11:
|
||||
case UC_RISCV_REG_X12:
|
||||
case UC_RISCV_REG_X13:
|
||||
case UC_RISCV_REG_X14:
|
||||
case UC_RISCV_REG_X15:
|
||||
case UC_RISCV_REG_X16:
|
||||
case UC_RISCV_REG_X17:
|
||||
case UC_RISCV_REG_X18:
|
||||
case UC_RISCV_REG_X19:
|
||||
case UC_RISCV_REG_X20:
|
||||
case UC_RISCV_REG_X21:
|
||||
case UC_RISCV_REG_X22:
|
||||
case UC_RISCV_REG_X23:
|
||||
case UC_RISCV_REG_X24:
|
||||
case UC_RISCV_REG_X25:
|
||||
case UC_RISCV_REG_X26:
|
||||
case UC_RISCV_REG_X27:
|
||||
case UC_RISCV_REG_X28:
|
||||
case UC_RISCV_REG_X29:
|
||||
case UC_RISCV_REG_X30:
|
||||
case UC_RISCV_REG_X31:
|
||||
#ifdef TARGET_RISCV64
|
||||
*(int64_t *)value = env->gpr[regid - UC_RISCV_REG_X0];
|
||||
#else
|
||||
*(int32_t *)value = env->gpr[regid - UC_RISCV_REG_X0];
|
||||
#endif
|
||||
break;
|
||||
case UC_RISCV_REG_PC:
|
||||
#ifdef TARGET_RISCV64
|
||||
*(int64_t *)value = env->pc;
|
||||
#else
|
||||
*(int32_t *)value = env->pc;
|
||||
#endif
|
||||
break;
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
case UC_RISCV_REG_F0: // "ft0"
|
||||
case UC_RISCV_REG_F1: // "ft1"
|
||||
case UC_RISCV_REG_F2: // "ft2"
|
||||
case UC_RISCV_REG_F3: // "ft3"
|
||||
case UC_RISCV_REG_F4: // "ft4"
|
||||
case UC_RISCV_REG_F5: // "ft5"
|
||||
case UC_RISCV_REG_F6: // "ft6"
|
||||
case UC_RISCV_REG_F7: // "ft7"
|
||||
case UC_RISCV_REG_F8: // "fs0"
|
||||
case UC_RISCV_REG_F9: // "fs1"
|
||||
case UC_RISCV_REG_F10: // "fa0"
|
||||
case UC_RISCV_REG_F11: // "fa1"
|
||||
case UC_RISCV_REG_F12: // "fa2"
|
||||
case UC_RISCV_REG_F13: // "fa3"
|
||||
case UC_RISCV_REG_F14: // "fa4"
|
||||
case UC_RISCV_REG_F15: // "fa5"
|
||||
case UC_RISCV_REG_F16: // "fa6"
|
||||
case UC_RISCV_REG_F17: // "fa7"
|
||||
case UC_RISCV_REG_F18: // "fs2"
|
||||
case UC_RISCV_REG_F19: // "fs3"
|
||||
case UC_RISCV_REG_F20: // "fs4"
|
||||
case UC_RISCV_REG_F21: // "fs5"
|
||||
case UC_RISCV_REG_F22: // "fs6"
|
||||
case UC_RISCV_REG_F23: // "fs7"
|
||||
case UC_RISCV_REG_F24: // "fs8"
|
||||
case UC_RISCV_REG_F25: // "fs9"
|
||||
case UC_RISCV_REG_F26: // "fs10"
|
||||
case UC_RISCV_REG_F27: // "fs11"
|
||||
case UC_RISCV_REG_F28: // "ft8"
|
||||
case UC_RISCV_REG_F29: // "ft9"
|
||||
case UC_RISCV_REG_F30: // "ft10"
|
||||
case UC_RISCV_REG_F31: // "ft11"
|
||||
if (regid >= UC_RISCV_REG_X0 && regid <= UC_RISCV_REG_X31) {
|
||||
#ifdef TARGET_RISCV64
|
||||
*(int64_t *)value = env->fpr[regid - UC_RISCV_REG_F0];
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->gpr[regid - UC_RISCV_REG_X0];
|
||||
#else
|
||||
*(int32_t *)value = env->fpr[regid - UC_RISCV_REG_F0];
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->gpr[regid - UC_RISCV_REG_X0];
|
||||
#endif
|
||||
break;
|
||||
case UC_RISCV_REG_USTATUS:
|
||||
case UC_RISCV_REG_UIE:
|
||||
case UC_RISCV_REG_UTVEC:
|
||||
case UC_RISCV_REG_USCRATCH:
|
||||
case UC_RISCV_REG_UEPC:
|
||||
case UC_RISCV_REG_UCAUSE:
|
||||
case UC_RISCV_REG_UTVAL:
|
||||
case UC_RISCV_REG_UIP:
|
||||
case UC_RISCV_REG_FFLAGS:
|
||||
case UC_RISCV_REG_FRM:
|
||||
case UC_RISCV_REG_FCSR:
|
||||
case UC_RISCV_REG_CYCLE:
|
||||
case UC_RISCV_REG_TIME:
|
||||
case UC_RISCV_REG_INSTRET:
|
||||
case UC_RISCV_REG_HPMCOUNTER3:
|
||||
case UC_RISCV_REG_HPMCOUNTER4:
|
||||
case UC_RISCV_REG_HPMCOUNTER5:
|
||||
case UC_RISCV_REG_HPMCOUNTER6:
|
||||
case UC_RISCV_REG_HPMCOUNTER7:
|
||||
case UC_RISCV_REG_HPMCOUNTER8:
|
||||
case UC_RISCV_REG_HPMCOUNTER9:
|
||||
case UC_RISCV_REG_HPMCOUNTER10:
|
||||
case UC_RISCV_REG_HPMCOUNTER11:
|
||||
case UC_RISCV_REG_HPMCOUNTER12:
|
||||
case UC_RISCV_REG_HPMCOUNTER13:
|
||||
case UC_RISCV_REG_HPMCOUNTER14:
|
||||
case UC_RISCV_REG_HPMCOUNTER15:
|
||||
case UC_RISCV_REG_HPMCOUNTER16:
|
||||
case UC_RISCV_REG_HPMCOUNTER17:
|
||||
case UC_RISCV_REG_HPMCOUNTER18:
|
||||
case UC_RISCV_REG_HPMCOUNTER19:
|
||||
case UC_RISCV_REG_HPMCOUNTER20:
|
||||
case UC_RISCV_REG_HPMCOUNTER21:
|
||||
case UC_RISCV_REG_HPMCOUNTER22:
|
||||
case UC_RISCV_REG_HPMCOUNTER23:
|
||||
case UC_RISCV_REG_HPMCOUNTER24:
|
||||
case UC_RISCV_REG_HPMCOUNTER25:
|
||||
case UC_RISCV_REG_HPMCOUNTER26:
|
||||
case UC_RISCV_REG_HPMCOUNTER27:
|
||||
case UC_RISCV_REG_HPMCOUNTER28:
|
||||
case UC_RISCV_REG_HPMCOUNTER29:
|
||||
case UC_RISCV_REG_HPMCOUNTER30:
|
||||
case UC_RISCV_REG_HPMCOUNTER31:
|
||||
case UC_RISCV_REG_CYCLEH:
|
||||
case UC_RISCV_REG_TIMEH:
|
||||
case UC_RISCV_REG_INSTRETH:
|
||||
case UC_RISCV_REG_HPMCOUNTER3H:
|
||||
case UC_RISCV_REG_HPMCOUNTER4H:
|
||||
case UC_RISCV_REG_HPMCOUNTER5H:
|
||||
case UC_RISCV_REG_HPMCOUNTER6H:
|
||||
case UC_RISCV_REG_HPMCOUNTER7H:
|
||||
case UC_RISCV_REG_HPMCOUNTER8H:
|
||||
case UC_RISCV_REG_HPMCOUNTER9H:
|
||||
case UC_RISCV_REG_HPMCOUNTER10H:
|
||||
case UC_RISCV_REG_HPMCOUNTER11H:
|
||||
case UC_RISCV_REG_HPMCOUNTER12H:
|
||||
case UC_RISCV_REG_HPMCOUNTER13H:
|
||||
case UC_RISCV_REG_HPMCOUNTER14H:
|
||||
case UC_RISCV_REG_HPMCOUNTER15H:
|
||||
case UC_RISCV_REG_HPMCOUNTER16H:
|
||||
case UC_RISCV_REG_HPMCOUNTER17H:
|
||||
case UC_RISCV_REG_HPMCOUNTER18H:
|
||||
case UC_RISCV_REG_HPMCOUNTER19H:
|
||||
case UC_RISCV_REG_HPMCOUNTER20H:
|
||||
case UC_RISCV_REG_HPMCOUNTER21H:
|
||||
case UC_RISCV_REG_HPMCOUNTER22H:
|
||||
case UC_RISCV_REG_HPMCOUNTER23H:
|
||||
case UC_RISCV_REG_HPMCOUNTER24H:
|
||||
case UC_RISCV_REG_HPMCOUNTER25H:
|
||||
case UC_RISCV_REG_HPMCOUNTER26H:
|
||||
case UC_RISCV_REG_HPMCOUNTER27H:
|
||||
case UC_RISCV_REG_HPMCOUNTER28H:
|
||||
case UC_RISCV_REG_HPMCOUNTER29H:
|
||||
case UC_RISCV_REG_HPMCOUNTER30H:
|
||||
case UC_RISCV_REG_HPMCOUNTER31H:
|
||||
case UC_RISCV_REG_MCYCLE:
|
||||
case UC_RISCV_REG_MINSTRET:
|
||||
case UC_RISCV_REG_MCYCLEH:
|
||||
case UC_RISCV_REG_MINSTRETH:
|
||||
case UC_RISCV_REG_MVENDORID:
|
||||
case UC_RISCV_REG_MARCHID:
|
||||
case UC_RISCV_REG_MIMPID:
|
||||
case UC_RISCV_REG_MHARTID:
|
||||
case UC_RISCV_REG_MSTATUS:
|
||||
case UC_RISCV_REG_MISA:
|
||||
case UC_RISCV_REG_MEDELEG:
|
||||
case UC_RISCV_REG_MIDELEG:
|
||||
case UC_RISCV_REG_MIE:
|
||||
case UC_RISCV_REG_MTVEC:
|
||||
case UC_RISCV_REG_MCOUNTEREN:
|
||||
case UC_RISCV_REG_MSTATUSH:
|
||||
case UC_RISCV_REG_MUCOUNTEREN:
|
||||
case UC_RISCV_REG_MSCOUNTEREN:
|
||||
case UC_RISCV_REG_MHCOUNTEREN:
|
||||
case UC_RISCV_REG_MSCRATCH:
|
||||
case UC_RISCV_REG_MEPC:
|
||||
case UC_RISCV_REG_MCAUSE:
|
||||
case UC_RISCV_REG_MTVAL:
|
||||
case UC_RISCV_REG_MIP:
|
||||
case UC_RISCV_REG_MBADADDR:
|
||||
case UC_RISCV_REG_SSTATUS:
|
||||
case UC_RISCV_REG_SEDELEG:
|
||||
case UC_RISCV_REG_SIDELEG:
|
||||
case UC_RISCV_REG_SIE:
|
||||
case UC_RISCV_REG_STVEC:
|
||||
case UC_RISCV_REG_SCOUNTEREN:
|
||||
case UC_RISCV_REG_SSCRATCH:
|
||||
case UC_RISCV_REG_SEPC:
|
||||
case UC_RISCV_REG_SCAUSE:
|
||||
case UC_RISCV_REG_STVAL:
|
||||
case UC_RISCV_REG_SIP:
|
||||
case UC_RISCV_REG_SBADADDR:
|
||||
case UC_RISCV_REG_SPTBR:
|
||||
case UC_RISCV_REG_SATP:
|
||||
case UC_RISCV_REG_HSTATUS:
|
||||
case UC_RISCV_REG_HEDELEG:
|
||||
case UC_RISCV_REG_HIDELEG:
|
||||
case UC_RISCV_REG_HIE:
|
||||
case UC_RISCV_REG_HCOUNTEREN:
|
||||
case UC_RISCV_REG_HTVAL:
|
||||
case UC_RISCV_REG_HIP:
|
||||
case UC_RISCV_REG_HTINST:
|
||||
case UC_RISCV_REG_HGATP:
|
||||
case UC_RISCV_REG_HTIMEDELTA:
|
||||
case UC_RISCV_REG_HTIMEDELTAH: {
|
||||
} else if (regid >= UC_RISCV_REG_F0 &&
|
||||
regid <= UC_RISCV_REG_F31) { // "ft0".."ft31"
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->fpr[regid - UC_RISCV_REG_F0];
|
||||
} else if (regid >= UC_RISCV_REG_USTATUS &&
|
||||
regid < UC_RISCV_REG_USTATUS + csrno_count) {
|
||||
target_ulong val;
|
||||
int csrno = csrno_map[regid - UC_RISCV_REG_USTATUS];
|
||||
riscv_csrrw(env, csrno, &val, -1, 0);
|
||||
#ifdef TARGET_RISCV64
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = (uint64_t)val;
|
||||
#else
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = (uint32_t)val;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
} else {
|
||||
switch (regid) {
|
||||
default:
|
||||
break;
|
||||
case UC_RISCV_REG_PC:
|
||||
#ifdef TARGET_RISCV64
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->pc;
|
||||
#else
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->pc;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void reg_write(CPURISCVState *env, unsigned int regid, const void *value)
|
||||
static uc_err reg_write(CPURISCVState *env, unsigned int regid,
|
||||
const void *value, size_t *size)
|
||||
{
|
||||
switch (regid) {
|
||||
case UC_RISCV_REG_X0:
|
||||
case UC_RISCV_REG_X1:
|
||||
case UC_RISCV_REG_X2:
|
||||
case UC_RISCV_REG_X3:
|
||||
case UC_RISCV_REG_X4:
|
||||
case UC_RISCV_REG_X5:
|
||||
case UC_RISCV_REG_X6:
|
||||
case UC_RISCV_REG_X7:
|
||||
case UC_RISCV_REG_X8:
|
||||
case UC_RISCV_REG_X9:
|
||||
case UC_RISCV_REG_X10:
|
||||
case UC_RISCV_REG_X11:
|
||||
case UC_RISCV_REG_X12:
|
||||
case UC_RISCV_REG_X13:
|
||||
case UC_RISCV_REG_X14:
|
||||
case UC_RISCV_REG_X15:
|
||||
case UC_RISCV_REG_X16:
|
||||
case UC_RISCV_REG_X17:
|
||||
case UC_RISCV_REG_X18:
|
||||
case UC_RISCV_REG_X19:
|
||||
case UC_RISCV_REG_X20:
|
||||
case UC_RISCV_REG_X21:
|
||||
case UC_RISCV_REG_X22:
|
||||
case UC_RISCV_REG_X23:
|
||||
case UC_RISCV_REG_X24:
|
||||
case UC_RISCV_REG_X25:
|
||||
case UC_RISCV_REG_X26:
|
||||
case UC_RISCV_REG_X27:
|
||||
case UC_RISCV_REG_X28:
|
||||
case UC_RISCV_REG_X29:
|
||||
case UC_RISCV_REG_X30:
|
||||
case UC_RISCV_REG_X31:
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_RISCV_REG_X0 && regid <= UC_RISCV_REG_X31) {
|
||||
#ifdef TARGET_RISCV64
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->gpr[regid - UC_RISCV_REG_X0] = *(uint64_t *)value;
|
||||
#else
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->gpr[regid - UC_RISCV_REG_X0] = *(uint32_t *)value;
|
||||
#endif
|
||||
break;
|
||||
case UC_RISCV_REG_PC:
|
||||
#ifdef TARGET_RISCV64
|
||||
env->pc = *(uint64_t *)value;
|
||||
#else
|
||||
env->pc = *(uint32_t *)value;
|
||||
#endif
|
||||
break;
|
||||
case UC_RISCV_REG_F0: // "ft0"
|
||||
case UC_RISCV_REG_F1: // "ft1"
|
||||
case UC_RISCV_REG_F2: // "ft2"
|
||||
case UC_RISCV_REG_F3: // "ft3"
|
||||
case UC_RISCV_REG_F4: // "ft4"
|
||||
case UC_RISCV_REG_F5: // "ft5"
|
||||
case UC_RISCV_REG_F6: // "ft6"
|
||||
case UC_RISCV_REG_F7: // "ft7"
|
||||
case UC_RISCV_REG_F8: // "fs0"
|
||||
case UC_RISCV_REG_F9: // "fs1"
|
||||
case UC_RISCV_REG_F10: // "fa0"
|
||||
case UC_RISCV_REG_F11: // "fa1"
|
||||
case UC_RISCV_REG_F12: // "fa2"
|
||||
case UC_RISCV_REG_F13: // "fa3"
|
||||
case UC_RISCV_REG_F14: // "fa4"
|
||||
case UC_RISCV_REG_F15: // "fa5"
|
||||
case UC_RISCV_REG_F16: // "fa6"
|
||||
case UC_RISCV_REG_F17: // "fa7"
|
||||
case UC_RISCV_REG_F18: // "fs2"
|
||||
case UC_RISCV_REG_F19: // "fs3"
|
||||
case UC_RISCV_REG_F20: // "fs4"
|
||||
case UC_RISCV_REG_F21: // "fs5"
|
||||
case UC_RISCV_REG_F22: // "fs6"
|
||||
case UC_RISCV_REG_F23: // "fs7"
|
||||
case UC_RISCV_REG_F24: // "fs8"
|
||||
case UC_RISCV_REG_F25: // "fs9"
|
||||
case UC_RISCV_REG_F26: // "fs10"
|
||||
case UC_RISCV_REG_F27: // "fs11"
|
||||
case UC_RISCV_REG_F28: // "ft8"
|
||||
case UC_RISCV_REG_F29: // "ft9"
|
||||
case UC_RISCV_REG_F30: // "ft10"
|
||||
case UC_RISCV_REG_F31: // "ft11"
|
||||
#ifdef TARGET_RISCV64
|
||||
} else if (regid >= UC_RISCV_REG_F0 &&
|
||||
regid <= UC_RISCV_REG_F31) { // "ft0".."ft31"
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->fpr[regid - UC_RISCV_REG_F0] = *(uint64_t *)value;
|
||||
#else
|
||||
env->fpr[regid - UC_RISCV_REG_F0] = *(uint32_t *)value;
|
||||
#endif
|
||||
break;
|
||||
case UC_RISCV_REG_USTATUS:
|
||||
case UC_RISCV_REG_UIE:
|
||||
case UC_RISCV_REG_UTVEC:
|
||||
case UC_RISCV_REG_USCRATCH:
|
||||
case UC_RISCV_REG_UEPC:
|
||||
case UC_RISCV_REG_UCAUSE:
|
||||
case UC_RISCV_REG_UTVAL:
|
||||
case UC_RISCV_REG_UIP:
|
||||
case UC_RISCV_REG_FFLAGS:
|
||||
case UC_RISCV_REG_FRM:
|
||||
case UC_RISCV_REG_FCSR:
|
||||
case UC_RISCV_REG_CYCLE:
|
||||
case UC_RISCV_REG_TIME:
|
||||
case UC_RISCV_REG_INSTRET:
|
||||
case UC_RISCV_REG_HPMCOUNTER3:
|
||||
case UC_RISCV_REG_HPMCOUNTER4:
|
||||
case UC_RISCV_REG_HPMCOUNTER5:
|
||||
case UC_RISCV_REG_HPMCOUNTER6:
|
||||
case UC_RISCV_REG_HPMCOUNTER7:
|
||||
case UC_RISCV_REG_HPMCOUNTER8:
|
||||
case UC_RISCV_REG_HPMCOUNTER9:
|
||||
case UC_RISCV_REG_HPMCOUNTER10:
|
||||
case UC_RISCV_REG_HPMCOUNTER11:
|
||||
case UC_RISCV_REG_HPMCOUNTER12:
|
||||
case UC_RISCV_REG_HPMCOUNTER13:
|
||||
case UC_RISCV_REG_HPMCOUNTER14:
|
||||
case UC_RISCV_REG_HPMCOUNTER15:
|
||||
case UC_RISCV_REG_HPMCOUNTER16:
|
||||
case UC_RISCV_REG_HPMCOUNTER17:
|
||||
case UC_RISCV_REG_HPMCOUNTER18:
|
||||
case UC_RISCV_REG_HPMCOUNTER19:
|
||||
case UC_RISCV_REG_HPMCOUNTER20:
|
||||
case UC_RISCV_REG_HPMCOUNTER21:
|
||||
case UC_RISCV_REG_HPMCOUNTER22:
|
||||
case UC_RISCV_REG_HPMCOUNTER23:
|
||||
case UC_RISCV_REG_HPMCOUNTER24:
|
||||
case UC_RISCV_REG_HPMCOUNTER25:
|
||||
case UC_RISCV_REG_HPMCOUNTER26:
|
||||
case UC_RISCV_REG_HPMCOUNTER27:
|
||||
case UC_RISCV_REG_HPMCOUNTER28:
|
||||
case UC_RISCV_REG_HPMCOUNTER29:
|
||||
case UC_RISCV_REG_HPMCOUNTER30:
|
||||
case UC_RISCV_REG_HPMCOUNTER31:
|
||||
case UC_RISCV_REG_CYCLEH:
|
||||
case UC_RISCV_REG_TIMEH:
|
||||
case UC_RISCV_REG_INSTRETH:
|
||||
case UC_RISCV_REG_HPMCOUNTER3H:
|
||||
case UC_RISCV_REG_HPMCOUNTER4H:
|
||||
case UC_RISCV_REG_HPMCOUNTER5H:
|
||||
case UC_RISCV_REG_HPMCOUNTER6H:
|
||||
case UC_RISCV_REG_HPMCOUNTER7H:
|
||||
case UC_RISCV_REG_HPMCOUNTER8H:
|
||||
case UC_RISCV_REG_HPMCOUNTER9H:
|
||||
case UC_RISCV_REG_HPMCOUNTER10H:
|
||||
case UC_RISCV_REG_HPMCOUNTER11H:
|
||||
case UC_RISCV_REG_HPMCOUNTER12H:
|
||||
case UC_RISCV_REG_HPMCOUNTER13H:
|
||||
case UC_RISCV_REG_HPMCOUNTER14H:
|
||||
case UC_RISCV_REG_HPMCOUNTER15H:
|
||||
case UC_RISCV_REG_HPMCOUNTER16H:
|
||||
case UC_RISCV_REG_HPMCOUNTER17H:
|
||||
case UC_RISCV_REG_HPMCOUNTER18H:
|
||||
case UC_RISCV_REG_HPMCOUNTER19H:
|
||||
case UC_RISCV_REG_HPMCOUNTER20H:
|
||||
case UC_RISCV_REG_HPMCOUNTER21H:
|
||||
case UC_RISCV_REG_HPMCOUNTER22H:
|
||||
case UC_RISCV_REG_HPMCOUNTER23H:
|
||||
case UC_RISCV_REG_HPMCOUNTER24H:
|
||||
case UC_RISCV_REG_HPMCOUNTER25H:
|
||||
case UC_RISCV_REG_HPMCOUNTER26H:
|
||||
case UC_RISCV_REG_HPMCOUNTER27H:
|
||||
case UC_RISCV_REG_HPMCOUNTER28H:
|
||||
case UC_RISCV_REG_HPMCOUNTER29H:
|
||||
case UC_RISCV_REG_HPMCOUNTER30H:
|
||||
case UC_RISCV_REG_HPMCOUNTER31H:
|
||||
case UC_RISCV_REG_MCYCLE:
|
||||
case UC_RISCV_REG_MINSTRET:
|
||||
case UC_RISCV_REG_MCYCLEH:
|
||||
case UC_RISCV_REG_MINSTRETH:
|
||||
case UC_RISCV_REG_MVENDORID:
|
||||
case UC_RISCV_REG_MARCHID:
|
||||
case UC_RISCV_REG_MIMPID:
|
||||
case UC_RISCV_REG_MHARTID:
|
||||
case UC_RISCV_REG_MSTATUS:
|
||||
case UC_RISCV_REG_MISA:
|
||||
case UC_RISCV_REG_MEDELEG:
|
||||
case UC_RISCV_REG_MIDELEG:
|
||||
case UC_RISCV_REG_MIE:
|
||||
case UC_RISCV_REG_MTVEC:
|
||||
case UC_RISCV_REG_MCOUNTEREN:
|
||||
case UC_RISCV_REG_MSTATUSH:
|
||||
case UC_RISCV_REG_MUCOUNTEREN:
|
||||
case UC_RISCV_REG_MSCOUNTEREN:
|
||||
case UC_RISCV_REG_MHCOUNTEREN:
|
||||
case UC_RISCV_REG_MSCRATCH:
|
||||
case UC_RISCV_REG_MEPC:
|
||||
case UC_RISCV_REG_MCAUSE:
|
||||
case UC_RISCV_REG_MTVAL:
|
||||
case UC_RISCV_REG_MIP:
|
||||
case UC_RISCV_REG_MBADADDR:
|
||||
case UC_RISCV_REG_SSTATUS:
|
||||
case UC_RISCV_REG_SEDELEG:
|
||||
case UC_RISCV_REG_SIDELEG:
|
||||
case UC_RISCV_REG_SIE:
|
||||
case UC_RISCV_REG_STVEC:
|
||||
case UC_RISCV_REG_SCOUNTEREN:
|
||||
case UC_RISCV_REG_SSCRATCH:
|
||||
case UC_RISCV_REG_SEPC:
|
||||
case UC_RISCV_REG_SCAUSE:
|
||||
case UC_RISCV_REG_STVAL:
|
||||
case UC_RISCV_REG_SIP:
|
||||
case UC_RISCV_REG_SBADADDR:
|
||||
case UC_RISCV_REG_SPTBR:
|
||||
case UC_RISCV_REG_SATP:
|
||||
case UC_RISCV_REG_HSTATUS:
|
||||
case UC_RISCV_REG_HEDELEG:
|
||||
case UC_RISCV_REG_HIDELEG:
|
||||
case UC_RISCV_REG_HIE:
|
||||
case UC_RISCV_REG_HCOUNTEREN:
|
||||
case UC_RISCV_REG_HTVAL:
|
||||
case UC_RISCV_REG_HIP:
|
||||
case UC_RISCV_REG_HTINST:
|
||||
case UC_RISCV_REG_HGATP:
|
||||
case UC_RISCV_REG_HTIMEDELTA:
|
||||
case UC_RISCV_REG_HTIMEDELTAH: {
|
||||
} else if (regid >= UC_RISCV_REG_USTATUS &&
|
||||
regid < UC_RISCV_REG_USTATUS + csrno_count) {
|
||||
target_ulong val;
|
||||
int csrno = csrno_map[regid - UC_RISCV_REG_USTATUS];
|
||||
#ifdef TARGET_RISCV64
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
riscv_csrrw(env, csrno, &val, *(uint64_t *)value, -1);
|
||||
#else
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
riscv_csrrw(env, csrno, &val, *(uint32_t *)value, -1);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
} else {
|
||||
switch (regid) {
|
||||
default:
|
||||
break;
|
||||
case UC_RISCV_REG_PC:
|
||||
#ifdef TARGET_RISCV64
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->pc = *(uint64_t *)value;
|
||||
#else
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->pc = *(uint32_t *)value;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count)
|
||||
int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
size_t *sizes, int count)
|
||||
{
|
||||
CPURISCVState *env = &(RISCV_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
int count)
|
||||
int riscv_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPURISCVState *env = &(RISCV_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
if (regid == UC_RISCV_REG_PC) {
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
@@ -564,51 +214,59 @@ int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
#ifdef TARGET_RISCV32
|
||||
int riscv32_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count)
|
||||
void *const *vals, size_t *sizes, int count)
|
||||
#else
|
||||
/* TARGET_RISCV64 */
|
||||
int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count)
|
||||
void *const *vals, size_t *sizes, int count)
|
||||
#endif
|
||||
{
|
||||
CPURISCVState *env = (CPURISCVState *)ctx->data;
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
#ifdef TARGET_RISCV32
|
||||
int riscv32_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
#else
|
||||
/* TARGET_RISCV64 */
|
||||
int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
#endif
|
||||
{
|
||||
CPURISCVState *env = (CPURISCVState *)ctx->data;
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
static bool riscv_stop_interrupt(struct uc_struct *uc, int intno)
|
||||
|
||||
@@ -6,19 +6,21 @@
|
||||
#define UC_QEMU_TARGET_RISCV_H
|
||||
|
||||
// functions to read & write registers
|
||||
int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count);
|
||||
int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
int count);
|
||||
int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
size_t *sizes, int count);
|
||||
int riscv_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
|
||||
int riscv32_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count);
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
int riscv32_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes,
|
||||
int count);
|
||||
int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count);
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes,
|
||||
int count);
|
||||
|
||||
void riscv_reg_reset(struct uc_struct *uc);
|
||||
|
||||
|
||||
@@ -53,80 +53,99 @@ void s390_reg_reset(struct uc_struct *uc)
|
||||
env->psw.addr = 0;
|
||||
}
|
||||
|
||||
static void reg_read(CPUS390XState *env, unsigned int regid, void *value)
|
||||
static uc_err reg_read(CPUS390XState *env, unsigned int regid, void *value,
|
||||
size_t *size)
|
||||
{
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_S390X_REG_R0 && regid <= UC_S390X_REG_R15) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->regs[regid - UC_S390X_REG_R0];
|
||||
return;
|
||||
}
|
||||
|
||||
if (regid >= UC_S390X_REG_A0 && regid <= UC_S390X_REG_A15) {
|
||||
} else if (regid >= UC_S390X_REG_A0 && regid <= UC_S390X_REG_A15) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->regs[regid - UC_S390X_REG_A0];
|
||||
return;
|
||||
} else {
|
||||
switch (regid) {
|
||||
default:
|
||||
break;
|
||||
case UC_S390X_REG_PC:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->psw.addr;
|
||||
break;
|
||||
case UC_S390X_REG_PSWM:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = get_psw_mask(env);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (regid) {
|
||||
default:
|
||||
break;
|
||||
case UC_S390X_REG_PC:
|
||||
*(uint64_t *)value = env->psw.addr;
|
||||
break;
|
||||
case UC_S390X_REG_PSWM:
|
||||
*(uint64_t *)value = get_psw_mask(env);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void reg_write(CPUS390XState *env, unsigned int regid, const void *value)
|
||||
static uc_err reg_write(CPUS390XState *env, unsigned int regid,
|
||||
const void *value, size_t *size)
|
||||
{
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_S390X_REG_R0 && regid <= UC_S390X_REG_R15) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->regs[regid - UC_S390X_REG_R0] = *(uint64_t *)value;
|
||||
return;
|
||||
}
|
||||
|
||||
if (regid >= UC_S390X_REG_A0 && regid <= UC_S390X_REG_A15) {
|
||||
} else if (regid >= UC_S390X_REG_A0 && regid <= UC_S390X_REG_A15) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->regs[regid - UC_S390X_REG_A0] = *(uint32_t *)value;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (regid) {
|
||||
default:
|
||||
break;
|
||||
case UC_S390X_REG_PC:
|
||||
env->psw.addr = *(uint64_t *)value;
|
||||
break;
|
||||
case UC_S390X_REG_PSWM:
|
||||
env->psw.mask = *(uint64_t *)value;
|
||||
env->cc_op = (env->psw.mask >> 44) & 3;
|
||||
break;
|
||||
} else {
|
||||
switch (regid) {
|
||||
default:
|
||||
break;
|
||||
case UC_S390X_REG_PC:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->psw.addr = *(uint64_t *)value;
|
||||
break;
|
||||
case UC_S390X_REG_PSWM:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->psw.mask = *(uint64_t *)value;
|
||||
env->cc_op = (env->psw.mask >> 44) & 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int s390_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count)
|
||||
DEFAULT_VISIBILITY
|
||||
int s390_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
size_t *sizes, int count)
|
||||
{
|
||||
CPUS390XState *env = &(S390_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
static int s390_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
DEFAULT_VISIBILITY
|
||||
int s390_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUS390XState *env = &(S390_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
if (regid == UC_S390X_REG_PC) {
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
@@ -134,39 +153,47 @@ static int s390_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
int s390_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count)
|
||||
void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUS390XState *env = (CPUS390XState *)ctx->data;
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
int s390_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUS390XState *env = (CPUS390XState *)ctx->data;
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
static int s390_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
#define UC_QEMU_TARGET_S390X_H
|
||||
|
||||
// functions to read & write registers
|
||||
// int s390_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int
|
||||
// count); int s390_reg_write(struct uc_struct *uc, unsigned int *regs, void
|
||||
// *const *vals, int count);
|
||||
int s390_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
size_t *sizes, int count);
|
||||
int s390_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
int s390_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count);
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
int s390_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
|
||||
void s390_reg_reset(struct uc_struct *uc);
|
||||
|
||||
|
||||
@@ -61,119 +61,149 @@ void sparc_reg_reset(struct uc_struct *uc)
|
||||
env->regwptr = env->regbase;
|
||||
}
|
||||
|
||||
static void reg_read(CPUSPARCState *env, unsigned int regid, void *value)
|
||||
static uc_err reg_read(CPUSPARCState *env, unsigned int regid, void *value,
|
||||
size_t *size)
|
||||
{
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
|
||||
*(int32_t *)value = env->gregs[regid - UC_SPARC_REG_G0];
|
||||
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
|
||||
*(int32_t *)value = env->regwptr[regid - UC_SPARC_REG_O0];
|
||||
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
|
||||
*(int32_t *)value = env->regwptr[8 + regid - UC_SPARC_REG_L0];
|
||||
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
|
||||
*(int32_t *)value = env->regwptr[16 + regid - UC_SPARC_REG_I0];
|
||||
else {
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->gregs[regid - UC_SPARC_REG_G0];
|
||||
} else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->regwptr[regid - UC_SPARC_REG_O0];
|
||||
} else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->regwptr[8 + regid - UC_SPARC_REG_L0];
|
||||
} else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) {
|
||||
*(uint32_t *)value = env->regwptr[16 + regid - UC_SPARC_REG_I0];
|
||||
} else {
|
||||
switch (regid) {
|
||||
default:
|
||||
break;
|
||||
case UC_SPARC_REG_PC:
|
||||
*(int32_t *)value = env->pc;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->pc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void reg_write(CPUSPARCState *env, unsigned int regid, const void *value)
|
||||
static uc_err reg_write(CPUSPARCState *env, unsigned int regid,
|
||||
const void *value, size_t *size)
|
||||
{
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->gregs[regid - UC_SPARC_REG_G0] = *(uint32_t *)value;
|
||||
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
|
||||
} else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->regwptr[regid - UC_SPARC_REG_O0] = *(uint32_t *)value;
|
||||
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
|
||||
} else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->regwptr[8 + regid - UC_SPARC_REG_L0] = *(uint32_t *)value;
|
||||
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
|
||||
} else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint32_t *)value;
|
||||
else {
|
||||
} else {
|
||||
switch (regid) {
|
||||
default:
|
||||
break;
|
||||
case UC_SPARC_REG_PC:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->pc = *(uint32_t *)value;
|
||||
env->npc = *(uint32_t *)value + 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count)
|
||||
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
size_t *sizes, int count)
|
||||
{
|
||||
CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
int count)
|
||||
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
if (regid == UC_SPARC_REG_PC) {
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break;
|
||||
break_translation_loop(uc);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count)
|
||||
void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUSPARCState *env = (CPUSPARCState *)ctx->data;
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
int sparc_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUSPARCState *env = (CPUSPARCState *)ctx->data;
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
static int sparc_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
||||
|
||||
@@ -5,19 +5,20 @@
|
||||
#define UC_QEMU_TARGET_SPARC_H
|
||||
|
||||
// functions to read & write registers
|
||||
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count);
|
||||
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
int count);
|
||||
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
size_t *sizes, int count);
|
||||
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
|
||||
int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count);
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
int sparc_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
int sparc64_context_reg_read(struct uc_context *ctx, unsigned int *regs,
|
||||
void **vals, int count);
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
int sparc64_context_reg_write(struct uc_context *ctx, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes,
|
||||
int count);
|
||||
|
||||
void sparc_reg_reset(struct uc_struct *uc);
|
||||
|
||||
|
||||
@@ -83,103 +83,144 @@ void sparc_reg_reset(struct uc_struct *uc)
|
||||
env->regwptr = env->regbase;
|
||||
}
|
||||
|
||||
static void reg_read(CPUSPARCState *env, unsigned int regid, void *value)
|
||||
static uc_err reg_read(CPUSPARCState *env, unsigned int regid, void *value, size_t *size)
|
||||
{
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
|
||||
*(int64_t *)value = env->gregs[regid - UC_SPARC_REG_G0];
|
||||
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
|
||||
*(int64_t *)value = env->regwptr[regid - UC_SPARC_REG_O0];
|
||||
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
|
||||
*(int64_t *)value = env->regwptr[8 + regid - UC_SPARC_REG_L0];
|
||||
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
|
||||
*(int64_t *)value = env->regwptr[16 + regid - UC_SPARC_REG_I0];
|
||||
else {
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->gregs[regid - UC_SPARC_REG_G0];
|
||||
} else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->regwptr[regid - UC_SPARC_REG_O0];
|
||||
} else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->regwptr[8 + regid - UC_SPARC_REG_L0];
|
||||
} else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->regwptr[16 + regid - UC_SPARC_REG_I0];
|
||||
} else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_SPARC_REG_PC:
|
||||
*(int64_t *)value = env->pc;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case UC_SPARC_REG_PC:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
*(uint64_t *)value = env->pc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void reg_write(CPUSPARCState *env, unsigned int regid, const void *value)
|
||||
static uc_err reg_write(CPUSPARCState *env, unsigned int regid, const void *value, size_t *size)
|
||||
{
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->gregs[regid - UC_SPARC_REG_G0] = *(uint64_t *)value;
|
||||
else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
|
||||
} else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->regwptr[regid - UC_SPARC_REG_O0] = *(uint64_t *)value;
|
||||
else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
|
||||
} else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->regwptr[8 + regid - UC_SPARC_REG_L0] = *(uint64_t *)value;
|
||||
else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
|
||||
} else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) {
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint64_t *)value;
|
||||
else {
|
||||
} else {
|
||||
switch(regid) {
|
||||
default: break;
|
||||
case UC_SPARC_REG_PC:
|
||||
env->pc = *(uint64_t *)value;
|
||||
env->npc = *(uint64_t *)value + 4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case UC_SPARC_REG_PC:
|
||||
CHECK_REG_TYPE(uint64_t);
|
||||
env->pc = *(uint64_t *)value;
|
||||
env->npc = *(uint64_t *)value + 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count)
|
||||
int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, int count)
|
||||
int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, const void* const* vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
if (regid == UC_SPARC_REG_PC) {
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
break_translation_loop(uc);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
int sparc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count)
|
||||
int sparc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUSPARCState *env = (CPUSPARCState *)ctx->data;
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
int sparc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count)
|
||||
int sparc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, const void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUSPARCState *env = (CPUSPARCState *)ctx->data;
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
static int sparc_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
||||
|
||||
@@ -39,193 +39,258 @@ void tricore_reg_reset(struct uc_struct *uc)
|
||||
env->PC = 0;
|
||||
}
|
||||
|
||||
static void reg_read(CPUTriCoreState *env, unsigned int regid, void *value)
|
||||
static uc_err reg_read(CPUTriCoreState *env, unsigned int regid, void *value,
|
||||
size_t *size)
|
||||
{
|
||||
if (regid >= UC_TRICORE_REG_A0 && regid <= UC_TRICORE_REG_A9)
|
||||
*(int32_t *)value = env->gpr_a[regid - UC_TRICORE_REG_A0];
|
||||
if (regid >= UC_TRICORE_REG_A12 && regid <= UC_TRICORE_REG_A15)
|
||||
*(int32_t *)value = env->gpr_a[regid - UC_TRICORE_REG_A0];
|
||||
else if (regid >= UC_TRICORE_REG_D0 && regid <= UC_TRICORE_REG_D15)
|
||||
*(int32_t *)value = env->gpr_d[regid - UC_TRICORE_REG_D0];
|
||||
else {
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_TRICORE_REG_A0 && regid <= UC_TRICORE_REG_A9) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->gpr_a[regid - UC_TRICORE_REG_A0];
|
||||
} else if (regid >= UC_TRICORE_REG_A12 && regid <= UC_TRICORE_REG_A15) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->gpr_a[regid - UC_TRICORE_REG_A0];
|
||||
} else if (regid >= UC_TRICORE_REG_D0 && regid <= UC_TRICORE_REG_D15) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->gpr_d[regid - UC_TRICORE_REG_D0];
|
||||
} else {
|
||||
switch (regid) {
|
||||
// case UC_TRICORE_REG_SP:
|
||||
case UC_TRICORE_REG_A10:
|
||||
*(int32_t *)value = env->gpr_a[10];
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->gpr_a[10];
|
||||
break;
|
||||
// case UC_TRICORE_REG_LR:
|
||||
case UC_TRICORE_REG_A11:
|
||||
*(int32_t *)value = env->gpr_a[11];
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->gpr_a[11];
|
||||
break;
|
||||
case UC_TRICORE_REG_PC:
|
||||
*(int32_t *)value = env->PC;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->PC;
|
||||
break;
|
||||
case UC_TRICORE_REG_PCXI:
|
||||
*(int32_t *)value = env->PCXI;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->PCXI;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW:
|
||||
*(int32_t *)value = env->PSW;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->PSW;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_C:
|
||||
*(int32_t *)value = env->PSW_USB_C;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->PSW_USB_C;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_V:
|
||||
*(int32_t *)value = env->PSW_USB_V;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->PSW_USB_V;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_SV:
|
||||
*(int32_t *)value = env->PSW_USB_SV;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->PSW_USB_SV;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_AV:
|
||||
*(int32_t *)value = env->PSW_USB_AV;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->PSW_USB_AV;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_SAV:
|
||||
*(int32_t *)value = env->PSW_USB_SAV;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->PSW_USB_SAV;
|
||||
break;
|
||||
case UC_TRICORE_REG_SYSCON:
|
||||
*(int32_t *)value = env->SYSCON;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->SYSCON;
|
||||
break;
|
||||
case UC_TRICORE_REG_CPU_ID:
|
||||
*(int32_t *)value = env->CPU_ID;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->CPU_ID;
|
||||
break;
|
||||
case UC_TRICORE_REG_BIV:
|
||||
*(int32_t *)value = env->BIV;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->BIV;
|
||||
break;
|
||||
case UC_TRICORE_REG_BTV:
|
||||
*(int32_t *)value = env->BTV;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->BTV;
|
||||
break;
|
||||
case UC_TRICORE_REG_ISP:
|
||||
*(int32_t *)value = env->ISP;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->ISP;
|
||||
break;
|
||||
case UC_TRICORE_REG_ICR:
|
||||
*(int32_t *)value = env->ICR;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->ICR;
|
||||
break;
|
||||
case UC_TRICORE_REG_FCX:
|
||||
*(int32_t *)value = env->FCX;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->FCX;
|
||||
break;
|
||||
case UC_TRICORE_REG_LCX:
|
||||
*(int32_t *)value = env->LCX;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->LCX;
|
||||
break;
|
||||
case UC_TRICORE_REG_COMPAT:
|
||||
*(int32_t *)value = env->COMPAT;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->COMPAT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tricore_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count)
|
||||
int tricore_reg_read(struct uc_struct *uc, unsigned int *regs,
|
||||
void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUTriCoreState *env = &(TRICORE_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
int tricore_context_reg_read(struct uc_context *uc, unsigned int *regs,
|
||||
void **vals, int count)
|
||||
void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUTriCoreState *env = (CPUTriCoreState *)uc->data;
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_read(env, regid, value);
|
||||
err = reg_read(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
static void reg_write(CPUTriCoreState *env, unsigned int regid,
|
||||
const void *value)
|
||||
static uc_err reg_write(CPUTriCoreState *env, unsigned int regid,
|
||||
const void *value, size_t *size)
|
||||
{
|
||||
if (regid >= UC_TRICORE_REG_A0 && regid <= UC_TRICORE_REG_A9)
|
||||
env->gpr_a[regid - UC_TRICORE_REG_A0] = *(int32_t *)value;
|
||||
if (regid >= UC_TRICORE_REG_A12 && regid <= UC_TRICORE_REG_A15)
|
||||
env->gpr_a[regid - UC_TRICORE_REG_A0] = *(int32_t *)value;
|
||||
else if (regid >= UC_TRICORE_REG_D0 && regid <= UC_TRICORE_REG_D15)
|
||||
env->gpr_d[regid - UC_TRICORE_REG_D0] = *(int32_t *)value;
|
||||
else {
|
||||
uc_err ret = UC_ERR_ARG;
|
||||
|
||||
if (regid >= UC_TRICORE_REG_A0 && regid <= UC_TRICORE_REG_A9) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->gpr_a[regid - UC_TRICORE_REG_A0] = *(uint32_t *)value;
|
||||
} else if (regid >= UC_TRICORE_REG_A12 && regid <= UC_TRICORE_REG_A15) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->gpr_a[regid - UC_TRICORE_REG_A0] = *(uint32_t *)value;
|
||||
} else if (regid >= UC_TRICORE_REG_D0 && regid <= UC_TRICORE_REG_D15) {
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->gpr_d[regid - UC_TRICORE_REG_D0] = *(uint32_t *)value;
|
||||
} else {
|
||||
switch (regid) {
|
||||
// case UC_TRICORE_REG_SP:
|
||||
case UC_TRICORE_REG_A10:
|
||||
env->gpr_a[10] = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->gpr_a[10] = *(uint32_t *)value;
|
||||
break;
|
||||
// case UC_TRICORE_REG_LR:
|
||||
case UC_TRICORE_REG_A11:
|
||||
env->gpr_a[11] = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->gpr_a[11] = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_PC:
|
||||
env->PC = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->PC = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_PCXI:
|
||||
env->PCXI = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->PCXI = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW:
|
||||
env->PSW = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->PSW = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_C:
|
||||
env->PSW_USB_C = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->PSW_USB_C = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_V:
|
||||
env->PSW_USB_V = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->PSW_USB_V = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_SV:
|
||||
env->PSW_USB_SV = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->PSW_USB_SV = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_AV:
|
||||
env->PSW_USB_AV = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->PSW_USB_AV = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_SAV:
|
||||
env->PSW_USB_SAV = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->PSW_USB_SAV = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_SYSCON:
|
||||
env->SYSCON = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->SYSCON = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_CPU_ID:
|
||||
env->CPU_ID = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->CPU_ID = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_BIV:
|
||||
env->BIV = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->BIV = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_BTV:
|
||||
env->BTV = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->BTV = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_ISP:
|
||||
env->ISP = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->ISP = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_ICR:
|
||||
env->ICR = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->ICR = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_FCX:
|
||||
env->FCX = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->FCX = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_LCX:
|
||||
env->LCX = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->LCX = *(uint32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_COMPAT:
|
||||
env->COMPAT = *(int32_t *)value;
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
env->COMPAT = *(uint32_t *)value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tricore_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUTriCoreState *env = &(TRICORE_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_write(env, regid, value);
|
||||
const void *value = vals[i];
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
if (regid == UC_TRICORE_REG_PC) {
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
@@ -233,22 +298,26 @@ int tricore_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
int tricore_context_reg_write(struct uc_context *uc, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
const void *const *vals, size_t *sizes, int count)
|
||||
{
|
||||
CPUTriCoreState *env = (CPUTriCoreState *)uc->data;
|
||||
int i;
|
||||
uc_err err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
reg_write(env, regid, value);
|
||||
err = reg_write(env, regid, value, sizes ? sizes + i : NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
static int tricore_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
||||
|
||||
@@ -10,15 +10,16 @@
|
||||
#define UC_QEMU_TARGET_TRICORE_H
|
||||
|
||||
// functions to read & write registers
|
||||
int tricore_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count);
|
||||
int tricore_reg_read(struct uc_struct *uc, unsigned int *regs,
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
int tricore_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes, int count);
|
||||
|
||||
int tricore_context_reg_read(struct uc_context *uc, unsigned int *regs,
|
||||
void **vals, int count);
|
||||
void *const *vals, size_t *sizes, int count);
|
||||
int tricore_context_reg_write(struct uc_context *uc, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
const void *const *vals, size_t *sizes,
|
||||
int count);
|
||||
|
||||
void tricore_reg_reset(struct uc_struct *uc);
|
||||
|
||||
|
||||
@@ -128,4 +128,15 @@ static inline void uc_common_init(struct uc_struct* uc)
|
||||
if (!uc->release)
|
||||
uc->release = release_common;
|
||||
}
|
||||
|
||||
#define CHECK_REG_TYPE(type) do { \
|
||||
if (size) { \
|
||||
if (*size < sizeof(type)) { \
|
||||
return UC_ERR_NOMEM; \
|
||||
} \
|
||||
*size = sizeof(type); \
|
||||
} \
|
||||
ret = UC_ERR_OK; \
|
||||
} while(0)
|
||||
|
||||
#endif
|
||||
|
||||
108
uc.c
108
uc.c
@@ -507,47 +507,63 @@ uc_err uc_close(uc_engine *uc)
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_read_batch(uc_engine *uc, int *ids, void **vals, int count)
|
||||
{
|
||||
int ret = UC_ERR_OK;
|
||||
|
||||
UC_INIT(uc);
|
||||
|
||||
if (uc->reg_read) {
|
||||
ret = uc->reg_read(uc, (unsigned int *)ids, vals, count);
|
||||
} else {
|
||||
return UC_ERR_HANDLE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return uc_reg_read_batch2(uc, ids, vals, NULL, count);
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_write_batch(uc_engine *uc, int *ids, void *const *vals, int count)
|
||||
{
|
||||
int ret = UC_ERR_OK;
|
||||
return uc_reg_write_batch2(uc, ids, (const void *const *)vals, NULL, count);
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_read_batch2(uc_engine *uc, int *ids, void *const *vals,
|
||||
size_t *sizes, int count)
|
||||
{
|
||||
UC_INIT(uc);
|
||||
|
||||
if (uc->reg_write) {
|
||||
ret = uc->reg_write(uc, (unsigned int *)ids, vals, count);
|
||||
if (uc->reg_read) {
|
||||
return uc->reg_read(uc, (unsigned int *)ids, vals, sizes, count);
|
||||
} else {
|
||||
return UC_ERR_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_write_batch2(uc_engine *uc, int *ids, const void *const *vals,
|
||||
size_t *sizes, int count)
|
||||
{
|
||||
UC_INIT(uc);
|
||||
|
||||
if (uc->reg_write) {
|
||||
return uc->reg_write(uc, (unsigned int *)ids, vals, sizes, count);
|
||||
} else {
|
||||
return UC_ERR_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_read(uc_engine *uc, int regid, void *value)
|
||||
{
|
||||
UC_INIT(uc);
|
||||
return uc_reg_read_batch(uc, ®id, &value, 1);
|
||||
return uc_reg_read_batch2(uc, ®id, &value, NULL, 1);
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_write(uc_engine *uc, int regid, const void *value)
|
||||
{
|
||||
UC_INIT(uc);
|
||||
return uc_reg_write_batch(uc, ®id, (void *const *)&value, 1);
|
||||
return uc_reg_write_batch2(uc, ®id, &value, NULL, 1);
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_read2(uc_engine *uc, int regid, void *value, size_t *size)
|
||||
{
|
||||
return uc_reg_read_batch2(uc, ®id, &value, size, 1);
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_reg_write2(uc_engine *uc, int regid, const void *value, size_t *size)
|
||||
{
|
||||
return uc_reg_write_batch2(uc, ®id, &value, size, 1);
|
||||
}
|
||||
|
||||
// check if a memory area is mapped
|
||||
@@ -1869,13 +1885,42 @@ uc_err uc_context_save(uc_engine *uc, uc_context *context)
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_reg_write(uc_context *ctx, int regid, const void *value)
|
||||
{
|
||||
return uc_context_reg_write_batch(ctx, ®id, (void *const *)&value, 1);
|
||||
return uc_context_reg_write_batch2(ctx, ®id, &value, NULL, 1);
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_reg_read(uc_context *ctx, int regid, void *value)
|
||||
{
|
||||
return uc_context_reg_read_batch(ctx, ®id, &value, 1);
|
||||
return uc_context_reg_read_batch2(ctx, ®id, &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, ®id, &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, ®id, &value, size, 1);
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_reg_write_batch(uc_context *ctx, int *ids, void *const *vals,
|
||||
int count)
|
||||
{
|
||||
return uc_context_reg_write_batch2(ctx, ids, (const void *const *)vals,
|
||||
NULL, count);
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_reg_read_batch(uc_context *ctx, int *ids, void **vals,
|
||||
int count)
|
||||
{
|
||||
return uc_context_reg_read_batch2(ctx, ids, vals, NULL, count);
|
||||
}
|
||||
|
||||
// Keep in mind that we don't a uc_engine when r/w the registers of a context.
|
||||
@@ -1997,37 +2042,34 @@ static void find_context_reg_rw_function(uc_arch arch, uc_mode mode,
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_reg_write_batch(uc_context *ctx, int *ids, void *const *vals,
|
||||
int count)
|
||||
uc_err uc_context_reg_write_batch2(uc_context *ctx, int *ids,
|
||||
const void *const *vals, size_t *sizes,
|
||||
int count)
|
||||
{
|
||||
int ret = UC_ERR_OK;
|
||||
context_reg_rw_t rw;
|
||||
|
||||
find_context_reg_rw_function(ctx->arch, ctx->mode, &rw);
|
||||
if (rw.context_reg_write) {
|
||||
ret = rw.context_reg_write(ctx, (unsigned int *)ids, vals, count);
|
||||
return rw.context_reg_write(ctx, (unsigned int *)ids, vals, sizes,
|
||||
count);
|
||||
} else {
|
||||
return UC_ERR_HANDLE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
uc_err uc_context_reg_read_batch(uc_context *ctx, int *ids, void **vals,
|
||||
int count)
|
||||
uc_err uc_context_reg_read_batch2(uc_context *ctx, int *ids, void *const *vals,
|
||||
size_t *sizes, int count)
|
||||
{
|
||||
int ret = UC_ERR_OK;
|
||||
context_reg_rw_t rw;
|
||||
|
||||
find_context_reg_rw_function(ctx->arch, ctx->mode, &rw);
|
||||
if (rw.context_reg_read) {
|
||||
ret = rw.context_reg_read(ctx, (unsigned int *)ids, vals, count);
|
||||
return rw.context_reg_read(ctx, (unsigned int *)ids, vals, sizes,
|
||||
count);
|
||||
} else {
|
||||
return UC_ERR_HANDLE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
|
||||
Reference in New Issue
Block a user