xref: /kvm-unit-tests/x86/emulator.c (revision 7d36db351752e29ad27eaafe3f102de7064e429b)
1*7d36db35SAvi Kivity #include "ioram.h"
2*7d36db35SAvi Kivity #include "vm.h"
3*7d36db35SAvi Kivity #include "libcflat.h"
4*7d36db35SAvi Kivity 
5*7d36db35SAvi Kivity #define memset __builtin_memset
6*7d36db35SAvi Kivity #define TESTDEV_IO_PORT 0xe0
7*7d36db35SAvi Kivity 
8*7d36db35SAvi Kivity int fails, tests;
9*7d36db35SAvi Kivity 
10*7d36db35SAvi Kivity void report(const char *name, int result)
11*7d36db35SAvi Kivity {
12*7d36db35SAvi Kivity 	++tests;
13*7d36db35SAvi Kivity 	if (result)
14*7d36db35SAvi Kivity 		printf("PASS: %s\n", name);
15*7d36db35SAvi Kivity 	else {
16*7d36db35SAvi Kivity 		printf("FAIL: %s\n", name);
17*7d36db35SAvi Kivity 		++fails;
18*7d36db35SAvi Kivity 	}
19*7d36db35SAvi Kivity }
20*7d36db35SAvi Kivity 
21*7d36db35SAvi Kivity static char st1[] = "abcdefghijklmnop";
22*7d36db35SAvi Kivity 
23*7d36db35SAvi Kivity void test_stringio()
24*7d36db35SAvi Kivity {
25*7d36db35SAvi Kivity 	unsigned char r = 0;
26*7d36db35SAvi Kivity 	asm volatile("cld \n\t"
27*7d36db35SAvi Kivity 		     "movw %0, %%dx \n\t"
28*7d36db35SAvi Kivity 		     "rep outsb \n\t"
29*7d36db35SAvi Kivity 		     : : "i"((short)TESTDEV_IO_PORT),
30*7d36db35SAvi Kivity 		       "S"(st1), "c"(sizeof(st1) - 1));
31*7d36db35SAvi Kivity 	asm volatile("inb %1, %0\n\t" : "=a"(r) : "i"((short)TESTDEV_IO_PORT));
32*7d36db35SAvi Kivity 	report("outsb up", r == st1[sizeof(st1) - 2]); /* last char */
33*7d36db35SAvi Kivity 
34*7d36db35SAvi Kivity 	asm volatile("std \n\t"
35*7d36db35SAvi Kivity 		     "movw %0, %%dx \n\t"
36*7d36db35SAvi Kivity 		     "rep outsb \n\t"
37*7d36db35SAvi Kivity 		     : : "i"((short)TESTDEV_IO_PORT),
38*7d36db35SAvi Kivity 		       "S"(st1 + sizeof(st1) - 2), "c"(sizeof(st1) - 1));
39*7d36db35SAvi Kivity 	asm volatile("cld \n\t" : : );
40*7d36db35SAvi Kivity 	asm volatile("in %1, %0\n\t" : "=a"(r) : "i"((short)TESTDEV_IO_PORT));
41*7d36db35SAvi Kivity 	report("outsb down", r == st1[0]);
42*7d36db35SAvi Kivity }
43*7d36db35SAvi Kivity 
44*7d36db35SAvi Kivity void test_cmps_one(unsigned char *m1, unsigned char *m3)
45*7d36db35SAvi Kivity {
46*7d36db35SAvi Kivity 	void *rsi, *rdi;
47*7d36db35SAvi Kivity 	long rcx, tmp;
48*7d36db35SAvi Kivity 
49*7d36db35SAvi Kivity 	rsi = m1; rdi = m3; rcx = 30;
50*7d36db35SAvi Kivity 	asm volatile("xor %[tmp], %[tmp] \n\t"
51*7d36db35SAvi Kivity 		     "repe/cmpsb"
52*7d36db35SAvi Kivity 		     : "+S"(rsi), "+D"(rdi), "+c"(rcx), [tmp]"=&r"(tmp)
53*7d36db35SAvi Kivity 		     : : "cc");
54*7d36db35SAvi Kivity 	report("repe/cmpsb (1)", rcx == 0 && rsi == m1 + 30 && rdi == m3 + 30);
55*7d36db35SAvi Kivity 
56*7d36db35SAvi Kivity 	rsi = m1; rdi = m3; rcx = 15;
57*7d36db35SAvi Kivity 	asm volatile("xor %[tmp], %[tmp] \n\t"
58*7d36db35SAvi Kivity 		     "repe/cmpsw"
59*7d36db35SAvi Kivity 		     : "+S"(rsi), "+D"(rdi), "+c"(rcx), [tmp]"=&r"(tmp)
60*7d36db35SAvi Kivity 		     : : "cc");
61*7d36db35SAvi Kivity 	report("repe/cmpsw (1)", rcx == 0 && rsi == m1 + 30 && rdi == m3 + 30);
62*7d36db35SAvi Kivity 
63*7d36db35SAvi Kivity 	rsi = m1; rdi = m3; rcx = 7;
64*7d36db35SAvi Kivity 	asm volatile("xor %[tmp], %[tmp] \n\t"
65*7d36db35SAvi Kivity 		     "repe/cmpsl"
66*7d36db35SAvi Kivity 		     : "+S"(rsi), "+D"(rdi), "+c"(rcx), [tmp]"=&r"(tmp)
67*7d36db35SAvi Kivity 		     : : "cc");
68*7d36db35SAvi Kivity 	report("repe/cmpll (1)", rcx == 0 && rsi == m1 + 28 && rdi == m3 + 28);
69*7d36db35SAvi Kivity 
70*7d36db35SAvi Kivity 	rsi = m1; rdi = m3; rcx = 4;
71*7d36db35SAvi Kivity 	asm volatile("xor %[tmp], %[tmp] \n\t"
72*7d36db35SAvi Kivity 		     "repe/cmpsq"
73*7d36db35SAvi Kivity 		     : "+S"(rsi), "+D"(rdi), "+c"(rcx), [tmp]"=&r"(tmp)
74*7d36db35SAvi Kivity 		     : : "cc");
75*7d36db35SAvi Kivity 	report("repe/cmpsq (1)", rcx == 0 && rsi == m1 + 32 && rdi == m3 + 32);
76*7d36db35SAvi Kivity 
77*7d36db35SAvi Kivity 	rsi = m1; rdi = m3; rcx = 130;
78*7d36db35SAvi Kivity 	asm volatile("xor %[tmp], %[tmp] \n\t"
79*7d36db35SAvi Kivity 		     "repe/cmpsb"
80*7d36db35SAvi Kivity 		     : "+S"(rsi), "+D"(rdi), "+c"(rcx), [tmp]"=&r"(tmp)
81*7d36db35SAvi Kivity 		     : : "cc");
82*7d36db35SAvi Kivity 	report("repe/cmpsb (2)",
83*7d36db35SAvi Kivity 	       rcx == 29 && rsi == m1 + 101 && rdi == m3 + 101);
84*7d36db35SAvi Kivity 
85*7d36db35SAvi Kivity 	rsi = m1; rdi = m3; rcx = 65;
86*7d36db35SAvi Kivity 	asm volatile("xor %[tmp], %[tmp] \n\t"
87*7d36db35SAvi Kivity 		     "repe/cmpsw"
88*7d36db35SAvi Kivity 		     : "+S"(rsi), "+D"(rdi), "+c"(rcx), [tmp]"=&r"(tmp)
89*7d36db35SAvi Kivity 		     : : "cc");
90*7d36db35SAvi Kivity 	report("repe/cmpsw (2)",
91*7d36db35SAvi Kivity 	       rcx == 14 && rsi == m1 + 102 && rdi == m3 + 102);
92*7d36db35SAvi Kivity 
93*7d36db35SAvi Kivity 	rsi = m1; rdi = m3; rcx = 32;
94*7d36db35SAvi Kivity 	asm volatile("xor %[tmp], %[tmp] \n\t"
95*7d36db35SAvi Kivity 		     "repe/cmpsl"
96*7d36db35SAvi Kivity 		     : "+S"(rsi), "+D"(rdi), "+c"(rcx), [tmp]"=&r"(tmp)
97*7d36db35SAvi Kivity 		     : : "cc");
98*7d36db35SAvi Kivity 	report("repe/cmpll (2)",
99*7d36db35SAvi Kivity 	       rcx == 6 && rsi == m1 + 104 && rdi == m3 + 104);
100*7d36db35SAvi Kivity 
101*7d36db35SAvi Kivity 	rsi = m1; rdi = m3; rcx = 16;
102*7d36db35SAvi Kivity 	asm volatile("xor %[tmp], %[tmp] \n\t"
103*7d36db35SAvi Kivity 		     "repe/cmpsq"
104*7d36db35SAvi Kivity 		     : "+S"(rsi), "+D"(rdi), "+c"(rcx), [tmp]"=&r"(tmp)
105*7d36db35SAvi Kivity 		     : : "cc");
106*7d36db35SAvi Kivity 	report("repe/cmpsq (2)",
107*7d36db35SAvi Kivity 	       rcx == 3 && rsi == m1 + 104 && rdi == m3 + 104);
108*7d36db35SAvi Kivity 
109*7d36db35SAvi Kivity }
110*7d36db35SAvi Kivity 
111*7d36db35SAvi Kivity void test_cmps(void *mem)
112*7d36db35SAvi Kivity {
113*7d36db35SAvi Kivity 	unsigned char *m1 = mem, *m2 = mem + 1024;
114*7d36db35SAvi Kivity 	unsigned char m3[1024];
115*7d36db35SAvi Kivity 
116*7d36db35SAvi Kivity 	for (int i = 0; i < 100; ++i)
117*7d36db35SAvi Kivity 		m1[i] = m2[i] = m3[i] = i;
118*7d36db35SAvi Kivity 	for (int i = 100; i < 200; ++i)
119*7d36db35SAvi Kivity 		m1[i] = (m3[i] = m2[i] = i) + 1;
120*7d36db35SAvi Kivity 	test_cmps_one(m1, m3);
121*7d36db35SAvi Kivity 	test_cmps_one(m1, m2);
122*7d36db35SAvi Kivity }
123*7d36db35SAvi Kivity 
124*7d36db35SAvi Kivity void test_cr8(void)
125*7d36db35SAvi Kivity {
126*7d36db35SAvi Kivity 	unsigned long src, dst;
127*7d36db35SAvi Kivity 
128*7d36db35SAvi Kivity 	dst = 777;
129*7d36db35SAvi Kivity 	src = 3;
130*7d36db35SAvi Kivity 	asm volatile("mov %[src], %%cr8; mov %%cr8, %[dst]"
131*7d36db35SAvi Kivity 		     : [dst]"+r"(dst), [src]"+r"(src));
132*7d36db35SAvi Kivity 	report("mov %cr8", dst == 3 && src == 3);
133*7d36db35SAvi Kivity }
134*7d36db35SAvi Kivity 
135*7d36db35SAvi Kivity void test_push(void *mem)
136*7d36db35SAvi Kivity {
137*7d36db35SAvi Kivity 	unsigned long tmp;
138*7d36db35SAvi Kivity 	unsigned long *stack_top = mem + 4096;
139*7d36db35SAvi Kivity 	unsigned long *new_stack_top;
140*7d36db35SAvi Kivity 	unsigned long memw = 0x123456789abcdeful;
141*7d36db35SAvi Kivity 
142*7d36db35SAvi Kivity 	memset(mem, 0x55, (void *)stack_top - mem);
143*7d36db35SAvi Kivity 
144*7d36db35SAvi Kivity 	asm volatile("mov %%rsp, %[tmp] \n\t"
145*7d36db35SAvi Kivity 		     "mov %[stack_top], %%rsp \n\t"
146*7d36db35SAvi Kivity 		     "pushq $-7 \n\t"
147*7d36db35SAvi Kivity 		     "pushq %[reg] \n\t"
148*7d36db35SAvi Kivity 		     "pushq (%[mem]) \n\t"
149*7d36db35SAvi Kivity 		     "pushq $-7070707 \n\t"
150*7d36db35SAvi Kivity 		     "mov %%rsp, %[new_stack_top] \n\t"
151*7d36db35SAvi Kivity 		     "mov %[tmp], %%rsp"
152*7d36db35SAvi Kivity 		     : [tmp]"=&r"(tmp), [new_stack_top]"=r"(new_stack_top)
153*7d36db35SAvi Kivity 		     : [stack_top]"r"(stack_top),
154*7d36db35SAvi Kivity 		       [reg]"r"(-17l), [mem]"r"(&memw)
155*7d36db35SAvi Kivity 		     : "memory");
156*7d36db35SAvi Kivity 
157*7d36db35SAvi Kivity 	report("push $imm8", stack_top[-1] == -7ul);
158*7d36db35SAvi Kivity 	report("push %reg", stack_top[-2] == -17ul);
159*7d36db35SAvi Kivity 	report("push mem", stack_top[-3] == 0x123456789abcdeful);
160*7d36db35SAvi Kivity 	report("push $imm", stack_top[-4] == -7070707);
161*7d36db35SAvi Kivity }
162*7d36db35SAvi Kivity 
163*7d36db35SAvi Kivity void test_pop(void *mem)
164*7d36db35SAvi Kivity {
165*7d36db35SAvi Kivity 	unsigned long tmp;
166*7d36db35SAvi Kivity 	unsigned long *stack_top = mem + 4096;
167*7d36db35SAvi Kivity 	unsigned long memw = 0x123456789abcdeful;
168*7d36db35SAvi Kivity 	static unsigned long tmp2;
169*7d36db35SAvi Kivity 
170*7d36db35SAvi Kivity 	memset(mem, 0x55, (void *)stack_top - mem);
171*7d36db35SAvi Kivity 
172*7d36db35SAvi Kivity 	asm volatile("pushq %[val] \n\t"
173*7d36db35SAvi Kivity 		     "popq (%[mem])"
174*7d36db35SAvi Kivity 		     : : [val]"m"(memw), [mem]"r"(mem) : "memory");
175*7d36db35SAvi Kivity 	report("pop mem", *(unsigned long *)mem == memw);
176*7d36db35SAvi Kivity 
177*7d36db35SAvi Kivity 	memw = 7 - memw;
178*7d36db35SAvi Kivity 	asm volatile("mov %%rsp, %[tmp] \n\t"
179*7d36db35SAvi Kivity 		     "mov %[stack_top], %%rsp \n\t"
180*7d36db35SAvi Kivity 		     "pushq %[val] \n\t"
181*7d36db35SAvi Kivity 		     "popq %[tmp2] \n\t"
182*7d36db35SAvi Kivity 		     "mov %[tmp], %%rsp"
183*7d36db35SAvi Kivity 		     : [tmp]"=&r"(tmp), [tmp2]"=m"(tmp2)
184*7d36db35SAvi Kivity 		     : [val]"r"(memw), [stack_top]"r"(stack_top)
185*7d36db35SAvi Kivity 		     : "memory");
186*7d36db35SAvi Kivity 	report("pop mem (2)", tmp2 == memw);
187*7d36db35SAvi Kivity 
188*7d36db35SAvi Kivity 	memw = 129443 - memw;
189*7d36db35SAvi Kivity 	asm volatile("mov %%rsp, %[tmp] \n\t"
190*7d36db35SAvi Kivity 		     "mov %[stack_top], %%rsp \n\t"
191*7d36db35SAvi Kivity 		     "pushq %[val] \n\t"
192*7d36db35SAvi Kivity 		     "popq %[tmp2] \n\t"
193*7d36db35SAvi Kivity 		     "mov %[tmp], %%rsp"
194*7d36db35SAvi Kivity 		     : [tmp]"=&r"(tmp), [tmp2]"=r"(tmp2)
195*7d36db35SAvi Kivity 		     : [val]"r"(memw), [stack_top]"r"(stack_top)
196*7d36db35SAvi Kivity 		     : "memory");
197*7d36db35SAvi Kivity 	report("pop reg", tmp2 == memw);
198*7d36db35SAvi Kivity 
199*7d36db35SAvi Kivity 	asm volatile("mov %%rsp, %[tmp] \n\t"
200*7d36db35SAvi Kivity 		     "mov %[stack_top], %%rsp \n\t"
201*7d36db35SAvi Kivity 		     "push $1f \n\t"
202*7d36db35SAvi Kivity 		     "ret \n\t"
203*7d36db35SAvi Kivity 		     "2: jmp 2b \n\t"
204*7d36db35SAvi Kivity 		     "1: mov %[tmp], %%rsp"
205*7d36db35SAvi Kivity 		     : [tmp]"=&r"(tmp) : [stack_top]"r"(stack_top)
206*7d36db35SAvi Kivity 		     : "memory");
207*7d36db35SAvi Kivity 	report("ret", 1);
208*7d36db35SAvi Kivity }
209*7d36db35SAvi Kivity 
210*7d36db35SAvi Kivity void test_ljmp(void *mem)
211*7d36db35SAvi Kivity {
212*7d36db35SAvi Kivity     unsigned char *m = mem;
213*7d36db35SAvi Kivity     volatile int res = 1;
214*7d36db35SAvi Kivity 
215*7d36db35SAvi Kivity     *(unsigned long**)m = &&jmpf;
216*7d36db35SAvi Kivity     asm volatile ("data16/mov %%cs, %0":"=m"(*(m + sizeof(unsigned long))));
217*7d36db35SAvi Kivity     asm volatile ("rex64/ljmp *%0"::"m"(*m));
218*7d36db35SAvi Kivity     res = 0;
219*7d36db35SAvi Kivity jmpf:
220*7d36db35SAvi Kivity     report("ljmp", res);
221*7d36db35SAvi Kivity }
222*7d36db35SAvi Kivity 
223*7d36db35SAvi Kivity void test_incdecnotneg(void *mem)
224*7d36db35SAvi Kivity {
225*7d36db35SAvi Kivity     unsigned long *m = mem, v = 1234;
226*7d36db35SAvi Kivity     unsigned char *mb = mem, vb = 66;
227*7d36db35SAvi Kivity 
228*7d36db35SAvi Kivity     *m = 0;
229*7d36db35SAvi Kivity 
230*7d36db35SAvi Kivity     asm volatile ("incl %0":"+m"(*m));
231*7d36db35SAvi Kivity     report("incl",  *m == 1);
232*7d36db35SAvi Kivity     asm volatile ("decl %0":"+m"(*m));
233*7d36db35SAvi Kivity     report("decl",  *m == 0);
234*7d36db35SAvi Kivity     asm volatile ("incb %0":"+m"(*m));
235*7d36db35SAvi Kivity     report("incb",  *m == 1);
236*7d36db35SAvi Kivity     asm volatile ("decb %0":"+m"(*m));
237*7d36db35SAvi Kivity     report("decb",  *m == 0);
238*7d36db35SAvi Kivity 
239*7d36db35SAvi Kivity     asm volatile ("lock incl %0":"+m"(*m));
240*7d36db35SAvi Kivity     report("lock incl",  *m == 1);
241*7d36db35SAvi Kivity     asm volatile ("lock decl %0":"+m"(*m));
242*7d36db35SAvi Kivity     report("lock decl",  *m == 0);
243*7d36db35SAvi Kivity     asm volatile ("lock incb %0":"+m"(*m));
244*7d36db35SAvi Kivity     report("lock incb",  *m == 1);
245*7d36db35SAvi Kivity     asm volatile ("lock decb %0":"+m"(*m));
246*7d36db35SAvi Kivity     report("lock decb",  *m == 0);
247*7d36db35SAvi Kivity 
248*7d36db35SAvi Kivity     *m = v;
249*7d36db35SAvi Kivity 
250*7d36db35SAvi Kivity     asm ("lock negq %0" : "+m"(*m)); v = -v;
251*7d36db35SAvi Kivity     report("lock negl", *m == v);
252*7d36db35SAvi Kivity     asm ("lock notq %0" : "+m"(*m)); v = ~v;
253*7d36db35SAvi Kivity     report("lock notl", *m == v);
254*7d36db35SAvi Kivity 
255*7d36db35SAvi Kivity     *mb = vb;
256*7d36db35SAvi Kivity 
257*7d36db35SAvi Kivity     asm ("lock negb %0" : "+m"(*mb)); vb = -vb;
258*7d36db35SAvi Kivity     report("lock negb", *mb == vb);
259*7d36db35SAvi Kivity     asm ("lock notb %0" : "+m"(*mb)); vb = ~vb;
260*7d36db35SAvi Kivity     report("lock notb", *mb == vb);
261*7d36db35SAvi Kivity }
262*7d36db35SAvi Kivity 
263*7d36db35SAvi Kivity void test_smsw(void)
264*7d36db35SAvi Kivity {
265*7d36db35SAvi Kivity 	char mem[16];
266*7d36db35SAvi Kivity 	unsigned short msw, msw_orig, *pmsw;
267*7d36db35SAvi Kivity 	int i, zero;
268*7d36db35SAvi Kivity 
269*7d36db35SAvi Kivity 	msw_orig = read_cr0();
270*7d36db35SAvi Kivity 
271*7d36db35SAvi Kivity 	asm("smsw %0" : "=r"(msw));
272*7d36db35SAvi Kivity 	report("smsw (1)", msw == msw_orig);
273*7d36db35SAvi Kivity 
274*7d36db35SAvi Kivity 	memset(mem, 0, 16);
275*7d36db35SAvi Kivity 	pmsw = (void *)mem;
276*7d36db35SAvi Kivity 	asm("smsw %0" : "=m"(pmsw[4]));
277*7d36db35SAvi Kivity 	zero = 1;
278*7d36db35SAvi Kivity 	for (i = 0; i < 8; ++i)
279*7d36db35SAvi Kivity 		if (i != 4 && pmsw[i])
280*7d36db35SAvi Kivity 			zero = 0;
281*7d36db35SAvi Kivity 	report("smsw (2)", msw == pmsw[4] && zero);
282*7d36db35SAvi Kivity }
283*7d36db35SAvi Kivity 
284*7d36db35SAvi Kivity void test_lmsw(void)
285*7d36db35SAvi Kivity {
286*7d36db35SAvi Kivity 	char mem[16];
287*7d36db35SAvi Kivity 	unsigned short msw, *pmsw;
288*7d36db35SAvi Kivity 	unsigned long cr0;
289*7d36db35SAvi Kivity 
290*7d36db35SAvi Kivity 	cr0 = read_cr0();
291*7d36db35SAvi Kivity 
292*7d36db35SAvi Kivity 	msw = cr0 ^ 8;
293*7d36db35SAvi Kivity 	asm("lmsw %0" : : "r"(msw));
294*7d36db35SAvi Kivity 	printf("before %lx after %lx\n", cr0, read_cr0());
295*7d36db35SAvi Kivity 	report("lmsw (1)", (cr0 ^ read_cr0()) == 8);
296*7d36db35SAvi Kivity 
297*7d36db35SAvi Kivity 	pmsw = (void *)mem;
298*7d36db35SAvi Kivity 	*pmsw = cr0;
299*7d36db35SAvi Kivity 	asm("lmsw %0" : : "m"(*pmsw));
300*7d36db35SAvi Kivity 	printf("before %lx after %lx\n", cr0, read_cr0());
301*7d36db35SAvi Kivity 	report("lmsw (2)", cr0 == read_cr0());
302*7d36db35SAvi Kivity 
303*7d36db35SAvi Kivity 	/* lmsw can't clear cr0.pe */
304*7d36db35SAvi Kivity 	msw = (cr0 & ~1ul) ^ 4;  /* change EM to force trap */
305*7d36db35SAvi Kivity 	asm("lmsw %0" : : "r"(msw));
306*7d36db35SAvi Kivity 	report("lmsw (3)", (cr0 ^ read_cr0()) == 4 && (cr0 & 1));
307*7d36db35SAvi Kivity 
308*7d36db35SAvi Kivity 	/* back to normal */
309*7d36db35SAvi Kivity 	msw = cr0;
310*7d36db35SAvi Kivity 	asm("lmsw %0" : : "r"(msw));
311*7d36db35SAvi Kivity }
312*7d36db35SAvi Kivity 
313*7d36db35SAvi Kivity void test_xchg(void *mem)
314*7d36db35SAvi Kivity {
315*7d36db35SAvi Kivity 	unsigned long *memq = mem;
316*7d36db35SAvi Kivity 	unsigned long rax;
317*7d36db35SAvi Kivity 
318*7d36db35SAvi Kivity 	asm volatile("mov $0x123456789abcdef, %%rax\n\t"
319*7d36db35SAvi Kivity 		     "mov %%rax, (%[memq])\n\t"
320*7d36db35SAvi Kivity 		     "mov $0xfedcba9876543210, %%rax\n\t"
321*7d36db35SAvi Kivity 		     "xchg %%al, (%[memq])\n\t"
322*7d36db35SAvi Kivity 		     "mov %%rax, %[rax]\n\t"
323*7d36db35SAvi Kivity 		     : [rax]"=r"(rax)
324*7d36db35SAvi Kivity 		     : [memq]"r"(memq)
325*7d36db35SAvi Kivity 		     : "memory");
326*7d36db35SAvi Kivity 	report("xchg reg, r/m (1)",
327*7d36db35SAvi Kivity 	       rax == 0xfedcba98765432ef && *memq == 0x123456789abcd10);
328*7d36db35SAvi Kivity 
329*7d36db35SAvi Kivity 	asm volatile("mov $0x123456789abcdef, %%rax\n\t"
330*7d36db35SAvi Kivity 		     "mov %%rax, (%[memq])\n\t"
331*7d36db35SAvi Kivity 		     "mov $0xfedcba9876543210, %%rax\n\t"
332*7d36db35SAvi Kivity 		     "xchg %%ax, (%[memq])\n\t"
333*7d36db35SAvi Kivity 		     "mov %%rax, %[rax]\n\t"
334*7d36db35SAvi Kivity 		     : [rax]"=r"(rax)
335*7d36db35SAvi Kivity 		     : [memq]"r"(memq)
336*7d36db35SAvi Kivity 		     : "memory");
337*7d36db35SAvi Kivity 	report("xchg reg, r/m (2)",
338*7d36db35SAvi Kivity 	       rax == 0xfedcba987654cdef && *memq == 0x123456789ab3210);
339*7d36db35SAvi Kivity 
340*7d36db35SAvi Kivity 	asm volatile("mov $0x123456789abcdef, %%rax\n\t"
341*7d36db35SAvi Kivity 		     "mov %%rax, (%[memq])\n\t"
342*7d36db35SAvi Kivity 		     "mov $0xfedcba9876543210, %%rax\n\t"
343*7d36db35SAvi Kivity 		     "xchg %%eax, (%[memq])\n\t"
344*7d36db35SAvi Kivity 		     "mov %%rax, %[rax]\n\t"
345*7d36db35SAvi Kivity 		     : [rax]"=r"(rax)
346*7d36db35SAvi Kivity 		     : [memq]"r"(memq)
347*7d36db35SAvi Kivity 		     : "memory");
348*7d36db35SAvi Kivity 	report("xchg reg, r/m (3)",
349*7d36db35SAvi Kivity 	       rax == 0x89abcdef && *memq == 0x123456776543210);
350*7d36db35SAvi Kivity 
351*7d36db35SAvi Kivity 	asm volatile("mov $0x123456789abcdef, %%rax\n\t"
352*7d36db35SAvi Kivity 		     "mov %%rax, (%[memq])\n\t"
353*7d36db35SAvi Kivity 		     "mov $0xfedcba9876543210, %%rax\n\t"
354*7d36db35SAvi Kivity 		     "xchg %%rax, (%[memq])\n\t"
355*7d36db35SAvi Kivity 		     "mov %%rax, %[rax]\n\t"
356*7d36db35SAvi Kivity 		     : [rax]"=r"(rax)
357*7d36db35SAvi Kivity 		     : [memq]"r"(memq)
358*7d36db35SAvi Kivity 		     : "memory");
359*7d36db35SAvi Kivity 	report("xchg reg, r/m (4)",
360*7d36db35SAvi Kivity 	       rax == 0x123456789abcdef && *memq == 0xfedcba9876543210);
361*7d36db35SAvi Kivity }
362*7d36db35SAvi Kivity 
363*7d36db35SAvi Kivity int main()
364*7d36db35SAvi Kivity {
365*7d36db35SAvi Kivity 	void *mem;
366*7d36db35SAvi Kivity 	unsigned long t1, t2;
367*7d36db35SAvi Kivity 
368*7d36db35SAvi Kivity 	setup_vm();
369*7d36db35SAvi Kivity 	mem = vmap(IORAM_BASE_PHYS, IORAM_LEN);
370*7d36db35SAvi Kivity 
371*7d36db35SAvi Kivity 	// test mov reg, r/m and mov r/m, reg
372*7d36db35SAvi Kivity 	t1 = 0x123456789abcdef;
373*7d36db35SAvi Kivity 	asm volatile("mov %[t1], (%[mem]) \n\t"
374*7d36db35SAvi Kivity 		     "mov (%[mem]), %[t2]"
375*7d36db35SAvi Kivity 		     : [t2]"=r"(t2)
376*7d36db35SAvi Kivity 		     : [t1]"r"(t1), [mem]"r"(mem)
377*7d36db35SAvi Kivity 		     : "memory");
378*7d36db35SAvi Kivity 	report("mov reg, r/m (1)", t2 == 0x123456789abcdef);
379*7d36db35SAvi Kivity 
380*7d36db35SAvi Kivity 	test_cmps(mem);
381*7d36db35SAvi Kivity 
382*7d36db35SAvi Kivity 	test_push(mem);
383*7d36db35SAvi Kivity 	test_pop(mem);
384*7d36db35SAvi Kivity 
385*7d36db35SAvi Kivity 	test_xchg(mem);
386*7d36db35SAvi Kivity 
387*7d36db35SAvi Kivity 	test_cr8();
388*7d36db35SAvi Kivity 
389*7d36db35SAvi Kivity 	test_smsw();
390*7d36db35SAvi Kivity 	test_lmsw();
391*7d36db35SAvi Kivity 	test_ljmp(mem);
392*7d36db35SAvi Kivity 	test_stringio();
393*7d36db35SAvi Kivity 	test_incdecnotneg(mem);
394*7d36db35SAvi Kivity 
395*7d36db35SAvi Kivity 	printf("\nSUMMARY: %d tests, %d failures\n", tests, fails);
396*7d36db35SAvi Kivity 	return fails ? 1 : 0;
397*7d36db35SAvi Kivity }
398