xref: /kvm-unit-tests/x86/realmode.c (revision 32001692368961d7584c99091bee218628a209e2) !
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 void test_call(void)
608 {
609 	struct regs inregs = { 0 }, outregs;
610 	u32 esp[16];
611 
612 	inregs.esp = (u32)esp;
613 
614 	MK_INSN(call1, "mov $test_function, %eax \n\t"
615 		       "call *%eax\n\t");
616 	MK_INSN(call_near1, "jmp 2f\n\t"
617 			    "1: mov $0x1234, %eax\n\t"
618 			    "ret\n\t"
619 			    "2: call 1b\t");
620 	MK_INSN(call_near2, "call 1f\n\t"
621 			    "jmp 2f\n\t"
622 			    "1: mov $0x1234, %eax\n\t"
623 			    "ret\n\t"
624 			    "2:\t");
625 
626 	exec_in_big_real_mode(&inregs, &outregs,
627 			      insn_call1,
628 			      insn_call1_end - insn_call1);
629 	if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234)
630 		print_serial("Call Test 1: FAIL\n");
631 	else
632 		print_serial("Call Test 1: PASS\n");
633 
634 	exec_in_big_real_mode(&inregs, &outregs,
635 			insn_call_near1, insn_call_near1_end - insn_call_near1);
636 	if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234)
637 		print_serial("Call near Test 1: FAIL\n");
638 	else
639 		print_serial("Call near Test 1: PASS\n");
640 
641 	exec_in_big_real_mode(&inregs, &outregs,
642 			insn_call_near2, insn_call_near2_end - insn_call_near2);
643 	if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234)
644 		print_serial("Call near Test 2: FAIL\n");
645 	else
646 		print_serial("Call near Test 2: PASS\n");
647 }
648 
649 void test_jcc_short(void)
650 {
651 	struct regs inregs = { 0 }, outregs;
652 	MK_INSN(jnz_short1, "jnz 1f\n\t"
653 			    "mov $0x1234, %eax\n\t"
654 		            "1:\n\t");
655 	MK_INSN(jnz_short2, "1:\n\t"
656 			    "cmp $0x1234, %eax\n\t"
657 			    "mov $0x1234, %eax\n\t"
658 		            "jnz 1b\n\t");
659 	MK_INSN(jmp_short1, "jmp 1f\n\t"
660 		      "mov $0x1234, %eax\n\t"
661 		      "1:\n\t");
662 
663 	exec_in_big_real_mode(&inregs, &outregs,
664 			insn_jnz_short1, insn_jnz_short1_end - insn_jnz_short1);
665 	if(!regs_equal(&inregs, &outregs, 0))
666 		print_serial("JNZ short Test 1: FAIL\n");
667 	else
668 		print_serial("JNZ short Test 1: PASS\n");
669 
670 	exec_in_big_real_mode(&inregs, &outregs,
671 			insn_jnz_short2, insn_jnz_short2_end - insn_jnz_short2);
672 	if(!regs_equal(&inregs, &outregs, R_AX) || !(outregs.eflags & (1 << 6)))
673 		print_serial("JNZ short Test 2: FAIL\n");
674 	else
675 		print_serial("JNZ short Test 2: PASS\n");
676 
677 	exec_in_big_real_mode(&inregs, &outregs,
678 			insn_jmp_short1, insn_jmp_short1_end - insn_jmp_short1);
679 	if(!regs_equal(&inregs, &outregs, 0))
680 		print_serial("JMP short Test 1: FAIL\n");
681 	else
682 		print_serial("JMP short Test 1: PASS\n");
683 }
684 
685 void test_jcc_near(void)
686 {
687 	struct regs inregs = { 0 }, outregs;
688 	/* encode near jmp manually. gas will not do it if offsets < 127 byte */
689 	MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t"
690 		           "mov $0x1234, %eax\n\t");
691 	MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t"
692 			   "mov $0x1234, %eax\n\t"
693 		           ".byte 0x0f, 0x85, 0xf0, 0xff\n\t");
694 	MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t"
695 		           "mov $0x1234, %eax\n\t");
696 
697 	exec_in_big_real_mode(&inregs, &outregs,
698 			insn_jnz_near1, insn_jnz_near1_end - insn_jnz_near1);
699 	if(!regs_equal(&inregs, &outregs, 0))
700 		print_serial("JNZ near Test 1: FAIL\n");
701 	else
702 		print_serial("JNZ near Test 1: PASS\n");
703 
704 	exec_in_big_real_mode(&inregs, &outregs,
705 			insn_jnz_near2, insn_jnz_near2_end - insn_jnz_near2);
706 	if(!regs_equal(&inregs, &outregs, R_AX) || !(outregs.eflags & (1 << 6)))
707 		print_serial("JNZ near Test 2: FAIL\n");
708 	else
709 		print_serial("JNZ near Test 2: PASS\n");
710 
711 	exec_in_big_real_mode(&inregs, &outregs,
712 			insn_jmp_near1, insn_jmp_near1_end - insn_jmp_near1);
713 	if(!regs_equal(&inregs, &outregs, 0))
714 		print_serial("JMP near Test 1: FAIL\n");
715 	else
716 		print_serial("JMP near Test 1: PASS\n");
717 }
718 
719 void test_long_jmp()
720 {
721 	struct regs inregs = { 0 }, outregs;
722 	u32 esp[16];
723 
724 	inregs.esp = (u32)esp;
725 	MK_INSN(long_jmp, "call 1f\n\t"
726 			  "jmp 2f\n\t"
727 			  "1: jmp $0, $test_function\n\t"
728 		          "2:\n\t");
729 	exec_in_big_real_mode(&inregs, &outregs,
730 			      insn_long_jmp,
731 			      insn_long_jmp_end - insn_long_jmp);
732 	if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234)
733 		print_serial("Long JMP Test: FAIL\n");
734 	else
735 		print_serial("Long JMP Test: PASS\n");
736 }
737 
738 void test_push_pop()
739 {
740 	struct regs inregs = { 0 }, outregs;
741 	MK_INSN(push32, "mov $0x12345678, %eax\n\t"
742 			"push %eax\n\t"
743 			"pop %ebx\n\t");
744 	MK_INSN(push16, "mov $0x1234, %ax\n\t"
745 			"push %ax\n\t"
746 			"pop %bx\n\t");
747 
748 	MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten
749 			 "mov $0x123, %ax\n\t"
750 			 "mov %ax, %es\n\t"
751 			 "push %es\n\t"
752 			 "pop %bx \n\t"
753 			 );
754 	MK_INSN(pop_es, "push %ax\n\t"
755 			"pop %es\n\t"
756 			"mov %es, %bx\n\t"
757 			);
758 	MK_INSN(push_pop_ss, "push %ss\n\t"
759 			     "pushw %ax\n\t"
760 			     "popw %ss\n\t"
761 			     "mov %ss, %bx\n\t"
762 			     "pop %ss\n\t"
763 			);
764 	MK_INSN(push_pop_fs, "push %fs\n\t"
765 			     "pushl %eax\n\t"
766 			     "popl %fs\n\t"
767 			     "mov %fs, %ebx\n\t"
768 			     "pop %fs\n\t"
769 			);
770 
771 	exec_in_big_real_mode(&inregs, &outregs,
772 			      insn_push32,
773 			      insn_push32_end - insn_push32);
774 	if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.eax != outregs.ebx || outregs.eax != 0x12345678)
775 		print_serial("Push/Pop Test 1: FAIL\n");
776 	else
777 		print_serial("Push/Pop Test 1: PASS\n");
778 
779 	exec_in_big_real_mode(&inregs, &outregs,
780 			      insn_push16,
781 			      insn_push16_end - insn_push16);
782 
783 	if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.eax != outregs.ebx || outregs.eax != 0x1234)
784 		print_serial("Push/Pop Test 2: FAIL\n");
785 	else
786 		print_serial("Push/Pop Test 2: PASS\n");
787 
788 	exec_in_big_real_mode(&inregs, &outregs,
789 			      insn_push_es,
790 			      insn_push_es_end - insn_push_es);
791 	if (!regs_equal(&inregs, &outregs, R_AX|R_BX) ||  outregs.ebx != outregs.eax || outregs.eax != 0x123)
792 		print_serial("Push/Pop Test 3: FAIL\n");
793 	else
794 		print_serial("Push/Pop Test 3: PASS\n");
795 
796 	exec_in_big_real_mode(&inregs, &outregs,
797 			      insn_pop_es,
798 			      insn_pop_es_end - insn_pop_es);
799 
800 	if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.ebx != outregs.eax)
801 		print_serial("Push/Pop Test 4: FAIL\n");
802 	else
803 		print_serial("Push/Pop Test 4: PASS\n");
804 
805 	exec_in_big_real_mode(&inregs, &outregs,
806 			      insn_push_pop_ss,
807 			      insn_push_pop_ss_end - insn_push_pop_ss);
808 
809 	if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.ebx != outregs.eax)
810 		print_serial("Push/Pop Test 5: FAIL\n");
811 	else
812 		print_serial("Push/Pop Test 5: PASS\n");
813 
814 	exec_in_big_real_mode(&inregs, &outregs,
815 			      insn_push_pop_fs,
816 			      insn_push_pop_fs_end - insn_push_pop_fs);
817 
818 	if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.ebx != outregs.eax)
819 		print_serial("Push/Pop Test 6: FAIL\n");
820 	else
821 		print_serial("Push/Pop Test 6: PASS\n");
822 }
823 
824 void test_null(void)
825 {
826 	struct regs inregs = { 0 }, outregs;
827 	exec_in_big_real_mode(&inregs, &outregs, 0, 0);
828 	if (!regs_equal(&inregs, &outregs, 0))
829 		print_serial("null test: FAIL\n");
830 	else
831 		print_serial("null test: PASS\n");
832 }
833 
834 struct {
835     char stack[500];
836     char top[];
837 } tmp_stack;
838 
839 void test_pusha_popa()
840 {
841 	struct regs inregs = { .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top }, outregs;
842 
843 	MK_INSN(pusha, "pusha\n\t"
844 		       "pop %edi\n\t"
845 		       "pop %esi\n\t"
846 		       "pop %ebp\n\t"
847 		       "add $4, %esp\n\t"
848 		       "pop %ebx\n\t"
849 		       "pop %edx\n\t"
850 		       "pop %ecx\n\t"
851 		       "pop %eax\n\t"
852 		       );
853 
854 	MK_INSN(popa, "push %eax\n\t"
855 		      "push %ecx\n\t"
856 		      "push %edx\n\t"
857 		      "push %ebx\n\t"
858 		      "push %esp\n\t"
859 		      "push %ebp\n\t"
860 		      "push %esi\n\t"
861 		      "push %edi\n\t"
862 		      "popa\n\t"
863 		      );
864 
865 	exec_in_big_real_mode(&inregs, &outregs,
866 			      insn_pusha,
867 			      insn_pusha_end - insn_pusha);
868 
869 	if (!regs_equal(&inregs, &outregs, 0))
870 		print_serial("Pusha/Popa Test1: FAIL\n");
871 	else
872 		print_serial("Pusha/Popa Test1: PASS\n");
873 
874 	exec_in_big_real_mode(&inregs, &outregs,
875 			      insn_popa,
876 			      insn_popa_end - insn_popa);
877 	if (!regs_equal(&inregs, &outregs, 0))
878 		print_serial("Pusha/Popa Test2: FAIL\n");
879 	else
880 		print_serial("Pusha/Popa Test2: PASS\n");
881 }
882 
883 void test_iret()
884 {
885 	struct regs inregs = { 0 }, outregs;
886 
887 	MK_INSN(iret32, "pushf\n\t"
888 			"pushl %cs\n\t"
889 			"call 1f\n\t" /* a near call will push eip onto the stack */
890 			"jmp 2f\n\t"
891 			"1: iret\n\t"
892 			"2:\n\t"
893 		     );
894 
895 	MK_INSN(iret16, "pushfw\n\t"
896 			"pushw %cs\n\t"
897 			"callw 1f\n\t"
898 			"jmp 2f\n\t"
899 			"1: iretw\n\t"
900 			"2:\n\t");
901 
902 	MK_INSN(iret_flags32, "pushfl\n\t"
903 			      "popl %eax\n\t"
904 			      "andl $~0x2, %eax\n\t"
905 			      "orl $0xffc08028, %eax\n\t"
906 			      "pushl %eax\n\t"
907 			      "pushl %cs\n\t"
908 			      "call 1f\n\t"
909 			      "jmp 2f\n\t"
910 			      "1: iret\n\t"
911 			      "2:\n\t");
912 
913 	MK_INSN(iret_flags16, "pushfw\n\t"
914 			      "popw %ax\n\t"
915 			      "and $~0x2, %ax\n\t"
916 			      "or $0x8028, %ax\n\t"
917 			      "pushw %ax\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 	exec_in_big_real_mode(&inregs, &outregs,
925 			      insn_iret32,
926 			      insn_iret32_end - insn_iret32);
927 
928 	if (!regs_equal(&inregs, &outregs, 0))
929 		print_serial("iret Test 1: FAIL\n");
930 	else
931 		print_serial("iret Test 1: PASS\n");
932 
933 	exec_in_big_real_mode(&inregs, &outregs,
934 			      insn_iret16,
935 			      insn_iret16_end - insn_iret16);
936 
937 	if (!regs_equal(&inregs, &outregs, 0))
938 		print_serial("iret Test 2: FAIL\n");
939 	else
940 		print_serial("iret Test 2: PASS\n");
941 
942 	exec_in_big_real_mode(&inregs, &outregs,
943 			      insn_iret_flags32,
944 			      insn_iret_flags32_end - insn_iret_flags32);
945 
946 	if (!regs_equal(&inregs, &outregs, R_AX))
947 		print_serial("iret Test 3: FAIL\n");
948 	else
949 		print_serial("iret Test 3: PASS\n");
950 
951 	exec_in_big_real_mode(&inregs, &outregs,
952 			      insn_iret_flags16,
953 			      insn_iret_flags16_end - insn_iret_flags16);
954 
955 	if (!regs_equal(&inregs, &outregs, R_AX))
956 		print_serial("iret Test 4: FAIL\n");
957 	else
958 		print_serial("iret Test 4: PASS\n");
959 }
960 
961 void test_int()
962 {
963 	struct regs inregs = { 0 }, outregs;
964 
965 	*(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */
966 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
967 
968 	MK_INSN(int11, "int $0x11\n\t");
969 
970 	exec_in_big_real_mode(&inregs, &outregs,
971 			      insn_int11,
972 			      insn_int11_end - insn_int11);
973 
974 	if (!regs_equal(&inregs, &outregs, 0))
975 		print_serial("int Test 1: FAIL\n");
976 	else
977 		print_serial("int Test 1: PASS\n");
978 }
979 
980 void test_imul()
981 {
982 	struct regs inregs = { 0 }, outregs;
983 
984 	MK_INSN(imul8_1, "mov $2, %al\n\t"
985 			"mov $-4, %cx\n\t"
986 			"imul %cl\n\t");
987 
988 	MK_INSN(imul16_1, "mov $2, %ax\n\t"
989 		      "mov $-4, %cx\n\t"
990 		      "imul %cx\n\t");
991 
992 	MK_INSN(imul32_1, "mov $2, %eax\n\t"
993 		       "mov $-4, %ecx\n\t"
994 		       "imul %ecx\n\t");
995 
996 	MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t"
997 			"mov $4, %cx\n\t"
998 			"imul %cl\n\t");
999 
1000 	MK_INSN(imul16_2, "mov $2, %ax\n\t"
1001 			"mov $4, %cx\n\t"
1002 			"imul %cx\n\t");
1003 
1004 	MK_INSN(imul32_2, "mov $2, %eax\n\t"
1005 			"mov $4, %ecx\n\t"
1006 			"imul %ecx\n\t");
1007 
1008 	exec_in_big_real_mode(&inregs, &outregs,
1009 			      insn_imul8_1,
1010 			      insn_imul8_1_end - insn_imul8_1);
1011 
1012 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || (outregs.eax & 0xff) != (u8)-8)
1013 		print_serial("imul Test 1: FAIL\n");
1014 	else
1015 		print_serial("imul Test 1: PASS\n");
1016 
1017 	exec_in_big_real_mode(&inregs, &outregs,
1018 			      insn_imul16_1,
1019 			      insn_imul16_1_end - insn_imul16_1);
1020 
1021 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u16)-8)
1022 		print_serial("imul Test 2: FAIL\n");
1023 	else
1024 		print_serial("imul Test 2: PASS\n");
1025 
1026 	exec_in_big_real_mode(&inregs, &outregs,
1027 			      insn_imul32_1,
1028 			      insn_imul32_1_end - insn_imul32_1);
1029 
1030 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u32)-8)
1031 		print_serial("imul Test 3: FAIL\n");
1032 	else
1033 		print_serial("imul Test 3: PASS\n");
1034 
1035 	exec_in_big_real_mode(&inregs, &outregs,
1036 			      insn_imul8_2,
1037 			      insn_imul8_2_end - insn_imul8_2);
1038 
1039 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || (outregs.eax & 0xffff) != 8 ||
1040 	     (outregs.eax & 0xffff0000) != 0x12340000)
1041 		print_serial("imul Test 4: FAIL\n");
1042 	else
1043 		print_serial("imul Test 4: PASS\n");
1044 
1045 	exec_in_big_real_mode(&inregs, &outregs,
1046 			      insn_imul16_2,
1047 			      insn_imul16_2_end - insn_imul16_2);
1048 
1049 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 8)
1050 		print_serial("imul Test 5: FAIL\n");
1051 	else
1052 		print_serial("imul Test 5: PASS\n");
1053 
1054 	exec_in_big_real_mode(&inregs, &outregs,
1055 			      insn_imul32_2,
1056 			      insn_imul32_2_end - insn_imul32_2);
1057 
1058 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 8)
1059 		print_serial("imul Test 6: FAIL\n");
1060 	else
1061 		print_serial("imul Test 6: PASS\n");
1062 }
1063 
1064 void test_mul()
1065 {
1066 	struct regs inregs = { 0 }, outregs;
1067 
1068 	MK_INSN(mul8, "mov $2, %al\n\t"
1069 			"mov $4, %cx\n\t"
1070 			"imul %cl\n\t");
1071 
1072 	MK_INSN(mul16, "mov $2, %ax\n\t"
1073 			"mov $4, %cx\n\t"
1074 			"imul %cx\n\t");
1075 
1076 	MK_INSN(mul32, "mov $2, %eax\n\t"
1077 			"mov $4, %ecx\n\t"
1078 			"imul %ecx\n\t");
1079 
1080 	exec_in_big_real_mode(&inregs, &outregs,
1081 			      insn_mul8,
1082 			      insn_mul8_end - insn_mul8);
1083 
1084 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || (outregs.eax & 0xff) != 8)
1085 		print_serial("mul Test 1: FAIL\n");
1086 	else
1087 		print_serial("mul Test 1: PASS\n");
1088 
1089 	exec_in_big_real_mode(&inregs, &outregs,
1090 			      insn_mul16,
1091 			      insn_mul16_end - insn_mul16);
1092 
1093 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 8)
1094 		print_serial("mul Test 2: FAIL\n");
1095 	else
1096 		print_serial("mul Test 2: PASS\n");
1097 
1098 	exec_in_big_real_mode(&inregs, &outregs,
1099 			      insn_mul32,
1100 			      insn_mul32_end - insn_mul32);
1101 
1102 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 8)
1103 		print_serial("mul Test 3: FAIL\n");
1104 	else
1105 		print_serial("mul Test 3: PASS\n");
1106 }
1107 
1108 void test_div()
1109 {
1110 	struct regs inregs = { 0 }, outregs;
1111 
1112 	MK_INSN(div8, "mov $257, %ax\n\t"
1113 			"mov $2, %cl\n\t"
1114 			"div %cl\n\t");
1115 
1116 	MK_INSN(div16, "mov $512, %ax\n\t"
1117 			"mov $5, %cx\n\t"
1118 			"div %cx\n\t");
1119 
1120 	MK_INSN(div32, "mov $512, %eax\n\t"
1121 			"mov $5, %ecx\n\t"
1122 			"div %ecx\n\t");
1123 
1124 	exec_in_big_real_mode(&inregs, &outregs,
1125 			     insn_div8,
1126 			     insn_div8_end - insn_div8);
1127 
1128 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 384)
1129 		print_serial("div Test 1: FAIL\n");
1130 	else
1131 		print_serial("div Test 1: PASS\n");
1132 
1133 	exec_in_big_real_mode(&inregs, &outregs,
1134 			      insn_div16,
1135 			      insn_div16_end - insn_div16);
1136 
1137 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 102 ||
1138 	    outregs.edx != 2)
1139 		print_serial("div Test 2: FAIL\n");
1140 	else
1141 		print_serial("div Test 2: PASS\n");
1142 
1143 	exec_in_big_real_mode(&inregs, &outregs,
1144 			      insn_div32,
1145 			      insn_div32_end - insn_div32);
1146 
1147 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 102 ||
1148 	    outregs.edx != 2)
1149 		print_serial("div Test 3: FAIL\n");
1150 	else
1151 		print_serial("div Test 3: PASS\n");
1152 }
1153 
1154 void test_idiv()
1155 {
1156 	struct regs inregs = { 0 }, outregs;
1157 
1158 	MK_INSN(idiv8, "mov $256, %ax\n\t"
1159 			"mov $-2, %cl\n\t"
1160 			"idiv %cl\n\t");
1161 
1162 	MK_INSN(idiv16, "mov $512, %ax\n\t"
1163 			"mov $-2, %cx\n\t"
1164 			"idiv %cx\n\t");
1165 
1166 	MK_INSN(idiv32, "mov $512, %eax\n\t"
1167 			"mov $-2, %ecx\n\t"
1168 			"idiv %ecx\n\t");
1169 
1170 	exec_in_big_real_mode(&inregs, &outregs,
1171 			     insn_idiv8,
1172 			     insn_idiv8_end - insn_idiv8);
1173 
1174 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u8)-128)
1175 		print_serial("idiv Test 1: FAIL\n");
1176 	else
1177 		print_serial("idiv Test 1: PASS\n");
1178 
1179 	exec_in_big_real_mode(&inregs, &outregs,
1180 			      insn_idiv16,
1181 			      insn_idiv16_end - insn_idiv16);
1182 
1183 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u16)-256)
1184 		print_serial("idiv Test 2: FAIL\n");
1185 	else
1186 		print_serial("idiv Test 2: PASS\n");
1187 
1188 	exec_in_big_real_mode(&inregs, &outregs,
1189 			      insn_idiv32,
1190 			      insn_idiv32_end - insn_idiv32);
1191 
1192 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u32)-256)
1193 		print_serial("idiv Test 3: FAIL\n");
1194 	else
1195 		print_serial("idiv Test 3: PASS\n");
1196 }
1197 
1198 void test_cbw(void)
1199 {
1200 	struct regs inregs = { 0 }, outregs;
1201 
1202 	MK_INSN(cbw, "mov $0xFE, %eax \n\t"
1203 		     "cbw\n\t");
1204 	MK_INSN(cwde, "mov $0xFFFE, %eax \n\t"
1205 		      "cwde\n\t");
1206 
1207 	exec_in_big_real_mode(&inregs, &outregs,
1208 			      insn_cbw,
1209 			      insn_cbw_end - insn_cbw);
1210 	if (outregs.eax != 0xFFFE)
1211 		print_serial("cbw test1: FAIL\n");
1212 	else
1213 		print_serial("cbw test 1: PASS\n");
1214 
1215 	exec_in_big_real_mode(&inregs, &outregs,
1216 			      insn_cwde,
1217 			      insn_cwde_end - insn_cwde);
1218 	if (outregs.eax != 0xFFFFFFFE)
1219 		print_serial("cwde test1: FAIL\n");
1220 	else
1221 		print_serial("cwde test 1: PASS\n");
1222 }
1223 
1224 void test_loopcc(void)
1225 {
1226 	struct regs inregs = { 0 }, outregs;
1227 
1228 	MK_INSN(loop, "mov $10, %ecx\n\t"
1229 		      "1: inc %eax\n\t"
1230 		      "loop 1b\n\t");
1231 
1232 	MK_INSN(loope, "mov $10, %ecx\n\t"
1233 		       "mov $1, %eax\n\t"
1234 		       "1: dec %eax\n\t"
1235 		       "loope 1b\n\t");
1236 
1237 	MK_INSN(loopne, "mov $10, %ecx\n\t"
1238 		        "mov $5, %eax\n\t"
1239 		        "1: dec %eax\n\t"
1240 			"loopne 1b\n\t");
1241 
1242 	exec_in_big_real_mode(&inregs, &outregs,
1243 			insn_loop, insn_loop_end - insn_loop);
1244 	if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 10)
1245 		print_serial("LOOPcc short Test 1: FAIL\n");
1246 	else
1247 		print_serial("LOOPcc short Test 1: PASS\n");
1248 
1249 	exec_in_big_real_mode(&inregs, &outregs,
1250 			insn_loope, insn_loope_end - insn_loope);
1251 	if(!regs_equal(&inregs, &outregs, R_AX | R_CX) ||
1252 	   outregs.eax != -1 || outregs.ecx != 8)
1253 		print_serial("LOOPcc short Test 2: FAIL\n");
1254 	else
1255 		print_serial("LOOPcc short Test 2: PASS\n");
1256 
1257 	exec_in_big_real_mode(&inregs, &outregs,
1258 			insn_loopne, insn_loopne_end - insn_loopne);
1259 	if(!regs_equal(&inregs, &outregs, R_AX | R_CX) ||
1260 	   outregs.eax != 0 || outregs.ecx != 5)
1261 		print_serial("LOOPcc short Test 3: FAIL\n");
1262 	else
1263 		print_serial("LOOPcc short Test 3: PASS\n");
1264 }
1265 
1266 void realmode_start(void)
1267 {
1268 	test_null();
1269 
1270 	test_shld();
1271 	test_push_pop();
1272 	test_pusha_popa();
1273 	test_mov_imm();
1274 	test_cmp_imm();
1275 	test_add_imm();
1276 	test_sub_imm();
1277 	test_xor_imm();
1278 	test_io();
1279 	test_eflags_insn();
1280 	test_jcc_short();
1281 	test_jcc_near();
1282 	/* test_call() uses short jump so call it after testing jcc */
1283 	test_call();
1284 	/* long jmp test uses call near so test it after testing call */
1285 	test_long_jmp();
1286 	test_xchg();
1287 	test_iret();
1288 	test_int();
1289 	test_imul();
1290 	test_mul();
1291 	test_div();
1292 	test_idiv();
1293 	test_loopcc();
1294 	test_cbw();
1295 
1296 	exit(0);
1297 }
1298 
1299 unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff };
1300 
1301 struct __attribute__((packed)) {
1302 	unsigned short limit;
1303 	void *base;
1304 } r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt };
1305 
1306 asm(
1307 	".section .init \n\t"
1308 
1309 	".code32 \n\t"
1310 
1311 	"mb_magic = 0x1BADB002 \n\t"
1312 	"mb_flags = 0x0 \n\t"
1313 
1314 	"# multiboot header \n\t"
1315 	".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t"
1316 
1317 	".globl start \n\t"
1318 	".data \n\t"
1319 	". = . + 4096 \n\t"
1320 	"stacktop: \n\t"
1321 
1322 	".text \n\t"
1323 	"start: \n\t"
1324 	"lgdt r_gdt_descr \n\t"
1325 	"ljmp $8, $1f; 1: \n\t"
1326 	".code16gcc \n\t"
1327 	"mov $16, %eax \n\t"
1328 	"mov %ax, %ds \n\t"
1329 	"mov %ax, %es \n\t"
1330 	"mov %ax, %fs \n\t"
1331 	"mov %ax, %gs \n\t"
1332 	"mov %ax, %ss \n\t"
1333 	"mov %cr0, %eax \n\t"
1334 	"btc $0, %eax \n\t"
1335 	"mov %eax, %cr0 \n\t"
1336 	"ljmp $0, $realmode_entry \n\t"
1337 
1338 	"realmode_entry: \n\t"
1339 
1340 	"xor %ax, %ax \n\t"
1341 	"mov %ax, %ds \n\t"
1342 	"mov %ax, %es \n\t"
1343 	"mov %ax, %ss \n\t"
1344 	"mov %ax, %fs \n\t"
1345 	"mov %ax, %gs \n\t"
1346 	"mov $stacktop, %esp\n\t"
1347 	"ljmp $0, $realmode_start \n\t"
1348 
1349 	".code16gcc \n\t"
1350 	);
1351