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