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