ia64/xen-unstable
changeset 12746:43c8cb5a895c
[XEN] Emulate XADD instruction.
Signed-off-by: Keir Fraser <keir@xensource.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kfraser@localhost.localdomain |
---|---|
date | Fri Dec 01 13:57:46 2006 +0000 (2006-12-01) |
parents | ef1dadde3631 |
children | f7b7daed94d6 |
files | tools/tests/test_x86_emulator.c xen/arch/x86/x86_emulate.c |
line diff
1.1 --- a/tools/tests/test_x86_emulator.c Fri Dec 01 13:55:28 2006 +0000 1.2 +++ b/tools/tests/test_x86_emulator.c Fri Dec 01 13:57:46 2006 +0000 1.3 @@ -304,6 +304,7 @@ int main(int argc, char **argv) 1.4 1.5 printf("%-40s", "Testing cmpxchg8b (%edi) [failing]..."); 1.6 instr[0] = 0x0f; instr[1] = 0xc7; instr[2] = 0x0f; 1.7 + regs.eflags = 0x200; 1.8 regs.eip = (unsigned long)&instr[0]; 1.9 regs.edi = (unsigned long)res; 1.10 regs.error_code = PFEC_write_access; 1.11 @@ -320,6 +321,7 @@ int main(int argc, char **argv) 1.12 1.13 printf("%-40s", "Testing movsxbd (%%eax),%%ecx..."); 1.14 instr[0] = 0x0f; instr[1] = 0xbe; instr[2] = 0x08; 1.15 + regs.eflags = 0x200; 1.16 regs.eip = (unsigned long)&instr[0]; 1.17 regs.ecx = 0x12345678; 1.18 regs.eax = (unsigned long)res; 1.19 @@ -336,6 +338,7 @@ int main(int argc, char **argv) 1.20 1.21 printf("%-40s", "Testing movzxwd (%%eax),%%ecx..."); 1.22 instr[0] = 0x0f; instr[1] = 0xb7; instr[2] = 0x08; 1.23 + regs.eflags = 0x200; 1.24 regs.eip = (unsigned long)&instr[0]; 1.25 regs.ecx = 0x12345678; 1.26 regs.eax = (unsigned long)res; 1.27 @@ -350,6 +353,23 @@ int main(int argc, char **argv) 1.28 goto fail; 1.29 printf("okay\n"); 1.30 1.31 + printf("%-40s", "Testing xadd %%ax,(%%ecx)..."); 1.32 + instr[0] = 0x66; instr[1] = 0x0f; instr[2] = 0xc1; instr[3] = 0x01; 1.33 + regs.eflags = 0x200; 1.34 + regs.eip = (unsigned long)&instr[0]; 1.35 + regs.ecx = (unsigned long)res; 1.36 + regs.eax = 0x12345678; 1.37 + *res = 0x11111111; 1.38 + regs.error_code = 0; 1.39 + rc = x86_emulate_memop(&ctxt, &emulops); 1.40 + if ( (rc != 0) || 1.41 + (*res != 0x11116789) || 1.42 + (regs.eax != 0x12341111) || 1.43 + ((regs.eflags&0x240) != 0x200) || 1.44 + (regs.eip != (unsigned long)&instr[4]) ) 1.45 + goto fail; 1.46 + printf("okay\n"); 1.47 + 1.48 return 0; 1.49 1.50 fail:
2.1 --- a/xen/arch/x86/x86_emulate.c Fri Dec 01 13:55:28 2006 +0000 2.2 +++ b/xen/arch/x86/x86_emulate.c Fri Dec 01 13:57:46 2006 +0000 2.3 @@ -179,8 +179,11 @@ static uint8_t twobyte_table[256] = { 2.4 /* 0xB8 - 0xBF */ 2.5 0, 0, DstBitBase|SrcImmByte|ModRM, DstBitBase|SrcReg|ModRM, 2.6 0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov, 2.7 - /* 0xC0 - 0xCF */ 2.8 - 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, 0, 0, 0, 0, 0, 0, 2.9 + /* 0xC0 - 0xC7 */ 2.10 + ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, 0, 0, 2.11 + 0, 0, 0, ImplicitOps|ModRM, 2.12 + /* 0xC8 - 0xCF */ 2.13 + 0, 0, 0, 0, 0, 0, 0, 0, 2.14 /* 0xD0 - 0xDF */ 2.15 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.16 /* 0xE0 - 0xEF */ 2.17 @@ -1116,6 +1119,16 @@ x86_emulate_memop( 2.18 dst.bytes = op_bytes; 2.19 dst.val = (d & ByteOp) ? (int8_t)src.val : (int16_t)src.val; 2.20 break; 2.21 + case 0xc0 ... 0xc1: /* xadd */ 2.22 + /* Write back the register source. */ 2.23 + switch ( dst.bytes ) 2.24 + { 2.25 + case 1: *(uint8_t *)src.reg = (uint8_t)dst.val; break; 2.26 + case 2: *(uint16_t *)src.reg = (uint16_t)dst.val; break; 2.27 + case 4: *src.reg = (uint32_t)dst.val; break; /* 64b reg: zero-extend */ 2.28 + case 8: *src.reg = dst.val; break; 2.29 + } 2.30 + goto add; 2.31 } 2.32 goto writeback; 2.33