target/i386/emulate: stop overloading decode->op[N].ptr

decode->op[N].ptr can contain either a host pointer (!) in CPUState
or a guest virtual address.  Pass the whole struct to read_val_ext
and write_val_ext, so that it can decide the contents based on the
operand type.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2025-05-02 22:21:42 +02:00
parent ad441b8b79
commit 77a2dba45c
4 changed files with 109 additions and 101 deletions

View file

@ -109,8 +109,8 @@ static void decode_modrm_reg(CPUX86State *env, struct x86_decode *decode,
{ {
op->type = X86_VAR_REG; op->type = X86_VAR_REG;
op->reg = decode->modrm.reg; op->reg = decode->modrm.reg;
op->ptr = get_reg_ref(env, op->reg, decode->rex.rex, decode->rex.r, op->regptr = get_reg_ref(env, op->reg, decode->rex.rex, decode->rex.r,
decode->operand_size); decode->operand_size);
} }
static void decode_rax(CPUX86State *env, struct x86_decode *decode, static void decode_rax(CPUX86State *env, struct x86_decode *decode,
@ -119,8 +119,8 @@ static void decode_rax(CPUX86State *env, struct x86_decode *decode,
op->type = X86_VAR_REG; op->type = X86_VAR_REG;
op->reg = R_EAX; op->reg = R_EAX;
/* Since reg is always AX, REX prefix has no impact. */ /* Since reg is always AX, REX prefix has no impact. */
op->ptr = get_reg_ref(env, op->reg, false, 0, op->regptr = get_reg_ref(env, op->reg, false, 0,
decode->operand_size); decode->operand_size);
} }
static inline void decode_immediate(CPUX86State *env, struct x86_decode *decode, static inline void decode_immediate(CPUX86State *env, struct x86_decode *decode,
@ -262,16 +262,16 @@ static void decode_incgroup(CPUX86State *env, struct x86_decode *decode)
{ {
decode->op[0].type = X86_VAR_REG; decode->op[0].type = X86_VAR_REG;
decode->op[0].reg = decode->opcode[0] - 0x40; decode->op[0].reg = decode->opcode[0] - 0x40;
decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, decode->op[0].regptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
decode->rex.b, decode->operand_size); decode->rex.b, decode->operand_size);
} }
static void decode_decgroup(CPUX86State *env, struct x86_decode *decode) static void decode_decgroup(CPUX86State *env, struct x86_decode *decode)
{ {
decode->op[0].type = X86_VAR_REG; decode->op[0].type = X86_VAR_REG;
decode->op[0].reg = decode->opcode[0] - 0x48; decode->op[0].reg = decode->opcode[0] - 0x48;
decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, decode->op[0].regptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
decode->rex.b, decode->operand_size); decode->rex.b, decode->operand_size);
} }
static void decode_incgroup2(CPUX86State *env, struct x86_decode *decode) static void decode_incgroup2(CPUX86State *env, struct x86_decode *decode)
@ -287,16 +287,16 @@ static void decode_pushgroup(CPUX86State *env, struct x86_decode *decode)
{ {
decode->op[0].type = X86_VAR_REG; decode->op[0].type = X86_VAR_REG;
decode->op[0].reg = decode->opcode[0] - 0x50; decode->op[0].reg = decode->opcode[0] - 0x50;
decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, decode->op[0].regptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
decode->rex.b, decode->operand_size); decode->rex.b, decode->operand_size);
} }
static void decode_popgroup(CPUX86State *env, struct x86_decode *decode) static void decode_popgroup(CPUX86State *env, struct x86_decode *decode)
{ {
decode->op[0].type = X86_VAR_REG; decode->op[0].type = X86_VAR_REG;
decode->op[0].reg = decode->opcode[0] - 0x58; decode->op[0].reg = decode->opcode[0] - 0x58;
decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, decode->op[0].regptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
decode->rex.b, decode->operand_size); decode->rex.b, decode->operand_size);
} }
static void decode_jxx(CPUX86State *env, struct x86_decode *decode) static void decode_jxx(CPUX86State *env, struct x86_decode *decode)
@ -377,16 +377,16 @@ static void decode_xchgroup(CPUX86State *env, struct x86_decode *decode)
{ {
decode->op[0].type = X86_VAR_REG; decode->op[0].type = X86_VAR_REG;
decode->op[0].reg = decode->opcode[0] - 0x90; decode->op[0].reg = decode->opcode[0] - 0x90;
decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, decode->op[0].regptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
decode->rex.b, decode->operand_size); decode->rex.b, decode->operand_size);
} }
static void decode_movgroup(CPUX86State *env, struct x86_decode *decode) static void decode_movgroup(CPUX86State *env, struct x86_decode *decode)
{ {
decode->op[0].type = X86_VAR_REG; decode->op[0].type = X86_VAR_REG;
decode->op[0].reg = decode->opcode[0] - 0xb8; decode->op[0].reg = decode->opcode[0] - 0xb8;
decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, decode->op[0].regptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
decode->rex.b, decode->operand_size); decode->rex.b, decode->operand_size);
decode_immediate(env, decode, &decode->op[1], decode->operand_size); decode_immediate(env, decode, &decode->op[1], decode->operand_size);
} }
@ -394,15 +394,15 @@ static void fetch_moffs(CPUX86State *env, struct x86_decode *decode,
struct x86_decode_op *op) struct x86_decode_op *op)
{ {
op->type = X86_VAR_OFFSET; op->type = X86_VAR_OFFSET;
op->ptr = decode_bytes(env, decode, decode->addressing_size); op->addr = decode_bytes(env, decode, decode->addressing_size);
} }
static void decode_movgroup8(CPUX86State *env, struct x86_decode *decode) static void decode_movgroup8(CPUX86State *env, struct x86_decode *decode)
{ {
decode->op[0].type = X86_VAR_REG; decode->op[0].type = X86_VAR_REG;
decode->op[0].reg = decode->opcode[0] - 0xb0; decode->op[0].reg = decode->opcode[0] - 0xb0;
decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, decode->op[0].regptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
decode->rex.b, decode->operand_size); decode->rex.b, decode->operand_size);
decode_immediate(env, decode, &decode->op[1], decode->operand_size); decode_immediate(env, decode, &decode->op[1], decode->operand_size);
} }
@ -411,8 +411,8 @@ static void decode_rcx(CPUX86State *env, struct x86_decode *decode,
{ {
op->type = X86_VAR_REG; op->type = X86_VAR_REG;
op->reg = R_ECX; op->reg = R_ECX;
op->ptr = get_reg_ref(env, op->reg, decode->rex.rex, decode->rex.b, op->regptr = get_reg_ref(env, op->reg, decode->rex.rex, decode->rex.b,
decode->operand_size); decode->operand_size);
} }
struct decode_tbl { struct decode_tbl {
@ -631,8 +631,8 @@ static void decode_bswap(CPUX86State *env, struct x86_decode *decode)
{ {
decode->op[0].type = X86_VAR_REG; decode->op[0].type = X86_VAR_REG;
decode->op[0].reg = decode->opcode[1] - 0xc8; decode->op[0].reg = decode->opcode[1] - 0xc8;
decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, decode->op[0].regptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex,
decode->rex.b, decode->operand_size); decode->rex.b, decode->operand_size);
} }
static void decode_d9_4(CPUX86State *env, struct x86_decode *decode) static void decode_d9_4(CPUX86State *env, struct x86_decode *decode)
@ -1656,16 +1656,16 @@ void calc_modrm_operand16(CPUX86State *env, struct x86_decode *decode,
} }
calc_addr: calc_addr:
if (X86_DECODE_CMD_LEA == decode->cmd) { if (X86_DECODE_CMD_LEA == decode->cmd) {
op->ptr = (uint16_t)ptr; op->addr = (uint16_t)ptr;
} else { } else {
op->ptr = decode_linear_addr(env, decode, (uint16_t)ptr, seg); op->addr = decode_linear_addr(env, decode, (uint16_t)ptr, seg);
} }
} }
target_ulong get_reg_ref(CPUX86State *env, int reg, int rex_present, void *get_reg_ref(CPUX86State *env, int reg, int rex_present,
int is_extended, int size) int is_extended, int size)
{ {
target_ulong ptr = 0; void *ptr = NULL;
if (is_extended) { if (is_extended) {
reg |= R_R8; reg |= R_R8;
@ -1674,13 +1674,13 @@ target_ulong get_reg_ref(CPUX86State *env, int reg, int rex_present,
switch (size) { switch (size) {
case 1: case 1:
if (is_extended || reg < 4 || rex_present) { if (is_extended || reg < 4 || rex_present) {
ptr = (target_ulong)&RL(env, reg); ptr = &RL(env, reg);
} else { } else {
ptr = (target_ulong)&RH(env, reg - 4); ptr = &RH(env, reg - 4);
} }
break; break;
default: default:
ptr = (target_ulong)&RRX(env, reg); ptr = &RRX(env, reg);
break; break;
} }
return ptr; return ptr;
@ -1691,7 +1691,7 @@ target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present,
{ {
target_ulong val = 0; target_ulong val = 0;
memcpy(&val, memcpy(&val,
(void *)get_reg_ref(env, reg, rex_present, is_extended, size), get_reg_ref(env, reg, rex_present, is_extended, size),
size); size);
return val; return val;
} }
@ -1758,9 +1758,9 @@ void calc_modrm_operand32(CPUX86State *env, struct x86_decode *decode,
} }
if (X86_DECODE_CMD_LEA == decode->cmd) { if (X86_DECODE_CMD_LEA == decode->cmd) {
op->ptr = (uint32_t)ptr; op->addr = (uint32_t)ptr;
} else { } else {
op->ptr = decode_linear_addr(env, decode, (uint32_t)ptr, seg); op->addr = decode_linear_addr(env, decode, (uint32_t)ptr, seg);
} }
} }
@ -1788,9 +1788,9 @@ void calc_modrm_operand64(CPUX86State *env, struct x86_decode *decode,
} }
if (X86_DECODE_CMD_LEA == decode->cmd) { if (X86_DECODE_CMD_LEA == decode->cmd) {
op->ptr = ptr; op->addr = ptr;
} else { } else {
op->ptr = decode_linear_addr(env, decode, ptr, seg); op->addr = decode_linear_addr(env, decode, ptr, seg);
} }
} }
@ -1801,8 +1801,8 @@ void calc_modrm_operand(CPUX86State *env, struct x86_decode *decode,
if (3 == decode->modrm.mod) { if (3 == decode->modrm.mod) {
op->reg = decode->modrm.reg; op->reg = decode->modrm.reg;
op->type = X86_VAR_REG; op->type = X86_VAR_REG;
op->ptr = get_reg_ref(env, decode->modrm.rm, decode->rex.rex, op->regptr = get_reg_ref(env, decode->modrm.rm, decode->rex.rex,
decode->rex.b, decode->operand_size); decode->rex.b, decode->operand_size);
return; return;
} }

View file

@ -266,7 +266,10 @@ typedef struct x86_decode_op {
int reg; int reg;
target_ulong val; target_ulong val;
target_ulong ptr; union {
target_ulong addr;
void *regptr;
};
} x86_decode_op; } x86_decode_op;
typedef struct x86_decode { typedef struct x86_decode {
@ -301,8 +304,8 @@ uint64_t sign(uint64_t val, int size);
uint32_t decode_instruction(CPUX86State *env, struct x86_decode *decode); uint32_t decode_instruction(CPUX86State *env, struct x86_decode *decode);
target_ulong get_reg_ref(CPUX86State *env, int reg, int rex_present, void *get_reg_ref(CPUX86State *env, int reg, int rex_present,
int is_extended, int size); int is_extended, int size);
target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present, target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present,
int is_extended, int size); int is_extended, int size);
void calc_modrm_operand(CPUX86State *env, struct x86_decode *decode, void calc_modrm_operand(CPUX86State *env, struct x86_decode *decode,

View file

@ -52,7 +52,7 @@
uint8_t v2 = (uint8_t)decode->op[1].val; \ uint8_t v2 = (uint8_t)decode->op[1].val; \
uint8_t diff = v1 cmd v2; \ uint8_t diff = v1 cmd v2; \
if (save_res) { \ if (save_res) { \
write_val_ext(env, decode->op[0].ptr, diff, 1); \ write_val_ext(env, &decode->op[0], diff, 1); \
} \ } \
FLAGS_FUNC##8(env, v1, v2, diff); \ FLAGS_FUNC##8(env, v1, v2, diff); \
break; \ break; \
@ -63,7 +63,7 @@
uint16_t v2 = (uint16_t)decode->op[1].val; \ uint16_t v2 = (uint16_t)decode->op[1].val; \
uint16_t diff = v1 cmd v2; \ uint16_t diff = v1 cmd v2; \
if (save_res) { \ if (save_res) { \
write_val_ext(env, decode->op[0].ptr, diff, 2); \ write_val_ext(env, &decode->op[0], diff, 2); \
} \ } \
FLAGS_FUNC##16(env, v1, v2, diff); \ FLAGS_FUNC##16(env, v1, v2, diff); \
break; \ break; \
@ -74,7 +74,7 @@
uint32_t v2 = (uint32_t)decode->op[1].val; \ uint32_t v2 = (uint32_t)decode->op[1].val; \
uint32_t diff = v1 cmd v2; \ uint32_t diff = v1 cmd v2; \
if (save_res) { \ if (save_res) { \
write_val_ext(env, decode->op[0].ptr, diff, 4); \ write_val_ext(env, &decode->op[0], diff, 4); \
} \ } \
FLAGS_FUNC##32(env, v1, v2, diff); \ FLAGS_FUNC##32(env, v1, v2, diff); \
break; \ break; \
@ -121,7 +121,7 @@ void write_reg(CPUX86State *env, int reg, target_ulong val, int size)
} }
} }
target_ulong read_val_from_reg(target_ulong reg_ptr, int size) target_ulong read_val_from_reg(void *reg_ptr, int size)
{ {
target_ulong val; target_ulong val;
@ -144,7 +144,7 @@ target_ulong read_val_from_reg(target_ulong reg_ptr, int size)
return val; return val;
} }
void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size) void write_val_to_reg(void *reg_ptr, target_ulong val, int size)
{ {
switch (size) { switch (size) {
case 1: case 1:
@ -164,18 +164,18 @@ void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size)
} }
} }
static bool is_host_reg(CPUX86State *env, target_ulong ptr) static void write_val_to_mem(CPUX86State *env, target_ulong ptr, target_ulong val, int size)
{ {
return (ptr - (target_ulong)&env->regs[0]) < sizeof(env->regs); emul_ops->write_mem(env_cpu(env), &val, ptr, size);
} }
void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int size) void write_val_ext(CPUX86State *env, struct x86_decode_op *decode, target_ulong val, int size)
{ {
if (is_host_reg(env, ptr)) { if (decode->type == X86_VAR_REG) {
write_val_to_reg(ptr, val, size); write_val_to_reg(decode->regptr, val, size);
return; } else {
write_val_to_mem(env, decode->addr, val, size);
} }
emul_ops->write_mem(env_cpu(env), &val, ptr, size);
} }
uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes) uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes)
@ -185,15 +185,11 @@ uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes)
} }
target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size) static target_ulong read_val_from_mem(CPUX86State *env, target_long ptr, int size)
{ {
target_ulong val; target_ulong val;
uint8_t *mmio_ptr; uint8_t *mmio_ptr;
if (is_host_reg(env, ptr)) {
return read_val_from_reg(ptr, size);
}
mmio_ptr = read_mmio(env, ptr, size); mmio_ptr = read_mmio(env, ptr, size);
switch (size) { switch (size) {
case 1: case 1:
@ -215,6 +211,15 @@ target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size)
return val; return val;
} }
target_ulong read_val_ext(CPUX86State *env, struct x86_decode_op *decode, int size)
{
if (decode->type == X86_VAR_REG) {
return read_val_from_reg(decode->regptr, size);
} else {
return read_val_from_mem(env, decode->addr, size);
}
}
static void fetch_operands(CPUX86State *env, struct x86_decode *decode, static void fetch_operands(CPUX86State *env, struct x86_decode *decode,
int n, bool val_op0, bool val_op1, bool val_op2) int n, bool val_op0, bool val_op1, bool val_op2)
{ {
@ -226,25 +231,25 @@ static void fetch_operands(CPUX86State *env, struct x86_decode *decode,
case X86_VAR_IMMEDIATE: case X86_VAR_IMMEDIATE:
break; break;
case X86_VAR_REG: case X86_VAR_REG:
VM_PANIC_ON(!decode->op[i].ptr); VM_PANIC_ON(!decode->op[i].regptr);
if (calc_val[i]) { if (calc_val[i]) {
decode->op[i].val = read_val_from_reg(decode->op[i].ptr, decode->op[i].val = read_val_from_reg(decode->op[i].regptr,
decode->operand_size); decode->operand_size);
} }
break; break;
case X86_VAR_RM: case X86_VAR_RM:
calc_modrm_operand(env, decode, &decode->op[i]); calc_modrm_operand(env, decode, &decode->op[i]);
if (calc_val[i]) { if (calc_val[i]) {
decode->op[i].val = read_val_ext(env, decode->op[i].ptr, decode->op[i].val = read_val_ext(env, &decode->op[i],
decode->operand_size); decode->operand_size);
} }
break; break;
case X86_VAR_OFFSET: case X86_VAR_OFFSET:
decode->op[i].ptr = decode_linear_addr(env, decode, decode->op[i].addr = decode_linear_addr(env, decode,
decode->op[i].ptr, decode->op[i].addr,
R_DS); R_DS);
if (calc_val[i]) { if (calc_val[i]) {
decode->op[i].val = read_val_ext(env, decode->op[i].ptr, decode->op[i].val = read_val_ext(env, &decode->op[i],
decode->operand_size); decode->operand_size);
} }
break; break;
@ -257,7 +262,7 @@ static void fetch_operands(CPUX86State *env, struct x86_decode *decode,
static void exec_mov(CPUX86State *env, struct x86_decode *decode) static void exec_mov(CPUX86State *env, struct x86_decode *decode)
{ {
fetch_operands(env, decode, 2, false, true, false); fetch_operands(env, decode, 2, false, true, false);
write_val_ext(env, decode->op[0].ptr, decode->op[1].val, write_val_ext(env, &decode->op[0], decode->op[1].val,
decode->operand_size); decode->operand_size);
env->eip += decode->len; env->eip += decode->len;
@ -312,7 +317,7 @@ static void exec_neg(CPUX86State *env, struct x86_decode *decode)
fetch_operands(env, decode, 2, true, true, false); fetch_operands(env, decode, 2, true, true, false);
val = 0 - sign(decode->op[1].val, decode->operand_size); val = 0 - sign(decode->op[1].val, decode->operand_size);
write_val_ext(env, decode->op[1].ptr, val, decode->operand_size); write_val_ext(env, &decode->op[1], val, decode->operand_size);
if (4 == decode->operand_size) { if (4 == decode->operand_size) {
SET_FLAGS_OSZAPC_SUB32(env, 0, 0 - val, val); SET_FLAGS_OSZAPC_SUB32(env, 0, 0 - val, val);
@ -363,7 +368,7 @@ static void exec_not(CPUX86State *env, struct x86_decode *decode)
{ {
fetch_operands(env, decode, 1, true, false, false); fetch_operands(env, decode, 1, true, false, false);
write_val_ext(env, decode->op[0].ptr, ~decode->op[0].val, write_val_ext(env, &decode->op[0], ~decode->op[0].val,
decode->operand_size); decode->operand_size);
env->eip += decode->len; env->eip += decode->len;
} }
@ -382,8 +387,8 @@ void exec_movzx(CPUX86State *env, struct x86_decode *decode)
} }
decode->operand_size = src_op_size; decode->operand_size = src_op_size;
calc_modrm_operand(env, decode, &decode->op[1]); calc_modrm_operand(env, decode, &decode->op[1]);
decode->op[1].val = read_val_ext(env, decode->op[1].ptr, src_op_size); decode->op[1].val = read_val_ext(env, &decode->op[1], src_op_size);
write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size); write_val_ext(env, &decode->op[0], decode->op[1].val, op_size);
env->eip += decode->len; env->eip += decode->len;
} }
@ -535,8 +540,8 @@ static void exec_movs_single(CPUX86State *env, struct x86_decode *decode)
dst_addr = linear_addr_size(env_cpu(env), RDI(env), dst_addr = linear_addr_size(env_cpu(env), RDI(env),
decode->addressing_size, R_ES); decode->addressing_size, R_ES);
val = read_val_ext(env, src_addr, decode->operand_size); val = read_val_from_mem(env, src_addr, decode->operand_size);
write_val_ext(env, dst_addr, val, decode->operand_size); write_val_to_mem(env, dst_addr, val, decode->operand_size);
string_increment_reg(env, R_ESI, decode); string_increment_reg(env, R_ESI, decode);
string_increment_reg(env, R_EDI, decode); string_increment_reg(env, R_EDI, decode);
@ -563,9 +568,9 @@ static void exec_cmps_single(CPUX86State *env, struct x86_decode *decode)
decode->addressing_size, R_ES); decode->addressing_size, R_ES);
decode->op[0].type = X86_VAR_IMMEDIATE; decode->op[0].type = X86_VAR_IMMEDIATE;
decode->op[0].val = read_val_ext(env, src_addr, decode->operand_size); decode->op[0].val = read_val_from_mem(env, src_addr, decode->operand_size);
decode->op[1].type = X86_VAR_IMMEDIATE; decode->op[1].type = X86_VAR_IMMEDIATE;
decode->op[1].val = read_val_ext(env, dst_addr, decode->operand_size); decode->op[1].val = read_val_from_mem(env, dst_addr, decode->operand_size);
EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
@ -697,15 +702,15 @@ static void do_bt(CPUX86State *env, struct x86_decode *decode, int flag)
if (decode->op[0].type != X86_VAR_REG) { if (decode->op[0].type != X86_VAR_REG) {
if (4 == decode->operand_size) { if (4 == decode->operand_size) {
displacement = ((int32_t) (decode->op[1].val & 0xffffffe0)) / 32; displacement = ((int32_t) (decode->op[1].val & 0xffffffe0)) / 32;
decode->op[0].ptr += 4 * displacement; decode->op[0].addr += 4 * displacement;
} else if (2 == decode->operand_size) { } else if (2 == decode->operand_size) {
displacement = ((int16_t) (decode->op[1].val & 0xfff0)) / 16; displacement = ((int16_t) (decode->op[1].val & 0xfff0)) / 16;
decode->op[0].ptr += 2 * displacement; decode->op[0].addr += 2 * displacement;
} else { } else {
VM_PANIC("bt 64bit\n"); VM_PANIC("bt 64bit\n");
} }
} }
decode->op[0].val = read_val_ext(env, decode->op[0].ptr, decode->op[0].val = read_val_ext(env, &decode->op[0],
decode->operand_size); decode->operand_size);
cf = (decode->op[0].val >> index) & 0x01; cf = (decode->op[0].val >> index) & 0x01;
@ -723,7 +728,7 @@ static void do_bt(CPUX86State *env, struct x86_decode *decode, int flag)
decode->op[0].val &= ~(1u << index); decode->op[0].val &= ~(1u << index);
break; break;
} }
write_val_ext(env, decode->op[0].ptr, decode->op[0].val, write_val_ext(env, &decode->op[0], decode->op[0].val,
decode->operand_size); decode->operand_size);
set_CF(env, cf); set_CF(env, cf);
} }
@ -775,7 +780,7 @@ void exec_shl(CPUX86State *env, struct x86_decode *decode)
of = cf ^ (res >> 7); of = cf ^ (res >> 7);
} }
write_val_ext(env, decode->op[0].ptr, res, 1); write_val_ext(env, &decode->op[0], res, 1);
SET_FLAGS_OSZAPC_LOGIC8(env, 0, 0, res); SET_FLAGS_OSZAPC_LOGIC8(env, 0, 0, res);
SET_FLAGS_OxxxxC(env, of, cf); SET_FLAGS_OxxxxC(env, of, cf);
break; break;
@ -791,7 +796,7 @@ void exec_shl(CPUX86State *env, struct x86_decode *decode)
of = cf ^ (res >> 15); /* of = cf ^ result15 */ of = cf ^ (res >> 15); /* of = cf ^ result15 */
} }
write_val_ext(env, decode->op[0].ptr, res, 2); write_val_ext(env, &decode->op[0], res, 2);
SET_FLAGS_OSZAPC_LOGIC16(env, 0, 0, res); SET_FLAGS_OSZAPC_LOGIC16(env, 0, 0, res);
SET_FLAGS_OxxxxC(env, of, cf); SET_FLAGS_OxxxxC(env, of, cf);
break; break;
@ -800,7 +805,7 @@ void exec_shl(CPUX86State *env, struct x86_decode *decode)
{ {
uint32_t res = decode->op[0].val << count; uint32_t res = decode->op[0].val << count;
write_val_ext(env, decode->op[0].ptr, res, 4); write_val_ext(env, &decode->op[0], res, 4);
SET_FLAGS_OSZAPC_LOGIC32(env, 0, 0, res); SET_FLAGS_OSZAPC_LOGIC32(env, 0, 0, res);
cf = (decode->op[0].val >> (32 - count)) & 0x1; cf = (decode->op[0].val >> (32 - count)) & 0x1;
of = cf ^ (res >> 31); /* of = cf ^ result31 */ of = cf ^ (res >> 31); /* of = cf ^ result31 */
@ -831,10 +836,10 @@ void exec_movsx(CPUX86State *env, struct x86_decode *decode)
decode->operand_size = src_op_size; decode->operand_size = src_op_size;
calc_modrm_operand(env, decode, &decode->op[1]); calc_modrm_operand(env, decode, &decode->op[1]);
decode->op[1].val = sign(read_val_ext(env, decode->op[1].ptr, src_op_size), decode->op[1].val = sign(read_val_ext(env, &decode->op[1], src_op_size),
src_op_size); src_op_size);
write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size); write_val_ext(env, &decode->op[0], decode->op[1].val, op_size);
env->eip += decode->len; env->eip += decode->len;
} }
@ -862,7 +867,7 @@ void exec_ror(CPUX86State *env, struct x86_decode *decode)
count &= 0x7; /* use only bottom 3 bits */ count &= 0x7; /* use only bottom 3 bits */
res = ((uint8_t)decode->op[0].val >> count) | res = ((uint8_t)decode->op[0].val >> count) |
((uint8_t)decode->op[0].val << (8 - count)); ((uint8_t)decode->op[0].val << (8 - count));
write_val_ext(env, decode->op[0].ptr, res, 1); write_val_ext(env, &decode->op[0], res, 1);
bit6 = (res >> 6) & 1; bit6 = (res >> 6) & 1;
bit7 = (res >> 7) & 1; bit7 = (res >> 7) & 1;
/* set eflags: ROR count affects the following flags: C, O */ /* set eflags: ROR count affects the following flags: C, O */
@ -886,7 +891,7 @@ void exec_ror(CPUX86State *env, struct x86_decode *decode)
count &= 0x0f; /* use only 4 LSB's */ count &= 0x0f; /* use only 4 LSB's */
res = ((uint16_t)decode->op[0].val >> count) | res = ((uint16_t)decode->op[0].val >> count) |
((uint16_t)decode->op[0].val << (16 - count)); ((uint16_t)decode->op[0].val << (16 - count));
write_val_ext(env, decode->op[0].ptr, res, 2); write_val_ext(env, &decode->op[0], res, 2);
bit14 = (res >> 14) & 1; bit14 = (res >> 14) & 1;
bit15 = (res >> 15) & 1; bit15 = (res >> 15) & 1;
@ -904,7 +909,7 @@ void exec_ror(CPUX86State *env, struct x86_decode *decode)
if (count) { if (count) {
res = ((uint32_t)decode->op[0].val >> count) | res = ((uint32_t)decode->op[0].val >> count) |
((uint32_t)decode->op[0].val << (32 - count)); ((uint32_t)decode->op[0].val << (32 - count));
write_val_ext(env, decode->op[0].ptr, res, 4); write_val_ext(env, &decode->op[0], res, 4);
bit31 = (res >> 31) & 1; bit31 = (res >> 31) & 1;
bit30 = (res >> 30) & 1; bit30 = (res >> 30) & 1;
@ -941,7 +946,7 @@ void exec_rol(CPUX86State *env, struct x86_decode *decode)
res = ((uint8_t)decode->op[0].val << count) | res = ((uint8_t)decode->op[0].val << count) |
((uint8_t)decode->op[0].val >> (8 - count)); ((uint8_t)decode->op[0].val >> (8 - count));
write_val_ext(env, decode->op[0].ptr, res, 1); write_val_ext(env, &decode->op[0], res, 1);
/* set eflags: /* set eflags:
* ROL count affects the following flags: C, O * ROL count affects the following flags: C, O
*/ */
@ -968,7 +973,7 @@ void exec_rol(CPUX86State *env, struct x86_decode *decode)
res = ((uint16_t)decode->op[0].val << count) | res = ((uint16_t)decode->op[0].val << count) |
((uint16_t)decode->op[0].val >> (16 - count)); ((uint16_t)decode->op[0].val >> (16 - count));
write_val_ext(env, decode->op[0].ptr, res, 2); write_val_ext(env, &decode->op[0], res, 2);
bit0 = (res & 0x1); bit0 = (res & 0x1);
bit15 = (res >> 15); bit15 = (res >> 15);
/* of = cf ^ result15 */ /* of = cf ^ result15 */
@ -986,7 +991,7 @@ void exec_rol(CPUX86State *env, struct x86_decode *decode)
res = ((uint32_t)decode->op[0].val << count) | res = ((uint32_t)decode->op[0].val << count) |
((uint32_t)decode->op[0].val >> (32 - count)); ((uint32_t)decode->op[0].val >> (32 - count));
write_val_ext(env, decode->op[0].ptr, res, 4); write_val_ext(env, &decode->op[0], res, 4);
bit0 = (res & 0x1); bit0 = (res & 0x1);
bit31 = (res >> 31); bit31 = (res >> 31);
/* of = cf ^ result31 */ /* of = cf ^ result31 */
@ -1024,7 +1029,7 @@ void exec_rcl(CPUX86State *env, struct x86_decode *decode)
(op1_8 >> (9 - count)); (op1_8 >> (9 - count));
} }
write_val_ext(env, decode->op[0].ptr, res, 1); write_val_ext(env, &decode->op[0], res, 1);
cf = (op1_8 >> (8 - count)) & 0x01; cf = (op1_8 >> (8 - count)) & 0x01;
of = cf ^ (res >> 7); /* of = cf ^ result7 */ of = cf ^ (res >> 7); /* of = cf ^ result7 */
@ -1050,7 +1055,7 @@ void exec_rcl(CPUX86State *env, struct x86_decode *decode)
(op1_16 >> (17 - count)); (op1_16 >> (17 - count));
} }
write_val_ext(env, decode->op[0].ptr, res, 2); write_val_ext(env, &decode->op[0], res, 2);
cf = (op1_16 >> (16 - count)) & 0x1; cf = (op1_16 >> (16 - count)) & 0x1;
of = cf ^ (res >> 15); /* of = cf ^ result15 */ of = cf ^ (res >> 15); /* of = cf ^ result15 */
@ -1073,7 +1078,7 @@ void exec_rcl(CPUX86State *env, struct x86_decode *decode)
(op1_32 >> (33 - count)); (op1_32 >> (33 - count));
} }
write_val_ext(env, decode->op[0].ptr, res, 4); write_val_ext(env, &decode->op[0], res, 4);
cf = (op1_32 >> (32 - count)) & 0x1; cf = (op1_32 >> (32 - count)) & 0x1;
of = cf ^ (res >> 31); /* of = cf ^ result31 */ of = cf ^ (res >> 31); /* of = cf ^ result31 */
@ -1105,7 +1110,7 @@ void exec_rcr(CPUX86State *env, struct x86_decode *decode)
res = (op1_8 >> count) | (get_CF(env) << (8 - count)) | res = (op1_8 >> count) | (get_CF(env) << (8 - count)) |
(op1_8 << (9 - count)); (op1_8 << (9 - count));
write_val_ext(env, decode->op[0].ptr, res, 1); write_val_ext(env, &decode->op[0], res, 1);
cf = (op1_8 >> (count - 1)) & 0x1; cf = (op1_8 >> (count - 1)) & 0x1;
of = (((res << 1) ^ res) >> 7) & 0x1; /* of = result6 ^ result7 */ of = (((res << 1) ^ res) >> 7) & 0x1; /* of = result6 ^ result7 */
@ -1124,7 +1129,7 @@ void exec_rcr(CPUX86State *env, struct x86_decode *decode)
res = (op1_16 >> count) | (get_CF(env) << (16 - count)) | res = (op1_16 >> count) | (get_CF(env) << (16 - count)) |
(op1_16 << (17 - count)); (op1_16 << (17 - count));
write_val_ext(env, decode->op[0].ptr, res, 2); write_val_ext(env, &decode->op[0], res, 2);
cf = (op1_16 >> (count - 1)) & 0x1; cf = (op1_16 >> (count - 1)) & 0x1;
of = ((uint16_t)((res << 1) ^ res) >> 15) & 0x1; /* of = result15 ^ of = ((uint16_t)((res << 1) ^ res) >> 15) & 0x1; /* of = result15 ^
@ -1148,7 +1153,7 @@ void exec_rcr(CPUX86State *env, struct x86_decode *decode)
(op1_32 << (33 - count)); (op1_32 << (33 - count));
} }
write_val_ext(env, decode->op[0].ptr, res, 4); write_val_ext(env, &decode->op[0], res, 4);
cf = (op1_32 >> (count - 1)) & 0x1; cf = (op1_32 >> (count - 1)) & 0x1;
of = ((res << 1) ^ res) >> 31; /* of = result30 ^ result31 */ of = ((res << 1) ^ res) >> 31; /* of = result30 ^ result31 */
@ -1163,9 +1168,9 @@ static void exec_xchg(CPUX86State *env, struct x86_decode *decode)
{ {
fetch_operands(env, decode, 2, true, true, false); fetch_operands(env, decode, 2, true, true, false);
write_val_ext(env, decode->op[0].ptr, decode->op[1].val, write_val_ext(env, &decode->op[0], decode->op[1].val,
decode->operand_size); decode->operand_size);
write_val_ext(env, decode->op[1].ptr, decode->op[0].val, write_val_ext(env, &decode->op[1], decode->op[0].val,
decode->operand_size); decode->operand_size);
env->eip += decode->len; env->eip += decode->len;
@ -1174,7 +1179,7 @@ static void exec_xchg(CPUX86State *env, struct x86_decode *decode)
static void exec_xadd(CPUX86State *env, struct x86_decode *decode) static void exec_xadd(CPUX86State *env, struct x86_decode *decode)
{ {
EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true); EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true);
write_val_ext(env, decode->op[1].ptr, decode->op[0].val, write_val_ext(env, &decode->op[1], decode->op[0].val,
decode->operand_size); decode->operand_size);
env->eip += decode->len; env->eip += decode->len;

View file

@ -42,11 +42,11 @@ void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_c
target_ulong read_reg(CPUX86State *env, int reg, int size); target_ulong read_reg(CPUX86State *env, int reg, int size);
void write_reg(CPUX86State *env, int reg, target_ulong val, int size); void write_reg(CPUX86State *env, int reg, target_ulong val, int size);
target_ulong read_val_from_reg(target_ulong reg_ptr, int size); target_ulong read_val_from_reg(void *reg_ptr, int size);
void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size); void write_val_to_reg(void *reg_ptr, target_ulong val, int size);
void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int size); void write_val_ext(CPUX86State *env, struct x86_decode_op *decode, target_ulong val, int size);
uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes); uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes);
target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size); target_ulong read_val_ext(CPUX86State *env, struct x86_decode_op *decode, int size);
void exec_movzx(CPUX86State *env, struct x86_decode *decode); void exec_movzx(CPUX86State *env, struct x86_decode *decode);
void exec_shl(CPUX86State *env, struct x86_decode *decode); void exec_shl(CPUX86State *env, struct x86_decode *decode);