xref: /kvm-unit-tests/x86/realmode.c (revision b5105e8b489b626bae2c1fc45e4ab1263b626eb9)
1 #ifndef USE_SERIAL
2 #define USE_SERIAL
3 #endif
4 
5 asm(".code16gcc");
6 
7 typedef unsigned char u8;
8 typedef unsigned short u16;
9 typedef unsigned u32;
10 typedef unsigned long long u64;
11 
12 void test_function(void);
13 
14 asm(
15 	"test_function: \n\t"
16 	"mov $0x1234, %eax \n\t"
17 	"ret"
18    );
19 
20 static int strlen(const char *str)
21 {
22 	int n;
23 
24 	for (n = 0; *str; ++str)
25 		++n;
26 	return n;
27 }
28 
29 static void outb(u8 data, u16 port)
30 {
31 	asm volatile("out %0, %1" : : "a"(data), "d"(port));
32 }
33 
34 #ifdef USE_SERIAL
35 static int serial_iobase = 0x3f8;
36 static int serial_inited = 0;
37 
38 static u8 inb(u16 port)
39 {
40 	u8 data;
41 	asm volatile("in %1, %0" : "=a"(data) : "d"(port));
42 	return data;
43 }
44 
45 static void serial_outb(char ch)
46 {
47 	u8 lsr;
48 
49 	do {
50 		lsr = inb(serial_iobase + 0x05);
51 	} while (!(lsr & 0x20));
52 
53 	outb(ch, serial_iobase + 0x00);
54 }
55 
56 static void serial_init(void)
57 {
58 	u8 lcr;
59 
60 	/* set DLAB */
61 	lcr = inb(serial_iobase + 0x03);
62 	lcr |= 0x80;
63 	outb(lcr, serial_iobase + 0x03);
64 
65 	/* set baud rate to 115200 */
66 	outb(0x01, serial_iobase + 0x00);
67 	outb(0x00, serial_iobase + 0x01);
68 
69 	/* clear DLAB */
70 	lcr = inb(serial_iobase + 0x03);
71 	lcr &= ~0x80;
72 	outb(lcr, serial_iobase + 0x03);
73 }
74 #endif
75 
76 static void print_serial(const char *buf)
77 {
78 	unsigned long len = strlen(buf);
79 #ifdef USE_SERIAL
80 	unsigned long i;
81 	if (!serial_inited) {
82 	    serial_init();
83 	    serial_inited = 1;
84 	}
85 
86 	for (i = 0; i < len; i++) {
87 	    serial_outb(buf[i]);
88 	}
89 #else
90 	asm volatile ("addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1));
91 #endif
92 }
93 
94 static void print_serial_u32(u32 value)
95 {
96 	char n[12], *p;
97 	p = &n[11];
98 	*p = 0;
99 	do {
100 		*--p = '0' + (value % 10);
101 		value /= 10;
102 	} while (value > 0);
103 	print_serial(p);
104 }
105 
106 static void exit(int code)
107 {
108 	outb(code, 0xf4);
109 }
110 
111 struct regs {
112 	u32 eax, ebx, ecx, edx;
113 	u32 esi, edi, esp, ebp;
114 	u32 eip, eflags;
115 };
116 
117 static u64 gdt[] = {
118 	0,
119 	0x00cf9b000000ffffull, // flat 32-bit code segment
120 	0x00cf93000000ffffull, // flat 32-bit data segment
121 };
122 
123 static struct {
124 	u16 limit;
125 	void *base;
126 } __attribute__((packed)) gdt_descr = {
127 	sizeof(gdt) - 1,
128 	gdt,
129 };
130 
131 struct insn_desc {
132     u16 ptr;
133     u16 len;
134 };
135 
136 static struct regs inregs, outregs;
137 
138 static void exec_in_big_real_mode(struct insn_desc *insn)
139 {
140 	unsigned long tmp;
141 	static struct regs save;
142 	int i;
143 	extern u8 test_insn[], test_insn_end[];
144 
145 	for (i = 0; i < insn->len; ++i)
146 	    test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i];
147 	for (; i < test_insn_end - test_insn; ++i)
148 		test_insn[i] = 0x90; // nop
149 
150 	save = inregs;
151 	asm volatile(
152 		"lgdtl %[gdt_descr] \n\t"
153 		"mov %%cr0, %[tmp] \n\t"
154 		"or $1, %[tmp] \n\t"
155 		"mov %[tmp], %%cr0 \n\t"
156 		"mov %[bigseg], %%gs \n\t"
157 		"and $-2, %[tmp] \n\t"
158 		"mov %[tmp], %%cr0 \n\t"
159 
160                 "pushw %[save]+36; popfw \n\t"
161 		"xchg %%eax, %[save]+0 \n\t"
162 		"xchg %%ebx, %[save]+4 \n\t"
163 		"xchg %%ecx, %[save]+8 \n\t"
164 		"xchg %%edx, %[save]+12 \n\t"
165 		"xchg %%esi, %[save]+16 \n\t"
166 		"xchg %%edi, %[save]+20 \n\t"
167 		"xchg %%esp, %[save]+24 \n\t"
168 		"xchg %%ebp, %[save]+28 \n\t"
169 
170 		"test_insn: . = . + 32\n\t"
171 		"test_insn_end: \n\t"
172 
173 		"xchg %%eax, %[save]+0 \n\t"
174 		"xchg %%ebx, %[save]+4 \n\t"
175 		"xchg %%ecx, %[save]+8 \n\t"
176 		"xchg %%edx, %[save]+12 \n\t"
177 		"xchg %%esi, %[save]+16 \n\t"
178 		"xchg %%edi, %[save]+20 \n\t"
179 		"xchg %%esp, %[save]+24 \n\t"
180 		"xchg %%ebp, %[save]+28 \n\t"
181 
182 		/* Save EFLAGS in outregs*/
183 		"pushfl \n\t"
184 		"popl %[save]+36 \n\t"
185 
186 		/* Restore DF for the harness code */
187 		"cld\n\t"
188 		"xor %[tmp], %[tmp] \n\t"
189 		"mov %[tmp], %%gs \n\t"
190 		: [tmp]"=&r"(tmp), [save]"+m"(save)
191 		: [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16)
192 		: "cc", "memory"
193 		);
194 	outregs = save;
195 }
196 
197 #define R_AX 1
198 #define R_BX 2
199 #define R_CX 4
200 #define R_DX 8
201 #define R_SI 16
202 #define R_DI 32
203 #define R_SP 64
204 #define R_BP 128
205 
206 int regs_equal(int ignore)
207 {
208 	const u32 *p1 = &inregs.eax, *p2 = &outregs.eax;  // yuck
209 	int i;
210 
211 	for (i = 0; i < 8; ++i)
212 		if (!(ignore & (1 << i)) && p1[i] != p2[i])
213 			return 0;
214 	return 1;
215 }
216 
217 static void report(const char *name, u16 regs_ignore, _Bool ok)
218 {
219     if (!regs_equal(regs_ignore)) {
220 	ok = 0;
221     }
222     print_serial(ok ? "PASS: " : "FAIL: ");
223     print_serial(name);
224     print_serial("\n");
225 }
226 
227 #define MK_INSN(name, str)				\
228     asm (						\
229 	 ".pushsection .data.insn  \n\t"		\
230 	 "insn_" #name ": \n\t"				\
231 	 ".word 1001f, 1002f - 1001f \n\t"		\
232 	 ".popsection \n\t"				\
233 	 ".pushsection .text.insn, \"ax\" \n\t"		\
234 	 "1001: \n\t"					\
235 	 "insn_code_" #name ": " str " \n\t"		\
236 	 "1002: \n\t"					\
237 	 ".popsection"					\
238     );							\
239     extern struct insn_desc insn_##name;
240 
241 void test_xchg(void)
242 {
243 	MK_INSN(xchg_test1, "xchg %eax,%eax\n\t");
244 	MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t");
245 	MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t");
246 	MK_INSN(xchg_test4, "xchg %eax,%edx\n\t");
247 	MK_INSN(xchg_test5, "xchg %eax,%esi\n\t");
248 	MK_INSN(xchg_test6, "xchg %eax,%edi\n\t");
249 	MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t");
250 	MK_INSN(xchg_test8, "xchg %eax,%esp\n\t");
251 
252 	inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7};
253 
254 	exec_in_big_real_mode(&insn_xchg_test1);
255 	report("xchg 1", 0, 1);
256 
257 	exec_in_big_real_mode(&insn_xchg_test2);
258 	report("xchg 2", R_AX | R_BX,
259 	       outregs.eax == inregs.ebx && outregs.ebx == inregs.eax);
260 
261 	exec_in_big_real_mode(&insn_xchg_test3);
262 	report("xchg 3", R_AX | R_CX,
263 	       outregs.eax == inregs.ecx && outregs.ecx == inregs.eax);
264 
265 	exec_in_big_real_mode(&insn_xchg_test4);
266 	report("xchg 4", R_AX | R_DX,
267 	       outregs.eax == inregs.edx && outregs.edx == inregs.eax);
268 
269 	exec_in_big_real_mode(&insn_xchg_test5);
270 	report("xchg 5", R_AX | R_SI,
271 	       outregs.eax == inregs.esi && outregs.esi == inregs.eax);
272 
273 	exec_in_big_real_mode(&insn_xchg_test6);
274 	report("xchg 6", R_AX | R_DI,
275 	       outregs.eax == inregs.edi && outregs.edi == inregs.eax);
276 
277 	exec_in_big_real_mode(&insn_xchg_test7);
278 	report("xchg 7", R_AX | R_BP,
279 	       outregs.eax == inregs.ebp && outregs.ebp == inregs.eax);
280 
281 	exec_in_big_real_mode(&insn_xchg_test8);
282 	report("xchg 8", R_AX | R_SP,
283 	       outregs.eax == inregs.esp && outregs.esp == inregs.eax);
284 }
285 
286 void test_shld(void)
287 {
288 	MK_INSN(shld_test, "shld $8,%edx,%eax\n\t");
289 
290 	inregs = (struct regs){ .eax = 0xbe, .edx = 0xef000000 };
291 	exec_in_big_real_mode(&insn_shld_test);
292 	report("shld", ~0, outregs.eax == 0xbeef);
293 }
294 
295 void test_mov_imm(void)
296 {
297 	MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax");
298 	MK_INSN(mov_r16_imm_1, "mov $1234, %ax");
299 	MK_INSN(mov_r8_imm_1, "mov $0x12, %ah");
300 	MK_INSN(mov_r8_imm_2, "mov $0x34, %al");
301 	MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t");
302 
303 	inregs = (struct regs){ 0 };
304 
305 	exec_in_big_real_mode(&insn_mov_r16_imm_1);
306 	report("mov 1", R_AX, outregs.eax == 1234);
307 
308 	/* test mov $imm, %eax */
309 	exec_in_big_real_mode(&insn_mov_r32_imm_1);
310 	report("mov 2", R_AX, outregs.eax == 1234567890);
311 
312 	/* test mov $imm, %al/%ah */
313 	exec_in_big_real_mode(&insn_mov_r8_imm_1);
314 	report("mov 3", R_AX, outregs.eax == 0x1200);
315 
316 	exec_in_big_real_mode(&insn_mov_r8_imm_2);
317 	report("mov 4", R_AX, outregs.eax == 0x34);
318 
319 	exec_in_big_real_mode(&insn_mov_r8_imm_3);
320 	report("mov 5", R_AX, outregs.eax == 0x1234);
321 }
322 
323 void test_sub_imm(void)
324 {
325 	MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t");
326 	MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t");
327 	MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t");
328 	MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t");
329 
330 	inregs = (struct regs){ 0 };
331 
332 	exec_in_big_real_mode(&insn_sub_r16_imm_1);
333 	report("sub 1", R_AX, outregs.eax == 1224);
334 
335 	/* test mov $imm, %eax */
336 	exec_in_big_real_mode(&insn_sub_r32_imm_1);
337 	report("sub 2", R_AX, outregs.eax == 1234567880);
338 
339 	/* test mov $imm, %al/%ah */
340 	exec_in_big_real_mode(&insn_sub_r8_imm_1);
341 	report("sub 3", R_AX, outregs.eax == 0x0200);
342 
343 	exec_in_big_real_mode(&insn_sub_r8_imm_2);
344 	report("sub 4", R_AX, outregs.eax == 0x24);
345 }
346 
347 void test_xor_imm(void)
348 {
349 	MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t");
350 	MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t");
351 	MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t");
352 	MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t");
353 
354 	inregs = (struct regs){ 0 };
355 
356 	exec_in_big_real_mode(&insn_xor_r16_imm_1);
357 	report("xor 1", R_AX, outregs.eax == 0);
358 
359 	/* test mov $imm, %eax */
360 	exec_in_big_real_mode(&insn_xor_r32_imm_1);
361 	report("xor 2", R_AX, outregs.eax == 0);
362 
363 	/* test mov $imm, %al/%ah */
364 	exec_in_big_real_mode(&insn_xor_r8_imm_1);
365 	report("xor 3", R_AX, outregs.eax == 0);
366 
367 	exec_in_big_real_mode(&insn_xor_r8_imm_2);
368 	report("xor 4", R_AX, outregs.eax == 0);
369 }
370 
371 void test_cmp_imm(void)
372 {
373 	MK_INSN(cmp_test1, "mov $0x34, %al\n\t"
374 			   "cmp $0x34, %al\n\t");
375 	MK_INSN(cmp_test2, "mov $0x34, %al\n\t"
376 			   "cmp $0x39, %al\n\t");
377 	MK_INSN(cmp_test3, "mov $0x34, %al\n\t"
378 			   "cmp $0x24, %al\n\t");
379 
380 	inregs = (struct regs){ 0 };
381 
382 	/* test cmp imm8 with AL */
383 	/* ZF: (bit 6) Zero Flag becomes 1 if an operation results
384 	 * in a 0 writeback, or 0 register
385 	 */
386 	exec_in_big_real_mode(&insn_cmp_test1);
387 	report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6));
388 
389 	exec_in_big_real_mode(&insn_cmp_test2);
390 	report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0);
391 
392 	exec_in_big_real_mode(&insn_cmp_test3);
393 	report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0);
394 }
395 
396 void test_add_imm(void)
397 {
398 	MK_INSN(add_test1, "mov $0x43211234, %eax \n\t"
399 			   "add $0x12344321, %eax \n\t");
400 	MK_INSN(add_test2, "mov $0x12, %eax \n\t"
401 			   "add $0x21, %al\n\t");
402 
403 	inregs = (struct regs){ 0 };
404 
405 	exec_in_big_real_mode(&insn_add_test1);
406 	report("add 1", ~0, outregs.eax == 0x55555555);
407 
408 	exec_in_big_real_mode(&insn_add_test2);
409 	report("add 2", ~0, outregs.eax == 0x33);
410 }
411 
412 void test_eflags_insn(void)
413 {
414 	MK_INSN(clc, "clc");
415 	MK_INSN(stc, "stc");
416 	MK_INSN(cli, "cli");
417 	MK_INSN(sti, "sti");
418 	MK_INSN(cld, "cld");
419 	MK_INSN(std, "std");
420 
421 	inregs = (struct regs){ 0 };
422 
423 	exec_in_big_real_mode(&insn_clc);
424 	report("clc", ~0, (outregs.eflags & 1) == 0);
425 
426 	exec_in_big_real_mode(&insn_stc);
427 	report("stc", ~0, (outregs.eflags & 1) == 1);
428 
429 	exec_in_big_real_mode(&insn_cli);
430 	report("cli", ~0, !(outregs.eflags & (1 << 9)));
431 
432 	exec_in_big_real_mode(&insn_sti);
433 	report("sti", ~0, outregs.eflags & (1 << 9));
434 
435 	exec_in_big_real_mode(&insn_cld);
436 	report("cld", ~0, !(outregs.eflags & (1 << 10)));
437 
438 	exec_in_big_real_mode(&insn_std);
439 	report("std", ~0, (outregs.eflags & (1 << 10)));
440 }
441 
442 void test_io(void)
443 {
444 	MK_INSN(io_test1, "mov $0xff, %al \n\t"
445 		          "out %al, $0xe0 \n\t"
446 		          "mov $0x00, %al \n\t"
447 			  "in $0xe0, %al \n\t");
448 	MK_INSN(io_test2, "mov $0xffff, %ax \n\t"
449 			  "out %ax, $0xe0 \n\t"
450 			  "mov $0x0000, %ax \n\t"
451 			  "in $0xe0, %ax \n\t");
452 	MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t"
453 			  "out %eax, $0xe0 \n\t"
454 			  "mov $0x000000, %eax \n\t"
455 			  "in $0xe0, %eax \n\t");
456 	MK_INSN(io_test4, "mov $0xe0, %dx \n\t"
457 			  "mov $0xff, %al \n\t"
458 			  "out %al, %dx \n\t"
459 			  "mov $0x00, %al \n\t"
460 			  "in %dx, %al \n\t");
461 	MK_INSN(io_test5, "mov $0xe0, %dx \n\t"
462 			  "mov $0xffff, %ax \n\t"
463 			  "out %ax, %dx \n\t"
464 			  "mov $0x0000, %ax \n\t"
465 			  "in %dx, %ax \n\t");
466 	MK_INSN(io_test6, "mov $0xe0, %dx \n\t"
467 			  "mov $0xffffffff, %eax \n\t"
468 			  "out %eax, %dx \n\t"
469 			  "mov $0x00000000, %eax \n\t"
470 			  "in %dx, %eax \n\t");
471 
472 	inregs = (struct regs){ 0 };
473 
474 	exec_in_big_real_mode(&insn_io_test1);
475 	report("pio 1", R_AX, outregs.eax == 0xff);
476 
477 	exec_in_big_real_mode(&insn_io_test2);
478 	report("pio 2", R_AX, outregs.eax == 0xffff);
479 
480 	exec_in_big_real_mode(&insn_io_test3);
481 	report("pio 3", R_AX, outregs.eax == 0xffffffff);
482 
483 	exec_in_big_real_mode(&insn_io_test4);
484 	report("pio 4", R_AX|R_DX, outregs.eax == 0xff);
485 
486 	exec_in_big_real_mode(&insn_io_test5);
487 	report("pio 5", R_AX|R_DX, outregs.eax == 0xffff);
488 
489 	exec_in_big_real_mode(&insn_io_test6);
490 	report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff);
491 }
492 
493 asm ("retf: lretw");
494 extern void retf();
495 
496 asm ("retf_imm: lretw $10");
497 extern void retf_imm();
498 
499 void test_call(void)
500 {
501 	u32 esp[16];
502 	u32 addr;
503 
504 	inregs = (struct regs){ 0 };
505 	inregs.esp = (u32)esp;
506 
507 	MK_INSN(call1, "mov $test_function, %eax \n\t"
508 		       "call *%eax\n\t");
509 	MK_INSN(call_near1, "jmp 2f\n\t"
510 			    "1: mov $0x1234, %eax\n\t"
511 			    "ret\n\t"
512 			    "2: call 1b\t");
513 	MK_INSN(call_near2, "call 1f\n\t"
514 			    "jmp 2f\n\t"
515 			    "1: mov $0x1234, %eax\n\t"
516 			    "ret\n\t"
517 			    "2:\t");
518 	MK_INSN(call_far1,  "lcallw *(%ebx)\n\t");
519 	MK_INSN(call_far2,  "lcallw $0, $retf\n\t");
520 	MK_INSN(ret_imm,    "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b");
521 	MK_INSN(retf_imm,   "sub $10, %sp; lcallw $0, $retf_imm");
522 
523 	exec_in_big_real_mode(&insn_call1);
524 	report("call 1", R_AX, outregs.eax == 0x1234);
525 
526 	exec_in_big_real_mode(&insn_call_near1);
527 	report("call near 1", R_AX, outregs.eax == 0x1234);
528 
529 	exec_in_big_real_mode(&insn_call_near2);
530 	report("call near 2", R_AX, outregs.eax == 0x1234);
531 
532 	addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f);
533 	inregs.ebx = (unsigned)&addr;
534 	exec_in_big_real_mode(&insn_call_far1);
535 	report("call far 1", 0, 1);
536 
537 	exec_in_big_real_mode(&insn_call_far2);
538 	report("call far 2", 0, 1);
539 
540 	exec_in_big_real_mode(&insn_ret_imm);
541 	report("ret imm 1", 0, 1);
542 
543 	exec_in_big_real_mode(&insn_retf_imm);
544 	report("retf imm 1", 0, 1);
545 }
546 
547 void test_jcc_short(void)
548 {
549 	MK_INSN(jnz_short1, "jnz 1f\n\t"
550 			    "mov $0x1234, %eax\n\t"
551 		            "1:\n\t");
552 	MK_INSN(jnz_short2, "1:\n\t"
553 			    "cmp $0x1234, %eax\n\t"
554 			    "mov $0x1234, %eax\n\t"
555 		            "jnz 1b\n\t");
556 	MK_INSN(jmp_short1, "jmp 1f\n\t"
557 		      "mov $0x1234, %eax\n\t"
558 		      "1:\n\t");
559 
560 	inregs = (struct regs){ 0 };
561 
562 	exec_in_big_real_mode(&insn_jnz_short1);
563 	report("jnz short 1", ~0, 1);
564 
565 	exec_in_big_real_mode(&insn_jnz_short2);
566 	report("jnz short 2", R_AX, (outregs.eflags & (1 << 6)));
567 
568 	exec_in_big_real_mode(&insn_jmp_short1);
569 	report("jmp short 1", ~0, 1);
570 }
571 
572 void test_jcc_near(void)
573 {
574 	/* encode near jmp manually. gas will not do it if offsets < 127 byte */
575 	MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t"
576 		           "mov $0x1234, %eax\n\t");
577 	MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t"
578 			   "mov $0x1234, %eax\n\t"
579 		           ".byte 0x0f, 0x85, 0xf0, 0xff\n\t");
580 	MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t"
581 		           "mov $0x1234, %eax\n\t");
582 
583 	inregs = (struct regs){ 0 };
584 
585 	exec_in_big_real_mode(&insn_jnz_near1);
586 	report("jnz near 1", 0, 1);
587 
588 	exec_in_big_real_mode(&insn_jnz_near2);
589 	report("jnz near 2", R_AX, outregs.eflags & (1 << 6));
590 
591 	exec_in_big_real_mode(&insn_jmp_near1);
592 	report("jmp near 1", 0, 1);
593 }
594 
595 void test_long_jmp()
596 {
597 	u32 esp[16];
598 
599 	inregs = (struct regs){ 0 };
600 	inregs.esp = (u32)(esp+16);
601 	MK_INSN(long_jmp, "call 1f\n\t"
602 			  "jmp 2f\n\t"
603 			  "1: jmp $0, $test_function\n\t"
604 		          "2:\n\t");
605 	exec_in_big_real_mode(&insn_long_jmp);
606 	report("jmp far 1", R_AX, outregs.eax == 0x1234);
607 }
608 
609 void test_push_pop()
610 {
611 	MK_INSN(push32, "mov $0x12345678, %eax\n\t"
612 			"push %eax\n\t"
613 			"pop %ebx\n\t");
614 	MK_INSN(push16, "mov $0x1234, %ax\n\t"
615 			"push %ax\n\t"
616 			"pop %bx\n\t");
617 
618 	MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten
619 			 "mov $0x123, %ax\n\t"
620 			 "mov %ax, %es\n\t"
621 			 "push %es\n\t"
622 			 "pop %bx \n\t"
623 			 );
624 	MK_INSN(pop_es, "push %ax\n\t"
625 			"pop %es\n\t"
626 			"mov %es, %bx\n\t"
627 			);
628 	MK_INSN(push_pop_ss, "push %ss\n\t"
629 			     "pushw %ax\n\t"
630 			     "popw %ss\n\t"
631 			     "mov %ss, %bx\n\t"
632 			     "pop %ss\n\t"
633 			);
634 	MK_INSN(push_pop_fs, "push %fs\n\t"
635 			     "pushl %eax\n\t"
636 			     "popl %fs\n\t"
637 			     "mov %fs, %ebx\n\t"
638 			     "pop %fs\n\t"
639 			);
640 	MK_INSN(push_pop_high_esp_bits,
641 		"xor $0x12340000, %esp \n\t"
642 		"push %ax; \n\t"
643 		"xor $0x12340000, %esp \n\t"
644 		"pop %bx");
645 
646 	inregs = (struct regs){ 0 };
647 
648 	exec_in_big_real_mode(&insn_push32);
649 	report("push/pop 1", R_AX|R_BX,
650 	       outregs.eax == outregs.ebx && outregs.eax == 0x12345678);
651 
652 	exec_in_big_real_mode(&insn_push16);
653 	report("push/pop 2", R_AX|R_BX,
654 	       outregs.eax == outregs.ebx && outregs.eax == 0x1234);
655 
656 	exec_in_big_real_mode(&insn_push_es);
657 	report("push/pop 3", R_AX|R_BX,
658 	       outregs.ebx == outregs.eax && outregs.eax == 0x123);
659 
660 	exec_in_big_real_mode(&insn_pop_es);
661 	report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax);
662 
663 	exec_in_big_real_mode(&insn_push_pop_ss);
664 	report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax);
665 
666 	exec_in_big_real_mode(&insn_push_pop_fs);
667 	report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax);
668 
669 	inregs.eax = 0x9977;
670 	inregs.ebx = 0x7799;
671 	exec_in_big_real_mode(&insn_push_pop_high_esp_bits);
672 	report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977);
673 }
674 
675 void test_null(void)
676 {
677 	MK_INSN(null, "");
678 
679 	inregs = (struct regs){ 0 };
680 
681 	exec_in_big_real_mode(&insn_null);
682 	report("null", 0, 1);
683 }
684 
685 struct {
686     char stack[500];
687     char top[];
688 } tmp_stack;
689 
690 void test_pusha_popa()
691 {
692 	MK_INSN(pusha, "pusha\n\t"
693 		       "pop %edi\n\t"
694 		       "pop %esi\n\t"
695 		       "pop %ebp\n\t"
696 		       "add $4, %esp\n\t"
697 		       "pop %ebx\n\t"
698 		       "pop %edx\n\t"
699 		       "pop %ecx\n\t"
700 		       "pop %eax\n\t"
701 		       );
702 
703 	MK_INSN(popa, "push %eax\n\t"
704 		      "push %ecx\n\t"
705 		      "push %edx\n\t"
706 		      "push %ebx\n\t"
707 		      "push %esp\n\t"
708 		      "push %ebp\n\t"
709 		      "push %esi\n\t"
710 		      "push %edi\n\t"
711 		      "popa\n\t"
712 		      );
713 
714 	inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top };
715 
716 	exec_in_big_real_mode(&insn_pusha);
717 	report("pusha/popa 1", 0, 1);
718 
719 	exec_in_big_real_mode(&insn_popa);
720 	report("pusha/popa 1", 0, 1);
721 }
722 
723 void test_iret()
724 {
725 	MK_INSN(iret32, "pushf\n\t"
726 			"pushl %cs\n\t"
727 			"call 1f\n\t" /* a near call will push eip onto the stack */
728 			"jmp 2f\n\t"
729 			"1: iret\n\t"
730 			"2:\n\t"
731 		     );
732 
733 	MK_INSN(iret16, "pushfw\n\t"
734 			"pushw %cs\n\t"
735 			"callw 1f\n\t"
736 			"jmp 2f\n\t"
737 			"1: iretw\n\t"
738 			"2:\n\t");
739 
740 	MK_INSN(iret_flags32, "pushfl\n\t"
741 			      "popl %eax\n\t"
742 			      "andl $~0x2, %eax\n\t"
743 			      "orl $0xffc08028, %eax\n\t"
744 			      "pushl %eax\n\t"
745 			      "pushl %cs\n\t"
746 			      "call 1f\n\t"
747 			      "jmp 2f\n\t"
748 			      "1: iret\n\t"
749 			      "2:\n\t");
750 
751 	MK_INSN(iret_flags16, "pushfw\n\t"
752 			      "popw %ax\n\t"
753 			      "and $~0x2, %ax\n\t"
754 			      "or $0x8028, %ax\n\t"
755 			      "pushw %ax\n\t"
756 			      "pushw %cs\n\t"
757 			      "callw 1f\n\t"
758 			      "jmp 2f\n\t"
759 			      "1: iretw\n\t"
760 			      "2:\n\t");
761 
762 	inregs = (struct regs){ 0 };
763 
764 	exec_in_big_real_mode(&insn_iret32);
765 	report("iret 1", 0, 1);
766 
767 	exec_in_big_real_mode(&insn_iret16);
768 	report("iret 2", 0, 1);
769 
770 	exec_in_big_real_mode(&insn_iret_flags32);
771 	report("iret 3", R_AX, 1);
772 
773 	exec_in_big_real_mode(&insn_iret_flags16);
774 	report("iret 4", R_AX, 1);
775 }
776 
777 void test_int()
778 {
779 	inregs = (struct regs){ 0 };
780 
781 	*(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */
782 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
783 
784 	MK_INSN(int11, "int $0x11\n\t");
785 
786 	exec_in_big_real_mode(&insn_int11);
787 	report("int 1", 0, 1);
788 }
789 
790 void test_imul()
791 {
792 	MK_INSN(imul8_1, "mov $2, %al\n\t"
793 			"mov $-4, %cx\n\t"
794 			"imul %cl\n\t");
795 
796 	MK_INSN(imul16_1, "mov $2, %ax\n\t"
797 		      "mov $-4, %cx\n\t"
798 		      "imul %cx\n\t");
799 
800 	MK_INSN(imul32_1, "mov $2, %eax\n\t"
801 		       "mov $-4, %ecx\n\t"
802 		       "imul %ecx\n\t");
803 
804 	MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t"
805 			"mov $4, %cx\n\t"
806 			"imul %cl\n\t");
807 
808 	MK_INSN(imul16_2, "mov $2, %ax\n\t"
809 			"mov $4, %cx\n\t"
810 			"imul %cx\n\t");
811 
812 	MK_INSN(imul32_2, "mov $2, %eax\n\t"
813 			"mov $4, %ecx\n\t"
814 			"imul %ecx\n\t");
815 
816 	inregs = (struct regs){ 0 };
817 
818 	exec_in_big_real_mode(&insn_imul8_1);
819 	report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8);
820 
821 	exec_in_big_real_mode(&insn_imul16_1);
822 	report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8);
823 
824 	exec_in_big_real_mode(&insn_imul32_1);
825 	report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8);
826 
827 	exec_in_big_real_mode(&insn_imul8_2);
828 	report("imul 4", R_AX | R_CX | R_DX,
829 	       (outregs.eax & 0xffff) == 8
830 	       && (outregs.eax & 0xffff0000) == 0x12340000);
831 
832 	exec_in_big_real_mode(&insn_imul16_2);
833 	report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8);
834 
835 	exec_in_big_real_mode(&insn_imul32_2);
836 	report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8);
837 }
838 
839 void test_mul()
840 {
841 	MK_INSN(mul8, "mov $2, %al\n\t"
842 			"mov $4, %cx\n\t"
843 			"imul %cl\n\t");
844 
845 	MK_INSN(mul16, "mov $2, %ax\n\t"
846 			"mov $4, %cx\n\t"
847 			"imul %cx\n\t");
848 
849 	MK_INSN(mul32, "mov $2, %eax\n\t"
850 			"mov $4, %ecx\n\t"
851 			"imul %ecx\n\t");
852 
853 	inregs = (struct regs){ 0 };
854 
855 	exec_in_big_real_mode(&insn_mul8);
856 	report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8);
857 
858 	exec_in_big_real_mode(&insn_mul16);
859 	report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8);
860 
861 	exec_in_big_real_mode(&insn_mul32);
862 	report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8);
863 }
864 
865 void test_div()
866 {
867 	MK_INSN(div8, "mov $257, %ax\n\t"
868 			"mov $2, %cl\n\t"
869 			"div %cl\n\t");
870 
871 	MK_INSN(div16, "mov $512, %ax\n\t"
872 			"mov $5, %cx\n\t"
873 			"div %cx\n\t");
874 
875 	MK_INSN(div32, "mov $512, %eax\n\t"
876 			"mov $5, %ecx\n\t"
877 			"div %ecx\n\t");
878 
879 	inregs = (struct regs){ 0 };
880 
881 	exec_in_big_real_mode(&insn_div8);
882 	report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384);
883 
884 	exec_in_big_real_mode(&insn_div16);
885 	report("div 2", R_AX | R_CX | R_DX,
886 	       outregs.eax == 102 && outregs.edx == 2);
887 
888 	exec_in_big_real_mode(&insn_div32);
889 	report("div 3", R_AX | R_CX | R_DX,
890 	       outregs.eax == 102 && outregs.edx == 2);
891 }
892 
893 void test_idiv()
894 {
895 	MK_INSN(idiv8, "mov $256, %ax\n\t"
896 			"mov $-2, %cl\n\t"
897 			"idiv %cl\n\t");
898 
899 	MK_INSN(idiv16, "mov $512, %ax\n\t"
900 			"mov $-2, %cx\n\t"
901 			"idiv %cx\n\t");
902 
903 	MK_INSN(idiv32, "mov $512, %eax\n\t"
904 			"mov $-2, %ecx\n\t"
905 			"idiv %ecx\n\t");
906 
907 	inregs = (struct regs){ 0 };
908 
909 	exec_in_big_real_mode(&insn_idiv8);
910 	report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128);
911 
912 	exec_in_big_real_mode(&insn_idiv16);
913 	report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256);
914 
915 	exec_in_big_real_mode(&insn_idiv32);
916 	report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256);
917 }
918 
919 void test_cbw(void)
920 {
921 	MK_INSN(cbw, "mov $0xFE, %eax \n\t"
922 		     "cbw\n\t");
923 	MK_INSN(cwde, "mov $0xFFFE, %eax \n\t"
924 		      "cwde\n\t");
925 
926 	inregs = (struct regs){ 0 };
927 
928 	exec_in_big_real_mode(&insn_cbw);
929 	report("cbq 1", ~0, outregs.eax == 0xFFFE);
930 
931 	exec_in_big_real_mode(&insn_cwde);
932 	report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE);
933 }
934 
935 void test_loopcc(void)
936 {
937 	MK_INSN(loop, "mov $10, %ecx\n\t"
938 		      "1: inc %eax\n\t"
939 		      "loop 1b\n\t");
940 
941 	MK_INSN(loope, "mov $10, %ecx\n\t"
942 		       "mov $1, %eax\n\t"
943 		       "1: dec %eax\n\t"
944 		       "loope 1b\n\t");
945 
946 	MK_INSN(loopne, "mov $10, %ecx\n\t"
947 		        "mov $5, %eax\n\t"
948 		        "1: dec %eax\n\t"
949 			"loopne 1b\n\t");
950 
951 	inregs = (struct regs){ 0 };
952 
953 	exec_in_big_real_mode(&insn_loop);
954 	report("LOOPcc short 1", R_AX, outregs.eax == 10);
955 
956 	exec_in_big_real_mode(&insn_loope);
957 	report("LOOPcc short 2", R_AX | R_CX,
958 	       outregs.eax == -1 && outregs.ecx == 8);
959 
960 	exec_in_big_real_mode(&insn_loopne);
961 	report("LOOPcc short 3", R_AX | R_CX,
962 	       outregs.eax == 0 && outregs.ecx == 5);
963 }
964 
965 static void test_das(void)
966 {
967     short i;
968     u16 nr_fail = 0;
969     static unsigned test_cases[1024] = {
970         0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00,
971         0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01,
972         0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02,
973         0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03,
974         0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04,
975         0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05,
976         0x06000606, 0x8701a606, 0x56100006, 0x9711a006,
977         0x02000707, 0x8301a707, 0x12100107, 0x9311a107,
978         0x02000808, 0x8301a808, 0x12100208, 0x9311a208,
979         0x06000909, 0x8701a909, 0x16100309, 0x9711a309,
980         0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a,
981         0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b,
982         0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c,
983         0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d,
984         0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e,
985         0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f,
986         0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10,
987         0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11,
988         0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12,
989         0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13,
990         0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14,
991         0x02001515, 0x8301b515, 0x16100f15, 0x9711af15,
992         0x02001616, 0x8301b616, 0x12101016, 0x9311b016,
993         0x06001717, 0x8701b717, 0x16101117, 0x9711b117,
994         0x06001818, 0x8701b818, 0x16101218, 0x9711b218,
995         0x02001919, 0x8301b919, 0x12101319, 0x9311b319,
996         0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a,
997         0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b,
998         0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c,
999         0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d,
1000         0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e,
1001         0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f,
1002         0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20,
1003         0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21,
1004         0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22,
1005         0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23,
1006         0x06002424, 0x8301c424, 0x16101e24, 0x9711be24,
1007         0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25,
1008         0x02002626, 0x8701c626, 0x12102026, 0x9711c026,
1009         0x06002727, 0x8301c727, 0x16102127, 0x9311c127,
1010         0x06002828, 0x8301c828, 0x16102228, 0x9311c228,
1011         0x02002929, 0x8701c929, 0x12102329, 0x9711c329,
1012         0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a,
1013         0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b,
1014         0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c,
1015         0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d,
1016         0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e,
1017         0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f,
1018         0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30,
1019         0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31,
1020         0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32,
1021         0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33,
1022         0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34,
1023         0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35,
1024         0x06003636, 0x8301d636, 0x16103036, 0x9311d036,
1025         0x02003737, 0x8701d737, 0x12103137, 0x9711d137,
1026         0x02003838, 0x8701d838, 0x12103238, 0x9711d238,
1027         0x06003939, 0x8301d939, 0x16103339, 0x9311d339,
1028         0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a,
1029         0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b,
1030         0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c,
1031         0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d,
1032         0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e,
1033         0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f,
1034         0x02004040, 0x8301e040, 0x16103a40, 0x9311da40,
1035         0x06004141, 0x8701e141, 0x12103b41, 0x9711db41,
1036         0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42,
1037         0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43,
1038         0x06004444, 0x8701e444, 0x12103e44, 0x9711de44,
1039         0x02004545, 0x8301e545, 0x16103f45, 0x9311df45,
1040         0x02004646, 0x8301e646, 0x12104046, 0x9311e046,
1041         0x06004747, 0x8701e747, 0x16104147, 0x9711e147,
1042         0x06004848, 0x8701e848, 0x16104248, 0x9711e248,
1043         0x02004949, 0x8301e949, 0x12104349, 0x9311e349,
1044         0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a,
1045         0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b,
1046         0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c,
1047         0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d,
1048         0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e,
1049         0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f,
1050         0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50,
1051         0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51,
1052         0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52,
1053         0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53,
1054         0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54,
1055         0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55,
1056         0x06005656, 0x8701f656, 0x16105056, 0x9711f056,
1057         0x02005757, 0x8301f757, 0x12105157, 0x9311f157,
1058         0x02005858, 0x8301f858, 0x12105258, 0x9311f258,
1059         0x06005959, 0x8701f959, 0x16105359, 0x9711f359,
1060         0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a,
1061         0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b,
1062         0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c,
1063         0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d,
1064         0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e,
1065         0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f,
1066         0x06006060, 0x47010060, 0x16105a60, 0x9711fa60,
1067         0x02006161, 0x03010161, 0x12105b61, 0x9311fb61,
1068         0x02006262, 0x03010262, 0x16105c62, 0x9711fc62,
1069         0x06006363, 0x07010363, 0x12105d63, 0x9311fd63,
1070         0x02006464, 0x03010464, 0x12105e64, 0x9311fe64,
1071         0x06006565, 0x07010565, 0x16105f65, 0x9711ff65,
1072         0x06006666, 0x07010666, 0x16106066, 0x57110066,
1073         0x02006767, 0x03010767, 0x12106167, 0x13110167,
1074         0x02006868, 0x03010868, 0x12106268, 0x13110268,
1075         0x06006969, 0x07010969, 0x16106369, 0x17110369,
1076         0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a,
1077         0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b,
1078         0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c,
1079         0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d,
1080         0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e,
1081         0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f,
1082         0x02007070, 0x03011070, 0x16106a70, 0x17110a70,
1083         0x06007171, 0x07011171, 0x12106b71, 0x13110b71,
1084         0x06007272, 0x07011272, 0x16106c72, 0x17110c72,
1085         0x02007373, 0x03011373, 0x12106d73, 0x13110d73,
1086         0x06007474, 0x07011474, 0x12106e74, 0x13110e74,
1087         0x02007575, 0x03011575, 0x16106f75, 0x17110f75,
1088         0x02007676, 0x03011676, 0x12107076, 0x13111076,
1089         0x06007777, 0x07011777, 0x16107177, 0x17111177,
1090         0x06007878, 0x07011878, 0x16107278, 0x17111278,
1091         0x02007979, 0x03011979, 0x12107379, 0x13111379,
1092         0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a,
1093         0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b,
1094         0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c,
1095         0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d,
1096         0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e,
1097         0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f,
1098         0x82008080, 0x03012080, 0x12107a80, 0x13111a80,
1099         0x86008181, 0x07012181, 0x16107b81, 0x17111b81,
1100         0x86008282, 0x07012282, 0x12107c82, 0x13111c82,
1101         0x82008383, 0x03012383, 0x16107d83, 0x17111d83,
1102         0x86008484, 0x07012484, 0x16107e84, 0x17111e84,
1103         0x82008585, 0x03012585, 0x12107f85, 0x13111f85,
1104         0x82008686, 0x03012686, 0x92108086, 0x13112086,
1105         0x86008787, 0x07012787, 0x96108187, 0x17112187,
1106         0x86008888, 0x07012888, 0x96108288, 0x17112288,
1107         0x82008989, 0x03012989, 0x92108389, 0x13112389,
1108         0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a,
1109         0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b,
1110         0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c,
1111         0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d,
1112         0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e,
1113         0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f,
1114         0x86009090, 0x07013090, 0x92108a90, 0x13112a90,
1115         0x82009191, 0x03013191, 0x96108b91, 0x17112b91,
1116         0x82009292, 0x03013292, 0x92108c92, 0x13112c92,
1117         0x86009393, 0x07013393, 0x96108d93, 0x17112d93,
1118         0x82009494, 0x03013494, 0x96108e94, 0x17112e94,
1119         0x86009595, 0x07013595, 0x92108f95, 0x13112f95,
1120         0x86009696, 0x07013696, 0x96109096, 0x17113096,
1121         0x82009797, 0x03013797, 0x92109197, 0x13113197,
1122         0x82009898, 0x03013898, 0x92109298, 0x13113298,
1123         0x86009999, 0x07013999, 0x96109399, 0x17113399,
1124         0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a,
1125         0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b,
1126         0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c,
1127         0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d,
1128         0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e,
1129         0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f,
1130         0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0,
1131         0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1,
1132         0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2,
1133         0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3,
1134         0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4,
1135         0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5,
1136         0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6,
1137         0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7,
1138         0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8,
1139         0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9,
1140         0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa,
1141         0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab,
1142         0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac,
1143         0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad,
1144         0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae,
1145         0x130049af, 0x130149af, 0x131049af, 0x131149af,
1146         0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0,
1147         0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1,
1148         0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2,
1149         0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3,
1150         0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4,
1151         0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5,
1152         0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6,
1153         0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7,
1154         0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8,
1155         0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9,
1156         0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba,
1157         0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb,
1158         0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc,
1159         0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd,
1160         0x130058be, 0x130158be, 0x131058be, 0x131158be,
1161         0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf,
1162         0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0,
1163         0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1,
1164         0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2,
1165         0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3,
1166         0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4,
1167         0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5,
1168         0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6,
1169         0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7,
1170         0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8,
1171         0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9,
1172         0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca,
1173         0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb,
1174         0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc,
1175         0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd,
1176         0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce,
1177         0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf,
1178         0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0,
1179         0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1,
1180         0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2,
1181         0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3,
1182         0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4,
1183         0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5,
1184         0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6,
1185         0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7,
1186         0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8,
1187         0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9,
1188         0x170074da, 0x170174da, 0x171074da, 0x171174da,
1189         0x130075db, 0x130175db, 0x131075db, 0x131175db,
1190         0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc,
1191         0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd,
1192         0x170078de, 0x170178de, 0x171078de, 0x171178de,
1193         0x130079df, 0x130179df, 0x131079df, 0x131179df,
1194         0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0,
1195         0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1,
1196         0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2,
1197         0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3,
1198         0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4,
1199         0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5,
1200         0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6,
1201         0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7,
1202         0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8,
1203         0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9,
1204         0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea,
1205         0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb,
1206         0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec,
1207         0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed,
1208         0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee,
1209         0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef,
1210         0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0,
1211         0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1,
1212         0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2,
1213         0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3,
1214         0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4,
1215         0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5,
1216         0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6,
1217         0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7,
1218         0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8,
1219         0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9,
1220         0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa,
1221         0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb,
1222         0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc,
1223         0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd,
1224         0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe,
1225         0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff,
1226     };
1227 
1228     MK_INSN(das, "das");
1229 
1230     inregs = (struct regs){ 0 };
1231 
1232     for (i = 0; i < 1024; ++i) {
1233         unsigned tmp = test_cases[i];
1234         inregs.eax = tmp & 0xff;
1235         inregs.eflags = (tmp >> 16) & 0xff;
1236 	exec_in_big_real_mode(&insn_das);
1237 	if (!regs_equal(R_AX)
1238             || outregs.eax != ((tmp >> 8) & 0xff)
1239             || (outregs.eflags & 0xff) != (tmp >> 24)) {
1240 	    ++nr_fail;
1241 	    break;
1242         }
1243     }
1244     report("DAS", ~0, nr_fail == 0);
1245 }
1246 
1247 void test_cwd_cdq()
1248 {
1249 	/* Sign-bit set */
1250 	MK_INSN(cwd_1, "mov $0x8000, %ax\n\t"
1251 		       "cwd\n\t");
1252 
1253 	/* Sign-bit not set */
1254 	MK_INSN(cwd_2, "mov $0x1000, %ax\n\t"
1255 		       "cwd\n\t");
1256 
1257 	/* Sign-bit set */
1258 	MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t"
1259 		       "cdq\n\t");
1260 
1261 	/* Sign-bit not set */
1262 	MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t"
1263 		       "cdq\n\t");
1264 
1265 	inregs = (struct regs){ 0 };
1266 
1267 	exec_in_big_real_mode(&insn_cwd_1);
1268 	report("cwd 1", R_AX | R_DX,
1269 	       outregs.eax == 0x8000 && outregs.edx == 0xffff);
1270 
1271 	exec_in_big_real_mode(&insn_cwd_2);
1272 	report("cwd 2", R_AX | R_DX,
1273 	       outregs.eax == 0x1000 && outregs.edx == 0);
1274 
1275 	exec_in_big_real_mode(&insn_cdq_1);
1276 	report("cdq 1", R_AX | R_DX,
1277 	       outregs.eax == 0x80000000 && outregs.edx == 0xffffffff);
1278 
1279 	exec_in_big_real_mode(&insn_cdq_2);
1280 	report("cdq 2", R_AX | R_DX,
1281 	       outregs.eax == 0x10000000 && outregs.edx == 0);
1282 }
1283 
1284 static struct {
1285         void *address;
1286         unsigned short sel;
1287 } __attribute__((packed)) desc = {
1288 	(void *)0x1234,
1289 	0x10,
1290 };
1291 
1292 void test_lds_lss()
1293 {
1294 	inregs = (struct regs){ .ebx = (unsigned long)&desc };
1295 
1296 	MK_INSN(lds, "push %ds\n\t"
1297 		     "lds (%ebx), %eax\n\t"
1298 		     "mov %ds, %ebx\n\t"
1299 		     "pop %ds\n\t");
1300 	exec_in_big_real_mode(&insn_lds);
1301 	report("lds", R_AX | R_BX,
1302 		outregs.eax == (unsigned long)desc.address &&
1303 		outregs.ebx == desc.sel);
1304 
1305 	MK_INSN(les, "push %es\n\t"
1306 		     "les (%ebx), %eax\n\t"
1307 		     "mov %es, %ebx\n\t"
1308 		     "pop %es\n\t");
1309 	exec_in_big_real_mode(&insn_les);
1310 	report("les", R_AX | R_BX,
1311 		outregs.eax == (unsigned long)desc.address &&
1312 		outregs.ebx == desc.sel);
1313 
1314 	MK_INSN(lfs, "push %fs\n\t"
1315 		     "lfs (%ebx), %eax\n\t"
1316 		     "mov %fs, %ebx\n\t"
1317 		     "pop %fs\n\t");
1318 	exec_in_big_real_mode(&insn_lfs);
1319 	report("lfs", R_AX | R_BX,
1320 		outregs.eax == (unsigned long)desc.address &&
1321 		outregs.ebx == desc.sel);
1322 
1323 	MK_INSN(lgs, "push %gs\n\t"
1324 		     "lgs (%ebx), %eax\n\t"
1325 		     "mov %gs, %ebx\n\t"
1326 		     "pop %gs\n\t");
1327 	exec_in_big_real_mode(&insn_lgs);
1328 	report("lgs", R_AX | R_BX,
1329 		outregs.eax == (unsigned long)desc.address &&
1330 		outregs.ebx == desc.sel);
1331 
1332 	MK_INSN(lss, "push %ss\n\t"
1333 		     "lss (%ebx), %eax\n\t"
1334 		     "mov %ss, %ebx\n\t"
1335 		     "pop %ss\n\t");
1336 	exec_in_big_real_mode(&insn_lss);
1337 	report("lss", R_AX | R_BX,
1338 		outregs.eax == (unsigned long)desc.address &&
1339 		outregs.ebx == desc.sel);
1340 }
1341 
1342 void test_jcxz(void)
1343 {
1344 	MK_INSN(jcxz1, "jcxz 1f\n\t"
1345 		       "mov $0x1234, %eax\n\t"
1346 		       "1:\n\t");
1347 	MK_INSN(jcxz2, "mov $0x100, %ecx\n\t"
1348 		       "jcxz 1f\n\t"
1349 		       "mov $0x1234, %eax\n\t"
1350 		       "mov $0, %ecx\n\t"
1351 		       "1:\n\t");
1352 	MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t"
1353 		       "jcxz 1f\n\t"
1354 		       "mov $0x1234, %eax\n\t"
1355 		       "1:\n\t");
1356 	MK_INSN(jecxz1, "jecxz 1f\n\t"
1357 			"mov $0x1234, %eax\n\t"
1358 			"1:\n\t");
1359 	MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t"
1360 			"jecxz 1f\n\t"
1361 			"mov $0x1234, %eax\n\t"
1362 			"mov $0, %ecx\n\t"
1363 			"1:\n\t");
1364 
1365 	inregs = (struct regs){ 0 };
1366 
1367 	exec_in_big_real_mode(&insn_jcxz1);
1368 	report("jcxz short 1", 0, 1);
1369 
1370 	exec_in_big_real_mode(&insn_jcxz2);
1371 	report("jcxz short 2", R_AX, outregs.eax == 0x1234);
1372 
1373 	exec_in_big_real_mode(&insn_jcxz3);
1374 	report("jcxz short 3", R_CX, outregs.ecx == 0x10000);
1375 
1376 	exec_in_big_real_mode(&insn_jecxz1);
1377 	report("jecxz short 1", 0, 1);
1378 
1379 	exec_in_big_real_mode(&insn_jecxz2);
1380 	report("jecxz short 2", R_AX, outregs.eax == 0x1234);
1381 }
1382 
1383 static void test_cpuid(void)
1384 {
1385     MK_INSN(cpuid, "cpuid");
1386     unsigned function = 0x1234;
1387     unsigned eax, ebx, ecx, edx;
1388 
1389     inregs.eax = eax = function;
1390     inregs.ecx = ecx = 0;
1391     asm("cpuid" : "+a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx));
1392     exec_in_big_real_mode(&insn_cpuid);
1393     report("cpuid", R_AX|R_BX|R_CX|R_DX,
1394 	   outregs.eax == eax && outregs.ebx == ebx
1395 	   && outregs.ecx == ecx && outregs.edx == edx);
1396 }
1397 
1398 static void test_ss_base_for_esp_ebp(void)
1399 {
1400     MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss");
1401     MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss");
1402     static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 };
1403 
1404     inregs.ebx = 1;
1405     inregs.ebp = (unsigned)array;
1406     exec_in_big_real_mode(&insn_ssrel1);
1407     report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321);
1408     inregs.ebx = 1;
1409     inregs.ebp = (unsigned)array;
1410     inregs.edi = 0;
1411     exec_in_big_real_mode(&insn_ssrel2);
1412     report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321);
1413 }
1414 
1415 static void test_sgdt_sidt(void)
1416 {
1417     MK_INSN(sgdt, "sgdtw (%eax)");
1418     MK_INSN(sidt, "sidtw (%eax)");
1419     unsigned x, y;
1420 
1421     inregs.eax = (unsigned)&y;
1422     asm volatile("sgdtw %0" : "=m"(x));
1423     exec_in_big_real_mode(&insn_sgdt);
1424     report("sgdt", 0, x == y);
1425 
1426     inregs.eax = (unsigned)&y;
1427     asm volatile("sidtw %0" : "=m"(x));
1428     exec_in_big_real_mode(&insn_sidt);
1429     report("sidt", 0, x == y);
1430 }
1431 
1432 static void test_sahf(void)
1433 {
1434     MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw");
1435 
1436     inregs.eax = 0xfd00;
1437     exec_in_big_real_mode(&insn_sahf);
1438     report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7));
1439 }
1440 
1441 static void test_lahf(void)
1442 {
1443     MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf");
1444 
1445     inregs.eax = 0xc7;
1446     exec_in_big_real_mode(&insn_lahf);
1447     report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax);
1448 }
1449 
1450 static void test_movzx_movsx(void)
1451 {
1452     MK_INSN(movsx, "movsx %al, %ebx");
1453     MK_INSN(movzx, "movzx %al, %ebx");
1454     MK_INSN(movzsah, "movsx %ah, %ebx");
1455     MK_INSN(movzxah, "movzx %ah, %ebx");
1456 
1457     inregs.eax = 0x1234569c;
1458     inregs.esp = 0xffff;
1459     exec_in_big_real_mode(&insn_movsx);
1460     report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax);
1461     exec_in_big_real_mode(&insn_movzx);
1462     report("movzx", R_BX, outregs.ebx == (unsigned char)inregs.eax);
1463     exec_in_big_real_mode(&insn_movzsah);
1464     report("movsx ah", R_BX, outregs.ebx == (signed char)(inregs.eax>>8));
1465     exec_in_big_real_mode(&insn_movzxah);
1466     report("movzx ah", R_BX, outregs.ebx == (unsigned char)(inregs.eax >> 8));
1467 }
1468 
1469 static void test_bswap(void)
1470 {
1471     MK_INSN(bswap, "bswap %ecx");
1472 
1473     inregs.ecx = 0x12345678;
1474     exec_in_big_real_mode(&insn_bswap);
1475     report("bswap", R_CX, outregs.ecx == 0x78563412);
1476 }
1477 
1478 static void test_aad(void)
1479 {
1480     MK_INSN(aad, "aad");
1481 
1482     inregs.eax = 0x12345678;
1483     exec_in_big_real_mode(&insn_aad);
1484     report("aad", R_AX, outregs.eax == 0x123400d4);
1485 }
1486 
1487 static void test_aam(void)
1488 {
1489     MK_INSN(aam, "aam");
1490 
1491     inregs.eax = 0x76543210;
1492     exec_in_big_real_mode(&insn_aam);
1493     report("aam", R_AX, outregs.eax == 0x76540106);
1494 }
1495 
1496 static void test_xlat(void)
1497 {
1498     MK_INSN(xlat, "xlat");
1499     u8 table[256];
1500     int i;
1501 
1502     for (i = 0; i < 256; i++) {
1503         table[i] = i + 1;
1504     }
1505 
1506     inregs.eax = 0x89abcdef;
1507     inregs.ebx = (u32)table;
1508     exec_in_big_real_mode(&insn_xlat);
1509     report("xlat", R_AX, outregs.eax == 0x89abcdf0);
1510 }
1511 
1512 static void test_salc(void)
1513 {
1514     MK_INSN(clc_salc, "clc; .byte 0xd6");
1515     MK_INSN(stc_salc, "stc; .byte 0xd6");
1516 
1517     inregs.eax = 0x12345678;
1518     exec_in_big_real_mode(&insn_clc_salc);
1519     report("salc (1)", R_AX, outregs.eax == 0x12345600);
1520     exec_in_big_real_mode(&insn_stc_salc);
1521     report("salc (2)", R_AX, outregs.eax == 0x123456ff);
1522 }
1523 
1524 static void test_fninit(void)
1525 {
1526 	u16 fcw = -1, fsw = -1;
1527 	MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)");
1528 
1529 	inregs.eax = (u32)&fsw;
1530 	inregs.ebx = (u32)&fcw;
1531 
1532 	exec_in_big_real_mode(&insn_fninit);
1533 	report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f);
1534 }
1535 
1536 static void test_nopl(void)
1537 {
1538 	MK_INSN(nopl1, ".byte 0x90\n\r"); // 1 byte nop
1539 	MK_INSN(nopl2, ".byte 0x66, 0x90\n\r"); // 2 bytes nop
1540 	MK_INSN(nopl3, ".byte 0x0f, 0x1f, 0x00\n\r"); // 3 bytes nop
1541 	MK_INSN(nopl4, ".byte 0x0f, 0x1f, 0x40, 0x00\n\r"); // 4 bytes nop
1542 	exec_in_big_real_mode(&insn_nopl1);
1543 	exec_in_big_real_mode(&insn_nopl2);
1544 	exec_in_big_real_mode(&insn_nopl3);
1545 	exec_in_big_real_mode(&insn_nopl4);
1546 	report("nopl", 0, 1);
1547 }
1548 
1549 static u32 perf_baseline;
1550 
1551 #define PERF_COUNT 100000
1552 
1553 #define MK_INSN_PERF(name, insn)                                \
1554 	MK_INSN(name, "rdtsc; mov %eax, %ebx; mov %edx, %esi\n" \
1555 		      "1:" insn "\n"                            \
1556 		      "loop 1b\n"                               \
1557 		      "rdtsc");
1558 
1559 static u32 cycles_in_big_real_mode(struct insn_desc *insn)
1560 {
1561 	u64 start, end;
1562 
1563 	inregs.ecx = PERF_COUNT;
1564 	exec_in_big_real_mode(insn);
1565 	start = ((u64)outregs.esi << 32) | outregs.ebx;
1566 	end = ((u64)outregs.edx << 32) | outregs.eax;
1567 
1568 	return end - start;
1569 }
1570 
1571 static void test_perf_loop(void)
1572 {
1573 	/*
1574 	 * This test runs simple instructions that should roughly take the
1575 	 * the same time to emulate: PERF_COUNT iterations of "loop" and 3
1576 	 * setup instructions.  Other performance tests can run PERF_COUNT
1577 	 * iterations of the same instruction and subtract the cycle count
1578 	 * of this test.
1579 	 */
1580 	MK_INSN_PERF(perf_loop, "");
1581 	perf_baseline = cycles_in_big_real_mode(&insn_perf_loop);
1582 	print_serial_u32(perf_baseline / (PERF_COUNT + 3));
1583 	print_serial(" cycles/emulated jump instruction\n");
1584 }
1585 
1586 static void test_perf_mov(void)
1587 {
1588 	u32 cyc;
1589 
1590 	MK_INSN_PERF(perf_move, "mov %esi, %edi");
1591 	cyc = cycles_in_big_real_mode(&insn_perf_move);
1592 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1593 	print_serial(" cycles/emulated move instruction\n");
1594 }
1595 
1596 static void test_perf_arith(void)
1597 {
1598 	u32 cyc;
1599 
1600 	MK_INSN_PERF(perf_arith, "add $4, %edi");
1601 	cyc = cycles_in_big_real_mode(&insn_perf_arith);
1602 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1603 	print_serial(" cycles/emulated arithmetic instruction\n");
1604 }
1605 
1606 static void test_perf_memory_load(void)
1607 {
1608 	u32 cyc, tmp;
1609 
1610 	MK_INSN_PERF(perf_memory_load, "cmp $0, (%edi)");
1611 	inregs.edi = (u32)&tmp;
1612 	cyc = cycles_in_big_real_mode(&insn_perf_memory_load);
1613 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1614 	print_serial(" cycles/emulated memory load instruction\n");
1615 }
1616 
1617 static void test_perf_memory_rmw(void)
1618 {
1619 	u32 cyc, tmp;
1620 
1621 	MK_INSN_PERF(perf_memory_rmw, "add $1, (%edi)");
1622 	inregs.edi = (u32)&tmp;
1623 	cyc = cycles_in_big_real_mode(&insn_perf_memory_rmw);
1624 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1625 	print_serial(" cycles/emulated memory RMW instruction\n");
1626 }
1627 
1628 void realmode_start(void)
1629 {
1630 	test_null();
1631 
1632 	test_shld();
1633 	test_push_pop();
1634 	test_pusha_popa();
1635 	test_mov_imm();
1636 	test_cmp_imm();
1637 	test_add_imm();
1638 	test_sub_imm();
1639 	test_xor_imm();
1640 	test_io();
1641 	test_eflags_insn();
1642 	test_jcc_short();
1643 	test_jcc_near();
1644 	/* test_call() uses short jump so call it after testing jcc */
1645 	test_call();
1646 	/* long jmp test uses call near so test it after testing call */
1647 	test_long_jmp();
1648 	test_xchg();
1649 	test_iret();
1650 	test_int();
1651 	test_imul();
1652 	test_mul();
1653 	test_div();
1654 	test_idiv();
1655 	test_loopcc();
1656 	test_cbw();
1657 	test_cwd_cdq();
1658 	test_das();
1659 	test_lds_lss();
1660 	test_jcxz();
1661 	test_cpuid();
1662 	test_ss_base_for_esp_ebp();
1663 	test_sgdt_sidt();
1664 	test_lahf();
1665 	test_sahf();
1666 	test_movzx_movsx();
1667 	test_bswap();
1668 	test_aad();
1669 	test_aam();
1670 	test_xlat();
1671 	test_salc();
1672 	test_fninit();
1673 	test_nopl();
1674 	test_perf_loop();
1675 	test_perf_mov();
1676 	test_perf_arith();
1677 	test_perf_memory_load();
1678 	test_perf_memory_rmw();
1679 
1680 	exit(0);
1681 }
1682 
1683 unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff };
1684 
1685 struct __attribute__((packed)) {
1686 	unsigned short limit;
1687 	void *base;
1688 } r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt };
1689 
1690 asm(
1691 	".section .init \n\t"
1692 
1693 	".code32 \n\t"
1694 
1695 	"mb_magic = 0x1BADB002 \n\t"
1696 	"mb_flags = 0x0 \n\t"
1697 
1698 	"# multiboot header \n\t"
1699 	".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t"
1700 
1701 	".globl start \n\t"
1702 	".data \n\t"
1703 	". = . + 4096 \n\t"
1704 	"stacktop: \n\t"
1705 
1706 	".text \n\t"
1707 	"start: \n\t"
1708 	"lgdt r_gdt_descr \n\t"
1709 	"ljmp $8, $1f; 1: \n\t"
1710 	".code16gcc \n\t"
1711 	"mov $16, %eax \n\t"
1712 	"mov %ax, %ds \n\t"
1713 	"mov %ax, %es \n\t"
1714 	"mov %ax, %fs \n\t"
1715 	"mov %ax, %gs \n\t"
1716 	"mov %ax, %ss \n\t"
1717 	"mov %cr0, %eax \n\t"
1718 	"btc $0, %eax \n\t"
1719 	"mov %eax, %cr0 \n\t"
1720 	"ljmp $0, $realmode_entry \n\t"
1721 
1722 	"realmode_entry: \n\t"
1723 
1724 	"xor %ax, %ax \n\t"
1725 	"mov %ax, %ds \n\t"
1726 	"mov %ax, %es \n\t"
1727 	"mov %ax, %ss \n\t"
1728 	"mov %ax, %fs \n\t"
1729 	"mov %ax, %gs \n\t"
1730 	"mov $stacktop, %esp\n\t"
1731 	"ljmp $0, $realmode_start \n\t"
1732 
1733 	".code16gcc \n\t"
1734 	);
1735