ia64/xen-unstable
changeset 13145:4fb80f21c77d
[XEN] Emulator extensions to decode ModRM.MOD == 3.
This allows emulation of register-only instructions.
Signed-off-by: Keir Fraser <keir@xensource.com>
This allows emulation of register-only instructions.
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kfraser@localhost.localdomain |
---|---|
date | Wed Dec 20 15:16:13 2006 +0000 (2006-12-20) |
parents | ed815cbdc90e |
children | f58b0c778b90 |
files | tools/tests/test_x86_emulator.c xen/arch/x86/x86_32/seg_fixup.c xen/arch/x86/x86_emulate.c |
line diff
1.1 --- a/tools/tests/test_x86_emulator.c Wed Dec 20 13:54:04 2006 +0000 1.2 +++ b/tools/tests/test_x86_emulator.c Wed Dec 20 15:16:13 2006 +0000 1.3 @@ -15,8 +15,6 @@ typedef int64_t s64; 1.4 #include <asm-x86/x86_emulate.h> 1.5 #include <sys/mman.h> 1.6 1.7 -#define PFEC_write_access (1U<<1) 1.8 - 1.9 static int read( 1.10 unsigned int seg, 1.11 unsigned long offset, 1.12 @@ -119,7 +117,6 @@ int main(int argc, char **argv) 1.13 regs.eflags = 0x200; 1.14 regs.eip = (unsigned long)&instr[0]; 1.15 regs.ecx = 0x12345678; 1.16 - regs.error_code = PFEC_write_access; 1.17 regs.eax = (unsigned long)res; 1.18 *res = 0x7FFFFFFF; 1.19 rc = x86_emulate_memop(&ctxt, &emulops); 1.20 @@ -130,6 +127,21 @@ int main(int argc, char **argv) 1.21 goto fail; 1.22 printf("okay\n"); 1.23 1.24 + printf("%-40s", "Testing addl %%ecx,%%eax..."); 1.25 + instr[0] = 0x01; instr[1] = 0xc8; 1.26 + regs.eflags = 0x200; 1.27 + regs.eip = (unsigned long)&instr[0]; 1.28 + regs.ecx = 0x12345678; 1.29 + regs.eax = 0x7FFFFFFF; 1.30 + rc = x86_emulate_memop(&ctxt, &emulops); 1.31 + if ( (rc != 0) || 1.32 + (regs.ecx != 0x12345678) || 1.33 + (regs.eax != 0x92345677) || 1.34 + (regs.eflags != 0xa94) || 1.35 + (regs.eip != (unsigned long)&instr[2]) ) 1.36 + goto fail; 1.37 + printf("okay\n"); 1.38 + 1.39 printf("%-40s", "Testing xorl (%%eax),%%ecx..."); 1.40 instr[0] = 0x33; instr[1] = 0x08; 1.41 regs.eflags = 0x200; 1.42 @@ -140,7 +152,6 @@ int main(int argc, char **argv) 1.43 regs.ecx = 0x12345678UL; 1.44 #endif 1.45 regs.eax = (unsigned long)res; 1.46 - regs.error_code = 0; 1.47 rc = x86_emulate_memop(&ctxt, &emulops); 1.48 if ( (rc != 0) || 1.49 (*res != 0x92345677) || 1.50 @@ -155,7 +166,6 @@ int main(int argc, char **argv) 1.51 regs.eip = (unsigned long)&instr[0]; 1.52 regs.ecx = ~0UL; 1.53 regs.eax = (unsigned long)res; 1.54 - regs.error_code = 0; 1.55 rc = x86_emulate_memop(&ctxt, &emulops); 1.56 if ( (rc != 0) || 1.57 (*res != 0x92345677) || 1.58 @@ -171,7 +181,6 @@ int main(int argc, char **argv) 1.59 regs.eax = 0x92345677UL; 1.60 regs.ecx = 0xAA; 1.61 regs.ebx = (unsigned long)res; 1.62 - regs.error_code = PFEC_write_access; 1.63 rc = x86_emulate_memop(&ctxt, &emulops); 1.64 if ( (rc != 0) || 1.65 (*res != 0x923456AA) || 1.66 @@ -188,7 +197,6 @@ int main(int argc, char **argv) 1.67 regs.eax = 0xAABBCC77UL; 1.68 regs.ecx = 0xFF; 1.69 regs.ebx = (unsigned long)res; 1.70 - regs.error_code = PFEC_write_access; 1.71 rc = x86_emulate_memop(&ctxt, &emulops); 1.72 if ( (rc != 0) || 1.73 (*res != 0x923456AA) || 1.74 @@ -205,7 +213,6 @@ int main(int argc, char **argv) 1.75 regs.eip = (unsigned long)&instr[0]; 1.76 regs.ecx = 0x12345678; 1.77 regs.eax = (unsigned long)res; 1.78 - regs.error_code = PFEC_write_access; 1.79 rc = x86_emulate_memop(&ctxt, &emulops); 1.80 if ( (rc != 0) || 1.81 (*res != 0x12345678) || 1.82 @@ -223,7 +230,6 @@ int main(int argc, char **argv) 1.83 regs.eax = 0x923456AAUL; 1.84 regs.ecx = 0xDDEEFF00L; 1.85 regs.ebx = (unsigned long)res; 1.86 - regs.error_code = PFEC_write_access; 1.87 rc = x86_emulate_memop(&ctxt, &emulops); 1.88 if ( (rc != 0) || 1.89 (*res != 0xDDEEFF00) || 1.90 @@ -241,7 +247,6 @@ int main(int argc, char **argv) 1.91 regs.eip = (unsigned long)&instr[0]; 1.92 regs.esi = (unsigned long)res + 0; 1.93 regs.edi = (unsigned long)res + 2; 1.94 - regs.error_code = 0; /* read fault */ 1.95 rc = x86_emulate_memop(&ctxt, &emulops); 1.96 if ( (rc != 0) || 1.97 (*res != 0x44554455) || 1.98 @@ -259,9 +264,8 @@ int main(int argc, char **argv) 1.99 regs.eflags = 0x200; 1.100 regs.eip = (unsigned long)&instr[0]; 1.101 regs.edi = (unsigned long)res; 1.102 - regs.error_code = PFEC_write_access; 1.103 rc = x86_emulate_memop(&ctxt, &emulops); 1.104 - if ( (rc != 0) || 1.105 + if ( (rc != 0) || 1.106 (*res != 0x2233445D) || 1.107 ((regs.eflags&0x201) != 0x201) || 1.108 (regs.eip != (unsigned long)&instr[4]) ) 1.109 @@ -275,9 +279,8 @@ int main(int argc, char **argv) 1.110 regs.eip = (unsigned long)&instr[0]; 1.111 regs.eax = -32; 1.112 regs.edi = (unsigned long)(res+1); 1.113 - regs.error_code = PFEC_write_access; 1.114 rc = x86_emulate_memop(&ctxt, &emulops); 1.115 - if ( (rc != 0) || 1.116 + if ( (rc != 0) || 1.117 (*res != 0x2233445E) || 1.118 ((regs.eflags&0x201) != 0x201) || 1.119 (regs.eip != (unsigned long)&instr[3]) ) 1.120 @@ -296,9 +299,8 @@ int main(int argc, char **argv) 1.121 regs.ecx = 0xCCCCFFFF; 1.122 regs.eip = (unsigned long)&instr[0]; 1.123 regs.edi = (unsigned long)res; 1.124 - regs.error_code = PFEC_write_access; 1.125 rc = x86_emulate_memop(&ctxt, &emulops); 1.126 - if ( (rc != 0) || 1.127 + if ( (rc != 0) || 1.128 (res[0] != 0x9999AAAA) || 1.129 (res[1] != 0xCCCCFFFF) || 1.130 ((regs.eflags&0x240) != 0x240) || 1.131 @@ -311,7 +313,6 @@ int main(int argc, char **argv) 1.132 regs.eflags = 0x200; 1.133 regs.eip = (unsigned long)&instr[0]; 1.134 regs.edi = (unsigned long)res; 1.135 - regs.error_code = PFEC_write_access; 1.136 rc = x86_emulate_memop(&ctxt, &emulops); 1.137 if ( (rc != 0) || 1.138 (res[0] != 0x9999AAAA) || 1.139 @@ -330,7 +331,6 @@ int main(int argc, char **argv) 1.140 regs.ecx = 0x12345678; 1.141 regs.eax = (unsigned long)res; 1.142 *res = 0x82; 1.143 - regs.error_code = 0; 1.144 rc = x86_emulate_memop(&ctxt, &emulops); 1.145 if ( (rc != 0) || 1.146 (*res != 0x82) || 1.147 @@ -347,7 +347,6 @@ int main(int argc, char **argv) 1.148 regs.ecx = 0x12345678; 1.149 regs.eax = (unsigned long)res; 1.150 *res = 0x1234aa82; 1.151 - regs.error_code = 0; 1.152 rc = x86_emulate_memop(&ctxt, &emulops); 1.153 if ( (rc != 0) || 1.154 (*res != 0x1234aa82) || 1.155 @@ -364,7 +363,6 @@ int main(int argc, char **argv) 1.156 regs.ecx = (unsigned long)res; 1.157 regs.eax = 0x12345678; 1.158 *res = 0x11111111; 1.159 - regs.error_code = 0; 1.160 rc = x86_emulate_memop(&ctxt, &emulops); 1.161 if ( (rc != 0) || 1.162 (*res != 0x11116789) ||
2.1 --- a/xen/arch/x86/x86_32/seg_fixup.c Wed Dec 20 13:54:04 2006 +0000 2.2 +++ b/xen/arch/x86/x86_32/seg_fixup.c Wed Dec 20 15:16:13 2006 +0000 2.3 @@ -268,7 +268,7 @@ int gpf_emulate_4gb(struct cpu_user_regs 2.4 struct trap_info *ti; 2.5 struct trap_bounce *tb; 2.6 u8 modrm, mod, reg, rm, decode; 2.7 - void *memreg, *regreg; 2.8 + void *memreg; 2.9 unsigned long offset; 2.10 u8 disp8; 2.11 u32 disp32 = 0; 2.12 @@ -384,8 +384,7 @@ int gpf_emulate_4gb(struct cpu_user_regs 2.13 goto fixme; 2.14 } 2.15 2.16 - /* Decode Reg and R/M fields. */ 2.17 - regreg = decode_register(reg, regs, 0); 2.18 + /* Decode R/M field. */ 2.19 memreg = decode_register(rm, regs, 0); 2.20 2.21 /* Decode Mod field. */
3.1 --- a/xen/arch/x86/x86_emulate.c Wed Dec 20 13:54:04 2006 +0000 3.2 +++ b/xen/arch/x86/x86_emulate.c Wed Dec 20 15:16:13 2006 +0000 3.3 @@ -192,11 +192,15 @@ struct operand { 3.4 enum { OP_REG, OP_MEM, OP_IMM } type; 3.5 unsigned int bytes; 3.6 unsigned long val, orig_val; 3.7 - /* OP_REG: Pointer to register field. */ 3.8 - unsigned long *reg; 3.9 - /* OP_MEM: Segment and offset. */ 3.10 - enum x86_segment mem_seg; 3.11 - unsigned long mem_off; 3.12 + union { 3.13 + /* OP_REG: Pointer to register field. */ 3.14 + unsigned long *reg; 3.15 + /* OP_MEM: Segment and offset. */ 3.16 + struct { 3.17 + enum x86_segment seg; 3.18 + unsigned long off; 3.19 + } mem; 3.20 + }; 3.21 }; 3.22 3.23 /* EFLAGS bit definitions. */ 3.24 @@ -451,8 +455,13 @@ x86_emulate_memop( 3.25 struct operand src, dst; 3.26 int mode = ctxt->mode; 3.27 3.28 - enum x86_segment ea_seg = x86_seg_ds; 3.29 - unsigned long ea_off = 0; 3.30 + /* Data operand effective address (usually computed from ModRM). */ 3.31 + struct operand ea; 3.32 + 3.33 + /* Default is a memory operand relative to segment DS. */ 3.34 + ea.type = OP_MEM; 3.35 + ea.mem.seg = x86_seg_ds; 3.36 + ea.mem.off = 0; 3.37 3.38 switch ( mode ) 3.39 { 3.40 @@ -488,22 +497,22 @@ x86_emulate_memop( 3.41 ad_bytes ^= 6; /* switch between 2/4 bytes */ 3.42 break; 3.43 case 0x2e: /* CS override */ 3.44 - ea_seg = x86_seg_cs; 3.45 + ea.mem.seg = x86_seg_cs; 3.46 break; 3.47 case 0x3e: /* DS override */ 3.48 - ea_seg = x86_seg_ds; 3.49 + ea.mem.seg = x86_seg_ds; 3.50 break; 3.51 case 0x26: /* ES override */ 3.52 - ea_seg = x86_seg_es; 3.53 + ea.mem.seg = x86_seg_es; 3.54 break; 3.55 case 0x64: /* FS override */ 3.56 - ea_seg = x86_seg_fs; 3.57 + ea.mem.seg = x86_seg_fs; 3.58 break; 3.59 case 0x65: /* GS override */ 3.60 - ea_seg = x86_seg_gs; 3.61 + ea.mem.seg = x86_seg_gs; 3.62 break; 3.63 case 0x36: /* SS override */ 3.64 - ea_seg = x86_seg_ss; 3.65 + ea.mem.seg = x86_seg_ss; 3.66 break; 3.67 case 0xf0: /* LOCK */ 3.68 lock_prefix = 1; 3.69 @@ -554,35 +563,39 @@ x86_emulate_memop( 3.70 modrm_rm = modrm & 0x07; 3.71 3.72 if ( modrm_mod == 3 ) 3.73 - goto cannot_emulate; 3.74 - 3.75 - if ( ad_bytes == 2 ) 3.76 + { 3.77 + ea.type = OP_REG; 3.78 + ea.reg = decode_register( 3.79 + modrm_rm, &_regs, (d & ByteOp) && (rex_prefix == 0)); 3.80 + } 3.81 + else if ( ad_bytes == 2 ) 3.82 { 3.83 /* 16-bit ModR/M decode. */ 3.84 switch ( modrm_rm ) 3.85 { 3.86 - case 0: ea_off = _regs.ebx + _regs.esi; break; 3.87 - case 1: ea_off = _regs.ebx + _regs.edi; break; 3.88 - case 2: ea_off = _regs.ebp + _regs.esi; break; 3.89 - case 3: ea_off = _regs.ebp + _regs.edi; break; 3.90 - case 4: ea_off = _regs.esi; break; 3.91 - case 5: ea_off = _regs.edi; break; 3.92 - case 6: ea_off = _regs.ebp; break; 3.93 - case 7: ea_off = _regs.ebx; break; 3.94 + case 0: ea.mem.off = _regs.ebx + _regs.esi; break; 3.95 + case 1: ea.mem.off = _regs.ebx + _regs.edi; break; 3.96 + case 2: ea.mem.off = _regs.ebp + _regs.esi; break; 3.97 + case 3: ea.mem.off = _regs.ebp + _regs.edi; break; 3.98 + case 4: ea.mem.off = _regs.esi; break; 3.99 + case 5: ea.mem.off = _regs.edi; break; 3.100 + case 6: ea.mem.off = _regs.ebp; break; 3.101 + case 7: ea.mem.off = _regs.ebx; break; 3.102 } 3.103 switch ( modrm_mod ) 3.104 { 3.105 case 0: 3.106 if ( modrm_rm == 6 ) 3.107 - ea_off = insn_fetch_type(int16_t); 3.108 + ea.mem.off = insn_fetch_type(int16_t); 3.109 break; 3.110 case 1: 3.111 - ea_off += insn_fetch_type(int8_t); 3.112 + ea.mem.off += insn_fetch_type(int8_t); 3.113 break; 3.114 case 2: 3.115 - ea_off += insn_fetch_type(int16_t); 3.116 + ea.mem.off += insn_fetch_type(int16_t); 3.117 break; 3.118 } 3.119 + ea.mem.off = truncate_ea(ea.mem.off); 3.120 } 3.121 else 3.122 { 3.123 @@ -593,49 +606,48 @@ x86_emulate_memop( 3.124 sib_index = ((sib >> 3) & 7) | ((rex_prefix << 2) & 8); 3.125 sib_base = (sib & 7) | ((rex_prefix << 3) & 8); 3.126 if ( sib_index != 4 ) 3.127 - ea_off = *(long *)decode_register(sib_index, &_regs, 0); 3.128 - ea_off <<= (sib >> 6) & 3; 3.129 + ea.mem.off = *(long*)decode_register(sib_index, &_regs, 0); 3.130 + ea.mem.off <<= (sib >> 6) & 3; 3.131 if ( (modrm_mod == 0) && ((sib_base & 7) == 5) ) 3.132 - ea_off += insn_fetch_type(int32_t); 3.133 + ea.mem.off += insn_fetch_type(int32_t); 3.134 else 3.135 - ea_off += *(long *)decode_register(sib_base, &_regs, 0); 3.136 + ea.mem.off += *(long*)decode_register(sib_base, &_regs, 0); 3.137 } 3.138 else 3.139 { 3.140 modrm_rm |= (rex_prefix & 1) << 3; 3.141 - ea_off = *(long *)decode_register(modrm_rm, &_regs, 0); 3.142 + ea.mem.off = *(long *)decode_register(modrm_rm, &_regs, 0); 3.143 } 3.144 switch ( modrm_mod ) 3.145 { 3.146 case 0: 3.147 if ( (modrm_rm & 7) != 5 ) 3.148 break; 3.149 - ea_off = insn_fetch_type(int32_t); 3.150 + ea.mem.off = insn_fetch_type(int32_t); 3.151 if ( mode != X86EMUL_MODE_PROT64 ) 3.152 break; 3.153 /* Relative to RIP of next instruction. Argh! */ 3.154 - ea_off += _regs.eip; 3.155 + ea.mem.off += _regs.eip; 3.156 if ( (d & SrcMask) == SrcImm ) 3.157 - ea_off += (d & ByteOp) ? 1 : 3.158 + ea.mem.off += (d & ByteOp) ? 1 : 3.159 ((op_bytes == 8) ? 4 : op_bytes); 3.160 else if ( (d & SrcMask) == SrcImmByte ) 3.161 - ea_off += 1; 3.162 + ea.mem.off += 1; 3.163 else if ( ((b == 0xf6) || (b == 0xf7)) && 3.164 ((modrm_reg & 7) <= 1) ) 3.165 /* Special case in Grp3: test has immediate operand. */ 3.166 - ea_off += (d & ByteOp) ? 1 3.167 + ea.mem.off += (d & ByteOp) ? 1 3.168 : ((op_bytes == 8) ? 4 : op_bytes); 3.169 break; 3.170 case 1: 3.171 - ea_off += insn_fetch_type(int8_t); 3.172 + ea.mem.off += insn_fetch_type(int8_t); 3.173 break; 3.174 case 2: 3.175 - ea_off += insn_fetch_type(int32_t); 3.176 + ea.mem.off += insn_fetch_type(int32_t); 3.177 break; 3.178 } 3.179 + ea.mem.off = truncate_ea(ea.mem.off); 3.180 } 3.181 - 3.182 - ea_off = truncate_ea(ea_off); 3.183 } 3.184 3.185 /* Special instructions do their own operand decoding. */ 3.186 @@ -652,7 +664,7 @@ x86_emulate_memop( 3.187 if ( d & ByteOp ) 3.188 { 3.189 src.reg = decode_register(modrm_reg, &_regs, (rex_prefix == 0)); 3.190 - src.val = src.orig_val = *(uint8_t *)src.reg; 3.191 + src.val = *(uint8_t *)src.reg; 3.192 src.bytes = 1; 3.193 } 3.194 else 3.195 @@ -660,28 +672,35 @@ x86_emulate_memop( 3.196 src.reg = decode_register(modrm_reg, &_regs, 0); 3.197 switch ( (src.bytes = op_bytes) ) 3.198 { 3.199 - case 2: src.val = src.orig_val = *(uint16_t *)src.reg; break; 3.200 - case 4: src.val = src.orig_val = *(uint32_t *)src.reg; break; 3.201 - case 8: src.val = src.orig_val = *(uint64_t *)src.reg; break; 3.202 + case 2: src.val = *(uint16_t *)src.reg; break; 3.203 + case 4: src.val = *(uint32_t *)src.reg; break; 3.204 + case 8: src.val = *(uint64_t *)src.reg; break; 3.205 } 3.206 } 3.207 break; 3.208 case SrcMem16: 3.209 - src.bytes = 2; 3.210 + ea.bytes = 2; 3.211 goto srcmem_common; 3.212 case SrcMem32: 3.213 - src.bytes = 4; 3.214 + ea.bytes = 4; 3.215 goto srcmem_common; 3.216 case SrcMem: 3.217 - src.bytes = (d & ByteOp) ? 1 : op_bytes; 3.218 + ea.bytes = (d & ByteOp) ? 1 : op_bytes; 3.219 srcmem_common: 3.220 - src.type = OP_MEM; 3.221 - src.mem_seg = ea_seg; 3.222 - src.mem_off = ea_off; 3.223 - if ( (rc = ops->read(src.mem_seg, src.mem_off, 3.224 - &src.val, src.bytes, ctxt)) != 0 ) 3.225 + src = ea; 3.226 + if ( src.type == OP_REG ) 3.227 + { 3.228 + switch ( src.bytes ) 3.229 + { 3.230 + case 1: src.val = *(uint8_t *)src.reg; break; 3.231 + case 2: src.val = *(uint16_t *)src.reg; break; 3.232 + case 4: src.val = *(uint32_t *)src.reg; break; 3.233 + case 8: src.val = *(uint64_t *)src.reg; break; 3.234 + } 3.235 + } 3.236 + else if ( (rc = ops->read(src.mem.seg, src.mem.off, 3.237 + &src.val, src.bytes, ctxt)) ) 3.238 goto done; 3.239 - src.orig_val = src.val; 3.240 break; 3.241 case SrcImm: 3.242 src.type = OP_IMM; 3.243 @@ -725,8 +744,7 @@ x86_emulate_memop( 3.244 } 3.245 break; 3.246 case DstBitBase: 3.247 - dst.mem_off = ea_off; 3.248 - if ( (d & SrcMask) == SrcImmByte ) 3.249 + if ( ((d & SrcMask) == SrcImmByte) || (ea.type == OP_REG) ) 3.250 { 3.251 src.val &= (op_bytes << 3) - 1; 3.252 } 3.253 @@ -746,28 +764,34 @@ x86_emulate_memop( 3.254 { 3.255 unsigned long byte_offset; 3.256 byte_offset = op_bytes + (((-src.val-1) >> 3) & ~(op_bytes-1)); 3.257 - dst.mem_off -= byte_offset; 3.258 + ea.mem.off -= byte_offset; 3.259 src.val = (byte_offset << 3) + src.val; 3.260 } 3.261 else 3.262 { 3.263 - dst.mem_off += (src.val >> 3) & ~(op_bytes - 1); 3.264 + ea.mem.off += (src.val >> 3) & ~(op_bytes - 1); 3.265 src.val &= (op_bytes << 3) - 1; 3.266 } 3.267 } 3.268 /* Becomes a normal DstMem operation from here on. */ 3.269 d = (d & ~DstMask) | DstMem; 3.270 - goto dstmem_common; 3.271 case DstMem: 3.272 - dst.mem_off = ea_off; 3.273 - dstmem_common: 3.274 - dst.mem_seg = ea_seg; 3.275 - dst.type = OP_MEM; 3.276 - dst.bytes = (d & ByteOp) ? 1 : op_bytes; 3.277 - if ( !(d & Mov) && /* optimisation - avoid slow emulated read */ 3.278 - ((rc = ops->read(dst.mem_seg, dst.mem_off, 3.279 - &dst.val, dst.bytes, ctxt)) != 0) ) 3.280 - goto done; 3.281 + ea.bytes = (d & ByteOp) ? 1 : op_bytes; 3.282 + dst = ea; 3.283 + if ( dst.type == OP_REG ) 3.284 + { 3.285 + switch ( dst.bytes ) 3.286 + { 3.287 + case 1: dst.val = *(uint8_t *)dst.reg; break; 3.288 + case 2: dst.val = *(uint16_t *)dst.reg; break; 3.289 + case 4: dst.val = *(uint32_t *)dst.reg; break; 3.290 + case 8: dst.val = *(uint64_t *)dst.reg; break; 3.291 + } 3.292 + } 3.293 + else if ( !(d & Mov) && /* optimisation - avoid slow emulated read */ 3.294 + (rc = ops->read(dst.mem.seg, dst.mem.off, 3.295 + &dst.val, dst.bytes, ctxt)) ) 3.296 + goto done; 3.297 break; 3.298 } 3.299 dst.orig_val = dst.val; 3.300 @@ -920,7 +944,7 @@ x86_emulate_memop( 3.301 if ( mode == X86EMUL_MODE_PROT64 ) 3.302 { 3.303 dst.bytes = 8; 3.304 - if ( (rc = ops->read(dst.mem_seg, dst.mem_off, 3.305 + if ( (rc = ops->read(dst.mem.seg, dst.mem.off, 3.306 &dst.val, 8, ctxt)) != 0 ) 3.307 goto done; 3.308 } 3.309 @@ -954,11 +978,11 @@ x86_emulate_memop( 3.310 case OP_MEM: 3.311 if ( lock_prefix ) 3.312 rc = ops->cmpxchg( 3.313 - dst.mem_seg, dst.mem_off, dst.orig_val, 3.314 + dst.mem.seg, dst.mem.off, dst.orig_val, 3.315 dst.val, dst.bytes, ctxt); 3.316 else 3.317 rc = ops->write( 3.318 - dst.mem_seg, dst.mem_off, dst.val, dst.bytes, ctxt); 3.319 + dst.mem.seg, dst.mem.off, dst.val, dst.bytes, ctxt); 3.320 if ( rc != 0 ) 3.321 goto done; 3.322 default: 3.323 @@ -987,29 +1011,29 @@ x86_emulate_memop( 3.324 } 3.325 switch ( b ) 3.326 { 3.327 - case 0xa0 ... 0xa1: /* mov moffs,{%al,%ax,%eax,%rax} */ 3.328 + case 0xa0 ... 0xa1: /* mov mem.offs,{%al,%ax,%eax,%rax} */ 3.329 /* Source EA is not encoded via ModRM. */ 3.330 dst.type = OP_REG; 3.331 dst.reg = (unsigned long *)&_regs.eax; 3.332 dst.bytes = (d & ByteOp) ? 1 : op_bytes; 3.333 - if ( (rc = ops->read(ea_seg, insn_fetch_bytes(ad_bytes), 3.334 + if ( (rc = ops->read(ea.mem.seg, insn_fetch_bytes(ad_bytes), 3.335 &dst.val, dst.bytes, ctxt)) != 0 ) 3.336 goto done; 3.337 break; 3.338 - case 0xa2 ... 0xa3: /* mov {%al,%ax,%eax,%rax},moffs */ 3.339 + case 0xa2 ... 0xa3: /* mov {%al,%ax,%eax,%rax},mem.offs */ 3.340 /* Destination EA is not encoded via ModRM. */ 3.341 - dst.type = OP_MEM; 3.342 - dst.mem_seg = ea_seg; 3.343 - dst.mem_off = insn_fetch_bytes(ad_bytes); 3.344 - dst.bytes = (d & ByteOp) ? 1 : op_bytes; 3.345 - dst.val = (unsigned long)_regs.eax; 3.346 + dst.type = OP_MEM; 3.347 + dst.mem.seg = ea.mem.seg; 3.348 + dst.mem.off = insn_fetch_bytes(ad_bytes); 3.349 + dst.bytes = (d & ByteOp) ? 1 : op_bytes; 3.350 + dst.val = (unsigned long)_regs.eax; 3.351 break; 3.352 case 0xa4 ... 0xa5: /* movs */ 3.353 dst.type = OP_MEM; 3.354 dst.bytes = (d & ByteOp) ? 1 : op_bytes; 3.355 - dst.mem_seg = x86_seg_es; 3.356 - dst.mem_off = truncate_ea(_regs.edi); 3.357 - if ( (rc = ops->read(ea_seg, truncate_ea(_regs.esi), 3.358 + dst.mem.seg = x86_seg_es; 3.359 + dst.mem.off = truncate_ea(_regs.edi); 3.360 + if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi), 3.361 &dst.val, dst.bytes, ctxt)) != 0 ) 3.362 goto done; 3.363 register_address_increment( 3.364 @@ -1020,8 +1044,8 @@ x86_emulate_memop( 3.365 case 0xaa ... 0xab: /* stos */ 3.366 dst.type = OP_MEM; 3.367 dst.bytes = (d & ByteOp) ? 1 : op_bytes; 3.368 - dst.mem_seg = x86_seg_es; 3.369 - dst.mem_off = truncate_ea(_regs.edi); 3.370 + dst.mem.seg = x86_seg_es; 3.371 + dst.mem.off = truncate_ea(_regs.edi); 3.372 dst.val = _regs.eax; 3.373 register_address_increment( 3.374 _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); 3.375 @@ -1030,7 +1054,7 @@ x86_emulate_memop( 3.376 dst.type = OP_REG; 3.377 dst.bytes = (d & ByteOp) ? 1 : op_bytes; 3.378 dst.reg = (unsigned long *)&_regs.eax; 3.379 - if ( (rc = ops->read(ea_seg, truncate_ea(_regs.esi), 3.380 + if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi), 3.381 &dst.val, dst.bytes, ctxt)) != 0 ) 3.382 goto done; 3.383 register_address_increment( 3.384 @@ -1105,9 +1129,14 @@ x86_emulate_memop( 3.385 case 0xab: bts: /* bts */ 3.386 emulate_2op_SrcV_nobyte("bts", src, dst, _regs.eflags); 3.387 break; 3.388 - case 0xb6 ... 0xb7: /* movzx */ 3.389 + case 0xb6: /* movzx rm8,r{16,32,64} */ 3.390 + /* Recompute DstReg as we may have decoded AH/BH/CH/DH. */ 3.391 + dst.reg = decode_register(modrm_reg, &_regs, 0); 3.392 dst.bytes = op_bytes; 3.393 - dst.val = (d & ByteOp) ? (uint8_t)src.val : (uint16_t)src.val; 3.394 + dst.val = (uint8_t)src.val; 3.395 + break; 3.396 + case 0xb7: /* movzx rm16,r{16,32,64} */ 3.397 + dst.val = (uint16_t)src.val; 3.398 break; 3.399 case 0xbb: btc: /* btc */ 3.400 emulate_2op_SrcV_nobyte("btc", src, dst, _regs.eflags); 3.401 @@ -1121,9 +1150,14 @@ x86_emulate_memop( 3.402 case 3: goto btc; 3.403 } 3.404 break; 3.405 - case 0xbe ... 0xbf: /* movsx */ 3.406 + case 0xbe: /* movsx rm8,r{16,32,64} */ 3.407 + /* Recompute DstReg as we may have decoded AH/BH/CH/DH. */ 3.408 + dst.reg = decode_register(modrm_reg, &_regs, 0); 3.409 dst.bytes = op_bytes; 3.410 - dst.val = (d & ByteOp) ? (int8_t)src.val : (int16_t)src.val; 3.411 + dst.val = (int8_t)src.val; 3.412 + break; 3.413 + case 0xbf: /* movsx rm16,r{16,32,64} */ 3.414 + dst.val = (int16_t)src.val; 3.415 break; 3.416 case 0xc0 ... 0xc1: /* xadd */ 3.417 /* Write back the register source. */ 3.418 @@ -1150,8 +1184,8 @@ x86_emulate_memop( 3.419 #if defined(__i386__) 3.420 { 3.421 unsigned long old_lo, old_hi; 3.422 - if ( ((rc = ops->read(ea_seg, ea_off+0, &old_lo, 4, ctxt)) != 0) || 3.423 - ((rc = ops->read(ea_seg, ea_off+4, &old_hi, 4, ctxt)) != 0) ) 3.424 + if ( (rc = ops->read(ea.mem.seg, ea.mem.off+0, &old_lo, 4, ctxt)) || 3.425 + (rc = ops->read(ea.mem.seg, ea.mem.off+4, &old_hi, 4, ctxt)) ) 3.426 goto done; 3.427 if ( (old_lo != _regs.eax) || (old_hi != _regs.edx) ) 3.428 { 3.429 @@ -1166,7 +1200,7 @@ x86_emulate_memop( 3.430 } 3.431 else 3.432 { 3.433 - if ( (rc = ops->cmpxchg8b(ea_seg, ea_off, old_lo, old_hi, 3.434 + if ( (rc = ops->cmpxchg8b(ea.mem.seg, ea.mem.off, old_lo, old_hi, 3.435 _regs.ebx, _regs.ecx, ctxt)) != 0 ) 3.436 goto done; 3.437 _regs.eflags |= EFLG_ZF; 3.438 @@ -1176,7 +1210,7 @@ x86_emulate_memop( 3.439 #elif defined(__x86_64__) 3.440 { 3.441 unsigned long old, new; 3.442 - if ( (rc = ops->read(ea_seg, ea_off, &old, 8, ctxt)) != 0 ) 3.443 + if ( (rc = ops->read(ea.mem.seg, ea.mem.off, &old, 8, ctxt)) != 0 ) 3.444 goto done; 3.445 if ( ((uint32_t)(old>>0) != (uint32_t)_regs.eax) || 3.446 ((uint32_t)(old>>32) != (uint32_t)_regs.edx) ) 3.447 @@ -1188,7 +1222,8 @@ x86_emulate_memop( 3.448 else 3.449 { 3.450 new = (_regs.ecx<<32)|(uint32_t)_regs.ebx; 3.451 - if ( (rc = ops->cmpxchg(ea_seg, ea_off, old, new, 8, ctxt)) != 0 ) 3.452 + if ( (rc = ops->cmpxchg(ea.mem.seg, ea.mem.off, old, 3.453 + new, 8, ctxt)) != 0 ) 3.454 goto done; 3.455 _regs.eflags |= EFLG_ZF; 3.456 } 3.457 @@ -1201,10 +1236,10 @@ x86_emulate_memop( 3.458 cannot_emulate: 3.459 #ifdef __XEN__ 3.460 gdprintk(XENLOG_DEBUG, "Instr:"); 3.461 - for ( ea_off = ctxt->regs->eip; ea_off < _regs.eip; ea_off++ ) 3.462 + for ( ea.mem.off = ctxt->regs->eip; ea.mem.off < _regs.eip; ea.mem.off++ ) 3.463 { 3.464 unsigned long x; 3.465 - ops->insn_fetch(x86_seg_cs, ea_off, &x, 1, ctxt); 3.466 + ops->insn_fetch(x86_seg_cs, ea.mem.off, &x, 1, ctxt); 3.467 printk(" %02x", (uint8_t)x); 3.468 } 3.469 printk("\n");