mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-03 16:35:46 +00:00
add batched reg access
This commit is contained in:
parent
1486ccce70
commit
acd88856e1
23
bindings/go/unicorn/uc.c
Normal file
23
bindings/go/unicorn/uc.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
#include <stdlib.h>
|
||||
#include <unicorn/unicorn.h>
|
||||
#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;
|
||||
}
|
2
bindings/go/unicorn/uc.h
Normal file
2
bindings/go/unicorn/uc.h
Normal file
|
@ -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);
|
|
@ -7,8 +7,10 @@ import (
|
|||
)
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -O3
|
||||
#cgo LDFLAGS: -lunicorn
|
||||
#include <unicorn/unicorn.h>
|
||||
#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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -23,10 +23,14 @@ 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;
|
||||
|
||||
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 {
|
||||
|
@ -46,14 +50,19 @@ int arm64_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
|||
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;
|
||||
|
||||
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 {
|
||||
|
@ -76,6 +85,7 @@ int arm64_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -27,12 +27,16 @@ 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;
|
||||
|
||||
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 {
|
||||
|
@ -54,14 +58,19 @@ int arm_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
|||
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;
|
||||
|
||||
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 {
|
||||
|
@ -85,6 +94,7 @@ int arm_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -136,10 +136,14 @@ 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;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
switch(regid) {
|
||||
default:
|
||||
break;
|
||||
|
@ -148,7 +152,7 @@ int x86_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
|||
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;
|
||||
continue;
|
||||
case UC_X86_REG_FPSW:
|
||||
{
|
||||
uint16_t fpus = X86_CPU(uc, mycpu)->env.fpus;
|
||||
|
@ -156,10 +160,10 @@ int x86_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
|||
fpus |= ( X86_CPU(uc, mycpu)->env.fpstt & 0x7 ) << 11;
|
||||
*(uint16_t*) value = fpus;
|
||||
}
|
||||
return 0;
|
||||
continue;
|
||||
case UC_X86_REG_FPCW:
|
||||
*(uint16_t*) value = X86_CPU(uc, mycpu)->env.fpuc;
|
||||
return 0;
|
||||
continue;
|
||||
case UC_X86_REG_FPTAG:
|
||||
{
|
||||
#define EXPD(fp) (fp.l.upper & 0x7fff)
|
||||
|
@ -189,7 +193,7 @@ int x86_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
|||
}
|
||||
*(uint16_t*) value = fptag;
|
||||
}
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(uc->mode) {
|
||||
|
@ -200,19 +204,19 @@ int x86_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
|||
default: break;
|
||||
case UC_X86_REG_ES:
|
||||
*(int16_t *)value = X86_CPU(uc, mycpu)->env.segs[R_ES].selector;
|
||||
return 0;
|
||||
continue;
|
||||
case UC_X86_REG_SS:
|
||||
*(int16_t *)value = X86_CPU(uc, mycpu)->env.segs[R_SS].selector;
|
||||
return 0;
|
||||
continue;
|
||||
case UC_X86_REG_DS:
|
||||
*(int16_t *)value = X86_CPU(uc, mycpu)->env.segs[R_DS].selector;
|
||||
return 0;
|
||||
continue;
|
||||
case UC_X86_REG_FS:
|
||||
*(int16_t *)value = X86_CPU(uc, mycpu)->env.segs[R_FS].selector;
|
||||
return 0;
|
||||
continue;
|
||||
case UC_X86_REG_GS:
|
||||
*(int16_t *)value = X86_CPU(uc, mycpu)->env.segs[R_GS].selector;
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
// fall-thru
|
||||
case UC_MODE_32:
|
||||
|
@ -616,15 +620,19 @@ int x86_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
|||
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;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
switch(regid) {
|
||||
default:
|
||||
break;
|
||||
|
@ -634,17 +642,17 @@ int x86_reg_write(struct uc_struct *uc, unsigned int regid, const void *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;
|
||||
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;
|
||||
}
|
||||
return 0;
|
||||
continue;
|
||||
case UC_X86_REG_FPCW:
|
||||
X86_CPU(uc, mycpu)->env.fpuc = *(uint16_t *)value;
|
||||
return 0;
|
||||
continue;
|
||||
case UC_X86_REG_FPTAG:
|
||||
{
|
||||
int i;
|
||||
|
@ -654,7 +662,7 @@ int x86_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
|||
fptag >>= 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -668,19 +676,19 @@ int x86_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
|||
default: break;
|
||||
case UC_X86_REG_ES:
|
||||
X86_CPU(uc, mycpu)->env.segs[R_ES].selector = *(uint16_t *)value;
|
||||
return 0;
|
||||
continue;
|
||||
case UC_X86_REG_SS:
|
||||
X86_CPU(uc, mycpu)->env.segs[R_SS].selector = *(uint16_t *)value;
|
||||
return 0;
|
||||
continue;
|
||||
case UC_X86_REG_DS:
|
||||
X86_CPU(uc, mycpu)->env.segs[R_DS].selector = *(uint16_t *)value;
|
||||
return 0;
|
||||
continue;
|
||||
case UC_X86_REG_FS:
|
||||
X86_CPU(uc, mycpu)->env.segs[R_FS].selector = *(uint16_t *)value;
|
||||
return 0;
|
||||
continue;
|
||||
case UC_X86_REG_GS:
|
||||
X86_CPU(uc, mycpu)->env.segs[R_GS].selector = *(uint16_t *)value;
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
// fall-thru
|
||||
case UC_MODE_32:
|
||||
|
@ -1101,6 +1109,7 @@ int x86_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
|||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -25,10 +25,14 @@ 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;
|
||||
|
||||
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)
|
||||
|
@ -41,14 +45,19 @@ int m68k_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
|||
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;
|
||||
|
||||
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)
|
||||
|
@ -64,7 +73,7 @@ int m68k_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -39,10 +39,14 @@ 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;
|
||||
|
||||
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 {
|
||||
|
@ -53,14 +57,19 @@ int mips_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
|||
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;
|
||||
|
||||
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 {
|
||||
|
@ -74,7 +83,7 @@ int mips_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -39,10 +39,14 @@ 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;
|
||||
|
||||
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)
|
||||
|
@ -59,14 +63,19 @@ int sparc_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
|||
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;
|
||||
|
||||
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)
|
||||
|
@ -87,6 +96,7 @@ int sparc_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -39,10 +39,14 @@ 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;
|
||||
|
||||
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)
|
||||
|
@ -59,14 +63,19 @@ int sparc_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
|||
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;
|
||||
|
||||
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)
|
||||
|
@ -84,7 +93,7 @@ int sparc_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
22
uc.c
22
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)
|
||||
|
|
Loading…
Reference in a new issue