diff --git a/bindings/go/unicorn/uc.c b/bindings/go/unicorn/uc.c new file mode 100644 index 00000000..7d67c798 --- /dev/null +++ b/bindings/go/unicorn/uc.c @@ -0,0 +1,23 @@ +#include +#include +#include "_cgo_export.h" + +uc_err uc_reg_read_batch_helper(uc_engine *handle, int *regs, uint64_t *val_out, int count) { + void **val_ref = malloc(sizeof(void *) * count); + for (int i = 0; i < count; i++) { + val_ref[i] = (void *)&val_out[i]; + } + uc_err ret = uc_reg_read_batch(handle, regs, val_ref, count); + free(val_ref); + return ret; +} + +uc_err uc_reg_write_batch_helper(uc_engine *handle, int *regs, uint64_t *val_in, int count) { + const void **val_ref = malloc(sizeof(void *) * count); + for (int i = 0; i < count; i++) { + val_ref[i] = (void *)&val_in[i]; + } + uc_err ret = uc_reg_write_batch(handle, regs, val_ref, count); + free(val_ref); + return ret; +} diff --git a/bindings/go/unicorn/uc.h b/bindings/go/unicorn/uc.h new file mode 100644 index 00000000..06022346 --- /dev/null +++ b/bindings/go/unicorn/uc.h @@ -0,0 +1,2 @@ +uc_err uc_reg_read_batch_helper(uc_engine *handle, int *regs, uint64_t *val_out, int count); +uc_err uc_reg_write_batch_helper(uc_engine *handle, int *regs, uint64_t *val_in, int count); diff --git a/bindings/go/unicorn/unicorn.go b/bindings/go/unicorn/unicorn.go index fcebddda..42f619f9 100644 --- a/bindings/go/unicorn/unicorn.go +++ b/bindings/go/unicorn/unicorn.go @@ -7,8 +7,10 @@ import ( ) /* +#cgo CFLAGS: -O3 #cgo LDFLAGS: -lunicorn #include +#include "uc.h" */ import "C" @@ -41,7 +43,9 @@ type Unicorn interface { MemReadInto(dst []byte, addr uint64) error MemWrite(addr uint64, data []byte) error RegRead(reg int) (uint64, error) + RegReadBatch(regs []int) ([]uint64, error) RegWrite(reg int, value uint64) error + RegWriteBatch(regs []int, vals []uint64) error RegReadMmr(reg int) (*X86Mmr, error) RegWriteMmr(reg int, value *X86Mmr) error Start(begin, until uint64) error @@ -117,6 +121,38 @@ func (u *uc) RegRead(reg int) (uint64, error) { return uint64(val), errReturn(ucerr) } +func (u *uc) RegWriteBatch(regs []int, vals []uint64) error { + if len(regs) == 0 { + return nil + } + if len(vals) < len(regs) { + regs = regs[:len(vals)] + } + cregs := make([]C.int, len(regs)) + for i, v := range regs { + cregs[i] = C.int(v) + } + cregs2 := (*C.int)(unsafe.Pointer(&cregs[0])) + cvals := (*C.uint64_t)(unsafe.Pointer(&vals[0])) + ucerr := C.uc_reg_write_batch_helper(u.handle, cregs2, cvals, C.int(len(regs))) + return errReturn(ucerr) +} + +func (u *uc) RegReadBatch(regs []int) ([]uint64, error) { + if len(regs) == 0 { + return nil, nil + } + cregs := make([]C.int, len(regs)) + for i, v := range regs { + cregs[i] = C.int(v) + } + cregs2 := (*C.int)(unsafe.Pointer(&cregs[0])) + vals := make([]uint64, len(regs)) + cvals := (*C.uint64_t)(unsafe.Pointer(&vals[0])) + ucerr := C.uc_reg_read_batch_helper(u.handle, cregs2, cvals, C.int(len(regs))) + return vals, errReturn(ucerr) +} + func (u *uc) MemRegions() ([]*MemRegion, error) { var regions *C.struct_uc_mem_region var count C.uint32_t diff --git a/include/uc_priv.h b/include/uc_priv.h index e36a8c84..916f0c56 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -46,8 +46,8 @@ typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList; 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 regid, void *value); -typedef int (*reg_write_t)(struct uc_struct *uc, unsigned int regid, const void *value); +typedef int (*reg_read_t)(struct uc_struct *uc, unsigned int *regs, void **vals, int count); +typedef int (*reg_write_t)(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); typedef void (*reg_reset_t)(struct uc_struct *uc); diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 65d6aa53..0eb5390e 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -386,6 +386,34 @@ uc_err uc_reg_write(uc_engine *uc, int regid, const void *value); UNICORN_EXPORT uc_err uc_reg_read(uc_engine *uc, int regid, void *value); +/* + Write multiple register values. + + @uc: handle returned by uc_open() + @rges: array of register IDs to store + @value: pointer to array of 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). +*/ +UNICORN_EXPORT +uc_err uc_reg_write_batch(uc_engine *uc, int *regs, void *const *vals, int count); + +/* + 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 + @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). +*/ +UNICORN_EXPORT +uc_err uc_reg_read_batch(uc_engine *uc, int *regs, void **vals, int count); + /* Write to a range of bytes in memory. diff --git a/qemu/target-arm/unicorn.h b/qemu/target-arm/unicorn.h index 797ef979..0b3fb93d 100644 --- a/qemu/target-arm/unicorn.h +++ b/qemu/target-arm/unicorn.h @@ -5,10 +5,10 @@ #define UC_QEMU_TARGET_ARM_H // functions to read & write registers -int arm_reg_read(struct uc_struct *uc, unsigned int regid, void *value); -int arm_reg_write(struct uc_struct *uc, unsigned int regid, const void *value); -int arm64_reg_read(struct uc_struct *uc, unsigned int regid, void *value); -int arm64_reg_write(struct uc_struct *uc, unsigned int regid, const void *value); +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); void arm_reg_reset(struct uc_struct *uc); void arm64_reg_reset(struct uc_struct *uc); diff --git a/qemu/target-arm/unicorn_aarch64.c b/qemu/target-arm/unicorn_aarch64.c index c1d53a68..8e4bccfe 100644 --- a/qemu/target-arm/unicorn_aarch64.c +++ b/qemu/target-arm/unicorn_aarch64.c @@ -23,57 +23,67 @@ void arm64_reg_reset(struct uc_struct *uc) env->pc = 0; } -int arm64_reg_read(struct uc_struct *uc, unsigned int regid, void *value) +int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) { CPUState *mycpu = first_cpu; + int i; - if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28) - *(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_X0]; - else { - switch(regid) { - default: break; - case UC_ARM64_REG_X29: - *(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[29]; - break; - case UC_ARM64_REG_X30: - *(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[30]; - break; - case UC_ARM64_REG_PC: - *(uint64_t *)value = ARM_CPU(uc, mycpu)->env.pc; - break; - case UC_ARM64_REG_SP: - *(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[31]; - break; + for (i = 0; i < count; i++) { + unsigned int regid = regs[i]; + void *value = vals[i]; + if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28) + *(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_X0]; + else { + switch(regid) { + default: break; + case UC_ARM64_REG_X29: + *(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[29]; + break; + case UC_ARM64_REG_X30: + *(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[30]; + break; + case UC_ARM64_REG_PC: + *(uint64_t *)value = ARM_CPU(uc, mycpu)->env.pc; + break; + case UC_ARM64_REG_SP: + *(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[31]; + break; + } } } return 0; } -int arm64_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) +int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, int count) { CPUState *mycpu = first_cpu; + int i; - if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28) - ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_X0] = *(uint64_t *)value; - else { - switch(regid) { - default: break; - case UC_ARM64_REG_X29: - ARM_CPU(uc, mycpu)->env.xregs[29] = *(uint64_t *)value; - break; - case UC_ARM64_REG_X30: - ARM_CPU(uc, mycpu)->env.xregs[30] = *(uint64_t *)value; - break; - case UC_ARM64_REG_PC: - ARM_CPU(uc, mycpu)->env.pc = *(uint64_t *)value; - // force to quit execution and flush TB - uc->quit_request = true; - uc_emu_stop(uc); - break; - case UC_ARM64_REG_SP: - ARM_CPU(uc, mycpu)->env.xregs[31] = *(uint64_t *)value; - break; + for (i = 0; i < count; i++) { + unsigned int regid = regs[i]; + const void *value = vals[i]; + if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28) + ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_X0] = *(uint64_t *)value; + else { + switch(regid) { + default: break; + case UC_ARM64_REG_X29: + ARM_CPU(uc, mycpu)->env.xregs[29] = *(uint64_t *)value; + break; + case UC_ARM64_REG_X30: + ARM_CPU(uc, mycpu)->env.xregs[30] = *(uint64_t *)value; + break; + case UC_ARM64_REG_PC: + ARM_CPU(uc, mycpu)->env.pc = *(uint64_t *)value; + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); + break; + case UC_ARM64_REG_SP: + ARM_CPU(uc, mycpu)->env.xregs[31] = *(uint64_t *)value; + break; + } } } diff --git a/qemu/target-arm/unicorn_arm.c b/qemu/target-arm/unicorn_arm.c index 9fc2a44c..a6d9355f 100644 --- a/qemu/target-arm/unicorn_arm.c +++ b/qemu/target-arm/unicorn_arm.c @@ -27,62 +27,72 @@ void arm_reg_reset(struct uc_struct *uc) env->pc = 0; } -int arm_reg_read(struct uc_struct *uc, unsigned int regid, void *value) +int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) { CPUState *mycpu; + int i; mycpu = first_cpu; - if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) - *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0]; - else { - switch(regid) { - case UC_ARM_REG_CPSR: - *(int32_t *)value = cpsr_read(&ARM_CPU(uc, mycpu)->env); - break; - //case UC_ARM_REG_SP: - case UC_ARM_REG_R13: - *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[13]; - break; - //case UC_ARM_REG_LR: - case UC_ARM_REG_R14: - *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[14]; - break; - //case UC_ARM_REG_PC: - case UC_ARM_REG_R15: - *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[15]; - break; + for (i = 0; i < count; i++) { + unsigned int regid = regs[i]; + void *value = vals[i]; + if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) + *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0]; + else { + switch(regid) { + case UC_ARM_REG_CPSR: + *(int32_t *)value = cpsr_read(&ARM_CPU(uc, mycpu)->env); + break; + //case UC_ARM_REG_SP: + case UC_ARM_REG_R13: + *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[13]; + break; + //case UC_ARM_REG_LR: + case UC_ARM_REG_R14: + *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[14]; + break; + //case UC_ARM_REG_PC: + case UC_ARM_REG_R15: + *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[15]; + break; + } } } return 0; } -int arm_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) +int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, int count) { CPUState *mycpu = first_cpu; + int i; - if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) - ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0] = *(uint32_t *)value; - else { - switch(regid) { - //case UC_ARM_REG_SP: - case UC_ARM_REG_R13: - ARM_CPU(uc, mycpu)->env.regs[13] = *(uint32_t *)value; - break; - //case UC_ARM_REG_LR: - case UC_ARM_REG_R14: - ARM_CPU(uc, mycpu)->env.regs[14] = *(uint32_t *)value; - break; - //case UC_ARM_REG_PC: - case UC_ARM_REG_R15: - ARM_CPU(uc, mycpu)->env.pc = *(uint32_t *)value; - ARM_CPU(uc, mycpu)->env.regs[15] = *(uint32_t *)value; - // force to quit execution and flush TB - uc->quit_request = true; - uc_emu_stop(uc); + for (i = 0; i < count; i++) { + unsigned int regid = regs[i]; + const void *value = vals[i]; + if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) + ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0] = *(uint32_t *)value; + else { + switch(regid) { + //case UC_ARM_REG_SP: + case UC_ARM_REG_R13: + ARM_CPU(uc, mycpu)->env.regs[13] = *(uint32_t *)value; + break; + //case UC_ARM_REG_LR: + case UC_ARM_REG_R14: + ARM_CPU(uc, mycpu)->env.regs[14] = *(uint32_t *)value; + break; + //case UC_ARM_REG_PC: + case UC_ARM_REG_R15: + ARM_CPU(uc, mycpu)->env.pc = *(uint32_t *)value; + ARM_CPU(uc, mycpu)->env.regs[15] = *(uint32_t *)value; + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); - break; + break; + } } } diff --git a/qemu/target-i386/unicorn.c b/qemu/target-i386/unicorn.c index 961e8d98..f4d134bd 100644 --- a/qemu/target-i386/unicorn.c +++ b/qemu/target-i386/unicorn.c @@ -136,970 +136,979 @@ void x86_reg_reset(struct uc_struct *uc) } } -int x86_reg_read(struct uc_struct *uc, unsigned int regid, void *value) +int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) { CPUState *mycpu = first_cpu; + int i; - switch(regid) { - default: - break; - case UC_X86_REG_FP0 ... UC_X86_REG_FP7: - { - floatx80 reg = X86_CPU(uc, mycpu)->env.fpregs[regid - UC_X86_REG_FP0].d; - cpu_get_fp80(value, value+sizeof(uint64_t), reg); - } - return 0; - case UC_X86_REG_FPSW: - { - uint16_t fpus = X86_CPU(uc, mycpu)->env.fpus; - fpus = fpus & ~0x3800; - fpus |= ( X86_CPU(uc, mycpu)->env.fpstt & 0x7 ) << 11; - *(uint16_t*) value = fpus; - } - return 0; - case UC_X86_REG_FPCW: - *(uint16_t*) value = X86_CPU(uc, mycpu)->env.fpuc; - return 0; - case UC_X86_REG_FPTAG: - { - #define EXPD(fp) (fp.l.upper & 0x7fff) - #define MANTD(fp) (fp.l.lower) - #define MAXEXPD 0x7fff - int fptag, exp, i; - uint64_t mant; - CPU_LDoubleU tmp; - fptag = 0; - for (i = 7; i >= 0; i--) { - fptag <<= 2; - if (X86_CPU(uc, mycpu)->env.fptags[i]) { - fptag |= 3; - } else { - tmp.d = X86_CPU(uc, mycpu)->env.fpregs[i].d; - exp = EXPD(tmp); - mant = MANTD(tmp); - if (exp == 0 && mant == 0) { - /* zero */ - fptag |= 1; - } else if (exp == 0 || exp == MAXEXPD - || (mant & (1LL << 63)) == 0) { - /* NaNs, infinity, denormal */ - fptag |= 2; + for (i = 0; i < count; i++) { + unsigned int regid = regs[i]; + void *value = vals[i]; + switch(regid) { + default: + break; + case UC_X86_REG_FP0 ... UC_X86_REG_FP7: + { + floatx80 reg = X86_CPU(uc, mycpu)->env.fpregs[regid - UC_X86_REG_FP0].d; + cpu_get_fp80(value, value+sizeof(uint64_t), reg); + } + continue; + case UC_X86_REG_FPSW: + { + uint16_t fpus = X86_CPU(uc, mycpu)->env.fpus; + fpus = fpus & ~0x3800; + fpus |= ( X86_CPU(uc, mycpu)->env.fpstt & 0x7 ) << 11; + *(uint16_t*) value = fpus; + } + continue; + case UC_X86_REG_FPCW: + *(uint16_t*) value = X86_CPU(uc, mycpu)->env.fpuc; + continue; + case UC_X86_REG_FPTAG: + { + #define EXPD(fp) (fp.l.upper & 0x7fff) + #define MANTD(fp) (fp.l.lower) + #define MAXEXPD 0x7fff + int fptag, exp, i; + uint64_t mant; + CPU_LDoubleU tmp; + fptag = 0; + for (i = 7; i >= 0; i--) { + fptag <<= 2; + if (X86_CPU(uc, mycpu)->env.fptags[i]) { + fptag |= 3; + } else { + tmp.d = X86_CPU(uc, mycpu)->env.fpregs[i].d; + exp = EXPD(tmp); + mant = MANTD(tmp); + if (exp == 0 && mant == 0) { + /* zero */ + fptag |= 1; + } else if (exp == 0 || exp == MAXEXPD + || (mant & (1LL << 63)) == 0) { + /* NaNs, infinity, denormal */ + fptag |= 2; + } } } + *(uint16_t*) value = fptag; } - *(uint16_t*) value = fptag; - } - return 0; - } + continue; + } - switch(uc->mode) { - default: - break; - case UC_MODE_16: - switch(regid) { - default: break; - case UC_X86_REG_ES: - *(int16_t *)value = X86_CPU(uc, mycpu)->env.segs[R_ES].selector; - return 0; - case UC_X86_REG_SS: - *(int16_t *)value = X86_CPU(uc, mycpu)->env.segs[R_SS].selector; - return 0; - case UC_X86_REG_DS: - *(int16_t *)value = X86_CPU(uc, mycpu)->env.segs[R_DS].selector; - return 0; - case UC_X86_REG_FS: - *(int16_t *)value = X86_CPU(uc, mycpu)->env.segs[R_FS].selector; - return 0; - case UC_X86_REG_GS: - *(int16_t *)value = X86_CPU(uc, mycpu)->env.segs[R_GS].selector; - return 0; - } - // fall-thru - case UC_MODE_32: - switch(regid) { - default: - break; - case UC_X86_REG_CR0 ... UC_X86_REG_CR4: - *(int32_t *)value = X86_CPU(uc, mycpu)->env.cr[regid - UC_X86_REG_CR0]; - break; - case UC_X86_REG_DR0 ... UC_X86_REG_DR7: - *(int32_t *)value = X86_CPU(uc, mycpu)->env.dr[regid - UC_X86_REG_DR0]; - break; - case UC_X86_REG_EFLAGS: - *(int32_t *)value = X86_CPU(uc, mycpu)->env.eflags; - break; - case UC_X86_REG_EAX: - *(int32_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EAX]; - break; - case UC_X86_REG_AX: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EAX]); - break; - case UC_X86_REG_AH: - *(int8_t *)value = READ_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EAX]); - break; - case UC_X86_REG_AL: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EAX]); - break; - case UC_X86_REG_EBX: - *(int32_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EBX]; - break; - case UC_X86_REG_BX: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBX]); - break; - case UC_X86_REG_BH: - *(int8_t *)value = READ_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EBX]); - break; - case UC_X86_REG_BL: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EBX]); - break; - case UC_X86_REG_ECX: - *(int32_t *)value = X86_CPU(uc, mycpu)->env.regs[R_ECX]; - break; - case UC_X86_REG_CX: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_ECX]); - break; - case UC_X86_REG_CH: - *(int8_t *)value = READ_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_ECX]); - break; - case UC_X86_REG_CL: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ECX]); - break; - case UC_X86_REG_EDX: - *(int32_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EDX]; - break; - case UC_X86_REG_DX: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDX]); - break; - case UC_X86_REG_DH: - *(int8_t *)value = READ_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EDX]); - break; - case UC_X86_REG_DL: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EDX]); - break; - case UC_X86_REG_ESP: - *(int32_t *)value = X86_CPU(uc, mycpu)->env.regs[R_ESP]; - break; - case UC_X86_REG_SP: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESP]); - break; - case UC_X86_REG_EBP: - *(int32_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EBP]; - break; - case UC_X86_REG_BP: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBP]); - break; - case UC_X86_REG_ESI: - *(int32_t *)value = X86_CPU(uc, mycpu)->env.regs[R_ESI]; - break; - case UC_X86_REG_SI: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESI]); - break; - case UC_X86_REG_EDI: - *(int32_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EDI]; - break; - case UC_X86_REG_DI: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDI]); - break; - case UC_X86_REG_EIP: - *(int32_t *)value = X86_CPU(uc, mycpu)->env.eip; - break; - case UC_X86_REG_IP: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.eip); - break; - case UC_X86_REG_CS: - *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_CS].selector; - break; - case UC_X86_REG_DS: - *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_DS].selector; - break; - case UC_X86_REG_SS: - *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_SS].selector; - break; - case UC_X86_REG_ES: - *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_ES].selector; - break; - case UC_X86_REG_FS: - *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_FS].selector; - break; - case UC_X86_REG_GS: - *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_GS].selector; - break; - case UC_X86_REG_IDTR: - ((uc_x86_mmr *)value)->limit = (uint16_t)X86_CPU(uc, mycpu)->env.idt.limit; - ((uc_x86_mmr *)value)->base = (uint32_t)X86_CPU(uc, mycpu)->env.idt.base; - break; - case UC_X86_REG_GDTR: - ((uc_x86_mmr *)value)->limit = (uint16_t)X86_CPU(uc, mycpu)->env.gdt.limit; - ((uc_x86_mmr *)value)->base = (uint32_t)X86_CPU(uc, mycpu)->env.gdt.base; - break; - case UC_X86_REG_LDTR: - ((uc_x86_mmr *)value)->limit = X86_CPU(uc, mycpu)->env.ldt.limit; - ((uc_x86_mmr *)value)->base = (uint32_t)X86_CPU(uc, mycpu)->env.ldt.base; - ((uc_x86_mmr *)value)->selector = (uint16_t)X86_CPU(uc, mycpu)->env.ldt.selector; - ((uc_x86_mmr *)value)->flags = X86_CPU(uc, mycpu)->env.ldt.flags; - break; - case UC_X86_REG_TR: - ((uc_x86_mmr *)value)->limit = X86_CPU(uc, mycpu)->env.tr.limit; - ((uc_x86_mmr *)value)->base = (uint32_t)X86_CPU(uc, mycpu)->env.tr.base; - ((uc_x86_mmr *)value)->selector = (uint16_t)X86_CPU(uc, mycpu)->env.tr.selector; - ((uc_x86_mmr *)value)->flags = X86_CPU(uc, mycpu)->env.tr.flags; - break; - } - break; + switch(uc->mode) { + default: + break; + case UC_MODE_16: + switch(regid) { + default: break; + case UC_X86_REG_ES: + *(int16_t *)value = X86_CPU(uc, mycpu)->env.segs[R_ES].selector; + continue; + case UC_X86_REG_SS: + *(int16_t *)value = X86_CPU(uc, mycpu)->env.segs[R_SS].selector; + continue; + case UC_X86_REG_DS: + *(int16_t *)value = X86_CPU(uc, mycpu)->env.segs[R_DS].selector; + continue; + case UC_X86_REG_FS: + *(int16_t *)value = X86_CPU(uc, mycpu)->env.segs[R_FS].selector; + continue; + case UC_X86_REG_GS: + *(int16_t *)value = X86_CPU(uc, mycpu)->env.segs[R_GS].selector; + continue; + } + // fall-thru + case UC_MODE_32: + switch(regid) { + default: + break; + case UC_X86_REG_CR0 ... UC_X86_REG_CR4: + *(int32_t *)value = X86_CPU(uc, mycpu)->env.cr[regid - UC_X86_REG_CR0]; + break; + case UC_X86_REG_DR0 ... UC_X86_REG_DR7: + *(int32_t *)value = X86_CPU(uc, mycpu)->env.dr[regid - UC_X86_REG_DR0]; + break; + case UC_X86_REG_EFLAGS: + *(int32_t *)value = X86_CPU(uc, mycpu)->env.eflags; + break; + case UC_X86_REG_EAX: + *(int32_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EAX]; + break; + case UC_X86_REG_AX: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EAX]); + break; + case UC_X86_REG_AH: + *(int8_t *)value = READ_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EAX]); + break; + case UC_X86_REG_AL: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EAX]); + break; + case UC_X86_REG_EBX: + *(int32_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EBX]; + break; + case UC_X86_REG_BX: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBX]); + break; + case UC_X86_REG_BH: + *(int8_t *)value = READ_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EBX]); + break; + case UC_X86_REG_BL: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EBX]); + break; + case UC_X86_REG_ECX: + *(int32_t *)value = X86_CPU(uc, mycpu)->env.regs[R_ECX]; + break; + case UC_X86_REG_CX: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_ECX]); + break; + case UC_X86_REG_CH: + *(int8_t *)value = READ_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_ECX]); + break; + case UC_X86_REG_CL: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ECX]); + break; + case UC_X86_REG_EDX: + *(int32_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EDX]; + break; + case UC_X86_REG_DX: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDX]); + break; + case UC_X86_REG_DH: + *(int8_t *)value = READ_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EDX]); + break; + case UC_X86_REG_DL: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EDX]); + break; + case UC_X86_REG_ESP: + *(int32_t *)value = X86_CPU(uc, mycpu)->env.regs[R_ESP]; + break; + case UC_X86_REG_SP: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESP]); + break; + case UC_X86_REG_EBP: + *(int32_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EBP]; + break; + case UC_X86_REG_BP: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBP]); + break; + case UC_X86_REG_ESI: + *(int32_t *)value = X86_CPU(uc, mycpu)->env.regs[R_ESI]; + break; + case UC_X86_REG_SI: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESI]); + break; + case UC_X86_REG_EDI: + *(int32_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EDI]; + break; + case UC_X86_REG_DI: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDI]); + break; + case UC_X86_REG_EIP: + *(int32_t *)value = X86_CPU(uc, mycpu)->env.eip; + break; + case UC_X86_REG_IP: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.eip); + break; + case UC_X86_REG_CS: + *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_CS].selector; + break; + case UC_X86_REG_DS: + *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_DS].selector; + break; + case UC_X86_REG_SS: + *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_SS].selector; + break; + case UC_X86_REG_ES: + *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_ES].selector; + break; + case UC_X86_REG_FS: + *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_FS].selector; + break; + case UC_X86_REG_GS: + *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_GS].selector; + break; + case UC_X86_REG_IDTR: + ((uc_x86_mmr *)value)->limit = (uint16_t)X86_CPU(uc, mycpu)->env.idt.limit; + ((uc_x86_mmr *)value)->base = (uint32_t)X86_CPU(uc, mycpu)->env.idt.base; + break; + case UC_X86_REG_GDTR: + ((uc_x86_mmr *)value)->limit = (uint16_t)X86_CPU(uc, mycpu)->env.gdt.limit; + ((uc_x86_mmr *)value)->base = (uint32_t)X86_CPU(uc, mycpu)->env.gdt.base; + break; + case UC_X86_REG_LDTR: + ((uc_x86_mmr *)value)->limit = X86_CPU(uc, mycpu)->env.ldt.limit; + ((uc_x86_mmr *)value)->base = (uint32_t)X86_CPU(uc, mycpu)->env.ldt.base; + ((uc_x86_mmr *)value)->selector = (uint16_t)X86_CPU(uc, mycpu)->env.ldt.selector; + ((uc_x86_mmr *)value)->flags = X86_CPU(uc, mycpu)->env.ldt.flags; + break; + case UC_X86_REG_TR: + ((uc_x86_mmr *)value)->limit = X86_CPU(uc, mycpu)->env.tr.limit; + ((uc_x86_mmr *)value)->base = (uint32_t)X86_CPU(uc, mycpu)->env.tr.base; + ((uc_x86_mmr *)value)->selector = (uint16_t)X86_CPU(uc, mycpu)->env.tr.selector; + ((uc_x86_mmr *)value)->flags = X86_CPU(uc, mycpu)->env.tr.flags; + break; + } + break; #ifdef TARGET_X86_64 - case UC_MODE_64: - switch(regid) { - default: - break; - case UC_X86_REG_CR0 ... UC_X86_REG_CR4: - *(int64_t *)value = X86_CPU(uc, mycpu)->env.cr[regid - UC_X86_REG_CR0]; - break; - case UC_X86_REG_DR0 ... UC_X86_REG_DR7: - *(int64_t *)value = X86_CPU(uc, mycpu)->env.dr[regid - UC_X86_REG_DR0]; - break; - case UC_X86_REG_EFLAGS: - *(int64_t *)value = X86_CPU(uc, mycpu)->env.eflags; - break; - case UC_X86_REG_RAX: - *(uint64_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EAX]; - break; - case UC_X86_REG_EAX: - *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EAX]); - break; - case UC_X86_REG_AX: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EAX]); - break; - case UC_X86_REG_AH: - *(int8_t *)value = READ_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EAX]); - break; - case UC_X86_REG_AL: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EAX]); - break; - case UC_X86_REG_RBX: - *(uint64_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EBX]; - break; - case UC_X86_REG_EBX: - *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EBX]); - break; - case UC_X86_REG_BX: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBX]); - break; - case UC_X86_REG_BH: - *(int8_t *)value = READ_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EBX]); - break; - case UC_X86_REG_BL: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EBX]); - break; - case UC_X86_REG_RCX: - *(uint64_t *)value = X86_CPU(uc, mycpu)->env.regs[R_ECX]; - break; - case UC_X86_REG_ECX: - *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[R_ECX]); - break; - case UC_X86_REG_CX: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_ECX]); - break; - case UC_X86_REG_CH: - *(int8_t *)value = READ_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_ECX]); - break; - case UC_X86_REG_CL: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ECX]); - break; - case UC_X86_REG_RDX: - *(uint64_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EDX]; - break; - case UC_X86_REG_EDX: - *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EDX]); - break; - case UC_X86_REG_DX: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDX]); - break; - case UC_X86_REG_DH: - *(int8_t *)value = READ_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EDX]); - break; - case UC_X86_REG_DL: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EDX]); - break; - case UC_X86_REG_RSP: - *(uint64_t *)value = X86_CPU(uc, mycpu)->env.regs[R_ESP]; - break; - case UC_X86_REG_ESP: - *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[R_ESP]); - break; - case UC_X86_REG_SP: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESP]); - break; - case UC_X86_REG_SPL: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ESP]); - break; - case UC_X86_REG_RBP: - *(uint64_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EBP]; - break; - case UC_X86_REG_EBP: - *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EBP]); - break; - case UC_X86_REG_BP: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBP]); - break; - case UC_X86_REG_BPL: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EBP]); - break; - case UC_X86_REG_RSI: - *(uint64_t *)value = X86_CPU(uc, mycpu)->env.regs[R_ESI]; - break; - case UC_X86_REG_ESI: - *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[R_ESI]); - break; - case UC_X86_REG_SI: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESI]); - break; - case UC_X86_REG_SIL: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ESI]); - break; - case UC_X86_REG_RDI: - *(uint64_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EDI]; - break; - case UC_X86_REG_EDI: - *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EDI]); - break; - case UC_X86_REG_DI: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDI]); - break; - case UC_X86_REG_DIL: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EDI]); - break; - case UC_X86_REG_RIP: - *(uint64_t *)value = X86_CPU(uc, mycpu)->env.eip; - break; - case UC_X86_REG_EIP: - *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.eip); - break; - case UC_X86_REG_IP: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.eip); - break; - case UC_X86_REG_CS: - *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_CS].selector; - break; - case UC_X86_REG_DS: - *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_DS].selector; - break; - case UC_X86_REG_SS: - *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_SS].selector; - break; - case UC_X86_REG_ES: - *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_ES].selector; - break; - case UC_X86_REG_FS: - *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_FS].selector; - break; - case UC_X86_REG_GS: - *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_GS].selector; - break; - case UC_X86_REG_R8: - *(int64_t *)value = READ_QWORD(X86_CPU(uc, mycpu)->env.regs[8]); - break; - case UC_X86_REG_R8D: - *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[8]); - break; - case UC_X86_REG_R8W: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[8]); - break; - case UC_X86_REG_R8B: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[8]); - break; - case UC_X86_REG_R9: - *(int64_t *)value = READ_QWORD(X86_CPU(uc, mycpu)->env.regs[9]); - break; - case UC_X86_REG_R9D: - *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[9]); - break; - case UC_X86_REG_R9W: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[9]); - break; - case UC_X86_REG_R9B: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[9]); - break; - case UC_X86_REG_R10: - *(int64_t *)value = READ_QWORD(X86_CPU(uc, mycpu)->env.regs[10]); - break; - case UC_X86_REG_R10D: - *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[10]); - break; - case UC_X86_REG_R10W: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[10]); - break; - case UC_X86_REG_R10B: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[10]); - break; - case UC_X86_REG_R11: - *(int64_t *)value = READ_QWORD(X86_CPU(uc, mycpu)->env.regs[11]); - break; - case UC_X86_REG_R11D: - *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[11]); - break; - case UC_X86_REG_R11W: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[11]); - break; - case UC_X86_REG_R11B: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[11]); - break; - case UC_X86_REG_R12: - *(int64_t *)value = READ_QWORD(X86_CPU(uc, mycpu)->env.regs[12]); - break; - case UC_X86_REG_R12D: - *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[12]); - break; - case UC_X86_REG_R12W: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[12]); - break; - case UC_X86_REG_R12B: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[12]); - break; - case UC_X86_REG_R13: - *(int64_t *)value = READ_QWORD(X86_CPU(uc, mycpu)->env.regs[13]); - break; - case UC_X86_REG_R13D: - *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[13]); - break; - case UC_X86_REG_R13W: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[13]); - break; - case UC_X86_REG_R13B: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[13]); - break; - case UC_X86_REG_R14: - *(int64_t *)value = READ_QWORD(X86_CPU(uc, mycpu)->env.regs[14]); - break; - case UC_X86_REG_R14D: - *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[14]); - break; - case UC_X86_REG_R14W: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[14]); - break; - case UC_X86_REG_R14B: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[14]); - break; - case UC_X86_REG_R15: - *(int64_t *)value = READ_QWORD(X86_CPU(uc, mycpu)->env.regs[15]); - break; - case UC_X86_REG_R15D: - *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[15]); - break; - case UC_X86_REG_R15W: - *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[15]); - break; - case UC_X86_REG_R15B: - *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[15]); - break; - case UC_X86_REG_IDTR: - ((uc_x86_mmr *)value)->limit = (uint16_t)X86_CPU(uc, mycpu)->env.idt.limit; - ((uc_x86_mmr *)value)->base = X86_CPU(uc, mycpu)->env.idt.base; - break; - case UC_X86_REG_GDTR: - ((uc_x86_mmr *)value)->limit = (uint16_t)X86_CPU(uc, mycpu)->env.gdt.limit; - ((uc_x86_mmr *)value)->base = X86_CPU(uc, mycpu)->env.gdt.base; - break; - case UC_X86_REG_LDTR: - ((uc_x86_mmr *)value)->limit = X86_CPU(uc, mycpu)->env.ldt.limit; - ((uc_x86_mmr *)value)->base = X86_CPU(uc, mycpu)->env.ldt.base; - ((uc_x86_mmr *)value)->selector = (uint16_t)X86_CPU(uc, mycpu)->env.ldt.selector; - ((uc_x86_mmr *)value)->flags = X86_CPU(uc, mycpu)->env.ldt.flags; - break; - case UC_X86_REG_TR: - ((uc_x86_mmr *)value)->limit = X86_CPU(uc, mycpu)->env.tr.limit; - ((uc_x86_mmr *)value)->base = X86_CPU(uc, mycpu)->env.tr.base; - ((uc_x86_mmr *)value)->selector = (uint16_t)X86_CPU(uc, mycpu)->env.tr.selector; - ((uc_x86_mmr *)value)->flags = X86_CPU(uc, mycpu)->env.tr.flags; - break; - } - break; + case UC_MODE_64: + switch(regid) { + default: + break; + case UC_X86_REG_CR0 ... UC_X86_REG_CR4: + *(int64_t *)value = X86_CPU(uc, mycpu)->env.cr[regid - UC_X86_REG_CR0]; + break; + case UC_X86_REG_DR0 ... UC_X86_REG_DR7: + *(int64_t *)value = X86_CPU(uc, mycpu)->env.dr[regid - UC_X86_REG_DR0]; + break; + case UC_X86_REG_EFLAGS: + *(int64_t *)value = X86_CPU(uc, mycpu)->env.eflags; + break; + case UC_X86_REG_RAX: + *(uint64_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EAX]; + break; + case UC_X86_REG_EAX: + *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EAX]); + break; + case UC_X86_REG_AX: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EAX]); + break; + case UC_X86_REG_AH: + *(int8_t *)value = READ_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EAX]); + break; + case UC_X86_REG_AL: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EAX]); + break; + case UC_X86_REG_RBX: + *(uint64_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EBX]; + break; + case UC_X86_REG_EBX: + *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EBX]); + break; + case UC_X86_REG_BX: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBX]); + break; + case UC_X86_REG_BH: + *(int8_t *)value = READ_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EBX]); + break; + case UC_X86_REG_BL: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EBX]); + break; + case UC_X86_REG_RCX: + *(uint64_t *)value = X86_CPU(uc, mycpu)->env.regs[R_ECX]; + break; + case UC_X86_REG_ECX: + *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[R_ECX]); + break; + case UC_X86_REG_CX: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_ECX]); + break; + case UC_X86_REG_CH: + *(int8_t *)value = READ_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_ECX]); + break; + case UC_X86_REG_CL: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ECX]); + break; + case UC_X86_REG_RDX: + *(uint64_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EDX]; + break; + case UC_X86_REG_EDX: + *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EDX]); + break; + case UC_X86_REG_DX: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDX]); + break; + case UC_X86_REG_DH: + *(int8_t *)value = READ_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EDX]); + break; + case UC_X86_REG_DL: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EDX]); + break; + case UC_X86_REG_RSP: + *(uint64_t *)value = X86_CPU(uc, mycpu)->env.regs[R_ESP]; + break; + case UC_X86_REG_ESP: + *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[R_ESP]); + break; + case UC_X86_REG_SP: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESP]); + break; + case UC_X86_REG_SPL: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ESP]); + break; + case UC_X86_REG_RBP: + *(uint64_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EBP]; + break; + case UC_X86_REG_EBP: + *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EBP]); + break; + case UC_X86_REG_BP: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBP]); + break; + case UC_X86_REG_BPL: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EBP]); + break; + case UC_X86_REG_RSI: + *(uint64_t *)value = X86_CPU(uc, mycpu)->env.regs[R_ESI]; + break; + case UC_X86_REG_ESI: + *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[R_ESI]); + break; + case UC_X86_REG_SI: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESI]); + break; + case UC_X86_REG_SIL: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ESI]); + break; + case UC_X86_REG_RDI: + *(uint64_t *)value = X86_CPU(uc, mycpu)->env.regs[R_EDI]; + break; + case UC_X86_REG_EDI: + *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EDI]); + break; + case UC_X86_REG_DI: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDI]); + break; + case UC_X86_REG_DIL: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EDI]); + break; + case UC_X86_REG_RIP: + *(uint64_t *)value = X86_CPU(uc, mycpu)->env.eip; + break; + case UC_X86_REG_EIP: + *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.eip); + break; + case UC_X86_REG_IP: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.eip); + break; + case UC_X86_REG_CS: + *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_CS].selector; + break; + case UC_X86_REG_DS: + *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_DS].selector; + break; + case UC_X86_REG_SS: + *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_SS].selector; + break; + case UC_X86_REG_ES: + *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_ES].selector; + break; + case UC_X86_REG_FS: + *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_FS].selector; + break; + case UC_X86_REG_GS: + *(int16_t *)value = (uint16_t)X86_CPU(uc, mycpu)->env.segs[R_GS].selector; + break; + case UC_X86_REG_R8: + *(int64_t *)value = READ_QWORD(X86_CPU(uc, mycpu)->env.regs[8]); + break; + case UC_X86_REG_R8D: + *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[8]); + break; + case UC_X86_REG_R8W: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[8]); + break; + case UC_X86_REG_R8B: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[8]); + break; + case UC_X86_REG_R9: + *(int64_t *)value = READ_QWORD(X86_CPU(uc, mycpu)->env.regs[9]); + break; + case UC_X86_REG_R9D: + *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[9]); + break; + case UC_X86_REG_R9W: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[9]); + break; + case UC_X86_REG_R9B: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[9]); + break; + case UC_X86_REG_R10: + *(int64_t *)value = READ_QWORD(X86_CPU(uc, mycpu)->env.regs[10]); + break; + case UC_X86_REG_R10D: + *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[10]); + break; + case UC_X86_REG_R10W: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[10]); + break; + case UC_X86_REG_R10B: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[10]); + break; + case UC_X86_REG_R11: + *(int64_t *)value = READ_QWORD(X86_CPU(uc, mycpu)->env.regs[11]); + break; + case UC_X86_REG_R11D: + *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[11]); + break; + case UC_X86_REG_R11W: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[11]); + break; + case UC_X86_REG_R11B: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[11]); + break; + case UC_X86_REG_R12: + *(int64_t *)value = READ_QWORD(X86_CPU(uc, mycpu)->env.regs[12]); + break; + case UC_X86_REG_R12D: + *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[12]); + break; + case UC_X86_REG_R12W: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[12]); + break; + case UC_X86_REG_R12B: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[12]); + break; + case UC_X86_REG_R13: + *(int64_t *)value = READ_QWORD(X86_CPU(uc, mycpu)->env.regs[13]); + break; + case UC_X86_REG_R13D: + *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[13]); + break; + case UC_X86_REG_R13W: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[13]); + break; + case UC_X86_REG_R13B: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[13]); + break; + case UC_X86_REG_R14: + *(int64_t *)value = READ_QWORD(X86_CPU(uc, mycpu)->env.regs[14]); + break; + case UC_X86_REG_R14D: + *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[14]); + break; + case UC_X86_REG_R14W: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[14]); + break; + case UC_X86_REG_R14B: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[14]); + break; + case UC_X86_REG_R15: + *(int64_t *)value = READ_QWORD(X86_CPU(uc, mycpu)->env.regs[15]); + break; + case UC_X86_REG_R15D: + *(int32_t *)value = READ_DWORD(X86_CPU(uc, mycpu)->env.regs[15]); + break; + case UC_X86_REG_R15W: + *(int16_t *)value = READ_WORD(X86_CPU(uc, mycpu)->env.regs[15]); + break; + case UC_X86_REG_R15B: + *(int8_t *)value = READ_BYTE_L(X86_CPU(uc, mycpu)->env.regs[15]); + break; + case UC_X86_REG_IDTR: + ((uc_x86_mmr *)value)->limit = (uint16_t)X86_CPU(uc, mycpu)->env.idt.limit; + ((uc_x86_mmr *)value)->base = X86_CPU(uc, mycpu)->env.idt.base; + break; + case UC_X86_REG_GDTR: + ((uc_x86_mmr *)value)->limit = (uint16_t)X86_CPU(uc, mycpu)->env.gdt.limit; + ((uc_x86_mmr *)value)->base = X86_CPU(uc, mycpu)->env.gdt.base; + break; + case UC_X86_REG_LDTR: + ((uc_x86_mmr *)value)->limit = X86_CPU(uc, mycpu)->env.ldt.limit; + ((uc_x86_mmr *)value)->base = X86_CPU(uc, mycpu)->env.ldt.base; + ((uc_x86_mmr *)value)->selector = (uint16_t)X86_CPU(uc, mycpu)->env.ldt.selector; + ((uc_x86_mmr *)value)->flags = X86_CPU(uc, mycpu)->env.ldt.flags; + break; + case UC_X86_REG_TR: + ((uc_x86_mmr *)value)->limit = X86_CPU(uc, mycpu)->env.tr.limit; + ((uc_x86_mmr *)value)->base = X86_CPU(uc, mycpu)->env.tr.base; + ((uc_x86_mmr *)value)->selector = (uint16_t)X86_CPU(uc, mycpu)->env.tr.selector; + ((uc_x86_mmr *)value)->flags = X86_CPU(uc, mycpu)->env.tr.flags; + break; + } + break; #endif + } } - return 0; } -int x86_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) +int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count) { CPUState *mycpu = first_cpu; + int i; - switch(regid) { - default: - break; - case UC_X86_REG_FP0 ... UC_X86_REG_FP7: - { - uint64_t mant = *(uint64_t*) value; - uint16_t upper = *(uint16_t*) (value + sizeof(uint64_t)); - X86_CPU(uc, mycpu)->env.fpregs[regid - UC_X86_REG_FP0].d = cpu_set_fp80(mant, upper); - } - return 0; - case UC_X86_REG_FPSW: - { - uint16_t fpus = *(uint16_t*) value; - X86_CPU(uc, mycpu)->env.fpus = fpus & ~0x3800; - X86_CPU(uc, mycpu)->env.fpstt = (fpus >> 11) & 0x7; - } - return 0; - case UC_X86_REG_FPCW: - X86_CPU(uc, mycpu)->env.fpuc = *(uint16_t *)value; - return 0; - case UC_X86_REG_FPTAG: - { - int i; - uint16_t fptag = *(uint16_t*) value; - for (i = 0; i < 8; i++) { - X86_CPU(uc, mycpu)->env.fptags[i] = ((fptag & 3) == 3); - fptag >>= 2; + for (i = 0; i < count; i++) { + unsigned int regid = regs[i]; + const void *value = vals[i]; + switch(regid) { + default: + break; + case UC_X86_REG_FP0 ... UC_X86_REG_FP7: + { + uint64_t mant = *(uint64_t*) value; + uint16_t upper = *(uint16_t*) (value + sizeof(uint64_t)); + X86_CPU(uc, mycpu)->env.fpregs[regid - UC_X86_REG_FP0].d = cpu_set_fp80(mant, upper); } + continue; + case UC_X86_REG_FPSW: + { + uint16_t fpus = *(uint16_t*) value; + X86_CPU(uc, mycpu)->env.fpus = fpus & ~0x3800; + X86_CPU(uc, mycpu)->env.fpstt = (fpus >> 11) & 0x7; + } + continue; + case UC_X86_REG_FPCW: + X86_CPU(uc, mycpu)->env.fpuc = *(uint16_t *)value; + continue; + case UC_X86_REG_FPTAG: + { + int i; + uint16_t fptag = *(uint16_t*) value; + for (i = 0; i < 8; i++) { + X86_CPU(uc, mycpu)->env.fptags[i] = ((fptag & 3) == 3); + fptag >>= 2; + } - return 0; - } - break; - } + continue; + } + break; + } - switch(uc->mode) { - default: - break; + switch(uc->mode) { + default: + break; - case UC_MODE_16: - switch(regid) { - default: break; - case UC_X86_REG_ES: - X86_CPU(uc, mycpu)->env.segs[R_ES].selector = *(uint16_t *)value; - return 0; - case UC_X86_REG_SS: - X86_CPU(uc, mycpu)->env.segs[R_SS].selector = *(uint16_t *)value; - return 0; - case UC_X86_REG_DS: - X86_CPU(uc, mycpu)->env.segs[R_DS].selector = *(uint16_t *)value; - return 0; - case UC_X86_REG_FS: - X86_CPU(uc, mycpu)->env.segs[R_FS].selector = *(uint16_t *)value; - return 0; - case UC_X86_REG_GS: - X86_CPU(uc, mycpu)->env.segs[R_GS].selector = *(uint16_t *)value; - return 0; - } - // fall-thru - case UC_MODE_32: - switch(regid) { - default: - break; - case UC_X86_REG_CR0 ... UC_X86_REG_CR4: - X86_CPU(uc, mycpu)->env.cr[regid - UC_X86_REG_CR0] = *(uint32_t *)value; - break; - case UC_X86_REG_DR0 ... UC_X86_REG_DR7: - X86_CPU(uc, mycpu)->env.dr[regid - UC_X86_REG_DR0] = *(uint32_t *)value; - break; - case UC_X86_REG_EFLAGS: - X86_CPU(uc, mycpu)->env.eflags = *(uint32_t *)value; - X86_CPU(uc, mycpu)->env.eflags0 = *(uint32_t *)value; - break; - case UC_X86_REG_EAX: - X86_CPU(uc, mycpu)->env.regs[R_EAX] = *(uint32_t *)value; - break; - case UC_X86_REG_AX: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint16_t *)value); - break; - case UC_X86_REG_AH: - WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint8_t *)value); - break; - case UC_X86_REG_AL: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint8_t *)value); - break; - case UC_X86_REG_EBX: - X86_CPU(uc, mycpu)->env.regs[R_EBX] = *(uint32_t *)value; - break; - case UC_X86_REG_BX: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint16_t *)value); - break; - case UC_X86_REG_BH: - WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint8_t *)value); - break; - case UC_X86_REG_BL: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint8_t *)value); - break; - case UC_X86_REG_ECX: - X86_CPU(uc, mycpu)->env.regs[R_ECX] = *(uint32_t *)value; - break; - case UC_X86_REG_CX: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint16_t *)value); - break; - case UC_X86_REG_CH: - WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint8_t *)value); - break; - case UC_X86_REG_CL: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint8_t *)value); - break; - case UC_X86_REG_EDX: - X86_CPU(uc, mycpu)->env.regs[R_EDX] = *(uint32_t *)value; - break; - case UC_X86_REG_DX: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint16_t *)value); - break; - case UC_X86_REG_DH: - WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint8_t *)value); - break; - case UC_X86_REG_DL: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint8_t *)value); - break; - case UC_X86_REG_ESP: - X86_CPU(uc, mycpu)->env.regs[R_ESP] = *(uint32_t *)value; - break; - case UC_X86_REG_SP: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESP], *(uint16_t *)value); - break; - case UC_X86_REG_EBP: - X86_CPU(uc, mycpu)->env.regs[R_EBP] = *(uint32_t *)value; - break; - case UC_X86_REG_BP: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBP], *(uint16_t *)value); - break; - case UC_X86_REG_ESI: - X86_CPU(uc, mycpu)->env.regs[R_ESI] = *(uint32_t *)value; - break; - case UC_X86_REG_SI: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESI], *(uint16_t *)value); - break; - case UC_X86_REG_EDI: - X86_CPU(uc, mycpu)->env.regs[R_EDI] = *(uint32_t *)value; - break; - case UC_X86_REG_DI: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDI], *(uint16_t *)value); - break; - case UC_X86_REG_EIP: - X86_CPU(uc, mycpu)->env.eip = *(uint32_t *)value; - // force to quit execution and flush TB - uc->quit_request = true; - uc_emu_stop(uc); - break; - case UC_X86_REG_IP: - WRITE_WORD(X86_CPU(uc, mycpu)->env.eip, *(uint16_t *)value); - // force to quit execution and flush TB - uc->quit_request = true; - uc_emu_stop(uc); - break; - case UC_X86_REG_CS: - cpu_x86_load_seg(&X86_CPU(uc, mycpu)->env, R_CS, *(uint16_t *)value); - break; - case UC_X86_REG_DS: - cpu_x86_load_seg(&X86_CPU(uc, mycpu)->env, R_DS, *(uint16_t *)value); - break; - case UC_X86_REG_SS: - cpu_x86_load_seg(&X86_CPU(uc, mycpu)->env, R_SS, *(uint16_t *)value); - break; - case UC_X86_REG_ES: - cpu_x86_load_seg(&X86_CPU(uc, mycpu)->env, R_ES, *(uint16_t *)value); - break; - case UC_X86_REG_FS: - cpu_x86_load_seg(&X86_CPU(uc, mycpu)->env, R_FS, *(uint16_t *)value); - break; - case UC_X86_REG_GS: - cpu_x86_load_seg(&X86_CPU(uc, mycpu)->env, R_GS, *(uint16_t *)value); - break; - case UC_X86_REG_IDTR: - X86_CPU(uc, mycpu)->env.idt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; - X86_CPU(uc, mycpu)->env.idt.base = (uint32_t)((uc_x86_mmr *)value)->base; - break; - case UC_X86_REG_GDTR: - X86_CPU(uc, mycpu)->env.gdt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; - X86_CPU(uc, mycpu)->env.gdt.base = (uint32_t)((uc_x86_mmr *)value)->base; - break; - case UC_X86_REG_LDTR: - X86_CPU(uc, mycpu)->env.ldt.limit = ((uc_x86_mmr *)value)->limit; - X86_CPU(uc, mycpu)->env.ldt.base = (uint32_t)((uc_x86_mmr *)value)->base; - X86_CPU(uc, mycpu)->env.ldt.selector = (uint16_t)((uc_x86_mmr *)value)->selector; - X86_CPU(uc, mycpu)->env.ldt.flags = ((uc_x86_mmr *)value)->flags; - break; - case UC_X86_REG_TR: - X86_CPU(uc, mycpu)->env.tr.limit = ((uc_x86_mmr *)value)->limit; - X86_CPU(uc, mycpu)->env.tr.base = (uint32_t)((uc_x86_mmr *)value)->base; - X86_CPU(uc, mycpu)->env.tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector; - X86_CPU(uc, mycpu)->env.tr.flags = ((uc_x86_mmr *)value)->flags; - break; - } - break; + case UC_MODE_16: + switch(regid) { + default: break; + case UC_X86_REG_ES: + X86_CPU(uc, mycpu)->env.segs[R_ES].selector = *(uint16_t *)value; + continue; + case UC_X86_REG_SS: + X86_CPU(uc, mycpu)->env.segs[R_SS].selector = *(uint16_t *)value; + continue; + case UC_X86_REG_DS: + X86_CPU(uc, mycpu)->env.segs[R_DS].selector = *(uint16_t *)value; + continue; + case UC_X86_REG_FS: + X86_CPU(uc, mycpu)->env.segs[R_FS].selector = *(uint16_t *)value; + continue; + case UC_X86_REG_GS: + X86_CPU(uc, mycpu)->env.segs[R_GS].selector = *(uint16_t *)value; + continue; + } + // fall-thru + case UC_MODE_32: + switch(regid) { + default: + break; + case UC_X86_REG_CR0 ... UC_X86_REG_CR4: + X86_CPU(uc, mycpu)->env.cr[regid - UC_X86_REG_CR0] = *(uint32_t *)value; + break; + case UC_X86_REG_DR0 ... UC_X86_REG_DR7: + X86_CPU(uc, mycpu)->env.dr[regid - UC_X86_REG_DR0] = *(uint32_t *)value; + break; + case UC_X86_REG_EFLAGS: + X86_CPU(uc, mycpu)->env.eflags = *(uint32_t *)value; + X86_CPU(uc, mycpu)->env.eflags0 = *(uint32_t *)value; + break; + case UC_X86_REG_EAX: + X86_CPU(uc, mycpu)->env.regs[R_EAX] = *(uint32_t *)value; + break; + case UC_X86_REG_AX: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint16_t *)value); + break; + case UC_X86_REG_AH: + WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint8_t *)value); + break; + case UC_X86_REG_AL: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint8_t *)value); + break; + case UC_X86_REG_EBX: + X86_CPU(uc, mycpu)->env.regs[R_EBX] = *(uint32_t *)value; + break; + case UC_X86_REG_BX: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint16_t *)value); + break; + case UC_X86_REG_BH: + WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint8_t *)value); + break; + case UC_X86_REG_BL: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint8_t *)value); + break; + case UC_X86_REG_ECX: + X86_CPU(uc, mycpu)->env.regs[R_ECX] = *(uint32_t *)value; + break; + case UC_X86_REG_CX: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint16_t *)value); + break; + case UC_X86_REG_CH: + WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint8_t *)value); + break; + case UC_X86_REG_CL: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint8_t *)value); + break; + case UC_X86_REG_EDX: + X86_CPU(uc, mycpu)->env.regs[R_EDX] = *(uint32_t *)value; + break; + case UC_X86_REG_DX: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint16_t *)value); + break; + case UC_X86_REG_DH: + WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint8_t *)value); + break; + case UC_X86_REG_DL: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint8_t *)value); + break; + case UC_X86_REG_ESP: + X86_CPU(uc, mycpu)->env.regs[R_ESP] = *(uint32_t *)value; + break; + case UC_X86_REG_SP: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESP], *(uint16_t *)value); + break; + case UC_X86_REG_EBP: + X86_CPU(uc, mycpu)->env.regs[R_EBP] = *(uint32_t *)value; + break; + case UC_X86_REG_BP: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBP], *(uint16_t *)value); + break; + case UC_X86_REG_ESI: + X86_CPU(uc, mycpu)->env.regs[R_ESI] = *(uint32_t *)value; + break; + case UC_X86_REG_SI: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESI], *(uint16_t *)value); + break; + case UC_X86_REG_EDI: + X86_CPU(uc, mycpu)->env.regs[R_EDI] = *(uint32_t *)value; + break; + case UC_X86_REG_DI: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDI], *(uint16_t *)value); + break; + case UC_X86_REG_EIP: + X86_CPU(uc, mycpu)->env.eip = *(uint32_t *)value; + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); + break; + case UC_X86_REG_IP: + WRITE_WORD(X86_CPU(uc, mycpu)->env.eip, *(uint16_t *)value); + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); + break; + case UC_X86_REG_CS: + cpu_x86_load_seg(&X86_CPU(uc, mycpu)->env, R_CS, *(uint16_t *)value); + break; + case UC_X86_REG_DS: + cpu_x86_load_seg(&X86_CPU(uc, mycpu)->env, R_DS, *(uint16_t *)value); + break; + case UC_X86_REG_SS: + cpu_x86_load_seg(&X86_CPU(uc, mycpu)->env, R_SS, *(uint16_t *)value); + break; + case UC_X86_REG_ES: + cpu_x86_load_seg(&X86_CPU(uc, mycpu)->env, R_ES, *(uint16_t *)value); + break; + case UC_X86_REG_FS: + cpu_x86_load_seg(&X86_CPU(uc, mycpu)->env, R_FS, *(uint16_t *)value); + break; + case UC_X86_REG_GS: + cpu_x86_load_seg(&X86_CPU(uc, mycpu)->env, R_GS, *(uint16_t *)value); + break; + case UC_X86_REG_IDTR: + X86_CPU(uc, mycpu)->env.idt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; + X86_CPU(uc, mycpu)->env.idt.base = (uint32_t)((uc_x86_mmr *)value)->base; + break; + case UC_X86_REG_GDTR: + X86_CPU(uc, mycpu)->env.gdt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; + X86_CPU(uc, mycpu)->env.gdt.base = (uint32_t)((uc_x86_mmr *)value)->base; + break; + case UC_X86_REG_LDTR: + X86_CPU(uc, mycpu)->env.ldt.limit = ((uc_x86_mmr *)value)->limit; + X86_CPU(uc, mycpu)->env.ldt.base = (uint32_t)((uc_x86_mmr *)value)->base; + X86_CPU(uc, mycpu)->env.ldt.selector = (uint16_t)((uc_x86_mmr *)value)->selector; + X86_CPU(uc, mycpu)->env.ldt.flags = ((uc_x86_mmr *)value)->flags; + break; + case UC_X86_REG_TR: + X86_CPU(uc, mycpu)->env.tr.limit = ((uc_x86_mmr *)value)->limit; + X86_CPU(uc, mycpu)->env.tr.base = (uint32_t)((uc_x86_mmr *)value)->base; + X86_CPU(uc, mycpu)->env.tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector; + X86_CPU(uc, mycpu)->env.tr.flags = ((uc_x86_mmr *)value)->flags; + break; + } + break; #ifdef TARGET_X86_64 - case UC_MODE_64: - switch(regid) { - default: - break; - case UC_X86_REG_CR0 ... UC_X86_REG_CR4: - X86_CPU(uc, mycpu)->env.cr[regid - UC_X86_REG_CR0] = *(uint64_t *)value; - break; - case UC_X86_REG_DR0 ... UC_X86_REG_DR7: - X86_CPU(uc, mycpu)->env.dr[regid - UC_X86_REG_DR0] = *(uint64_t *)value; - break; - case UC_X86_REG_EFLAGS: - X86_CPU(uc, mycpu)->env.eflags = *(uint64_t *)value; - X86_CPU(uc, mycpu)->env.eflags0 = *(uint64_t *)value; - break; - case UC_X86_REG_RAX: - X86_CPU(uc, mycpu)->env.regs[R_EAX] = *(uint64_t *)value; - break; - case UC_X86_REG_EAX: - WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint32_t *)value); - break; - case UC_X86_REG_AX: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint16_t *)value); - break; - case UC_X86_REG_AH: - WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint8_t *)value); - break; - case UC_X86_REG_AL: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint8_t *)value); - break; - case UC_X86_REG_RBX: - X86_CPU(uc, mycpu)->env.regs[R_EBX] = *(uint64_t *)value; - break; - case UC_X86_REG_EBX: - WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint32_t *)value); - break; - case UC_X86_REG_BX: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint16_t *)value); - break; - case UC_X86_REG_BH: - WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint8_t *)value); - break; - case UC_X86_REG_BL: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint8_t *)value); - break; - case UC_X86_REG_RCX: - X86_CPU(uc, mycpu)->env.regs[R_ECX] = *(uint64_t *)value; - break; - case UC_X86_REG_ECX: - WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint32_t *)value); - break; - case UC_X86_REG_CX: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint16_t *)value); - break; - case UC_X86_REG_CH: - WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint8_t *)value); - break; - case UC_X86_REG_CL: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint8_t *)value); - break; - case UC_X86_REG_RDX: - X86_CPU(uc, mycpu)->env.regs[R_EDX] = *(uint64_t *)value; - break; - case UC_X86_REG_EDX: - WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint32_t *)value); - break; - case UC_X86_REG_DX: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint16_t *)value); - break; - case UC_X86_REG_DH: - WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint8_t *)value); - break; - case UC_X86_REG_DL: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint8_t *)value); - break; - case UC_X86_REG_RSP: - X86_CPU(uc, mycpu)->env.regs[R_ESP] = *(uint64_t *)value; - break; - case UC_X86_REG_ESP: - WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_ESP], *(uint32_t *)value); - break; - case UC_X86_REG_SP: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESP], *(uint16_t *)value); - break; - case UC_X86_REG_SPL: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ESP], *(uint8_t *)value); - break; - case UC_X86_REG_RBP: - X86_CPU(uc, mycpu)->env.regs[R_EBP] = *(uint64_t *)value; - break; - case UC_X86_REG_EBP: - WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EBP], *(uint32_t *)value); - break; - case UC_X86_REG_BP: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBP], *(uint16_t *)value); - break; - case UC_X86_REG_BPL: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EBP], *(uint8_t *)value); - break; - case UC_X86_REG_RSI: - X86_CPU(uc, mycpu)->env.regs[R_ESI] = *(uint64_t *)value; - break; - case UC_X86_REG_ESI: - WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_ESI], *(uint32_t *)value); - break; - case UC_X86_REG_SI: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESI], *(uint16_t *)value); - break; - case UC_X86_REG_SIL: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ESI], *(uint8_t *)value); - break; - case UC_X86_REG_RDI: - X86_CPU(uc, mycpu)->env.regs[R_EDI] = *(uint64_t *)value; - break; - case UC_X86_REG_EDI: - WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EDI], *(uint32_t *)value); - break; - case UC_X86_REG_DI: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDI], *(uint16_t *)value); - break; - case UC_X86_REG_DIL: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EDI], *(uint8_t *)value); - break; - case UC_X86_REG_RIP: - X86_CPU(uc, mycpu)->env.eip = *(uint64_t *)value; - // force to quit execution and flush TB - uc->quit_request = true; - uc_emu_stop(uc); - break; - case UC_X86_REG_EIP: - WRITE_DWORD(X86_CPU(uc, mycpu)->env.eip, *(uint32_t *)value); - // force to quit execution and flush TB - uc->quit_request = true; - uc_emu_stop(uc); - break; - case UC_X86_REG_IP: - WRITE_WORD(X86_CPU(uc, mycpu)->env.eip, *(uint16_t *)value); - // force to quit execution and flush TB - uc->quit_request = true; - uc_emu_stop(uc); - break; - case UC_X86_REG_CS: - X86_CPU(uc, mycpu)->env.segs[R_CS].selector = *(uint16_t *)value; - break; - case UC_X86_REG_DS: - X86_CPU(uc, mycpu)->env.segs[R_DS].selector = *(uint16_t *)value; - break; - case UC_X86_REG_SS: - X86_CPU(uc, mycpu)->env.segs[R_SS].selector = *(uint16_t *)value; - break; - case UC_X86_REG_ES: - X86_CPU(uc, mycpu)->env.segs[R_ES].selector = *(uint16_t *)value; - break; - case UC_X86_REG_FS: - X86_CPU(uc, mycpu)->env.segs[R_FS].selector = *(uint16_t *)value; - break; - case UC_X86_REG_GS: - X86_CPU(uc, mycpu)->env.segs[R_GS].selector = *(uint16_t *)value; - break; - case UC_X86_REG_R8: - X86_CPU(uc, mycpu)->env.regs[8] = *(uint64_t *)value; - break; - case UC_X86_REG_R8D: - WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[8], *(uint32_t *)value); - break; - case UC_X86_REG_R8W: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[8], *(uint16_t *)value); - break; - case UC_X86_REG_R8B: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[8], *(uint8_t *)value); - break; - case UC_X86_REG_R9: - X86_CPU(uc, mycpu)->env.regs[9] = *(uint64_t *)value; - break; - case UC_X86_REG_R9D: - WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[9], *(uint32_t *)value); - break; - case UC_X86_REG_R9W: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[9], *(uint16_t *)value); - break; - case UC_X86_REG_R9B: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[9], *(uint8_t *)value); - break; - case UC_X86_REG_R10: - X86_CPU(uc, mycpu)->env.regs[10] = *(uint64_t *)value; - break; - case UC_X86_REG_R10D: - WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[10], *(uint32_t *)value); - break; - case UC_X86_REG_R10W: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[10], *(uint16_t *)value); - break; - case UC_X86_REG_R10B: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[10], *(uint8_t *)value); - break; - case UC_X86_REG_R11: - X86_CPU(uc, mycpu)->env.regs[11] = *(uint64_t *)value; - break; - case UC_X86_REG_R11D: - WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[11], *(uint32_t *)value); - break; - case UC_X86_REG_R11W: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[11], *(uint16_t *)value); - break; - case UC_X86_REG_R11B: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[11], *(uint8_t *)value); - break; - case UC_X86_REG_R12: - X86_CPU(uc, mycpu)->env.regs[12] = *(uint64_t *)value; - break; - case UC_X86_REG_R12D: - WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[12], *(uint32_t *)value); - break; - case UC_X86_REG_R12W: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[12], *(uint16_t *)value); - break; - case UC_X86_REG_R12B: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[12], *(uint8_t *)value); - break; - case UC_X86_REG_R13: - X86_CPU(uc, mycpu)->env.regs[13] = *(uint64_t *)value; - break; - case UC_X86_REG_R13D: - WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[13], *(uint32_t *)value); - break; - case UC_X86_REG_R13W: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[13], *(uint16_t *)value); - break; - case UC_X86_REG_R13B: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[13], *(uint8_t *)value); - break; - case UC_X86_REG_R14: - X86_CPU(uc, mycpu)->env.regs[14] = *(uint64_t *)value; - break; - case UC_X86_REG_R14D: - WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[14], *(uint32_t *)value); - break; - case UC_X86_REG_R14W: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[14], *(uint16_t *)value); - break; - case UC_X86_REG_R14B: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[14], *(uint8_t *)value); - break; - case UC_X86_REG_R15: - X86_CPU(uc, mycpu)->env.regs[15] = *(uint64_t *)value; - break; - case UC_X86_REG_R15D: - WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[15], *(uint32_t *)value); - break; - case UC_X86_REG_R15W: - WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[15], *(uint16_t *)value); - break; - case UC_X86_REG_R15B: - WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[15], *(uint8_t *)value); - break; - case UC_X86_REG_IDTR: - X86_CPU(uc, mycpu)->env.idt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; - X86_CPU(uc, mycpu)->env.idt.base = ((uc_x86_mmr *)value)->base; - break; - case UC_X86_REG_GDTR: - X86_CPU(uc, mycpu)->env.gdt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; - X86_CPU(uc, mycpu)->env.gdt.base = ((uc_x86_mmr *)value)->base; - break; - case UC_X86_REG_LDTR: - X86_CPU(uc, mycpu)->env.ldt.limit = ((uc_x86_mmr *)value)->limit; - X86_CPU(uc, mycpu)->env.ldt.base = ((uc_x86_mmr *)value)->base; - X86_CPU(uc, mycpu)->env.ldt.selector = (uint16_t)((uc_x86_mmr *)value)->selector; - X86_CPU(uc, mycpu)->env.ldt.flags = ((uc_x86_mmr *)value)->flags; - break; - case UC_X86_REG_TR: - X86_CPU(uc, mycpu)->env.tr.limit = ((uc_x86_mmr *)value)->limit; - X86_CPU(uc, mycpu)->env.tr.base = ((uc_x86_mmr *)value)->base; - X86_CPU(uc, mycpu)->env.tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector; - X86_CPU(uc, mycpu)->env.tr.flags = ((uc_x86_mmr *)value)->flags; - break; - } - break; + case UC_MODE_64: + switch(regid) { + default: + break; + case UC_X86_REG_CR0 ... UC_X86_REG_CR4: + X86_CPU(uc, mycpu)->env.cr[regid - UC_X86_REG_CR0] = *(uint64_t *)value; + break; + case UC_X86_REG_DR0 ... UC_X86_REG_DR7: + X86_CPU(uc, mycpu)->env.dr[regid - UC_X86_REG_DR0] = *(uint64_t *)value; + break; + case UC_X86_REG_EFLAGS: + X86_CPU(uc, mycpu)->env.eflags = *(uint64_t *)value; + X86_CPU(uc, mycpu)->env.eflags0 = *(uint64_t *)value; + break; + case UC_X86_REG_RAX: + X86_CPU(uc, mycpu)->env.regs[R_EAX] = *(uint64_t *)value; + break; + case UC_X86_REG_EAX: + WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint32_t *)value); + break; + case UC_X86_REG_AX: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint16_t *)value); + break; + case UC_X86_REG_AH: + WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint8_t *)value); + break; + case UC_X86_REG_AL: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint8_t *)value); + break; + case UC_X86_REG_RBX: + X86_CPU(uc, mycpu)->env.regs[R_EBX] = *(uint64_t *)value; + break; + case UC_X86_REG_EBX: + WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint32_t *)value); + break; + case UC_X86_REG_BX: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint16_t *)value); + break; + case UC_X86_REG_BH: + WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint8_t *)value); + break; + case UC_X86_REG_BL: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint8_t *)value); + break; + case UC_X86_REG_RCX: + X86_CPU(uc, mycpu)->env.regs[R_ECX] = *(uint64_t *)value; + break; + case UC_X86_REG_ECX: + WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint32_t *)value); + break; + case UC_X86_REG_CX: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint16_t *)value); + break; + case UC_X86_REG_CH: + WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint8_t *)value); + break; + case UC_X86_REG_CL: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint8_t *)value); + break; + case UC_X86_REG_RDX: + X86_CPU(uc, mycpu)->env.regs[R_EDX] = *(uint64_t *)value; + break; + case UC_X86_REG_EDX: + WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint32_t *)value); + break; + case UC_X86_REG_DX: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint16_t *)value); + break; + case UC_X86_REG_DH: + WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint8_t *)value); + break; + case UC_X86_REG_DL: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint8_t *)value); + break; + case UC_X86_REG_RSP: + X86_CPU(uc, mycpu)->env.regs[R_ESP] = *(uint64_t *)value; + break; + case UC_X86_REG_ESP: + WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_ESP], *(uint32_t *)value); + break; + case UC_X86_REG_SP: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESP], *(uint16_t *)value); + break; + case UC_X86_REG_SPL: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ESP], *(uint8_t *)value); + break; + case UC_X86_REG_RBP: + X86_CPU(uc, mycpu)->env.regs[R_EBP] = *(uint64_t *)value; + break; + case UC_X86_REG_EBP: + WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EBP], *(uint32_t *)value); + break; + case UC_X86_REG_BP: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBP], *(uint16_t *)value); + break; + case UC_X86_REG_BPL: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EBP], *(uint8_t *)value); + break; + case UC_X86_REG_RSI: + X86_CPU(uc, mycpu)->env.regs[R_ESI] = *(uint64_t *)value; + break; + case UC_X86_REG_ESI: + WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_ESI], *(uint32_t *)value); + break; + case UC_X86_REG_SI: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESI], *(uint16_t *)value); + break; + case UC_X86_REG_SIL: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ESI], *(uint8_t *)value); + break; + case UC_X86_REG_RDI: + X86_CPU(uc, mycpu)->env.regs[R_EDI] = *(uint64_t *)value; + break; + case UC_X86_REG_EDI: + WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EDI], *(uint32_t *)value); + break; + case UC_X86_REG_DI: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDI], *(uint16_t *)value); + break; + case UC_X86_REG_DIL: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EDI], *(uint8_t *)value); + break; + case UC_X86_REG_RIP: + X86_CPU(uc, mycpu)->env.eip = *(uint64_t *)value; + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); + break; + case UC_X86_REG_EIP: + WRITE_DWORD(X86_CPU(uc, mycpu)->env.eip, *(uint32_t *)value); + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); + break; + case UC_X86_REG_IP: + WRITE_WORD(X86_CPU(uc, mycpu)->env.eip, *(uint16_t *)value); + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); + break; + case UC_X86_REG_CS: + X86_CPU(uc, mycpu)->env.segs[R_CS].selector = *(uint16_t *)value; + break; + case UC_X86_REG_DS: + X86_CPU(uc, mycpu)->env.segs[R_DS].selector = *(uint16_t *)value; + break; + case UC_X86_REG_SS: + X86_CPU(uc, mycpu)->env.segs[R_SS].selector = *(uint16_t *)value; + break; + case UC_X86_REG_ES: + X86_CPU(uc, mycpu)->env.segs[R_ES].selector = *(uint16_t *)value; + break; + case UC_X86_REG_FS: + X86_CPU(uc, mycpu)->env.segs[R_FS].selector = *(uint16_t *)value; + break; + case UC_X86_REG_GS: + X86_CPU(uc, mycpu)->env.segs[R_GS].selector = *(uint16_t *)value; + break; + case UC_X86_REG_R8: + X86_CPU(uc, mycpu)->env.regs[8] = *(uint64_t *)value; + break; + case UC_X86_REG_R8D: + WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[8], *(uint32_t *)value); + break; + case UC_X86_REG_R8W: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[8], *(uint16_t *)value); + break; + case UC_X86_REG_R8B: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[8], *(uint8_t *)value); + break; + case UC_X86_REG_R9: + X86_CPU(uc, mycpu)->env.regs[9] = *(uint64_t *)value; + break; + case UC_X86_REG_R9D: + WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[9], *(uint32_t *)value); + break; + case UC_X86_REG_R9W: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[9], *(uint16_t *)value); + break; + case UC_X86_REG_R9B: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[9], *(uint8_t *)value); + break; + case UC_X86_REG_R10: + X86_CPU(uc, mycpu)->env.regs[10] = *(uint64_t *)value; + break; + case UC_X86_REG_R10D: + WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[10], *(uint32_t *)value); + break; + case UC_X86_REG_R10W: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[10], *(uint16_t *)value); + break; + case UC_X86_REG_R10B: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[10], *(uint8_t *)value); + break; + case UC_X86_REG_R11: + X86_CPU(uc, mycpu)->env.regs[11] = *(uint64_t *)value; + break; + case UC_X86_REG_R11D: + WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[11], *(uint32_t *)value); + break; + case UC_X86_REG_R11W: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[11], *(uint16_t *)value); + break; + case UC_X86_REG_R11B: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[11], *(uint8_t *)value); + break; + case UC_X86_REG_R12: + X86_CPU(uc, mycpu)->env.regs[12] = *(uint64_t *)value; + break; + case UC_X86_REG_R12D: + WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[12], *(uint32_t *)value); + break; + case UC_X86_REG_R12W: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[12], *(uint16_t *)value); + break; + case UC_X86_REG_R12B: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[12], *(uint8_t *)value); + break; + case UC_X86_REG_R13: + X86_CPU(uc, mycpu)->env.regs[13] = *(uint64_t *)value; + break; + case UC_X86_REG_R13D: + WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[13], *(uint32_t *)value); + break; + case UC_X86_REG_R13W: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[13], *(uint16_t *)value); + break; + case UC_X86_REG_R13B: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[13], *(uint8_t *)value); + break; + case UC_X86_REG_R14: + X86_CPU(uc, mycpu)->env.regs[14] = *(uint64_t *)value; + break; + case UC_X86_REG_R14D: + WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[14], *(uint32_t *)value); + break; + case UC_X86_REG_R14W: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[14], *(uint16_t *)value); + break; + case UC_X86_REG_R14B: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[14], *(uint8_t *)value); + break; + case UC_X86_REG_R15: + X86_CPU(uc, mycpu)->env.regs[15] = *(uint64_t *)value; + break; + case UC_X86_REG_R15D: + WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[15], *(uint32_t *)value); + break; + case UC_X86_REG_R15W: + WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[15], *(uint16_t *)value); + break; + case UC_X86_REG_R15B: + WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[15], *(uint8_t *)value); + break; + case UC_X86_REG_IDTR: + X86_CPU(uc, mycpu)->env.idt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; + X86_CPU(uc, mycpu)->env.idt.base = ((uc_x86_mmr *)value)->base; + break; + case UC_X86_REG_GDTR: + X86_CPU(uc, mycpu)->env.gdt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; + X86_CPU(uc, mycpu)->env.gdt.base = ((uc_x86_mmr *)value)->base; + break; + case UC_X86_REG_LDTR: + X86_CPU(uc, mycpu)->env.ldt.limit = ((uc_x86_mmr *)value)->limit; + X86_CPU(uc, mycpu)->env.ldt.base = ((uc_x86_mmr *)value)->base; + X86_CPU(uc, mycpu)->env.ldt.selector = (uint16_t)((uc_x86_mmr *)value)->selector; + X86_CPU(uc, mycpu)->env.ldt.flags = ((uc_x86_mmr *)value)->flags; + break; + case UC_X86_REG_TR: + X86_CPU(uc, mycpu)->env.tr.limit = ((uc_x86_mmr *)value)->limit; + X86_CPU(uc, mycpu)->env.tr.base = ((uc_x86_mmr *)value)->base; + X86_CPU(uc, mycpu)->env.tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector; + X86_CPU(uc, mycpu)->env.tr.flags = ((uc_x86_mmr *)value)->flags; + break; + } + break; #endif + } } return 0; diff --git a/qemu/target-i386/unicorn.h b/qemu/target-i386/unicorn.h index a4dda81e..37e38b4f 100644 --- a/qemu/target-i386/unicorn.h +++ b/qemu/target-i386/unicorn.h @@ -5,8 +5,8 @@ #define UC_QEMU_TARGET_I386_H // functions to read & write registers -int x86_reg_read(struct uc_struct *uc, unsigned int regid, void *value); -int x86_reg_write(struct uc_struct *uc, unsigned int regid, const void *value); +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); void x86_reg_reset(struct uc_struct *uc); diff --git a/qemu/target-m68k/unicorn.c b/qemu/target-m68k/unicorn.c index 0edf04c2..d2818cfe 100644 --- a/qemu/target-m68k/unicorn.c +++ b/qemu/target-m68k/unicorn.c @@ -25,47 +25,56 @@ void m68k_reg_reset(struct uc_struct *uc) env->pc = 0; } -int m68k_reg_read(struct uc_struct *uc, unsigned int regid, void *value) +int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) { CPUState *mycpu = first_cpu; + int i; - if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7) - *(int32_t *)value = M68K_CPU(uc, mycpu)->env.aregs[regid - UC_M68K_REG_A0]; - else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7) - *(int32_t *)value = M68K_CPU(uc, mycpu)->env.dregs[regid - UC_M68K_REG_D0]; - else { - switch(regid) { - default: break; - case UC_M68K_REG_PC: - *(int32_t *)value = M68K_CPU(uc, mycpu)->env.pc; - break; + for (i = 0; i < count; i++) { + unsigned int regid = regs[i]; + void *value = vals[i]; + if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7) + *(int32_t *)value = M68K_CPU(uc, mycpu)->env.aregs[regid - UC_M68K_REG_A0]; + else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7) + *(int32_t *)value = M68K_CPU(uc, mycpu)->env.dregs[regid - UC_M68K_REG_D0]; + else { + switch(regid) { + default: break; + case UC_M68K_REG_PC: + *(int32_t *)value = M68K_CPU(uc, mycpu)->env.pc; + break; + } } } return 0; } -int m68k_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) +int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count) { CPUState *mycpu = first_cpu; + int i; - if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7) - M68K_CPU(uc, mycpu)->env.aregs[regid - UC_M68K_REG_A0] = *(uint32_t *)value; - else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7) - M68K_CPU(uc, mycpu)->env.dregs[regid - UC_M68K_REG_D0] = *(uint32_t *)value; - else { - switch(regid) { - default: break; - case UC_M68K_REG_PC: - M68K_CPU(uc, mycpu)->env.pc = *(uint32_t *)value; - // force to quit execution and flush TB - uc->quit_request = true; - uc_emu_stop(uc); - break; + for (i = 0; i < count; i++) { + unsigned int regid = regs[i]; + const void *value = vals[i]; + if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7) + M68K_CPU(uc, mycpu)->env.aregs[regid - UC_M68K_REG_A0] = *(uint32_t *)value; + else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7) + M68K_CPU(uc, mycpu)->env.dregs[regid - UC_M68K_REG_D0] = *(uint32_t *)value; + else { + switch(regid) { + default: break; + case UC_M68K_REG_PC: + M68K_CPU(uc, mycpu)->env.pc = *(uint32_t *)value; + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); + break; + } } } - return 0; } diff --git a/qemu/target-m68k/unicorn.h b/qemu/target-m68k/unicorn.h index 37ea828f..7cf8e21a 100644 --- a/qemu/target-m68k/unicorn.h +++ b/qemu/target-m68k/unicorn.h @@ -5,8 +5,8 @@ #define UC_QEMU_TARGET_M68K_H // functions to read & write registers -int m68k_reg_read(struct uc_struct *uc, unsigned int regid, void *value); -int m68k_reg_write(struct uc_struct *uc, unsigned int regid, const void *value); +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); void m68k_reg_reset(struct uc_struct *uc); diff --git a/qemu/target-mips/unicorn.c b/qemu/target-mips/unicorn.c index 7740d0d9..ec8779bf 100644 --- a/qemu/target-mips/unicorn.c +++ b/qemu/target-mips/unicorn.c @@ -39,43 +39,52 @@ void mips_reg_reset(struct uc_struct *uc) env->active_tc.PC = 0; } -int mips_reg_read(struct uc_struct *uc, unsigned int regid, void *value) +int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) { CPUState *mycpu = first_cpu; + int i; - if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31) - *(int32_t *)value = MIPS_CPU(uc, mycpu)->env.active_tc.gpr[regid - UC_MIPS_REG_0]; - else { - switch(regid) { - default: break; - case UC_MIPS_REG_PC: - *(int32_t *)value = MIPS_CPU(uc, mycpu)->env.active_tc.PC; - break; + for (i = 0; i < count; i++) { + unsigned int regid = regs[i]; + void *value = vals[i]; + if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31) + *(int32_t *)value = MIPS_CPU(uc, mycpu)->env.active_tc.gpr[regid - UC_MIPS_REG_0]; + else { + switch(regid) { + default: break; + case UC_MIPS_REG_PC: + *(int32_t *)value = MIPS_CPU(uc, mycpu)->env.active_tc.PC; + break; + } } } return 0; } -int mips_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) +int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count) { CPUState *mycpu = first_cpu; + int i; - if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31) - MIPS_CPU(uc, mycpu)->env.active_tc.gpr[regid - UC_MIPS_REG_0] = *(uint32_t *)value; - else { - switch(regid) { - default: break; - case UC_MIPS_REG_PC: - MIPS_CPU(uc, mycpu)->env.active_tc.PC = *(uint32_t *)value; - // force to quit execution and flush TB - uc->quit_request = true; - uc_emu_stop(uc); - break; + for (i = 0; i < count; i++) { + unsigned int regid = regs[i]; + const void *value = vals[i]; + if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31) + MIPS_CPU(uc, mycpu)->env.active_tc.gpr[regid - UC_MIPS_REG_0] = *(uint32_t *)value; + else { + switch(regid) { + default: break; + case UC_MIPS_REG_PC: + MIPS_CPU(uc, mycpu)->env.active_tc.PC = *(uint32_t *)value; + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); + break; + } } } - return 0; } diff --git a/qemu/target-mips/unicorn.h b/qemu/target-mips/unicorn.h index 874b82f1..c9639eb8 100644 --- a/qemu/target-mips/unicorn.h +++ b/qemu/target-mips/unicorn.h @@ -5,8 +5,8 @@ #define UC_QEMU_TARGET_MIPS_H // functions to read & write registers -int mips_reg_read(struct uc_struct *uc, unsigned int regid, void *value); -int mips_reg_write(struct uc_struct *uc, unsigned int regid, const void *value); +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); void mips_reg_reset(struct uc_struct *uc); diff --git a/qemu/target-sparc/unicorn.c b/qemu/target-sparc/unicorn.c index 3775776a..a2a3dcaa 100644 --- a/qemu/target-sparc/unicorn.c +++ b/qemu/target-sparc/unicorn.c @@ -39,52 +39,62 @@ void sparc_reg_reset(struct uc_struct *uc) env->regwptr = env->regbase; } -int sparc_reg_read(struct uc_struct *uc, unsigned int regid, void *value) +int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) { CPUState *mycpu = first_cpu; + int i; - if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7) - *(int32_t *)value = SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0]; - else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) - *(int32_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0]; - else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) - *(int32_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0]; - else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) - *(int32_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0]; - else { - switch(regid) { - default: break; - case UC_SPARC_REG_PC: - *(int32_t *)value = SPARC_CPU(uc, mycpu)->env.pc; - break; + for (i = 0; i < count; i++) { + unsigned int regid = regs[i]; + void *value = vals[i]; + if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7) + *(int32_t *)value = SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0]; + else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) + *(int32_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0]; + else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) + *(int32_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0]; + else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) + *(int32_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0]; + else { + switch(regid) { + default: break; + case UC_SPARC_REG_PC: + *(int32_t *)value = SPARC_CPU(uc, mycpu)->env.pc; + break; + } } } return 0; } -int sparc_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) +int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count) { CPUState *mycpu = first_cpu; + int i; - if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7) - SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0] = *(uint32_t *)value; - else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) - SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0] = *(uint32_t *)value; - else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) - SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0] = *(uint32_t *)value; - else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) - SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint32_t *)value; - else { - switch(regid) { - default: break; - case UC_SPARC_REG_PC: - SPARC_CPU(uc, mycpu)->env.pc = *(uint32_t *)value; - SPARC_CPU(uc, mycpu)->env.npc = *(uint32_t *)value + 4; - // force to quit execution and flush TB - uc->quit_request = true; - uc_emu_stop(uc); - break; + for (i = 0; i < count; i++) { + unsigned int regid = regs[i]; + const void *value = vals[i]; + if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7) + SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0] = *(uint32_t *)value; + else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) + SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0] = *(uint32_t *)value; + else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) + SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0] = *(uint32_t *)value; + else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) + SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint32_t *)value; + else { + switch(regid) { + default: break; + case UC_SPARC_REG_PC: + SPARC_CPU(uc, mycpu)->env.pc = *(uint32_t *)value; + SPARC_CPU(uc, mycpu)->env.npc = *(uint32_t *)value + 4; + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); + break; + } } } diff --git a/qemu/target-sparc/unicorn.h b/qemu/target-sparc/unicorn.h index 89771827..53bf1303 100644 --- a/qemu/target-sparc/unicorn.h +++ b/qemu/target-sparc/unicorn.h @@ -5,8 +5,8 @@ #define UC_QEMU_TARGET_SPARC_H // functions to read & write registers -int sparc_reg_read(struct uc_struct *uc, unsigned int regid, void *value); -int sparc_reg_write(struct uc_struct *uc, unsigned int regid, const void *value); +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); void sparc_reg_reset(struct uc_struct *uc); diff --git a/qemu/target-sparc/unicorn64.c b/qemu/target-sparc/unicorn64.c index ef99b5ab..9a748936 100644 --- a/qemu/target-sparc/unicorn64.c +++ b/qemu/target-sparc/unicorn64.c @@ -39,53 +39,62 @@ void sparc_reg_reset(struct uc_struct *uc) env->regwptr = env->regbase; } -int sparc_reg_read(struct uc_struct *uc, unsigned int regid, void *value) +int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) { CPUState *mycpu = first_cpu; + int i; - if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7) - *(int64_t *)value = SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0]; - else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) - *(int64_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0]; - else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) - *(int64_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0]; - else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) - *(int64_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0]; - else { - switch(regid) { - default: break; - case UC_SPARC_REG_PC: - *(int64_t *)value = SPARC_CPU(uc, mycpu)->env.pc; - break; + for (i = 0; i < count; i++) { + unsigned int regid = regs[i]; + void *value = vals[i]; + if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7) + *(int64_t *)value = SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0]; + else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) + *(int64_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0]; + else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) + *(int64_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0]; + else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) + *(int64_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0]; + else { + switch(regid) { + default: break; + case UC_SPARC_REG_PC: + *(int64_t *)value = SPARC_CPU(uc, mycpu)->env.pc; + break; + } } } return 0; } -int sparc_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) +int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, int count) { CPUState *mycpu = first_cpu; + int i; - if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7) - SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0] = *(uint64_t *)value; - else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) - SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0] = *(uint64_t *)value; - else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) - SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0] = *(uint64_t *)value; - else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) - SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint64_t *)value; - else { - switch(regid) { - default: break; - case UC_SPARC_REG_PC: - SPARC_CPU(uc, mycpu)->env.pc = *(uint64_t *)value; - SPARC_CPU(uc, mycpu)->env.npc = *(uint64_t *)value + 4; - break; + for (i = 0; i < count; i++) { + unsigned int regid = regs[i]; + const void *value = vals[i]; + if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7) + SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0] = *(uint64_t *)value; + else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) + SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0] = *(uint64_t *)value; + else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) + SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0] = *(uint64_t *)value; + else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) + SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint64_t *)value; + else { + switch(regid) { + default: break; + case UC_SPARC_REG_PC: + SPARC_CPU(uc, mycpu)->env.pc = *(uint64_t *)value; + SPARC_CPU(uc, mycpu)->env.npc = *(uint64_t *)value + 4; + break; + } } } - return 0; } diff --git a/uc.c b/uc.c index af504fe1..90ea8da3 100644 --- a/uc.c +++ b/uc.c @@ -332,10 +332,10 @@ uc_err uc_close(uc_engine *uc) UNICORN_EXPORT -uc_err uc_reg_read(uc_engine *uc, int regid, void *value) +uc_err uc_reg_read_batch(uc_engine *uc, int *ids, void **vals, int count) { if (uc->reg_read) - uc->reg_read(uc, regid, value); + uc->reg_read(uc, (unsigned int *)ids, vals, count); else return -1; // FIXME: need a proper uc_err @@ -344,10 +344,10 @@ uc_err uc_reg_read(uc_engine *uc, int regid, void *value) UNICORN_EXPORT -uc_err uc_reg_write(uc_engine *uc, int regid, const void *value) +uc_err uc_reg_write_batch(uc_engine *uc, int *ids, void *const *vals, int count) { if (uc->reg_write) - uc->reg_write(uc, regid, value); + uc->reg_write(uc, (unsigned int *)ids, vals, count); else return -1; // FIXME: need a proper uc_err @@ -355,6 +355,20 @@ uc_err uc_reg_write(uc_engine *uc, int regid, const void *value) } +UNICORN_EXPORT +uc_err uc_reg_read(uc_engine *uc, int regid, void *value) +{ + return uc_reg_read_batch(uc, ®id, &value, 1); +} + + +UNICORN_EXPORT +uc_err uc_reg_write(uc_engine *uc, int regid, const void *value) +{ + return uc_reg_write_batch(uc, ®id, (void *const *)&value, 1); +} + + // check if a memory area is mapped // this is complicated because an area can overlap adjacent blocks static bool check_mem_area(uc_engine *uc, uint64_t address, size_t size)