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