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