xref: /kvm-unit-tests/x86/realmode.c (revision d4dc402c8a8fbe8e41ffb0196fe3940c6fd87d33)
17d36db35SAvi Kivity asm(".code16gcc");
27d36db35SAvi Kivity 
37d36db35SAvi Kivity typedef unsigned char u8;
47d36db35SAvi Kivity typedef unsigned short u16;
57d36db35SAvi Kivity typedef unsigned u32;
67d36db35SAvi Kivity typedef unsigned long long u64;
77d36db35SAvi Kivity 
87d36db35SAvi Kivity void test_function(void);
97d36db35SAvi Kivity 
107d36db35SAvi Kivity asm(
117d36db35SAvi Kivity 	"test_function: \n\t"
127d36db35SAvi Kivity 	"mov $0x1234, %eax \n\t"
137d36db35SAvi Kivity 	"ret"
147d36db35SAvi Kivity    );
157d36db35SAvi Kivity 
167d36db35SAvi Kivity static int strlen(const char *str)
177d36db35SAvi Kivity {
187d36db35SAvi Kivity 	int n;
197d36db35SAvi Kivity 
207d36db35SAvi Kivity 	for (n = 0; *str; ++str)
217d36db35SAvi Kivity 		++n;
227d36db35SAvi Kivity 	return n;
237d36db35SAvi Kivity }
247d36db35SAvi Kivity 
257d36db35SAvi Kivity static void print_serial(const char *buf)
267d36db35SAvi Kivity {
277d36db35SAvi Kivity 	unsigned long len = strlen(buf);
287d36db35SAvi Kivity 
297d36db35SAvi Kivity 	asm volatile ("cld; addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1));
307d36db35SAvi Kivity }
317d36db35SAvi Kivity 
327d36db35SAvi Kivity static void exit(int code)
337d36db35SAvi Kivity {
347d36db35SAvi Kivity         asm volatile("out %0, %1" : : "a"(code), "d"((short)0xf4));
357d36db35SAvi Kivity }
367d36db35SAvi Kivity 
377d36db35SAvi Kivity struct regs {
387d36db35SAvi Kivity 	u32 eax, ebx, ecx, edx;
397d36db35SAvi Kivity 	u32 esi, edi, esp, ebp;
407d36db35SAvi Kivity 	u32 eip, eflags;
417d36db35SAvi Kivity };
427d36db35SAvi Kivity 
437d36db35SAvi Kivity static u64 gdt[] = {
447d36db35SAvi Kivity 	0,
457d36db35SAvi Kivity 	0x00cf9b000000ffffull, // flat 32-bit code segment
467d36db35SAvi Kivity 	0x00cf93000000ffffull, // flat 32-bit data segment
477d36db35SAvi Kivity };
487d36db35SAvi Kivity 
497d36db35SAvi Kivity static struct {
507d36db35SAvi Kivity 	u16 limit;
517d36db35SAvi Kivity 	void *base;
527d36db35SAvi Kivity } __attribute__((packed)) gdt_descr = {
537d36db35SAvi Kivity 	sizeof(gdt) - 1,
547d36db35SAvi Kivity 	gdt,
557d36db35SAvi Kivity };
567d36db35SAvi Kivity 
57*d4dc402cSAvi Kivity struct insn_desc {
58*d4dc402cSAvi Kivity     u16 ptr;
59*d4dc402cSAvi Kivity     u16 len;
60*d4dc402cSAvi Kivity };
61*d4dc402cSAvi Kivity 
627d36db35SAvi Kivity static void exec_in_big_real_mode(const struct regs *inregs,
637d36db35SAvi Kivity 				  struct regs *outregs,
64*d4dc402cSAvi Kivity 				  struct insn_desc *insn)
657d36db35SAvi Kivity {
667d36db35SAvi Kivity 	unsigned long tmp;
677d36db35SAvi Kivity 	static struct regs save;
687d36db35SAvi Kivity 	int i;
697d36db35SAvi Kivity 	extern u8 test_insn[], test_insn_end[];
707d36db35SAvi Kivity 
71*d4dc402cSAvi Kivity 	for (i = 0; i < insn->len; ++i)
72*d4dc402cSAvi Kivity 	    test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i];
737d36db35SAvi Kivity 	for (; i < test_insn_end - test_insn; ++i)
747d36db35SAvi Kivity 		test_insn[i] = 0x90; // nop
757d36db35SAvi Kivity 
767d36db35SAvi Kivity 	save = *inregs;
777d36db35SAvi Kivity 	asm volatile(
787d36db35SAvi Kivity 		"lgdtl %[gdt_descr] \n\t"
797d36db35SAvi Kivity 		"mov %%cr0, %[tmp] \n\t"
807d36db35SAvi Kivity 		"or $1, %[tmp] \n\t"
817d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
827d36db35SAvi Kivity 		"mov %[bigseg], %%gs \n\t"
837d36db35SAvi Kivity 		"and $-2, %[tmp] \n\t"
847d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
857d36db35SAvi Kivity 
8632001692SAvi Kivity                 "pushw %[save]+36; popfw \n\t"
877d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
887d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
897d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
907d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
917d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
927d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
937d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
947d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
957d36db35SAvi Kivity 
967d36db35SAvi Kivity 		"test_insn: . = . + 32\n\t"
977d36db35SAvi Kivity 		"test_insn_end: \n\t"
987d36db35SAvi Kivity 
997d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
1007d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
1017d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
1027d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
1037d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
1047d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
1057d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
1067d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
1077d36db35SAvi Kivity 
1087d36db35SAvi Kivity 		/* Save EFLAGS in outregs*/
1097d36db35SAvi Kivity 		"pushfl \n\t"
1107d36db35SAvi Kivity 		"popl %[save]+36 \n\t"
1117d36db35SAvi Kivity 
1127d36db35SAvi Kivity 		"xor %[tmp], %[tmp] \n\t"
1137d36db35SAvi Kivity 		"mov %[tmp], %%gs \n\t"
1147d36db35SAvi Kivity 		: [tmp]"=&r"(tmp), [save]"+m"(save)
1157d36db35SAvi Kivity 		: [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16)
1167d36db35SAvi Kivity 		: "cc", "memory"
1177d36db35SAvi Kivity 		);
1187d36db35SAvi Kivity 	*outregs = save;
1197d36db35SAvi Kivity }
1207d36db35SAvi Kivity 
1217d36db35SAvi Kivity #define R_AX 1
1227d36db35SAvi Kivity #define R_BX 2
1237d36db35SAvi Kivity #define R_CX 4
1247d36db35SAvi Kivity #define R_DX 8
1257d36db35SAvi Kivity #define R_SI 16
1267d36db35SAvi Kivity #define R_DI 32
1277d36db35SAvi Kivity #define R_SP 64
1287d36db35SAvi Kivity #define R_BP 128
1297d36db35SAvi Kivity 
1307d36db35SAvi Kivity int regs_equal(const struct regs *r1, const struct regs *r2, int ignore)
1317d36db35SAvi Kivity {
1327d36db35SAvi Kivity 	const u32 *p1 = &r1->eax, *p2 = &r2->eax;  // yuck
1337d36db35SAvi Kivity 	int i;
1347d36db35SAvi Kivity 
1357d36db35SAvi Kivity 	for (i = 0; i < 8; ++i)
1367d36db35SAvi Kivity 		if (!(ignore & (1 << i)) && p1[i] != p2[i])
1377d36db35SAvi Kivity 			return 0;
1387d36db35SAvi Kivity 	return 1;
1397d36db35SAvi Kivity }
1407d36db35SAvi Kivity 
1417d36db35SAvi Kivity #define MK_INSN(name, str)				\
1427d36db35SAvi Kivity     asm (						\
143*d4dc402cSAvi Kivity 	 ".pushsection .data.insn  \n\t"		\
144*d4dc402cSAvi Kivity 	 "insn_" #name ": \n\t"				\
145*d4dc402cSAvi Kivity 	 ".word 1001f, 1002f - 1001f \n\t"		\
146*d4dc402cSAvi Kivity 	 ".popsection \n\t"				\
147*d4dc402cSAvi Kivity 	 ".pushsection .text.insn, \"ax\" \n\t"		\
148*d4dc402cSAvi Kivity 	 "1001: \n\t"					\
149*d4dc402cSAvi Kivity 	 "insn_code_" #name ": " str " \n\t"		\
150*d4dc402cSAvi Kivity 	 "1002: \n\t"					\
151*d4dc402cSAvi Kivity 	 ".popsection"					\
1527d36db35SAvi Kivity     );							\
153*d4dc402cSAvi Kivity     extern struct insn_desc insn_##name;
1547d36db35SAvi Kivity 
1557d36db35SAvi Kivity void test_xchg(void)
1567d36db35SAvi Kivity {
1577d36db35SAvi Kivity 	struct regs inregs = { .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7}, outregs;
1587d36db35SAvi Kivity 
1597d36db35SAvi Kivity 	MK_INSN(xchg_test1, "xchg %eax,%eax\n\t");
1607d36db35SAvi Kivity 	MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t");
1617d36db35SAvi Kivity 	MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t");
1627d36db35SAvi Kivity 	MK_INSN(xchg_test4, "xchg %eax,%edx\n\t");
1637d36db35SAvi Kivity 	MK_INSN(xchg_test5, "xchg %eax,%esi\n\t");
1647d36db35SAvi Kivity 	MK_INSN(xchg_test6, "xchg %eax,%edi\n\t");
1657d36db35SAvi Kivity 	MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t");
1667d36db35SAvi Kivity 	MK_INSN(xchg_test8, "xchg %eax,%esp\n\t");
1677d36db35SAvi Kivity 
168*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_xchg_test1);
1697d36db35SAvi Kivity 
1707d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, 0))
1717d36db35SAvi Kivity 		print_serial("xchg test 1: FAIL\n");
1727d36db35SAvi Kivity 	else
1737d36db35SAvi Kivity 		print_serial("xchg test 1: PASS\n");
1747d36db35SAvi Kivity 
175*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_xchg_test2);
1767d36db35SAvi Kivity 
1777d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX | R_BX) ||
1787d36db35SAvi Kivity             outregs.eax != inregs.ebx ||
1797d36db35SAvi Kivity             outregs.ebx != inregs.eax)
1807d36db35SAvi Kivity 		print_serial("xchg test 2: FAIL\n");
1817d36db35SAvi Kivity 	else
1827d36db35SAvi Kivity 		print_serial("xchg test 2: PASS\n");
1837d36db35SAvi Kivity 
184*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_xchg_test3);
1857d36db35SAvi Kivity 
1867d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX) ||
1877d36db35SAvi Kivity             outregs.eax != inregs.ecx ||
1887d36db35SAvi Kivity             outregs.ecx != inregs.eax)
1897d36db35SAvi Kivity 		print_serial("xchg test 3: FAIL\n");
1907d36db35SAvi Kivity 	else
1917d36db35SAvi Kivity 		print_serial("xchg test 3: PASS\n");
1927d36db35SAvi Kivity 
193*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_xchg_test4);
1947d36db35SAvi Kivity 
1957d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX | R_DX) ||
1967d36db35SAvi Kivity             outregs.eax != inregs.edx ||
1977d36db35SAvi Kivity             outregs.edx != inregs.eax)
1987d36db35SAvi Kivity 		print_serial("xchg test 4: FAIL\n");
1997d36db35SAvi Kivity 	else
2007d36db35SAvi Kivity 		print_serial("xchg test 4: PASS\n");
2017d36db35SAvi Kivity 
202*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_xchg_test5);
2037d36db35SAvi Kivity 
2047d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX | R_SI) ||
2057d36db35SAvi Kivity             outregs.eax != inregs.esi ||
2067d36db35SAvi Kivity             outregs.esi != inregs.eax)
2077d36db35SAvi Kivity 		print_serial("xchg test 5: FAIL\n");
2087d36db35SAvi Kivity 	else
2097d36db35SAvi Kivity 		print_serial("xchg test 5: PASS\n");
2107d36db35SAvi Kivity 
211*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_xchg_test6);
2127d36db35SAvi Kivity 
2137d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX | R_DI) ||
2147d36db35SAvi Kivity             outregs.eax != inregs.edi ||
2157d36db35SAvi Kivity             outregs.edi != inregs.eax)
2167d36db35SAvi Kivity 		print_serial("xchg test 6: FAIL\n");
2177d36db35SAvi Kivity 	else
2187d36db35SAvi Kivity 		print_serial("xchg test 6: PASS\n");
2197d36db35SAvi Kivity 
220*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_xchg_test7);
2217d36db35SAvi Kivity 
2227d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX | R_BP) ||
2237d36db35SAvi Kivity             outregs.eax != inregs.ebp ||
2247d36db35SAvi Kivity             outregs.ebp != inregs.eax)
2257d36db35SAvi Kivity 		print_serial("xchg test 7: FAIL\n");
2267d36db35SAvi Kivity 	else
2277d36db35SAvi Kivity 		print_serial("xchg test 7: PASS\n");
2287d36db35SAvi Kivity 
229*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_xchg_test8);
2307d36db35SAvi Kivity 
2317d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX | R_SP) ||
2327d36db35SAvi Kivity             outregs.eax != inregs.esp ||
2337d36db35SAvi Kivity             outregs.esp != inregs.eax)
2347d36db35SAvi Kivity 		print_serial("xchg test 8: FAIL\n");
2357d36db35SAvi Kivity 	else
2367d36db35SAvi Kivity 		print_serial("xchg test 8: PASS\n");
2377d36db35SAvi Kivity }
2387d36db35SAvi Kivity 
2397d36db35SAvi Kivity void test_shld(void)
2407d36db35SAvi Kivity {
2417d36db35SAvi Kivity 	struct regs inregs = { .eax = 0xbe, .edx = 0xef000000 }, outregs;
2427d36db35SAvi Kivity 	MK_INSN(shld_test, "shld $8,%edx,%eax\n\t");
2437d36db35SAvi Kivity 
244*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_shld_test);
2457d36db35SAvi Kivity 	if (outregs.eax != 0xbeef)
2467d36db35SAvi Kivity 		print_serial("shld: FAIL\n");
2477d36db35SAvi Kivity 	else
2487d36db35SAvi Kivity 		print_serial("shld: PASS\n");
2497d36db35SAvi Kivity }
2507d36db35SAvi Kivity 
2517d36db35SAvi Kivity void test_mov_imm(void)
2527d36db35SAvi Kivity {
2537d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
2547d36db35SAvi Kivity 	MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax");
2557d36db35SAvi Kivity 	MK_INSN(mov_r16_imm_1, "mov $1234, %ax");
2567d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_1, "mov $0x12, %ah");
2577d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_2, "mov $0x34, %al");
2587d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t");
2597d36db35SAvi Kivity 
260*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_mov_r16_imm_1);
2617d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 1234)
2627d36db35SAvi Kivity 		print_serial("mov test 1: FAIL\n");
2637d36db35SAvi Kivity 	else
2647d36db35SAvi Kivity 		print_serial("mov test 1: PASS\n");
2657d36db35SAvi Kivity 
2667d36db35SAvi Kivity 	/* test mov $imm, %eax */
267*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_mov_r32_imm_1);
2687d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 1234567890)
2697d36db35SAvi Kivity 		print_serial("mov test 2: FAIL\n");
2707d36db35SAvi Kivity 	else
2717d36db35SAvi Kivity 		print_serial("mov test 2: PASS\n");
2727d36db35SAvi Kivity 
2737d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
274*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_mov_r8_imm_1);
2757d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1200)
2767d36db35SAvi Kivity 		print_serial("mov test 3: FAIL\n");
2777d36db35SAvi Kivity 	else
2787d36db35SAvi Kivity 		print_serial("mov test 3: PASS\n");
2797d36db35SAvi Kivity 
280*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_mov_r8_imm_2);
2817d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x34)
2827d36db35SAvi Kivity 		print_serial("mov test 4: FAIL\n");
2837d36db35SAvi Kivity 	else
2847d36db35SAvi Kivity 		print_serial("mov test 4: PASS\n");
2857d36db35SAvi Kivity 
286*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_mov_r8_imm_3);
2877d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234)
2887d36db35SAvi Kivity 		print_serial("mov test 5: FAIL\n");
2897d36db35SAvi Kivity 	else
2907d36db35SAvi Kivity 		print_serial("mov test 5: PASS\n");
2917d36db35SAvi Kivity }
2927d36db35SAvi Kivity 
2937d36db35SAvi Kivity void test_sub_imm(void)
2947d36db35SAvi Kivity {
2957d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
2967d36db35SAvi Kivity 	MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t");
2977d36db35SAvi Kivity 	MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t");
2987d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t");
2997d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t");
3007d36db35SAvi Kivity 
301*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_sub_r16_imm_1);
3027d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 1224)
3037d36db35SAvi Kivity 		print_serial("sub test 1: FAIL\n");
3047d36db35SAvi Kivity 	else
3057d36db35SAvi Kivity 		print_serial("sub test 1: PASS\n");
3067d36db35SAvi Kivity 
3077d36db35SAvi Kivity 	/* test mov $imm, %eax */
308*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_sub_r32_imm_1);
3097d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 1234567880)
3107d36db35SAvi Kivity 		print_serial("sub test 2: FAIL\n");
3117d36db35SAvi Kivity 	else
3127d36db35SAvi Kivity 		print_serial("sub test 2: PASS\n");
3137d36db35SAvi Kivity 
3147d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
315*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_sub_r8_imm_1);
3167d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x0200)
3177d36db35SAvi Kivity 		print_serial("sub test 3: FAIL\n");
3187d36db35SAvi Kivity 	else
3197d36db35SAvi Kivity 		print_serial("sub test 3: PASS\n");
3207d36db35SAvi Kivity 
321*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_sub_r8_imm_2);
3227d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x24)
3237d36db35SAvi Kivity 		print_serial("sub test 4: FAIL\n");
3247d36db35SAvi Kivity 	else
3257d36db35SAvi Kivity 		print_serial("sub test 4: PASS\n");
3267d36db35SAvi Kivity }
3277d36db35SAvi Kivity 
3287d36db35SAvi Kivity 
3297d36db35SAvi Kivity void test_xor_imm(void)
3307d36db35SAvi Kivity {
3317d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
3327d36db35SAvi Kivity 	MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t");
3337d36db35SAvi Kivity 	MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t");
3347d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t");
3357d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t");
3367d36db35SAvi Kivity 
337*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_xor_r16_imm_1);
3387d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0)
3397d36db35SAvi Kivity 		print_serial("xor test 1: FAIL\n");
3407d36db35SAvi Kivity 	else
3417d36db35SAvi Kivity 		print_serial("xor test 1: PASS\n");
3427d36db35SAvi Kivity 
3437d36db35SAvi Kivity 	/* test mov $imm, %eax */
344*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_xor_r32_imm_1);
3457d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0)
3467d36db35SAvi Kivity 		print_serial("xor test 2: FAIL\n");
3477d36db35SAvi Kivity 	else
3487d36db35SAvi Kivity 		print_serial("xor test 2: PASS\n");
3497d36db35SAvi Kivity 
3507d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
351*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_xor_r8_imm_1);
3527d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0)
3537d36db35SAvi Kivity 		print_serial("xor test 3: FAIL\n");
3547d36db35SAvi Kivity 	else
3557d36db35SAvi Kivity 		print_serial("xor test 3: PASS\n");
3567d36db35SAvi Kivity 
357*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_xor_r8_imm_2);
3587d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0)
3597d36db35SAvi Kivity 		print_serial("xor test 4: FAIL\n");
3607d36db35SAvi Kivity 	else
3617d36db35SAvi Kivity 		print_serial("xor test 4: PASS\n");
3627d36db35SAvi Kivity }
3637d36db35SAvi Kivity 
3647d36db35SAvi Kivity void test_cmp_imm(void)
3657d36db35SAvi Kivity {
3667d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
3677d36db35SAvi Kivity 	MK_INSN(cmp_test1, "mov $0x34, %al\n\t"
3687d36db35SAvi Kivity 			   "cmp $0x34, %al\n\t");
3697d36db35SAvi Kivity 	MK_INSN(cmp_test2, "mov $0x34, %al\n\t"
3707d36db35SAvi Kivity 			   "cmp $0x39, %al\n\t");
3717d36db35SAvi Kivity 	MK_INSN(cmp_test3, "mov $0x34, %al\n\t"
3727d36db35SAvi Kivity 			   "cmp $0x24, %al\n\t");
3737d36db35SAvi Kivity 
3747d36db35SAvi Kivity 	/* test cmp imm8 with AL */
3757d36db35SAvi Kivity 	/* ZF: (bit 6) Zero Flag becomes 1 if an operation results
3767d36db35SAvi Kivity 	 * in a 0 writeback, or 0 register
3777d36db35SAvi Kivity 	 */
378*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_cmp_test1);
3797d36db35SAvi Kivity 	if ((outregs.eflags & (1<<6)) != (1<<6))
3807d36db35SAvi Kivity 		print_serial("cmp test 1: FAIL\n");
3817d36db35SAvi Kivity 	else
3827d36db35SAvi Kivity 		print_serial("cmp test 1: PASS\n");
3837d36db35SAvi Kivity 
384*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_cmp_test2);
3857d36db35SAvi Kivity 	if ((outregs.eflags & (1<<6)) != 0)
3867d36db35SAvi Kivity 		print_serial("cmp test 2: FAIL\n");
3877d36db35SAvi Kivity 	else
3887d36db35SAvi Kivity 		print_serial("cmp test 2: PASS\n");
3897d36db35SAvi Kivity 
390*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_cmp_test3);
3917d36db35SAvi Kivity 	if ((outregs.eflags & (1<<6)) != 0)
3927d36db35SAvi Kivity 		print_serial("cmp test 3: FAIL\n");
3937d36db35SAvi Kivity 	else
3947d36db35SAvi Kivity 		print_serial("cmp test 3: PASS\n");
3957d36db35SAvi Kivity }
3967d36db35SAvi Kivity 
3977d36db35SAvi Kivity void test_add_imm(void)
3987d36db35SAvi Kivity {
3997d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
4007d36db35SAvi Kivity 	MK_INSN(add_test1, "mov $0x43211234, %eax \n\t"
4017d36db35SAvi Kivity 			   "add $0x12344321, %eax \n\t");
4027d36db35SAvi Kivity 	MK_INSN(add_test2, "mov $0x12, %eax \n\t"
4037d36db35SAvi Kivity 			   "add $0x21, %al\n\t");
4047d36db35SAvi Kivity 
405*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_add_test1);
4067d36db35SAvi Kivity 	if (outregs.eax != 0x55555555)
4077d36db35SAvi Kivity 		print_serial("add test 1: FAIL\n");
4087d36db35SAvi Kivity 	else
4097d36db35SAvi Kivity 		print_serial("add test 1: PASS\n");
4107d36db35SAvi Kivity 
411*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_add_test2);
4127d36db35SAvi Kivity 	if (outregs.eax != 0x33)
4137d36db35SAvi Kivity 		print_serial("add test 2: FAIL\n");
4147d36db35SAvi Kivity 	else
4157d36db35SAvi Kivity 		print_serial("add test 2: PASS\n");
4167d36db35SAvi Kivity }
4177d36db35SAvi Kivity 
4187d36db35SAvi Kivity void test_eflags_insn(void)
4197d36db35SAvi Kivity {
4207d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
4217d36db35SAvi Kivity 	MK_INSN(clc, "clc");
422b3261e48SMohammed Gamal 	MK_INSN(stc, "stc");
4237d36db35SAvi Kivity 	MK_INSN(cli, "cli");
4247d36db35SAvi Kivity 	MK_INSN(sti, "sti");
4257d36db35SAvi Kivity 	MK_INSN(cld, "cld");
4267d36db35SAvi Kivity 	MK_INSN(std, "std");
4277d36db35SAvi Kivity 
428*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_clc);
4297d36db35SAvi Kivity 	if (outregs.eflags & 1)
4307d36db35SAvi Kivity 		print_serial("clc test: FAIL\n");
4317d36db35SAvi Kivity 	else
4327d36db35SAvi Kivity 		print_serial("clc test: PASS\n");
4337d36db35SAvi Kivity 
434*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_stc);
435b3261e48SMohammed Gamal 	if (!(outregs.eflags & 1))
436b3261e48SMohammed Gamal 		print_serial("stc test: FAIL\n");
437b3261e48SMohammed Gamal 	else
438b3261e48SMohammed Gamal 		print_serial("stc test: PASS\n");
439b3261e48SMohammed Gamal 
440*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_cli);
4417d36db35SAvi Kivity 	if (outregs.eflags & (1 << 9))
4427d36db35SAvi Kivity 		print_serial("cli test: FAIL\n");
4437d36db35SAvi Kivity 	else
4447d36db35SAvi Kivity 		print_serial("cli test: PASS\n");
4457d36db35SAvi Kivity 
446*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_sti);
4477d36db35SAvi Kivity 	if (!(outregs.eflags & (1 << 9)))
4487d36db35SAvi Kivity 		print_serial("sti test: FAIL\n");
4497d36db35SAvi Kivity 	else
4507d36db35SAvi Kivity 		print_serial("sti test: PASS\n");
4517d36db35SAvi Kivity 
452*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_cld);
4537d36db35SAvi Kivity 	if (outregs.eflags & (1 << 10))
4547d36db35SAvi Kivity 		print_serial("cld test: FAIL\n");
4557d36db35SAvi Kivity 	else
4567d36db35SAvi Kivity 		print_serial("cld test: PASS\n");
4577d36db35SAvi Kivity 
458*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_std);
4597d36db35SAvi Kivity 	if (!(outregs.eflags & (1 << 10)))
4607d36db35SAvi Kivity 		print_serial("std test: FAIL\n");
4617d36db35SAvi Kivity 	else
4627d36db35SAvi Kivity 		print_serial("std test: PASS\n");
4637d36db35SAvi Kivity }
4647d36db35SAvi Kivity 
4657d36db35SAvi Kivity void test_io(void)
4667d36db35SAvi Kivity {
4677d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
4687d36db35SAvi Kivity 	MK_INSN(io_test1, "mov $0xff, %al \n\t"
4697d36db35SAvi Kivity 		          "out %al, $0xe0 \n\t"
4707d36db35SAvi Kivity 		          "mov $0x00, %al \n\t"
4717d36db35SAvi Kivity 			  "in $0xe0, %al \n\t");
4727d36db35SAvi Kivity 	MK_INSN(io_test2, "mov $0xffff, %ax \n\t"
4737d36db35SAvi Kivity 			  "out %ax, $0xe0 \n\t"
4747d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
4757d36db35SAvi Kivity 			  "in $0xe0, %ax \n\t");
4767d36db35SAvi Kivity 	MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t"
4777d36db35SAvi Kivity 			  "out %eax, $0xe0 \n\t"
4787d36db35SAvi Kivity 			  "mov $0x000000, %eax \n\t"
4797d36db35SAvi Kivity 			  "in $0xe0, %eax \n\t");
4807d36db35SAvi Kivity 	MK_INSN(io_test4, "mov $0xe0, %dx \n\t"
4817d36db35SAvi Kivity 			  "mov $0xff, %al \n\t"
4827d36db35SAvi Kivity 			  "out %al, %dx \n\t"
4837d36db35SAvi Kivity 			  "mov $0x00, %al \n\t"
4847d36db35SAvi Kivity 			  "in %dx, %al \n\t");
4857d36db35SAvi Kivity 	MK_INSN(io_test5, "mov $0xe0, %dx \n\t"
4867d36db35SAvi Kivity 			  "mov $0xffff, %ax \n\t"
4877d36db35SAvi Kivity 			  "out %ax, %dx \n\t"
4887d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
4897d36db35SAvi Kivity 			  "in %dx, %ax \n\t");
4907d36db35SAvi Kivity 	MK_INSN(io_test6, "mov $0xe0, %dx \n\t"
4917d36db35SAvi Kivity 			  "mov $0xffffffff, %eax \n\t"
4927d36db35SAvi Kivity 			  "out %eax, %dx \n\t"
4937d36db35SAvi Kivity 			  "mov $0x00000000, %eax \n\t"
4947d36db35SAvi Kivity 			  "in %dx, %eax \n\t");
4957d36db35SAvi Kivity 
496*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_io_test1);
4977d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0xff)
4987d36db35SAvi Kivity 		print_serial("I/O test 1: FAIL\n");
4997d36db35SAvi Kivity 	else
5007d36db35SAvi Kivity 		print_serial("I/O test 1: PASS\n");
5017d36db35SAvi Kivity 
502*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_io_test2);
5037d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0xffff)
5047d36db35SAvi Kivity 		print_serial("I/O test 2: FAIL\n");
5057d36db35SAvi Kivity 	else
5067d36db35SAvi Kivity 		print_serial("I/O test 2: PASS\n");
5077d36db35SAvi Kivity 
508*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_io_test3);
5097d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0xffffffff)
5107d36db35SAvi Kivity 		print_serial("I/O test 3: FAIL\n");
5117d36db35SAvi Kivity 	else
5127d36db35SAvi Kivity 		print_serial("I/O test 3: PASS\n");
5137d36db35SAvi Kivity 
514*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_io_test4);
5157d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX|R_DX) || outregs.eax != 0xff)
5167d36db35SAvi Kivity 		print_serial("I/O test 4: FAIL\n");
5177d36db35SAvi Kivity 	else
5187d36db35SAvi Kivity 		print_serial("I/O test 4: PASS\n");
5197d36db35SAvi Kivity 
520*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_io_test5);
5217d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX|R_DX) || outregs.eax != 0xffff)
5227d36db35SAvi Kivity 		print_serial("I/O test 5: FAIL\n");
5237d36db35SAvi Kivity 	else
5247d36db35SAvi Kivity 		print_serial("I/O test 5: PASS\n");
5257d36db35SAvi Kivity 
526*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_io_test6);
5277d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX|R_DX) || outregs.eax != 0xffffffff)
5287d36db35SAvi Kivity 		print_serial("I/O test 6: FAIL\n");
5297d36db35SAvi Kivity 	else
5307d36db35SAvi Kivity 		print_serial("I/O test 6: PASS\n");
5317d36db35SAvi Kivity }
5327d36db35SAvi Kivity 
533c0b7268dSAvi Kivity asm ("retf: lretw");
534c0b7268dSAvi Kivity extern void retf();
535c0b7268dSAvi Kivity 
5367d36db35SAvi Kivity void test_call(void)
5377d36db35SAvi Kivity {
5387d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
5397d36db35SAvi Kivity 	u32 esp[16];
540c0b7268dSAvi Kivity 	u32 addr;
5417d36db35SAvi Kivity 
5427d36db35SAvi Kivity 	inregs.esp = (u32)esp;
5437d36db35SAvi Kivity 
5447d36db35SAvi Kivity 	MK_INSN(call1, "mov $test_function, %eax \n\t"
5457d36db35SAvi Kivity 		       "call *%eax\n\t");
5467d36db35SAvi Kivity 	MK_INSN(call_near1, "jmp 2f\n\t"
5477d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5487d36db35SAvi Kivity 			    "ret\n\t"
5497d36db35SAvi Kivity 			    "2: call 1b\t");
5507d36db35SAvi Kivity 	MK_INSN(call_near2, "call 1f\n\t"
5517d36db35SAvi Kivity 			    "jmp 2f\n\t"
5527d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5537d36db35SAvi Kivity 			    "ret\n\t"
5547d36db35SAvi Kivity 			    "2:\t");
555c0b7268dSAvi Kivity 	MK_INSN(call_far1,  "lcallw *(%ebx)\n\t");
556c6061817SAvi Kivity 	MK_INSN(ret_imm,    "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b");
5577d36db35SAvi Kivity 
558*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_call1);
5597d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234)
5607d36db35SAvi Kivity 		print_serial("Call Test 1: FAIL\n");
5617d36db35SAvi Kivity 	else
5627d36db35SAvi Kivity 		print_serial("Call Test 1: PASS\n");
5637d36db35SAvi Kivity 
564*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_call_near1);
5657d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234)
5667d36db35SAvi Kivity 		print_serial("Call near Test 1: FAIL\n");
5677d36db35SAvi Kivity 	else
5687d36db35SAvi Kivity 		print_serial("Call near Test 1: PASS\n");
5697d36db35SAvi Kivity 
570*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_call_near2);
5717d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234)
5727d36db35SAvi Kivity 		print_serial("Call near Test 2: FAIL\n");
5737d36db35SAvi Kivity 	else
5747d36db35SAvi Kivity 		print_serial("Call near Test 2: PASS\n");
575c0b7268dSAvi Kivity 
576c0b7268dSAvi Kivity 	addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f);
577c0b7268dSAvi Kivity 	inregs.ebx = (unsigned)&addr;
578*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_call_far1);
579c0b7268dSAvi Kivity 	if (!regs_equal(&inregs, &outregs, 0))
580c0b7268dSAvi Kivity 		print_serial("Call far Test 1: FAIL\n");
581c0b7268dSAvi Kivity 	else
582c0b7268dSAvi Kivity 		print_serial("Call far Test 1: PASS\n");
583c6061817SAvi Kivity 
584*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_ret_imm);
585c6061817SAvi Kivity 	if (!regs_equal(&inregs, &outregs, 0))
586c6061817SAvi Kivity 		print_serial("ret imm Test 1: FAIL\n");
587c6061817SAvi Kivity 	else
588c6061817SAvi Kivity 		print_serial("ret imm Test 1: PASS\n");
5897d36db35SAvi Kivity }
5907d36db35SAvi Kivity 
5917d36db35SAvi Kivity void test_jcc_short(void)
5927d36db35SAvi Kivity {
5937d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
5947d36db35SAvi Kivity 	MK_INSN(jnz_short1, "jnz 1f\n\t"
5957d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
5967d36db35SAvi Kivity 		            "1:\n\t");
5977d36db35SAvi Kivity 	MK_INSN(jnz_short2, "1:\n\t"
5987d36db35SAvi Kivity 			    "cmp $0x1234, %eax\n\t"
5997d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
6007d36db35SAvi Kivity 		            "jnz 1b\n\t");
6017d36db35SAvi Kivity 	MK_INSN(jmp_short1, "jmp 1f\n\t"
6027d36db35SAvi Kivity 		      "mov $0x1234, %eax\n\t"
6037d36db35SAvi Kivity 		      "1:\n\t");
6047d36db35SAvi Kivity 
605*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_jnz_short1);
6067d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, 0))
6077d36db35SAvi Kivity 		print_serial("JNZ short Test 1: FAIL\n");
6087d36db35SAvi Kivity 	else
6097d36db35SAvi Kivity 		print_serial("JNZ short Test 1: PASS\n");
6107d36db35SAvi Kivity 
611*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_jnz_short2);
6127d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, R_AX) || !(outregs.eflags & (1 << 6)))
6137d36db35SAvi Kivity 		print_serial("JNZ short Test 2: FAIL\n");
6147d36db35SAvi Kivity 	else
6157d36db35SAvi Kivity 		print_serial("JNZ short Test 2: PASS\n");
6167d36db35SAvi Kivity 
617*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_jmp_short1);
6187d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, 0))
6197d36db35SAvi Kivity 		print_serial("JMP short Test 1: FAIL\n");
6207d36db35SAvi Kivity 	else
6217d36db35SAvi Kivity 		print_serial("JMP short Test 1: PASS\n");
6227d36db35SAvi Kivity }
6237d36db35SAvi Kivity 
6247d36db35SAvi Kivity void test_jcc_near(void)
6257d36db35SAvi Kivity {
6267d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
6277d36db35SAvi Kivity 	/* encode near jmp manually. gas will not do it if offsets < 127 byte */
6287d36db35SAvi Kivity 	MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t"
6297d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
6307d36db35SAvi Kivity 	MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t"
6317d36db35SAvi Kivity 			   "mov $0x1234, %eax\n\t"
6327d36db35SAvi Kivity 		           ".byte 0x0f, 0x85, 0xf0, 0xff\n\t");
6337d36db35SAvi Kivity 	MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t"
6347d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
6357d36db35SAvi Kivity 
636*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_jnz_near1);
6377d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, 0))
6387d36db35SAvi Kivity 		print_serial("JNZ near Test 1: FAIL\n");
6397d36db35SAvi Kivity 	else
6407d36db35SAvi Kivity 		print_serial("JNZ near Test 1: PASS\n");
6417d36db35SAvi Kivity 
642*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_jnz_near2);
6437d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, R_AX) || !(outregs.eflags & (1 << 6)))
6447d36db35SAvi Kivity 		print_serial("JNZ near Test 2: FAIL\n");
6457d36db35SAvi Kivity 	else
6467d36db35SAvi Kivity 		print_serial("JNZ near Test 2: PASS\n");
6477d36db35SAvi Kivity 
648*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_jmp_near1);
6497d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, 0))
6507d36db35SAvi Kivity 		print_serial("JMP near Test 1: FAIL\n");
6517d36db35SAvi Kivity 	else
6527d36db35SAvi Kivity 		print_serial("JMP near Test 1: PASS\n");
6537d36db35SAvi Kivity }
6547d36db35SAvi Kivity 
6557d36db35SAvi Kivity void test_long_jmp()
6567d36db35SAvi Kivity {
6577d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
6587d36db35SAvi Kivity 	u32 esp[16];
6597d36db35SAvi Kivity 
6607d36db35SAvi Kivity 	inregs.esp = (u32)esp;
6617d36db35SAvi Kivity 	MK_INSN(long_jmp, "call 1f\n\t"
6627d36db35SAvi Kivity 			  "jmp 2f\n\t"
6637d36db35SAvi Kivity 			  "1: jmp $0, $test_function\n\t"
6647d36db35SAvi Kivity 		          "2:\n\t");
665*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_long_jmp);
6667d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234)
6677d36db35SAvi Kivity 		print_serial("Long JMP Test: FAIL\n");
6687d36db35SAvi Kivity 	else
6697d36db35SAvi Kivity 		print_serial("Long JMP Test: PASS\n");
6707d36db35SAvi Kivity }
671fa74f8a6SMohammed Gamal 
6727d36db35SAvi Kivity void test_push_pop()
6737d36db35SAvi Kivity {
6747d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
6757d36db35SAvi Kivity 	MK_INSN(push32, "mov $0x12345678, %eax\n\t"
6767d36db35SAvi Kivity 			"push %eax\n\t"
6777d36db35SAvi Kivity 			"pop %ebx\n\t");
6787d36db35SAvi Kivity 	MK_INSN(push16, "mov $0x1234, %ax\n\t"
6797d36db35SAvi Kivity 			"push %ax\n\t"
6807d36db35SAvi Kivity 			"pop %bx\n\t");
6817d36db35SAvi Kivity 
6827d36db35SAvi Kivity 	MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten
6837d36db35SAvi Kivity 			 "mov $0x123, %ax\n\t"
6847d36db35SAvi Kivity 			 "mov %ax, %es\n\t"
6857d36db35SAvi Kivity 			 "push %es\n\t"
6867d36db35SAvi Kivity 			 "pop %bx \n\t"
6877d36db35SAvi Kivity 			 );
6887d36db35SAvi Kivity 	MK_INSN(pop_es, "push %ax\n\t"
6897d36db35SAvi Kivity 			"pop %es\n\t"
6907d36db35SAvi Kivity 			"mov %es, %bx\n\t"
6917d36db35SAvi Kivity 			);
6927d36db35SAvi Kivity 	MK_INSN(push_pop_ss, "push %ss\n\t"
6937d36db35SAvi Kivity 			     "pushw %ax\n\t"
6947d36db35SAvi Kivity 			     "popw %ss\n\t"
6957d36db35SAvi Kivity 			     "mov %ss, %bx\n\t"
6967d36db35SAvi Kivity 			     "pop %ss\n\t"
6977d36db35SAvi Kivity 			);
6987d36db35SAvi Kivity 	MK_INSN(push_pop_fs, "push %fs\n\t"
6997d36db35SAvi Kivity 			     "pushl %eax\n\t"
7007d36db35SAvi Kivity 			     "popl %fs\n\t"
7017d36db35SAvi Kivity 			     "mov %fs, %ebx\n\t"
7027d36db35SAvi Kivity 			     "pop %fs\n\t"
7037d36db35SAvi Kivity 			);
7047d36db35SAvi Kivity 
705*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_push32);
7067d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.eax != outregs.ebx || outregs.eax != 0x12345678)
7077d36db35SAvi Kivity 		print_serial("Push/Pop Test 1: FAIL\n");
7087d36db35SAvi Kivity 	else
7097d36db35SAvi Kivity 		print_serial("Push/Pop Test 1: PASS\n");
7107d36db35SAvi Kivity 
711*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_push16);
7127d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.eax != outregs.ebx || outregs.eax != 0x1234)
7137d36db35SAvi Kivity 		print_serial("Push/Pop Test 2: FAIL\n");
7147d36db35SAvi Kivity 	else
7157d36db35SAvi Kivity 		print_serial("Push/Pop Test 2: PASS\n");
7167d36db35SAvi Kivity 
717*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_push_es);
7187d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX|R_BX) ||  outregs.ebx != outregs.eax || outregs.eax != 0x123)
7197d36db35SAvi Kivity 		print_serial("Push/Pop Test 3: FAIL\n");
7207d36db35SAvi Kivity 	else
7217d36db35SAvi Kivity 		print_serial("Push/Pop Test 3: PASS\n");
7227d36db35SAvi Kivity 
723*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_pop_es);
7247d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.ebx != outregs.eax)
7257d36db35SAvi Kivity 		print_serial("Push/Pop Test 4: FAIL\n");
7267d36db35SAvi Kivity 	else
7277d36db35SAvi Kivity 		print_serial("Push/Pop Test 4: PASS\n");
7287d36db35SAvi Kivity 
729*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_push_pop_ss);
7307d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.ebx != outregs.eax)
7317d36db35SAvi Kivity 		print_serial("Push/Pop Test 5: FAIL\n");
7327d36db35SAvi Kivity 	else
7337d36db35SAvi Kivity 		print_serial("Push/Pop Test 5: PASS\n");
7347d36db35SAvi Kivity 
735*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_push_pop_fs);
7367d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.ebx != outregs.eax)
7377d36db35SAvi Kivity 		print_serial("Push/Pop Test 6: FAIL\n");
7387d36db35SAvi Kivity 	else
7397d36db35SAvi Kivity 		print_serial("Push/Pop Test 6: PASS\n");
7407d36db35SAvi Kivity }
7417d36db35SAvi Kivity 
7427d36db35SAvi Kivity void test_null(void)
7437d36db35SAvi Kivity {
7447d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
745*d4dc402cSAvi Kivity 	MK_INSN(null, "");
746*d4dc402cSAvi Kivity 
747*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_null);
7487d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, 0))
7497d36db35SAvi Kivity 		print_serial("null test: FAIL\n");
7507d36db35SAvi Kivity 	else
7517d36db35SAvi Kivity 		print_serial("null test: PASS\n");
7527d36db35SAvi Kivity }
7537d36db35SAvi Kivity 
7547d36db35SAvi Kivity struct {
7557d36db35SAvi Kivity     char stack[500];
7567d36db35SAvi Kivity     char top[];
7577d36db35SAvi Kivity } tmp_stack;
7587d36db35SAvi Kivity 
7597d36db35SAvi Kivity void test_pusha_popa()
7607d36db35SAvi Kivity {
7617d36db35SAvi Kivity 	struct regs inregs = { .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top }, outregs;
7627d36db35SAvi Kivity 
7637d36db35SAvi Kivity 	MK_INSN(pusha, "pusha\n\t"
7647d36db35SAvi Kivity 		       "pop %edi\n\t"
7657d36db35SAvi Kivity 		       "pop %esi\n\t"
7667d36db35SAvi Kivity 		       "pop %ebp\n\t"
7677d36db35SAvi Kivity 		       "add $4, %esp\n\t"
7687d36db35SAvi Kivity 		       "pop %ebx\n\t"
7697d36db35SAvi Kivity 		       "pop %edx\n\t"
7707d36db35SAvi Kivity 		       "pop %ecx\n\t"
7717d36db35SAvi Kivity 		       "pop %eax\n\t"
7727d36db35SAvi Kivity 		       );
7737d36db35SAvi Kivity 
7747d36db35SAvi Kivity 	MK_INSN(popa, "push %eax\n\t"
7757d36db35SAvi Kivity 		      "push %ecx\n\t"
7767d36db35SAvi Kivity 		      "push %edx\n\t"
7777d36db35SAvi Kivity 		      "push %ebx\n\t"
7787d36db35SAvi Kivity 		      "push %esp\n\t"
7797d36db35SAvi Kivity 		      "push %ebp\n\t"
7807d36db35SAvi Kivity 		      "push %esi\n\t"
7817d36db35SAvi Kivity 		      "push %edi\n\t"
7827d36db35SAvi Kivity 		      "popa\n\t"
7837d36db35SAvi Kivity 		      );
7847d36db35SAvi Kivity 
785*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_pusha);
7867d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, 0))
7877d36db35SAvi Kivity 		print_serial("Pusha/Popa Test1: FAIL\n");
7887d36db35SAvi Kivity 	else
7897d36db35SAvi Kivity 		print_serial("Pusha/Popa Test1: PASS\n");
7907d36db35SAvi Kivity 
791*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_popa);
7927d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, 0))
7937d36db35SAvi Kivity 		print_serial("Pusha/Popa Test2: FAIL\n");
7947d36db35SAvi Kivity 	else
7957d36db35SAvi Kivity 		print_serial("Pusha/Popa Test2: PASS\n");
7967d36db35SAvi Kivity }
7977d36db35SAvi Kivity 
7987d36db35SAvi Kivity void test_iret()
7997d36db35SAvi Kivity {
8007d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
8017d36db35SAvi Kivity 
8027d36db35SAvi Kivity 	MK_INSN(iret32, "pushf\n\t"
8037d36db35SAvi Kivity 			"pushl %cs\n\t"
8047d36db35SAvi Kivity 			"call 1f\n\t" /* a near call will push eip onto the stack */
8057d36db35SAvi Kivity 			"jmp 2f\n\t"
8067d36db35SAvi Kivity 			"1: iret\n\t"
8077d36db35SAvi Kivity 			"2:\n\t"
8087d36db35SAvi Kivity 		     );
8097d36db35SAvi Kivity 
8107d36db35SAvi Kivity 	MK_INSN(iret16, "pushfw\n\t"
8117d36db35SAvi Kivity 			"pushw %cs\n\t"
8127d36db35SAvi Kivity 			"callw 1f\n\t"
8137d36db35SAvi Kivity 			"jmp 2f\n\t"
8147d36db35SAvi Kivity 			"1: iretw\n\t"
8157d36db35SAvi Kivity 			"2:\n\t");
8167d36db35SAvi Kivity 
8177d36db35SAvi Kivity 	MK_INSN(iret_flags32, "pushfl\n\t"
8187d36db35SAvi Kivity 			      "popl %eax\n\t"
8197d36db35SAvi Kivity 			      "andl $~0x2, %eax\n\t"
8207d36db35SAvi Kivity 			      "orl $0xffc08028, %eax\n\t"
8217d36db35SAvi Kivity 			      "pushl %eax\n\t"
8227d36db35SAvi Kivity 			      "pushl %cs\n\t"
8237d36db35SAvi Kivity 			      "call 1f\n\t"
8247d36db35SAvi Kivity 			      "jmp 2f\n\t"
8257d36db35SAvi Kivity 			      "1: iret\n\t"
8267d36db35SAvi Kivity 			      "2:\n\t");
8277d36db35SAvi Kivity 
8287d36db35SAvi Kivity 	MK_INSN(iret_flags16, "pushfw\n\t"
8297d36db35SAvi Kivity 			      "popw %ax\n\t"
8307d36db35SAvi Kivity 			      "and $~0x2, %ax\n\t"
8317d36db35SAvi Kivity 			      "or $0x8028, %ax\n\t"
8327d36db35SAvi Kivity 			      "pushw %ax\n\t"
8337d36db35SAvi Kivity 			      "pushw %cs\n\t"
8347d36db35SAvi Kivity 			      "callw 1f\n\t"
8357d36db35SAvi Kivity 			      "jmp 2f\n\t"
8367d36db35SAvi Kivity 			      "1: iretw\n\t"
8377d36db35SAvi Kivity 			      "2:\n\t");
8387d36db35SAvi Kivity 
839*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_iret32);
8407d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, 0))
8417d36db35SAvi Kivity 		print_serial("iret Test 1: FAIL\n");
8427d36db35SAvi Kivity 	else
8437d36db35SAvi Kivity 		print_serial("iret Test 1: PASS\n");
8447d36db35SAvi Kivity 
845*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_iret16);
8467d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, 0))
8477d36db35SAvi Kivity 		print_serial("iret Test 2: FAIL\n");
8487d36db35SAvi Kivity 	else
8497d36db35SAvi Kivity 		print_serial("iret Test 2: PASS\n");
8507d36db35SAvi Kivity 
851*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_iret_flags32);
8527d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX))
8537d36db35SAvi Kivity 		print_serial("iret Test 3: FAIL\n");
8547d36db35SAvi Kivity 	else
8557d36db35SAvi Kivity 		print_serial("iret Test 3: PASS\n");
8567d36db35SAvi Kivity 
857*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_iret_flags16);
8587d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX))
8597d36db35SAvi Kivity 		print_serial("iret Test 4: FAIL\n");
8607d36db35SAvi Kivity 	else
8617d36db35SAvi Kivity 		print_serial("iret Test 4: PASS\n");
8627d36db35SAvi Kivity }
8637d36db35SAvi Kivity 
86496b9ca1eSMohammed Gamal void test_int()
86596b9ca1eSMohammed Gamal {
86696b9ca1eSMohammed Gamal 	struct regs inregs = { 0 }, outregs;
86796b9ca1eSMohammed Gamal 
86896b9ca1eSMohammed Gamal 	*(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */
86996b9ca1eSMohammed Gamal 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
87096b9ca1eSMohammed Gamal 
87196b9ca1eSMohammed Gamal 	MK_INSN(int11, "int $0x11\n\t");
87296b9ca1eSMohammed Gamal 
873*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_int11);
87496b9ca1eSMohammed Gamal 	if (!regs_equal(&inregs, &outregs, 0))
87596b9ca1eSMohammed Gamal 		print_serial("int Test 1: FAIL\n");
87696b9ca1eSMohammed Gamal 	else
87796b9ca1eSMohammed Gamal 		print_serial("int Test 1: PASS\n");
87896b9ca1eSMohammed Gamal }
87996b9ca1eSMohammed Gamal 
880fa74f8a6SMohammed Gamal void test_imul()
881fa74f8a6SMohammed Gamal {
882fa74f8a6SMohammed Gamal 	struct regs inregs = { 0 }, outregs;
883fa74f8a6SMohammed Gamal 
884fa74f8a6SMohammed Gamal 	MK_INSN(imul8_1, "mov $2, %al\n\t"
885fa74f8a6SMohammed Gamal 			"mov $-4, %cx\n\t"
886fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
887fa74f8a6SMohammed Gamal 
888fa74f8a6SMohammed Gamal 	MK_INSN(imul16_1, "mov $2, %ax\n\t"
889fa74f8a6SMohammed Gamal 		      "mov $-4, %cx\n\t"
890fa74f8a6SMohammed Gamal 		      "imul %cx\n\t");
891fa74f8a6SMohammed Gamal 
892fa74f8a6SMohammed Gamal 	MK_INSN(imul32_1, "mov $2, %eax\n\t"
893fa74f8a6SMohammed Gamal 		       "mov $-4, %ecx\n\t"
894fa74f8a6SMohammed Gamal 		       "imul %ecx\n\t");
895fa74f8a6SMohammed Gamal 
896fa74f8a6SMohammed Gamal 	MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t"
897fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
898fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
899fa74f8a6SMohammed Gamal 
900fa74f8a6SMohammed Gamal 	MK_INSN(imul16_2, "mov $2, %ax\n\t"
901fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
902fa74f8a6SMohammed Gamal 			"imul %cx\n\t");
903fa74f8a6SMohammed Gamal 
904fa74f8a6SMohammed Gamal 	MK_INSN(imul32_2, "mov $2, %eax\n\t"
905fa74f8a6SMohammed Gamal 			"mov $4, %ecx\n\t"
906fa74f8a6SMohammed Gamal 			"imul %ecx\n\t");
907fa74f8a6SMohammed Gamal 
908*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_imul8_1);
909fa74f8a6SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || (outregs.eax & 0xff) != (u8)-8)
910fa74f8a6SMohammed Gamal 		print_serial("imul Test 1: FAIL\n");
911fa74f8a6SMohammed Gamal 	else
912fa74f8a6SMohammed Gamal 		print_serial("imul Test 1: PASS\n");
913fa74f8a6SMohammed Gamal 
914*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_imul16_1);
915fa74f8a6SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u16)-8)
916fa74f8a6SMohammed Gamal 		print_serial("imul Test 2: FAIL\n");
917fa74f8a6SMohammed Gamal 	else
918fa74f8a6SMohammed Gamal 		print_serial("imul Test 2: PASS\n");
919fa74f8a6SMohammed Gamal 
920*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_imul32_1);
921fa74f8a6SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u32)-8)
922fa74f8a6SMohammed Gamal 		print_serial("imul Test 3: FAIL\n");
923fa74f8a6SMohammed Gamal 	else
924fa74f8a6SMohammed Gamal 		print_serial("imul Test 3: PASS\n");
925fa74f8a6SMohammed Gamal 
926*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_imul8_2);
927fa74f8a6SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || (outregs.eax & 0xffff) != 8 ||
928fa74f8a6SMohammed Gamal 	     (outregs.eax & 0xffff0000) != 0x12340000)
929fa74f8a6SMohammed Gamal 		print_serial("imul Test 4: FAIL\n");
930fa74f8a6SMohammed Gamal 	else
931fa74f8a6SMohammed Gamal 		print_serial("imul Test 4: PASS\n");
932fa74f8a6SMohammed Gamal 
933*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_imul16_2);
934fa74f8a6SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 8)
935fa74f8a6SMohammed Gamal 		print_serial("imul Test 5: FAIL\n");
936fa74f8a6SMohammed Gamal 	else
937fa74f8a6SMohammed Gamal 		print_serial("imul Test 5: PASS\n");
938fa74f8a6SMohammed Gamal 
939*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_imul32_2);
940fa74f8a6SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 8)
941fa74f8a6SMohammed Gamal 		print_serial("imul Test 6: FAIL\n");
942fa74f8a6SMohammed Gamal 	else
943fa74f8a6SMohammed Gamal 		print_serial("imul Test 6: PASS\n");
944fa74f8a6SMohammed Gamal }
945fa74f8a6SMohammed Gamal 
94659317bd1SMohammed Gamal void test_mul()
94759317bd1SMohammed Gamal {
94859317bd1SMohammed Gamal 	struct regs inregs = { 0 }, outregs;
94959317bd1SMohammed Gamal 
95059317bd1SMohammed Gamal 	MK_INSN(mul8, "mov $2, %al\n\t"
95159317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
95259317bd1SMohammed Gamal 			"imul %cl\n\t");
95359317bd1SMohammed Gamal 
95459317bd1SMohammed Gamal 	MK_INSN(mul16, "mov $2, %ax\n\t"
95559317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
95659317bd1SMohammed Gamal 			"imul %cx\n\t");
95759317bd1SMohammed Gamal 
95859317bd1SMohammed Gamal 	MK_INSN(mul32, "mov $2, %eax\n\t"
95959317bd1SMohammed Gamal 			"mov $4, %ecx\n\t"
96059317bd1SMohammed Gamal 			"imul %ecx\n\t");
96159317bd1SMohammed Gamal 
962*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_mul8);
96359317bd1SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || (outregs.eax & 0xff) != 8)
96459317bd1SMohammed Gamal 		print_serial("mul Test 1: FAIL\n");
96559317bd1SMohammed Gamal 	else
96659317bd1SMohammed Gamal 		print_serial("mul Test 1: PASS\n");
96759317bd1SMohammed Gamal 
968*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_mul16);
96959317bd1SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 8)
97059317bd1SMohammed Gamal 		print_serial("mul Test 2: FAIL\n");
97159317bd1SMohammed Gamal 	else
97259317bd1SMohammed Gamal 		print_serial("mul Test 2: PASS\n");
97359317bd1SMohammed Gamal 
974*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_mul32);
97559317bd1SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 8)
97659317bd1SMohammed Gamal 		print_serial("mul Test 3: FAIL\n");
97759317bd1SMohammed Gamal 	else
97859317bd1SMohammed Gamal 		print_serial("mul Test 3: PASS\n");
97959317bd1SMohammed Gamal }
98059317bd1SMohammed Gamal 
9810d4c7614SMohammed Gamal void test_div()
9820d4c7614SMohammed Gamal {
9830d4c7614SMohammed Gamal 	struct regs inregs = { 0 }, outregs;
9840d4c7614SMohammed Gamal 
9850d4c7614SMohammed Gamal 	MK_INSN(div8, "mov $257, %ax\n\t"
9860d4c7614SMohammed Gamal 			"mov $2, %cl\n\t"
9870d4c7614SMohammed Gamal 			"div %cl\n\t");
9880d4c7614SMohammed Gamal 
9890d4c7614SMohammed Gamal 	MK_INSN(div16, "mov $512, %ax\n\t"
9900d4c7614SMohammed Gamal 			"mov $5, %cx\n\t"
9910d4c7614SMohammed Gamal 			"div %cx\n\t");
9920d4c7614SMohammed Gamal 
9930d4c7614SMohammed Gamal 	MK_INSN(div32, "mov $512, %eax\n\t"
9940d4c7614SMohammed Gamal 			"mov $5, %ecx\n\t"
9950d4c7614SMohammed Gamal 			"div %ecx\n\t");
9960d4c7614SMohammed Gamal 
997*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_div8);
9980d4c7614SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 384)
9990d4c7614SMohammed Gamal 		print_serial("div Test 1: FAIL\n");
10000d4c7614SMohammed Gamal 	else
10010d4c7614SMohammed Gamal 		print_serial("div Test 1: PASS\n");
10020d4c7614SMohammed Gamal 
1003*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_div16);
10040d4c7614SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 102 ||
10050d4c7614SMohammed Gamal 	    outregs.edx != 2)
10060d4c7614SMohammed Gamal 		print_serial("div Test 2: FAIL\n");
10070d4c7614SMohammed Gamal 	else
10080d4c7614SMohammed Gamal 		print_serial("div Test 2: PASS\n");
10090d4c7614SMohammed Gamal 
1010*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_div32);
10110d4c7614SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 102 ||
10120d4c7614SMohammed Gamal 	    outregs.edx != 2)
10130d4c7614SMohammed Gamal 		print_serial("div Test 3: FAIL\n");
10140d4c7614SMohammed Gamal 	else
10150d4c7614SMohammed Gamal 		print_serial("div Test 3: PASS\n");
10160d4c7614SMohammed Gamal }
10170d4c7614SMohammed Gamal 
10180d4c7614SMohammed Gamal void test_idiv()
10190d4c7614SMohammed Gamal {
10200d4c7614SMohammed Gamal 	struct regs inregs = { 0 }, outregs;
10210d4c7614SMohammed Gamal 
10220d4c7614SMohammed Gamal 	MK_INSN(idiv8, "mov $256, %ax\n\t"
10230d4c7614SMohammed Gamal 			"mov $-2, %cl\n\t"
10240d4c7614SMohammed Gamal 			"idiv %cl\n\t");
10250d4c7614SMohammed Gamal 
10260d4c7614SMohammed Gamal 	MK_INSN(idiv16, "mov $512, %ax\n\t"
10270d4c7614SMohammed Gamal 			"mov $-2, %cx\n\t"
10280d4c7614SMohammed Gamal 			"idiv %cx\n\t");
10290d4c7614SMohammed Gamal 
10300d4c7614SMohammed Gamal 	MK_INSN(idiv32, "mov $512, %eax\n\t"
10310d4c7614SMohammed Gamal 			"mov $-2, %ecx\n\t"
10320d4c7614SMohammed Gamal 			"idiv %ecx\n\t");
10330d4c7614SMohammed Gamal 
1034*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_idiv8);
10350d4c7614SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u8)-128)
10360d4c7614SMohammed Gamal 		print_serial("idiv Test 1: FAIL\n");
10370d4c7614SMohammed Gamal 	else
10380d4c7614SMohammed Gamal 		print_serial("idiv Test 1: PASS\n");
10390d4c7614SMohammed Gamal 
1040*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_idiv16);
10410d4c7614SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u16)-256)
10420d4c7614SMohammed Gamal 		print_serial("idiv Test 2: FAIL\n");
10430d4c7614SMohammed Gamal 	else
10440d4c7614SMohammed Gamal 		print_serial("idiv Test 2: PASS\n");
10450d4c7614SMohammed Gamal 
1046*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_idiv32);
10470d4c7614SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u32)-256)
10480d4c7614SMohammed Gamal 		print_serial("idiv Test 3: FAIL\n");
10490d4c7614SMohammed Gamal 	else
10500d4c7614SMohammed Gamal 		print_serial("idiv Test 3: PASS\n");
10510d4c7614SMohammed Gamal }
10520d4c7614SMohammed Gamal 
10536e293cf5SWei Yongjun void test_cbw(void)
10546e293cf5SWei Yongjun {
10556e293cf5SWei Yongjun 	struct regs inregs = { 0 }, outregs;
10566e293cf5SWei Yongjun 
10576e293cf5SWei Yongjun 	MK_INSN(cbw, "mov $0xFE, %eax \n\t"
10586e293cf5SWei Yongjun 		     "cbw\n\t");
10596e293cf5SWei Yongjun 	MK_INSN(cwde, "mov $0xFFFE, %eax \n\t"
10606e293cf5SWei Yongjun 		      "cwde\n\t");
10616e293cf5SWei Yongjun 
1062*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_cbw);
10636e293cf5SWei Yongjun 	if (outregs.eax != 0xFFFE)
10646e293cf5SWei Yongjun 		print_serial("cbw test1: FAIL\n");
10656e293cf5SWei Yongjun 	else
10666e293cf5SWei Yongjun 		print_serial("cbw test 1: PASS\n");
10676e293cf5SWei Yongjun 
1068*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_cwde);
10696e293cf5SWei Yongjun 	if (outregs.eax != 0xFFFFFFFE)
10706e293cf5SWei Yongjun 		print_serial("cwde test1: FAIL\n");
10716e293cf5SWei Yongjun 	else
10726e293cf5SWei Yongjun 		print_serial("cwde test 1: PASS\n");
10736e293cf5SWei Yongjun }
10746e293cf5SWei Yongjun 
1075eacef4e2SWei Yongjun void test_loopcc(void)
1076eacef4e2SWei Yongjun {
1077eacef4e2SWei Yongjun 	struct regs inregs = { 0 }, outregs;
1078eacef4e2SWei Yongjun 
1079eacef4e2SWei Yongjun 	MK_INSN(loop, "mov $10, %ecx\n\t"
1080eacef4e2SWei Yongjun 		      "1: inc %eax\n\t"
1081eacef4e2SWei Yongjun 		      "loop 1b\n\t");
1082eacef4e2SWei Yongjun 
1083eacef4e2SWei Yongjun 	MK_INSN(loope, "mov $10, %ecx\n\t"
1084eacef4e2SWei Yongjun 		       "mov $1, %eax\n\t"
1085eacef4e2SWei Yongjun 		       "1: dec %eax\n\t"
1086eacef4e2SWei Yongjun 		       "loope 1b\n\t");
1087eacef4e2SWei Yongjun 
1088eacef4e2SWei Yongjun 	MK_INSN(loopne, "mov $10, %ecx\n\t"
1089eacef4e2SWei Yongjun 		        "mov $5, %eax\n\t"
1090eacef4e2SWei Yongjun 		        "1: dec %eax\n\t"
1091eacef4e2SWei Yongjun 			"loopne 1b\n\t");
1092eacef4e2SWei Yongjun 
1093*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_loop);
1094eacef4e2SWei Yongjun 	if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 10)
1095eacef4e2SWei Yongjun 		print_serial("LOOPcc short Test 1: FAIL\n");
1096eacef4e2SWei Yongjun 	else
1097eacef4e2SWei Yongjun 		print_serial("LOOPcc short Test 1: PASS\n");
1098eacef4e2SWei Yongjun 
1099*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_loope);
1100eacef4e2SWei Yongjun 	if(!regs_equal(&inregs, &outregs, R_AX | R_CX) ||
1101eacef4e2SWei Yongjun 	   outregs.eax != -1 || outregs.ecx != 8)
1102eacef4e2SWei Yongjun 		print_serial("LOOPcc short Test 2: FAIL\n");
1103eacef4e2SWei Yongjun 	else
1104eacef4e2SWei Yongjun 		print_serial("LOOPcc short Test 2: PASS\n");
1105eacef4e2SWei Yongjun 
1106*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_loopne);
1107eacef4e2SWei Yongjun 	if(!regs_equal(&inregs, &outregs, R_AX | R_CX) ||
1108eacef4e2SWei Yongjun 	   outregs.eax != 0 || outregs.ecx != 5)
1109eacef4e2SWei Yongjun 		print_serial("LOOPcc short Test 3: FAIL\n");
1110eacef4e2SWei Yongjun 	else
1111eacef4e2SWei Yongjun 		print_serial("LOOPcc short Test 3: PASS\n");
1112eacef4e2SWei Yongjun }
1113eacef4e2SWei Yongjun 
1114b274feedSAvi Kivity static void test_das(void)
1115b274feedSAvi Kivity {
1116b274feedSAvi Kivity     struct regs inregs = { 0 }, outregs = { 0 };
1117b274feedSAvi Kivity     short i;
1118b274feedSAvi Kivity     static unsigned test_cases[1024] = {
1119b274feedSAvi Kivity         0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00,
1120b274feedSAvi Kivity         0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01,
1121b274feedSAvi Kivity         0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02,
1122b274feedSAvi Kivity         0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03,
1123b274feedSAvi Kivity         0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04,
1124b274feedSAvi Kivity         0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05,
1125b274feedSAvi Kivity         0x06000606, 0x8701a606, 0x56100006, 0x9711a006,
1126b274feedSAvi Kivity         0x02000707, 0x8301a707, 0x12100107, 0x9311a107,
1127b274feedSAvi Kivity         0x02000808, 0x8301a808, 0x12100208, 0x9311a208,
1128b274feedSAvi Kivity         0x06000909, 0x8701a909, 0x16100309, 0x9711a309,
1129b274feedSAvi Kivity         0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a,
1130b274feedSAvi Kivity         0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b,
1131b274feedSAvi Kivity         0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c,
1132b274feedSAvi Kivity         0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d,
1133b274feedSAvi Kivity         0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e,
1134b274feedSAvi Kivity         0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f,
1135b274feedSAvi Kivity         0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10,
1136b274feedSAvi Kivity         0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11,
1137b274feedSAvi Kivity         0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12,
1138b274feedSAvi Kivity         0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13,
1139b274feedSAvi Kivity         0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14,
1140b274feedSAvi Kivity         0x02001515, 0x8301b515, 0x16100f15, 0x9711af15,
1141b274feedSAvi Kivity         0x02001616, 0x8301b616, 0x12101016, 0x9311b016,
1142b274feedSAvi Kivity         0x06001717, 0x8701b717, 0x16101117, 0x9711b117,
1143b274feedSAvi Kivity         0x06001818, 0x8701b818, 0x16101218, 0x9711b218,
1144b274feedSAvi Kivity         0x02001919, 0x8301b919, 0x12101319, 0x9311b319,
1145b274feedSAvi Kivity         0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a,
1146b274feedSAvi Kivity         0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b,
1147b274feedSAvi Kivity         0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c,
1148b274feedSAvi Kivity         0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d,
1149b274feedSAvi Kivity         0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e,
1150b274feedSAvi Kivity         0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f,
1151b274feedSAvi Kivity         0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20,
1152b274feedSAvi Kivity         0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21,
1153b274feedSAvi Kivity         0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22,
1154b274feedSAvi Kivity         0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23,
1155b274feedSAvi Kivity         0x06002424, 0x8301c424, 0x16101e24, 0x9711be24,
1156b274feedSAvi Kivity         0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25,
1157b274feedSAvi Kivity         0x02002626, 0x8701c626, 0x12102026, 0x9711c026,
1158b274feedSAvi Kivity         0x06002727, 0x8301c727, 0x16102127, 0x9311c127,
1159b274feedSAvi Kivity         0x06002828, 0x8301c828, 0x16102228, 0x9311c228,
1160b274feedSAvi Kivity         0x02002929, 0x8701c929, 0x12102329, 0x9711c329,
1161b274feedSAvi Kivity         0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a,
1162b274feedSAvi Kivity         0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b,
1163b274feedSAvi Kivity         0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c,
1164b274feedSAvi Kivity         0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d,
1165b274feedSAvi Kivity         0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e,
1166b274feedSAvi Kivity         0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f,
1167b274feedSAvi Kivity         0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30,
1168b274feedSAvi Kivity         0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31,
1169b274feedSAvi Kivity         0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32,
1170b274feedSAvi Kivity         0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33,
1171b274feedSAvi Kivity         0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34,
1172b274feedSAvi Kivity         0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35,
1173b274feedSAvi Kivity         0x06003636, 0x8301d636, 0x16103036, 0x9311d036,
1174b274feedSAvi Kivity         0x02003737, 0x8701d737, 0x12103137, 0x9711d137,
1175b274feedSAvi Kivity         0x02003838, 0x8701d838, 0x12103238, 0x9711d238,
1176b274feedSAvi Kivity         0x06003939, 0x8301d939, 0x16103339, 0x9311d339,
1177b274feedSAvi Kivity         0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a,
1178b274feedSAvi Kivity         0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b,
1179b274feedSAvi Kivity         0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c,
1180b274feedSAvi Kivity         0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d,
1181b274feedSAvi Kivity         0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e,
1182b274feedSAvi Kivity         0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f,
1183b274feedSAvi Kivity         0x02004040, 0x8301e040, 0x16103a40, 0x9311da40,
1184b274feedSAvi Kivity         0x06004141, 0x8701e141, 0x12103b41, 0x9711db41,
1185b274feedSAvi Kivity         0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42,
1186b274feedSAvi Kivity         0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43,
1187b274feedSAvi Kivity         0x06004444, 0x8701e444, 0x12103e44, 0x9711de44,
1188b274feedSAvi Kivity         0x02004545, 0x8301e545, 0x16103f45, 0x9311df45,
1189b274feedSAvi Kivity         0x02004646, 0x8301e646, 0x12104046, 0x9311e046,
1190b274feedSAvi Kivity         0x06004747, 0x8701e747, 0x16104147, 0x9711e147,
1191b274feedSAvi Kivity         0x06004848, 0x8701e848, 0x16104248, 0x9711e248,
1192b274feedSAvi Kivity         0x02004949, 0x8301e949, 0x12104349, 0x9311e349,
1193b274feedSAvi Kivity         0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a,
1194b274feedSAvi Kivity         0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b,
1195b274feedSAvi Kivity         0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c,
1196b274feedSAvi Kivity         0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d,
1197b274feedSAvi Kivity         0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e,
1198b274feedSAvi Kivity         0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f,
1199b274feedSAvi Kivity         0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50,
1200b274feedSAvi Kivity         0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51,
1201b274feedSAvi Kivity         0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52,
1202b274feedSAvi Kivity         0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53,
1203b274feedSAvi Kivity         0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54,
1204b274feedSAvi Kivity         0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55,
1205b274feedSAvi Kivity         0x06005656, 0x8701f656, 0x16105056, 0x9711f056,
1206b274feedSAvi Kivity         0x02005757, 0x8301f757, 0x12105157, 0x9311f157,
1207b274feedSAvi Kivity         0x02005858, 0x8301f858, 0x12105258, 0x9311f258,
1208b274feedSAvi Kivity         0x06005959, 0x8701f959, 0x16105359, 0x9711f359,
1209b274feedSAvi Kivity         0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a,
1210b274feedSAvi Kivity         0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b,
1211b274feedSAvi Kivity         0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c,
1212b274feedSAvi Kivity         0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d,
1213b274feedSAvi Kivity         0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e,
1214b274feedSAvi Kivity         0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f,
1215b274feedSAvi Kivity         0x06006060, 0x47010060, 0x16105a60, 0x9711fa60,
1216b274feedSAvi Kivity         0x02006161, 0x03010161, 0x12105b61, 0x9311fb61,
1217b274feedSAvi Kivity         0x02006262, 0x03010262, 0x16105c62, 0x9711fc62,
1218b274feedSAvi Kivity         0x06006363, 0x07010363, 0x12105d63, 0x9311fd63,
1219b274feedSAvi Kivity         0x02006464, 0x03010464, 0x12105e64, 0x9311fe64,
1220b274feedSAvi Kivity         0x06006565, 0x07010565, 0x16105f65, 0x9711ff65,
1221b274feedSAvi Kivity         0x06006666, 0x07010666, 0x16106066, 0x57110066,
1222b274feedSAvi Kivity         0x02006767, 0x03010767, 0x12106167, 0x13110167,
1223b274feedSAvi Kivity         0x02006868, 0x03010868, 0x12106268, 0x13110268,
1224b274feedSAvi Kivity         0x06006969, 0x07010969, 0x16106369, 0x17110369,
1225b274feedSAvi Kivity         0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a,
1226b274feedSAvi Kivity         0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b,
1227b274feedSAvi Kivity         0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c,
1228b274feedSAvi Kivity         0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d,
1229b274feedSAvi Kivity         0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e,
1230b274feedSAvi Kivity         0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f,
1231b274feedSAvi Kivity         0x02007070, 0x03011070, 0x16106a70, 0x17110a70,
1232b274feedSAvi Kivity         0x06007171, 0x07011171, 0x12106b71, 0x13110b71,
1233b274feedSAvi Kivity         0x06007272, 0x07011272, 0x16106c72, 0x17110c72,
1234b274feedSAvi Kivity         0x02007373, 0x03011373, 0x12106d73, 0x13110d73,
1235b274feedSAvi Kivity         0x06007474, 0x07011474, 0x12106e74, 0x13110e74,
1236b274feedSAvi Kivity         0x02007575, 0x03011575, 0x16106f75, 0x17110f75,
1237b274feedSAvi Kivity         0x02007676, 0x03011676, 0x12107076, 0x13111076,
1238b274feedSAvi Kivity         0x06007777, 0x07011777, 0x16107177, 0x17111177,
1239b274feedSAvi Kivity         0x06007878, 0x07011878, 0x16107278, 0x17111278,
1240b274feedSAvi Kivity         0x02007979, 0x03011979, 0x12107379, 0x13111379,
1241b274feedSAvi Kivity         0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a,
1242b274feedSAvi Kivity         0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b,
1243b274feedSAvi Kivity         0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c,
1244b274feedSAvi Kivity         0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d,
1245b274feedSAvi Kivity         0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e,
1246b274feedSAvi Kivity         0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f,
1247b274feedSAvi Kivity         0x82008080, 0x03012080, 0x12107a80, 0x13111a80,
1248b274feedSAvi Kivity         0x86008181, 0x07012181, 0x16107b81, 0x17111b81,
1249b274feedSAvi Kivity         0x86008282, 0x07012282, 0x12107c82, 0x13111c82,
1250b274feedSAvi Kivity         0x82008383, 0x03012383, 0x16107d83, 0x17111d83,
1251b274feedSAvi Kivity         0x86008484, 0x07012484, 0x16107e84, 0x17111e84,
1252b274feedSAvi Kivity         0x82008585, 0x03012585, 0x12107f85, 0x13111f85,
1253b274feedSAvi Kivity         0x82008686, 0x03012686, 0x92108086, 0x13112086,
1254b274feedSAvi Kivity         0x86008787, 0x07012787, 0x96108187, 0x17112187,
1255b274feedSAvi Kivity         0x86008888, 0x07012888, 0x96108288, 0x17112288,
1256b274feedSAvi Kivity         0x82008989, 0x03012989, 0x92108389, 0x13112389,
1257b274feedSAvi Kivity         0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a,
1258b274feedSAvi Kivity         0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b,
1259b274feedSAvi Kivity         0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c,
1260b274feedSAvi Kivity         0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d,
1261b274feedSAvi Kivity         0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e,
1262b274feedSAvi Kivity         0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f,
1263b274feedSAvi Kivity         0x86009090, 0x07013090, 0x92108a90, 0x13112a90,
1264b274feedSAvi Kivity         0x82009191, 0x03013191, 0x96108b91, 0x17112b91,
1265b274feedSAvi Kivity         0x82009292, 0x03013292, 0x92108c92, 0x13112c92,
1266b274feedSAvi Kivity         0x86009393, 0x07013393, 0x96108d93, 0x17112d93,
1267b274feedSAvi Kivity         0x82009494, 0x03013494, 0x96108e94, 0x17112e94,
1268b274feedSAvi Kivity         0x86009595, 0x07013595, 0x92108f95, 0x13112f95,
1269b274feedSAvi Kivity         0x86009696, 0x07013696, 0x96109096, 0x17113096,
1270b274feedSAvi Kivity         0x82009797, 0x03013797, 0x92109197, 0x13113197,
1271b274feedSAvi Kivity         0x82009898, 0x03013898, 0x92109298, 0x13113298,
1272b274feedSAvi Kivity         0x86009999, 0x07013999, 0x96109399, 0x17113399,
1273b274feedSAvi Kivity         0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a,
1274b274feedSAvi Kivity         0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b,
1275b274feedSAvi Kivity         0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c,
1276b274feedSAvi Kivity         0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d,
1277b274feedSAvi Kivity         0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e,
1278b274feedSAvi Kivity         0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f,
1279b274feedSAvi Kivity         0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0,
1280b274feedSAvi Kivity         0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1,
1281b274feedSAvi Kivity         0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2,
1282b274feedSAvi Kivity         0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3,
1283b274feedSAvi Kivity         0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4,
1284b274feedSAvi Kivity         0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5,
1285b274feedSAvi Kivity         0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6,
1286b274feedSAvi Kivity         0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7,
1287b274feedSAvi Kivity         0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8,
1288b274feedSAvi Kivity         0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9,
1289b274feedSAvi Kivity         0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa,
1290b274feedSAvi Kivity         0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab,
1291b274feedSAvi Kivity         0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac,
1292b274feedSAvi Kivity         0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad,
1293b274feedSAvi Kivity         0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae,
1294b274feedSAvi Kivity         0x130049af, 0x130149af, 0x131049af, 0x131149af,
1295b274feedSAvi Kivity         0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0,
1296b274feedSAvi Kivity         0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1,
1297b274feedSAvi Kivity         0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2,
1298b274feedSAvi Kivity         0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3,
1299b274feedSAvi Kivity         0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4,
1300b274feedSAvi Kivity         0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5,
1301b274feedSAvi Kivity         0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6,
1302b274feedSAvi Kivity         0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7,
1303b274feedSAvi Kivity         0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8,
1304b274feedSAvi Kivity         0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9,
1305b274feedSAvi Kivity         0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba,
1306b274feedSAvi Kivity         0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb,
1307b274feedSAvi Kivity         0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc,
1308b274feedSAvi Kivity         0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd,
1309b274feedSAvi Kivity         0x130058be, 0x130158be, 0x131058be, 0x131158be,
1310b274feedSAvi Kivity         0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf,
1311b274feedSAvi Kivity         0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0,
1312b274feedSAvi Kivity         0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1,
1313b274feedSAvi Kivity         0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2,
1314b274feedSAvi Kivity         0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3,
1315b274feedSAvi Kivity         0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4,
1316b274feedSAvi Kivity         0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5,
1317b274feedSAvi Kivity         0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6,
1318b274feedSAvi Kivity         0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7,
1319b274feedSAvi Kivity         0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8,
1320b274feedSAvi Kivity         0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9,
1321b274feedSAvi Kivity         0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca,
1322b274feedSAvi Kivity         0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb,
1323b274feedSAvi Kivity         0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc,
1324b274feedSAvi Kivity         0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd,
1325b274feedSAvi Kivity         0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce,
1326b274feedSAvi Kivity         0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf,
1327b274feedSAvi Kivity         0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0,
1328b274feedSAvi Kivity         0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1,
1329b274feedSAvi Kivity         0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2,
1330b274feedSAvi Kivity         0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3,
1331b274feedSAvi Kivity         0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4,
1332b274feedSAvi Kivity         0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5,
1333b274feedSAvi Kivity         0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6,
1334b274feedSAvi Kivity         0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7,
1335b274feedSAvi Kivity         0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8,
1336b274feedSAvi Kivity         0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9,
1337b274feedSAvi Kivity         0x170074da, 0x170174da, 0x171074da, 0x171174da,
1338b274feedSAvi Kivity         0x130075db, 0x130175db, 0x131075db, 0x131175db,
1339b274feedSAvi Kivity         0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc,
1340b274feedSAvi Kivity         0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd,
1341b274feedSAvi Kivity         0x170078de, 0x170178de, 0x171078de, 0x171178de,
1342b274feedSAvi Kivity         0x130079df, 0x130179df, 0x131079df, 0x131179df,
1343b274feedSAvi Kivity         0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0,
1344b274feedSAvi Kivity         0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1,
1345b274feedSAvi Kivity         0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2,
1346b274feedSAvi Kivity         0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3,
1347b274feedSAvi Kivity         0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4,
1348b274feedSAvi Kivity         0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5,
1349b274feedSAvi Kivity         0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6,
1350b274feedSAvi Kivity         0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7,
1351b274feedSAvi Kivity         0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8,
1352b274feedSAvi Kivity         0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9,
1353b274feedSAvi Kivity         0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea,
1354b274feedSAvi Kivity         0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb,
1355b274feedSAvi Kivity         0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec,
1356b274feedSAvi Kivity         0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed,
1357b274feedSAvi Kivity         0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee,
1358b274feedSAvi Kivity         0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef,
1359b274feedSAvi Kivity         0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0,
1360b274feedSAvi Kivity         0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1,
1361b274feedSAvi Kivity         0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2,
1362b274feedSAvi Kivity         0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3,
1363b274feedSAvi Kivity         0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4,
1364b274feedSAvi Kivity         0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5,
1365b274feedSAvi Kivity         0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6,
1366b274feedSAvi Kivity         0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7,
1367b274feedSAvi Kivity         0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8,
1368b274feedSAvi Kivity         0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9,
1369b274feedSAvi Kivity         0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa,
1370b274feedSAvi Kivity         0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb,
1371b274feedSAvi Kivity         0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc,
1372b274feedSAvi Kivity         0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd,
1373b274feedSAvi Kivity         0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe,
1374b274feedSAvi Kivity         0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff,
1375b274feedSAvi Kivity     };
1376b274feedSAvi Kivity 
1377b274feedSAvi Kivity     MK_INSN(das, "das");
1378b274feedSAvi Kivity 
1379b274feedSAvi Kivity     for (i = 0; i < 1024; ++i) {
1380b274feedSAvi Kivity         unsigned tmp = test_cases[i];
1381b274feedSAvi Kivity         inregs.eax = tmp & 0xff;
1382b274feedSAvi Kivity         inregs.eflags = (tmp >> 16) & 0xff;
1383*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_das);
1384b274feedSAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX)
1385b274feedSAvi Kivity             || outregs.eax != ((tmp >> 8) & 0xff)
1386b274feedSAvi Kivity             || (outregs.eflags & 0xff) != (tmp >> 24)) {
1387b274feedSAvi Kivity 		print_serial("DAS Test: FAIL\n");
1388b274feedSAvi Kivity                 return;
1389b274feedSAvi Kivity         }
1390b274feedSAvi Kivity     }
1391b274feedSAvi Kivity     print_serial("DAS Test: PASS\n");
1392b274feedSAvi Kivity }
1393b274feedSAvi Kivity 
13940cbd5b06SMohammed Gamal void test_cwd_cdq()
13950cbd5b06SMohammed Gamal {
13960cbd5b06SMohammed Gamal 	struct regs inregs = { 0 }, outregs;
13970cbd5b06SMohammed Gamal 
13980cbd5b06SMohammed Gamal 	/* Sign-bit set */
13990cbd5b06SMohammed Gamal 	MK_INSN(cwd_1, "mov $0x8000, %ax\n\t"
14000cbd5b06SMohammed Gamal 		       "cwd\n\t");
14010cbd5b06SMohammed Gamal 
14020cbd5b06SMohammed Gamal 	/* Sign-bit not set */
14030cbd5b06SMohammed Gamal 	MK_INSN(cwd_2, "mov $0x1000, %ax\n\t"
14040cbd5b06SMohammed Gamal 		       "cwd\n\t");
14050cbd5b06SMohammed Gamal 
14060cbd5b06SMohammed Gamal 	/* Sign-bit set */
14070cbd5b06SMohammed Gamal 	MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t"
14080cbd5b06SMohammed Gamal 		       "cdq\n\t");
14090cbd5b06SMohammed Gamal 
14100cbd5b06SMohammed Gamal 	/* Sign-bit not set */
14110cbd5b06SMohammed Gamal 	MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t"
14120cbd5b06SMohammed Gamal 		       "cdq\n\t");
14130cbd5b06SMohammed Gamal 
1414*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_cwd_1);
14150cbd5b06SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_DX) || outregs.eax != 0x8000 || outregs.edx != 0xffff)
14160cbd5b06SMohammed Gamal 		print_serial("cwd Test 1: FAIL\n");
14170cbd5b06SMohammed Gamal 	else
14180cbd5b06SMohammed Gamal 		print_serial("cwd Test 1: PASS\n");
14190cbd5b06SMohammed Gamal 
1420*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_cwd_2);
14210cbd5b06SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_DX) || outregs.eax != 0x1000 || outregs.edx != 0)
14220cbd5b06SMohammed Gamal 		print_serial("cwd Test 2: FAIL\n");
14230cbd5b06SMohammed Gamal 	else
14240cbd5b06SMohammed Gamal 		print_serial("cwd Test 2: PASS\n");
14250cbd5b06SMohammed Gamal 
1426*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_cdq_1);
14270cbd5b06SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_DX) || outregs.eax != 0x80000000 || outregs.edx != 0xffffffff)
14280cbd5b06SMohammed Gamal 		print_serial("cdq Test 1: FAIL\n");
14290cbd5b06SMohammed Gamal 	else
14300cbd5b06SMohammed Gamal 		print_serial("cdq Test 1: PASS\n");
14310cbd5b06SMohammed Gamal 
1432*d4dc402cSAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, &insn_cdq_2);
14330cbd5b06SMohammed Gamal 	if (!regs_equal(&inregs, &outregs, R_AX | R_DX) || outregs.eax != 0x10000000 || outregs.edx != 0)
14340cbd5b06SMohammed Gamal 		print_serial("cdq Test 2: FAIL\n");
14350cbd5b06SMohammed Gamal 	else
14360cbd5b06SMohammed Gamal 		print_serial("cdq Test 2: PASS\n");
14370cbd5b06SMohammed Gamal }
14380cbd5b06SMohammed Gamal 
14397d36db35SAvi Kivity void realmode_start(void)
14407d36db35SAvi Kivity {
14417d36db35SAvi Kivity 	test_null();
14427d36db35SAvi Kivity 
14437d36db35SAvi Kivity 	test_shld();
14447d36db35SAvi Kivity 	test_push_pop();
14457d36db35SAvi Kivity 	test_pusha_popa();
14467d36db35SAvi Kivity 	test_mov_imm();
14477d36db35SAvi Kivity 	test_cmp_imm();
14487d36db35SAvi Kivity 	test_add_imm();
14497d36db35SAvi Kivity 	test_sub_imm();
14507d36db35SAvi Kivity 	test_xor_imm();
14517d36db35SAvi Kivity 	test_io();
14527d36db35SAvi Kivity 	test_eflags_insn();
14537d36db35SAvi Kivity 	test_jcc_short();
14547d36db35SAvi Kivity 	test_jcc_near();
14557d36db35SAvi Kivity 	/* test_call() uses short jump so call it after testing jcc */
14567d36db35SAvi Kivity 	test_call();
14577d36db35SAvi Kivity 	/* long jmp test uses call near so test it after testing call */
14587d36db35SAvi Kivity 	test_long_jmp();
14597d36db35SAvi Kivity 	test_xchg();
14607d36db35SAvi Kivity 	test_iret();
146196b9ca1eSMohammed Gamal 	test_int();
1462fa74f8a6SMohammed Gamal 	test_imul();
146359317bd1SMohammed Gamal 	test_mul();
14640d4c7614SMohammed Gamal 	test_div();
14650d4c7614SMohammed Gamal 	test_idiv();
1466eacef4e2SWei Yongjun 	test_loopcc();
14676e293cf5SWei Yongjun 	test_cbw();
14680cbd5b06SMohammed Gamal 	test_cwd_cdq();
1469b274feedSAvi Kivity 	test_das();
14707d36db35SAvi Kivity 
14717d36db35SAvi Kivity 	exit(0);
14727d36db35SAvi Kivity }
14737d36db35SAvi Kivity 
14747d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff };
14757d36db35SAvi Kivity 
14767d36db35SAvi Kivity struct __attribute__((packed)) {
14777d36db35SAvi Kivity 	unsigned short limit;
14787d36db35SAvi Kivity 	void *base;
14797d36db35SAvi Kivity } r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt };
14807d36db35SAvi Kivity 
14817d36db35SAvi Kivity asm(
14827d36db35SAvi Kivity 	".section .init \n\t"
14837d36db35SAvi Kivity 
14847d36db35SAvi Kivity 	".code32 \n\t"
14857d36db35SAvi Kivity 
14867d36db35SAvi Kivity 	"mb_magic = 0x1BADB002 \n\t"
14877d36db35SAvi Kivity 	"mb_flags = 0x0 \n\t"
14887d36db35SAvi Kivity 
14897d36db35SAvi Kivity 	"# multiboot header \n\t"
14907d36db35SAvi Kivity 	".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t"
14917d36db35SAvi Kivity 
14927d36db35SAvi Kivity 	".globl start \n\t"
14937d36db35SAvi Kivity 	".data \n\t"
14947d36db35SAvi Kivity 	". = . + 4096 \n\t"
14957d36db35SAvi Kivity 	"stacktop: \n\t"
14967d36db35SAvi Kivity 
14977d36db35SAvi Kivity 	".text \n\t"
14987d36db35SAvi Kivity 	"start: \n\t"
14997d36db35SAvi Kivity 	"lgdt r_gdt_descr \n\t"
15007d36db35SAvi Kivity 	"ljmp $8, $1f; 1: \n\t"
15017d36db35SAvi Kivity 	".code16gcc \n\t"
15027d36db35SAvi Kivity 	"mov $16, %eax \n\t"
15037d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
15047d36db35SAvi Kivity 	"mov %ax, %es \n\t"
15057d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
15067d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
15077d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
15087d36db35SAvi Kivity 	"mov %cr0, %eax \n\t"
15097d36db35SAvi Kivity 	"btc $0, %eax \n\t"
15107d36db35SAvi Kivity 	"mov %eax, %cr0 \n\t"
15117d36db35SAvi Kivity 	"ljmp $0, $realmode_entry \n\t"
15127d36db35SAvi Kivity 
15137d36db35SAvi Kivity 	"realmode_entry: \n\t"
15147d36db35SAvi Kivity 
15157d36db35SAvi Kivity 	"xor %ax, %ax \n\t"
15167d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
15177d36db35SAvi Kivity 	"mov %ax, %es \n\t"
15187d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
15197d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
15207d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
15217d36db35SAvi Kivity 	"mov $stacktop, %esp\n\t"
15227d36db35SAvi Kivity 	"ljmp $0, $realmode_start \n\t"
15237d36db35SAvi Kivity 
15247d36db35SAvi Kivity 	".code16gcc \n\t"
15257d36db35SAvi Kivity 	);
1526