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