xref: /kvm-unit-tests/x86/realmode.c (revision 2a9b57186c6fb186bedf8dc1fa5fc541e8adfc27)
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 
57d4dc402cSAvi Kivity struct insn_desc {
58d4dc402cSAvi Kivity     u16 ptr;
59d4dc402cSAvi Kivity     u16 len;
60d4dc402cSAvi Kivity };
61d4dc402cSAvi Kivity 
6218253fdeSAvi Kivity static struct regs inregs, outregs;
6318253fdeSAvi Kivity 
6418253fdeSAvi Kivity static void exec_in_big_real_mode(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 
71d4dc402cSAvi Kivity 	for (i = 0; i < insn->len; ++i)
72d4dc402cSAvi 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 
7618253fdeSAvi 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 		);
11818253fdeSAvi 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 
13018253fdeSAvi Kivity int regs_equal(int ignore)
1317d36db35SAvi Kivity {
13218253fdeSAvi Kivity 	const u32 *p1 = &inregs.eax, *p2 = &outregs.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 
1416055ea1fSAvi Kivity static void report(const char *name, u16 regs_ignore, _Bool ok)
14281050840SAvi Kivity {
1436055ea1fSAvi Kivity     if (!regs_equal(regs_ignore)) {
1446055ea1fSAvi Kivity 	ok = 0;
1456055ea1fSAvi Kivity     }
14681050840SAvi Kivity     print_serial(ok ? "PASS: " : "FAIL: ");
14781050840SAvi Kivity     print_serial(name);
14881050840SAvi Kivity     print_serial("\n");
14981050840SAvi Kivity }
15081050840SAvi Kivity 
1517d36db35SAvi Kivity #define MK_INSN(name, str)				\
1527d36db35SAvi Kivity     asm (						\
153d4dc402cSAvi Kivity 	 ".pushsection .data.insn  \n\t"		\
154d4dc402cSAvi Kivity 	 "insn_" #name ": \n\t"				\
155d4dc402cSAvi Kivity 	 ".word 1001f, 1002f - 1001f \n\t"		\
156d4dc402cSAvi Kivity 	 ".popsection \n\t"				\
157d4dc402cSAvi Kivity 	 ".pushsection .text.insn, \"ax\" \n\t"		\
158d4dc402cSAvi Kivity 	 "1001: \n\t"					\
159d4dc402cSAvi Kivity 	 "insn_code_" #name ": " str " \n\t"		\
160d4dc402cSAvi Kivity 	 "1002: \n\t"					\
161d4dc402cSAvi Kivity 	 ".popsection"					\
1627d36db35SAvi Kivity     );							\
163d4dc402cSAvi Kivity     extern struct insn_desc insn_##name;
1647d36db35SAvi Kivity 
1657d36db35SAvi Kivity void test_xchg(void)
1667d36db35SAvi Kivity {
1677d36db35SAvi Kivity 	MK_INSN(xchg_test1, "xchg %eax,%eax\n\t");
1687d36db35SAvi Kivity 	MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t");
1697d36db35SAvi Kivity 	MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t");
1707d36db35SAvi Kivity 	MK_INSN(xchg_test4, "xchg %eax,%edx\n\t");
1717d36db35SAvi Kivity 	MK_INSN(xchg_test5, "xchg %eax,%esi\n\t");
1727d36db35SAvi Kivity 	MK_INSN(xchg_test6, "xchg %eax,%edi\n\t");
1737d36db35SAvi Kivity 	MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t");
1747d36db35SAvi Kivity 	MK_INSN(xchg_test8, "xchg %eax,%esp\n\t");
1757d36db35SAvi Kivity 
17618253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7};
1777d36db35SAvi Kivity 
17818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test1);
1796055ea1fSAvi Kivity 	report("xchg 1", 0, 1);
18018253fdeSAvi Kivity 
18118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test2);
1826055ea1fSAvi Kivity 	report("xchg 2", R_AX | R_BX,
1836055ea1fSAvi Kivity 	       outregs.eax == inregs.ebx && outregs.ebx == inregs.eax);
1847d36db35SAvi Kivity 
18518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test3);
1866055ea1fSAvi Kivity 	report("xchg 3", R_AX | R_CX,
1876055ea1fSAvi Kivity 	       outregs.eax == inregs.ecx && outregs.ecx == inregs.eax);
1887d36db35SAvi Kivity 
18918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test4);
1906055ea1fSAvi Kivity 	report("xchg 4", R_AX | R_DX,
1916055ea1fSAvi Kivity 	       outregs.eax == inregs.edx && outregs.edx == inregs.eax);
1927d36db35SAvi Kivity 
19318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test5);
1946055ea1fSAvi Kivity 	report("xchg 5", R_AX | R_SI,
1956055ea1fSAvi Kivity 	       outregs.eax == inregs.esi && outregs.esi == inregs.eax);
1967d36db35SAvi Kivity 
19718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test6);
1986055ea1fSAvi Kivity 	report("xchg 6", R_AX | R_DI,
1996055ea1fSAvi Kivity 	       outregs.eax == inregs.edi && outregs.edi == inregs.eax);
2007d36db35SAvi Kivity 
20118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test7);
2026055ea1fSAvi Kivity 	report("xchg 7", R_AX | R_BP,
2036055ea1fSAvi Kivity 	       outregs.eax == inregs.ebp && outregs.ebp == inregs.eax);
2047d36db35SAvi Kivity 
20518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test8);
2066055ea1fSAvi Kivity 	report("xchg 8", R_AX | R_SP,
2076055ea1fSAvi Kivity 	       outregs.eax == inregs.esp && outregs.esp == inregs.eax);
2087d36db35SAvi Kivity }
2097d36db35SAvi Kivity 
2107d36db35SAvi Kivity void test_shld(void)
2117d36db35SAvi Kivity {
2127d36db35SAvi Kivity 	MK_INSN(shld_test, "shld $8,%edx,%eax\n\t");
2137d36db35SAvi Kivity 
21418253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0xbe, .edx = 0xef000000 };
21518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_shld_test);
2166055ea1fSAvi Kivity 	report("shld", ~0, outregs.eax == 0xbeef);
2177d36db35SAvi Kivity }
2187d36db35SAvi Kivity 
2197d36db35SAvi Kivity void test_mov_imm(void)
2207d36db35SAvi Kivity {
2217d36db35SAvi Kivity 	MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax");
2227d36db35SAvi Kivity 	MK_INSN(mov_r16_imm_1, "mov $1234, %ax");
2237d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_1, "mov $0x12, %ah");
2247d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_2, "mov $0x34, %al");
2257d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t");
2267d36db35SAvi Kivity 
22718253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
22818253fdeSAvi Kivity 
22918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r16_imm_1);
2306055ea1fSAvi Kivity 	report("mov 1", R_AX, outregs.eax == 1234);
2317d36db35SAvi Kivity 
2327d36db35SAvi Kivity 	/* test mov $imm, %eax */
23318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r32_imm_1);
2346055ea1fSAvi Kivity 	report("mov 2", R_AX, outregs.eax == 1234567890);
2357d36db35SAvi Kivity 
2367d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
23718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_1);
2386055ea1fSAvi Kivity 	report("mov 3", R_AX, outregs.eax == 0x1200);
2397d36db35SAvi Kivity 
24018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_2);
2416055ea1fSAvi Kivity 	report("mov 4", R_AX, outregs.eax == 0x34);
2427d36db35SAvi Kivity 
24318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_3);
2446055ea1fSAvi Kivity 	report("mov 5", R_AX, outregs.eax == 0x1234);
2457d36db35SAvi Kivity }
2467d36db35SAvi Kivity 
2477d36db35SAvi Kivity void test_sub_imm(void)
2487d36db35SAvi Kivity {
2497d36db35SAvi Kivity 	MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t");
2507d36db35SAvi Kivity 	MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t");
2517d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t");
2527d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t");
2537d36db35SAvi Kivity 
25418253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
25518253fdeSAvi Kivity 
25618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r16_imm_1);
2576055ea1fSAvi Kivity 	report("sub 1", R_AX, outregs.eax == 1224);
2587d36db35SAvi Kivity 
2597d36db35SAvi Kivity 	/* test mov $imm, %eax */
26018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r32_imm_1);
2616055ea1fSAvi Kivity 	report("sub 2", R_AX, outregs.eax == 1234567880);
2627d36db35SAvi Kivity 
2637d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
26418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_1);
2656055ea1fSAvi Kivity 	report("sub 3", R_AX, outregs.eax == 0x0200);
2667d36db35SAvi Kivity 
26718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_2);
2686055ea1fSAvi Kivity 	report("sub 4", R_AX, outregs.eax == 0x24);
2697d36db35SAvi Kivity }
2707d36db35SAvi Kivity 
2717d36db35SAvi Kivity void test_xor_imm(void)
2727d36db35SAvi Kivity {
2737d36db35SAvi Kivity 	MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t");
2747d36db35SAvi Kivity 	MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t");
2757d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t");
2767d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t");
2777d36db35SAvi Kivity 
27818253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
27918253fdeSAvi Kivity 
28018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r16_imm_1);
2816055ea1fSAvi Kivity 	report("xor 1", R_AX, outregs.eax == 0);
2827d36db35SAvi Kivity 
2837d36db35SAvi Kivity 	/* test mov $imm, %eax */
28418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r32_imm_1);
2856055ea1fSAvi Kivity 	report("xor 2", R_AX, outregs.eax == 0);
2867d36db35SAvi Kivity 
2877d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
28818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_1);
2896055ea1fSAvi Kivity 	report("xor 3", R_AX, outregs.eax == 0);
2907d36db35SAvi Kivity 
29118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_2);
2926055ea1fSAvi Kivity 	report("xor 4", R_AX, outregs.eax == 0);
2937d36db35SAvi Kivity }
2947d36db35SAvi Kivity 
2957d36db35SAvi Kivity void test_cmp_imm(void)
2967d36db35SAvi Kivity {
2977d36db35SAvi Kivity 	MK_INSN(cmp_test1, "mov $0x34, %al\n\t"
2987d36db35SAvi Kivity 			   "cmp $0x34, %al\n\t");
2997d36db35SAvi Kivity 	MK_INSN(cmp_test2, "mov $0x34, %al\n\t"
3007d36db35SAvi Kivity 			   "cmp $0x39, %al\n\t");
3017d36db35SAvi Kivity 	MK_INSN(cmp_test3, "mov $0x34, %al\n\t"
3027d36db35SAvi Kivity 			   "cmp $0x24, %al\n\t");
3037d36db35SAvi Kivity 
30418253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
30518253fdeSAvi Kivity 
3067d36db35SAvi Kivity 	/* test cmp imm8 with AL */
3077d36db35SAvi Kivity 	/* ZF: (bit 6) Zero Flag becomes 1 if an operation results
3087d36db35SAvi Kivity 	 * in a 0 writeback, or 0 register
3097d36db35SAvi Kivity 	 */
31018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test1);
3116055ea1fSAvi Kivity 	report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6));
3127d36db35SAvi Kivity 
31318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test2);
3146055ea1fSAvi Kivity 	report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0);
3157d36db35SAvi Kivity 
31618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test3);
3176055ea1fSAvi Kivity 	report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0);
3187d36db35SAvi Kivity }
3197d36db35SAvi Kivity 
3207d36db35SAvi Kivity void test_add_imm(void)
3217d36db35SAvi Kivity {
3227d36db35SAvi Kivity 	MK_INSN(add_test1, "mov $0x43211234, %eax \n\t"
3237d36db35SAvi Kivity 			   "add $0x12344321, %eax \n\t");
3247d36db35SAvi Kivity 	MK_INSN(add_test2, "mov $0x12, %eax \n\t"
3257d36db35SAvi Kivity 			   "add $0x21, %al\n\t");
3267d36db35SAvi Kivity 
32718253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
32818253fdeSAvi Kivity 
32918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test1);
3306055ea1fSAvi Kivity 	report("add 1", ~0, outregs.eax == 0x55555555);
3317d36db35SAvi Kivity 
33218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test2);
3336055ea1fSAvi Kivity 	report("add 2", ~0, outregs.eax == 0x33);
3347d36db35SAvi Kivity }
3357d36db35SAvi Kivity 
3367d36db35SAvi Kivity void test_eflags_insn(void)
3377d36db35SAvi Kivity {
3387d36db35SAvi Kivity 	MK_INSN(clc, "clc");
339b3261e48SMohammed Gamal 	MK_INSN(stc, "stc");
3407d36db35SAvi Kivity 	MK_INSN(cli, "cli");
3417d36db35SAvi Kivity 	MK_INSN(sti, "sti");
3427d36db35SAvi Kivity 	MK_INSN(cld, "cld");
3437d36db35SAvi Kivity 	MK_INSN(std, "std");
3447d36db35SAvi Kivity 
34518253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
34618253fdeSAvi Kivity 
34718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_clc);
3486055ea1fSAvi Kivity 	report("clc", ~0, (outregs.eflags & 1) == 0);
3497d36db35SAvi Kivity 
35018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_stc);
3516055ea1fSAvi Kivity 	report("stc", ~0, (outregs.eflags & 1) == 1);
352b3261e48SMohammed Gamal 
35318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cli);
3546055ea1fSAvi Kivity 	report("cli", ~0, !(outregs.eflags & (1 << 9)));
3557d36db35SAvi Kivity 
35618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sti);
3576055ea1fSAvi Kivity 	report("sti", ~0, outregs.eflags & (1 << 9));
3587d36db35SAvi Kivity 
35918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cld);
3606055ea1fSAvi Kivity 	report("cld", ~0, !(outregs.eflags & (1 << 10)));
3617d36db35SAvi Kivity 
36218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_std);
3636055ea1fSAvi Kivity 	report("std", ~0, (outregs.eflags & (1 << 10)));
3647d36db35SAvi Kivity }
3657d36db35SAvi Kivity 
3667d36db35SAvi Kivity void test_io(void)
3677d36db35SAvi Kivity {
3687d36db35SAvi Kivity 	MK_INSN(io_test1, "mov $0xff, %al \n\t"
3697d36db35SAvi Kivity 		          "out %al, $0xe0 \n\t"
3707d36db35SAvi Kivity 		          "mov $0x00, %al \n\t"
3717d36db35SAvi Kivity 			  "in $0xe0, %al \n\t");
3727d36db35SAvi Kivity 	MK_INSN(io_test2, "mov $0xffff, %ax \n\t"
3737d36db35SAvi Kivity 			  "out %ax, $0xe0 \n\t"
3747d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
3757d36db35SAvi Kivity 			  "in $0xe0, %ax \n\t");
3767d36db35SAvi Kivity 	MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t"
3777d36db35SAvi Kivity 			  "out %eax, $0xe0 \n\t"
3787d36db35SAvi Kivity 			  "mov $0x000000, %eax \n\t"
3797d36db35SAvi Kivity 			  "in $0xe0, %eax \n\t");
3807d36db35SAvi Kivity 	MK_INSN(io_test4, "mov $0xe0, %dx \n\t"
3817d36db35SAvi Kivity 			  "mov $0xff, %al \n\t"
3827d36db35SAvi Kivity 			  "out %al, %dx \n\t"
3837d36db35SAvi Kivity 			  "mov $0x00, %al \n\t"
3847d36db35SAvi Kivity 			  "in %dx, %al \n\t");
3857d36db35SAvi Kivity 	MK_INSN(io_test5, "mov $0xe0, %dx \n\t"
3867d36db35SAvi Kivity 			  "mov $0xffff, %ax \n\t"
3877d36db35SAvi Kivity 			  "out %ax, %dx \n\t"
3887d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
3897d36db35SAvi Kivity 			  "in %dx, %ax \n\t");
3907d36db35SAvi Kivity 	MK_INSN(io_test6, "mov $0xe0, %dx \n\t"
3917d36db35SAvi Kivity 			  "mov $0xffffffff, %eax \n\t"
3927d36db35SAvi Kivity 			  "out %eax, %dx \n\t"
3937d36db35SAvi Kivity 			  "mov $0x00000000, %eax \n\t"
3947d36db35SAvi Kivity 			  "in %dx, %eax \n\t");
3957d36db35SAvi Kivity 
39618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
39718253fdeSAvi Kivity 
39818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test1);
3996055ea1fSAvi Kivity 	report("pio 1", R_AX, outregs.eax == 0xff);
4007d36db35SAvi Kivity 
40118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test2);
4026055ea1fSAvi Kivity 	report("pio 2", R_AX, outregs.eax == 0xffff);
4037d36db35SAvi Kivity 
40418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test3);
4056055ea1fSAvi Kivity 	report("pio 3", R_AX, outregs.eax == 0xffffffff);
4067d36db35SAvi Kivity 
40718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test4);
4086055ea1fSAvi Kivity 	report("pio 4", R_AX|R_DX, outregs.eax == 0xff);
4097d36db35SAvi Kivity 
41018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test5);
4116055ea1fSAvi Kivity 	report("pio 5", R_AX|R_DX, outregs.eax == 0xffff);
4127d36db35SAvi Kivity 
41318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test6);
4146055ea1fSAvi Kivity 	report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff);
4157d36db35SAvi Kivity }
4167d36db35SAvi Kivity 
417c0b7268dSAvi Kivity asm ("retf: lretw");
418c0b7268dSAvi Kivity extern void retf();
419c0b7268dSAvi Kivity 
4207d36db35SAvi Kivity void test_call(void)
4217d36db35SAvi Kivity {
4227d36db35SAvi Kivity 	u32 esp[16];
423c0b7268dSAvi Kivity 	u32 addr;
4247d36db35SAvi Kivity 
42518253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
4267d36db35SAvi Kivity 	inregs.esp = (u32)esp;
4277d36db35SAvi Kivity 
4287d36db35SAvi Kivity 	MK_INSN(call1, "mov $test_function, %eax \n\t"
4297d36db35SAvi Kivity 		       "call *%eax\n\t");
4307d36db35SAvi Kivity 	MK_INSN(call_near1, "jmp 2f\n\t"
4317d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
4327d36db35SAvi Kivity 			    "ret\n\t"
4337d36db35SAvi Kivity 			    "2: call 1b\t");
4347d36db35SAvi Kivity 	MK_INSN(call_near2, "call 1f\n\t"
4357d36db35SAvi Kivity 			    "jmp 2f\n\t"
4367d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
4377d36db35SAvi Kivity 			    "ret\n\t"
4387d36db35SAvi Kivity 			    "2:\t");
439c0b7268dSAvi Kivity 	MK_INSN(call_far1,  "lcallw *(%ebx)\n\t");
440556d2680SWei Yongjun 	MK_INSN(call_far2,  "lcallw $0, $retf\n\t");
441c6061817SAvi Kivity 	MK_INSN(ret_imm,    "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b");
4427d36db35SAvi Kivity 
44318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call1);
4446055ea1fSAvi Kivity 	report("call 1", R_AX, outregs.eax == 0x1234);
4457d36db35SAvi Kivity 
44618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near1);
4476055ea1fSAvi Kivity 	report("call near 1", R_AX, outregs.eax == 0x1234);
4487d36db35SAvi Kivity 
44918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near2);
4506055ea1fSAvi Kivity 	report("call near 2", R_AX, outregs.eax == 0x1234);
451c0b7268dSAvi Kivity 
452c0b7268dSAvi Kivity 	addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f);
453c0b7268dSAvi Kivity 	inregs.ebx = (unsigned)&addr;
45418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_far1);
4556055ea1fSAvi Kivity 	report("call far 1", 0, 1);
456c6061817SAvi Kivity 
457556d2680SWei Yongjun 	exec_in_big_real_mode(&insn_call_far2);
458556d2680SWei Yongjun 	report("call far 2", 0, 1);
459556d2680SWei Yongjun 
46018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_ret_imm);
4616055ea1fSAvi Kivity 	report("ret imm 1", 0, 1);
4627d36db35SAvi Kivity }
4637d36db35SAvi Kivity 
4647d36db35SAvi Kivity void test_jcc_short(void)
4657d36db35SAvi Kivity {
4667d36db35SAvi Kivity 	MK_INSN(jnz_short1, "jnz 1f\n\t"
4677d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
4687d36db35SAvi Kivity 		            "1:\n\t");
4697d36db35SAvi Kivity 	MK_INSN(jnz_short2, "1:\n\t"
4707d36db35SAvi Kivity 			    "cmp $0x1234, %eax\n\t"
4717d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
4727d36db35SAvi Kivity 		            "jnz 1b\n\t");
4737d36db35SAvi Kivity 	MK_INSN(jmp_short1, "jmp 1f\n\t"
4747d36db35SAvi Kivity 		      "mov $0x1234, %eax\n\t"
4757d36db35SAvi Kivity 		      "1:\n\t");
4767d36db35SAvi Kivity 
47718253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
4787d36db35SAvi Kivity 
47918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short1);
4806055ea1fSAvi Kivity 	report("jnz short 1", ~0, 1);
48118253fdeSAvi Kivity 
48218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short2);
4836055ea1fSAvi Kivity 	report("jnz short 2", R_AX, (outregs.eflags & (1 << 6)));
4847d36db35SAvi Kivity 
48518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_short1);
4866055ea1fSAvi Kivity 	report("jmp short 1", ~0, 1);
4877d36db35SAvi Kivity }
4887d36db35SAvi Kivity 
4897d36db35SAvi Kivity void test_jcc_near(void)
4907d36db35SAvi Kivity {
4917d36db35SAvi Kivity 	/* encode near jmp manually. gas will not do it if offsets < 127 byte */
4927d36db35SAvi Kivity 	MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t"
4937d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
4947d36db35SAvi Kivity 	MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t"
4957d36db35SAvi Kivity 			   "mov $0x1234, %eax\n\t"
4967d36db35SAvi Kivity 		           ".byte 0x0f, 0x85, 0xf0, 0xff\n\t");
4977d36db35SAvi Kivity 	MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t"
4987d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
4997d36db35SAvi Kivity 
50018253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
5017d36db35SAvi Kivity 
50218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near1);
5036055ea1fSAvi Kivity 	report("jnz near 1", 0, 1);
50418253fdeSAvi Kivity 
50518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near2);
5066055ea1fSAvi Kivity 	report("jnz near 2", R_AX, outregs.eflags & (1 << 6));
5077d36db35SAvi Kivity 
50818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_near1);
5096055ea1fSAvi Kivity 	report("jmp near 1", 0, 1);
5107d36db35SAvi Kivity }
5117d36db35SAvi Kivity 
5127d36db35SAvi Kivity void test_long_jmp()
5137d36db35SAvi Kivity {
5147d36db35SAvi Kivity 	u32 esp[16];
5157d36db35SAvi Kivity 
51618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
5174aa22949SAvi Kivity 	inregs.esp = (u32)(esp+16);
5187d36db35SAvi Kivity 	MK_INSN(long_jmp, "call 1f\n\t"
5197d36db35SAvi Kivity 			  "jmp 2f\n\t"
5207d36db35SAvi Kivity 			  "1: jmp $0, $test_function\n\t"
5217d36db35SAvi Kivity 		          "2:\n\t");
52218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_long_jmp);
5236055ea1fSAvi Kivity 	report("jmp far 1", R_AX, outregs.eax == 0x1234);
5247d36db35SAvi Kivity }
525fa74f8a6SMohammed Gamal 
5267d36db35SAvi Kivity void test_push_pop()
5277d36db35SAvi Kivity {
5287d36db35SAvi Kivity 	MK_INSN(push32, "mov $0x12345678, %eax\n\t"
5297d36db35SAvi Kivity 			"push %eax\n\t"
5307d36db35SAvi Kivity 			"pop %ebx\n\t");
5317d36db35SAvi Kivity 	MK_INSN(push16, "mov $0x1234, %ax\n\t"
5327d36db35SAvi Kivity 			"push %ax\n\t"
5337d36db35SAvi Kivity 			"pop %bx\n\t");
5347d36db35SAvi Kivity 
5357d36db35SAvi Kivity 	MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten
5367d36db35SAvi Kivity 			 "mov $0x123, %ax\n\t"
5377d36db35SAvi Kivity 			 "mov %ax, %es\n\t"
5387d36db35SAvi Kivity 			 "push %es\n\t"
5397d36db35SAvi Kivity 			 "pop %bx \n\t"
5407d36db35SAvi Kivity 			 );
5417d36db35SAvi Kivity 	MK_INSN(pop_es, "push %ax\n\t"
5427d36db35SAvi Kivity 			"pop %es\n\t"
5437d36db35SAvi Kivity 			"mov %es, %bx\n\t"
5447d36db35SAvi Kivity 			);
5457d36db35SAvi Kivity 	MK_INSN(push_pop_ss, "push %ss\n\t"
5467d36db35SAvi Kivity 			     "pushw %ax\n\t"
5477d36db35SAvi Kivity 			     "popw %ss\n\t"
5487d36db35SAvi Kivity 			     "mov %ss, %bx\n\t"
5497d36db35SAvi Kivity 			     "pop %ss\n\t"
5507d36db35SAvi Kivity 			);
5517d36db35SAvi Kivity 	MK_INSN(push_pop_fs, "push %fs\n\t"
5527d36db35SAvi Kivity 			     "pushl %eax\n\t"
5537d36db35SAvi Kivity 			     "popl %fs\n\t"
5547d36db35SAvi Kivity 			     "mov %fs, %ebx\n\t"
5557d36db35SAvi Kivity 			     "pop %fs\n\t"
5567d36db35SAvi Kivity 			);
55709b657b6SAvi Kivity 	MK_INSN(push_pop_high_esp_bits,
55809b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
55909b657b6SAvi Kivity 		"push %ax; \n\t"
56009b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
56109b657b6SAvi Kivity 		"pop %bx");
5627d36db35SAvi Kivity 
56318253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
56418253fdeSAvi Kivity 
56518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push32);
5666055ea1fSAvi Kivity 	report("push/pop 1", R_AX|R_BX,
5676055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x12345678);
5687d36db35SAvi Kivity 
56918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push16);
5706055ea1fSAvi Kivity 	report("push/pop 2", R_AX|R_BX,
5716055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x1234);
5727d36db35SAvi Kivity 
57318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_es);
5746055ea1fSAvi Kivity 	report("push/pop 3", R_AX|R_BX,
5756055ea1fSAvi Kivity 	       outregs.ebx == outregs.eax && outregs.eax == 0x123);
5767d36db35SAvi Kivity 
57718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pop_es);
5786055ea1fSAvi Kivity 	report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax);
5797d36db35SAvi Kivity 
58018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_ss);
5816055ea1fSAvi Kivity 	report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax);
5827d36db35SAvi Kivity 
58318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_fs);
5846055ea1fSAvi Kivity 	report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax);
58509b657b6SAvi Kivity 
58609b657b6SAvi Kivity 	inregs.eax = 0x9977;
58709b657b6SAvi Kivity 	inregs.ebx = 0x7799;
58809b657b6SAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_high_esp_bits);
58909b657b6SAvi Kivity 	report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977);
5907d36db35SAvi Kivity }
5917d36db35SAvi Kivity 
5927d36db35SAvi Kivity void test_null(void)
5937d36db35SAvi Kivity {
594d4dc402cSAvi Kivity 	MK_INSN(null, "");
595d4dc402cSAvi Kivity 
59618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
59718253fdeSAvi Kivity 
59818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_null);
5996055ea1fSAvi Kivity 	report("null", 0, 1);
6007d36db35SAvi Kivity }
6017d36db35SAvi Kivity 
6027d36db35SAvi Kivity struct {
6037d36db35SAvi Kivity     char stack[500];
6047d36db35SAvi Kivity     char top[];
6057d36db35SAvi Kivity } tmp_stack;
6067d36db35SAvi Kivity 
6077d36db35SAvi Kivity void test_pusha_popa()
6087d36db35SAvi Kivity {
6097d36db35SAvi Kivity 	MK_INSN(pusha, "pusha\n\t"
6107d36db35SAvi Kivity 		       "pop %edi\n\t"
6117d36db35SAvi Kivity 		       "pop %esi\n\t"
6127d36db35SAvi Kivity 		       "pop %ebp\n\t"
6137d36db35SAvi Kivity 		       "add $4, %esp\n\t"
6147d36db35SAvi Kivity 		       "pop %ebx\n\t"
6157d36db35SAvi Kivity 		       "pop %edx\n\t"
6167d36db35SAvi Kivity 		       "pop %ecx\n\t"
6177d36db35SAvi Kivity 		       "pop %eax\n\t"
6187d36db35SAvi Kivity 		       );
6197d36db35SAvi Kivity 
6207d36db35SAvi Kivity 	MK_INSN(popa, "push %eax\n\t"
6217d36db35SAvi Kivity 		      "push %ecx\n\t"
6227d36db35SAvi Kivity 		      "push %edx\n\t"
6237d36db35SAvi Kivity 		      "push %ebx\n\t"
6247d36db35SAvi Kivity 		      "push %esp\n\t"
6257d36db35SAvi Kivity 		      "push %ebp\n\t"
6267d36db35SAvi Kivity 		      "push %esi\n\t"
6277d36db35SAvi Kivity 		      "push %edi\n\t"
6287d36db35SAvi Kivity 		      "popa\n\t"
6297d36db35SAvi Kivity 		      );
6307d36db35SAvi Kivity 
63118253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top };
6327d36db35SAvi Kivity 
63318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pusha);
6346055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
63518253fdeSAvi Kivity 
63618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_popa);
6376055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
6387d36db35SAvi Kivity }
6397d36db35SAvi Kivity 
6407d36db35SAvi Kivity void test_iret()
6417d36db35SAvi Kivity {
6427d36db35SAvi Kivity 	MK_INSN(iret32, "pushf\n\t"
6437d36db35SAvi Kivity 			"pushl %cs\n\t"
6447d36db35SAvi Kivity 			"call 1f\n\t" /* a near call will push eip onto the stack */
6457d36db35SAvi Kivity 			"jmp 2f\n\t"
6467d36db35SAvi Kivity 			"1: iret\n\t"
6477d36db35SAvi Kivity 			"2:\n\t"
6487d36db35SAvi Kivity 		     );
6497d36db35SAvi Kivity 
6507d36db35SAvi Kivity 	MK_INSN(iret16, "pushfw\n\t"
6517d36db35SAvi Kivity 			"pushw %cs\n\t"
6527d36db35SAvi Kivity 			"callw 1f\n\t"
6537d36db35SAvi Kivity 			"jmp 2f\n\t"
6547d36db35SAvi Kivity 			"1: iretw\n\t"
6557d36db35SAvi Kivity 			"2:\n\t");
6567d36db35SAvi Kivity 
6577d36db35SAvi Kivity 	MK_INSN(iret_flags32, "pushfl\n\t"
6587d36db35SAvi Kivity 			      "popl %eax\n\t"
6597d36db35SAvi Kivity 			      "andl $~0x2, %eax\n\t"
6607d36db35SAvi Kivity 			      "orl $0xffc08028, %eax\n\t"
6617d36db35SAvi Kivity 			      "pushl %eax\n\t"
6627d36db35SAvi Kivity 			      "pushl %cs\n\t"
6637d36db35SAvi Kivity 			      "call 1f\n\t"
6647d36db35SAvi Kivity 			      "jmp 2f\n\t"
6657d36db35SAvi Kivity 			      "1: iret\n\t"
6667d36db35SAvi Kivity 			      "2:\n\t");
6677d36db35SAvi Kivity 
6687d36db35SAvi Kivity 	MK_INSN(iret_flags16, "pushfw\n\t"
6697d36db35SAvi Kivity 			      "popw %ax\n\t"
6707d36db35SAvi Kivity 			      "and $~0x2, %ax\n\t"
6717d36db35SAvi Kivity 			      "or $0x8028, %ax\n\t"
6727d36db35SAvi Kivity 			      "pushw %ax\n\t"
6737d36db35SAvi Kivity 			      "pushw %cs\n\t"
6747d36db35SAvi Kivity 			      "callw 1f\n\t"
6757d36db35SAvi Kivity 			      "jmp 2f\n\t"
6767d36db35SAvi Kivity 			      "1: iretw\n\t"
6777d36db35SAvi Kivity 			      "2:\n\t");
6787d36db35SAvi Kivity 
67918253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
6807d36db35SAvi Kivity 
68118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret32);
6826055ea1fSAvi Kivity 	report("iret 1", 0, 1);
6837d36db35SAvi Kivity 
68418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret16);
6856055ea1fSAvi Kivity 	report("iret 2", 0, 1);
6867d36db35SAvi Kivity 
68718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags32);
6886055ea1fSAvi Kivity 	report("iret 3", R_AX, 1);
68918253fdeSAvi Kivity 
69018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags16);
6916055ea1fSAvi Kivity 	report("iret 4", R_AX, 1);
6927d36db35SAvi Kivity }
6937d36db35SAvi Kivity 
69496b9ca1eSMohammed Gamal void test_int()
69596b9ca1eSMohammed Gamal {
69618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
69796b9ca1eSMohammed Gamal 
69896b9ca1eSMohammed Gamal 	*(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */
69996b9ca1eSMohammed Gamal 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
70096b9ca1eSMohammed Gamal 
70196b9ca1eSMohammed Gamal 	MK_INSN(int11, "int $0x11\n\t");
70296b9ca1eSMohammed Gamal 
70318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_int11);
7046055ea1fSAvi Kivity 	report("int 1", 0, 1);
70596b9ca1eSMohammed Gamal }
70696b9ca1eSMohammed Gamal 
707fa74f8a6SMohammed Gamal void test_imul()
708fa74f8a6SMohammed Gamal {
709fa74f8a6SMohammed Gamal 	MK_INSN(imul8_1, "mov $2, %al\n\t"
710fa74f8a6SMohammed Gamal 			"mov $-4, %cx\n\t"
711fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
712fa74f8a6SMohammed Gamal 
713fa74f8a6SMohammed Gamal 	MK_INSN(imul16_1, "mov $2, %ax\n\t"
714fa74f8a6SMohammed Gamal 		      "mov $-4, %cx\n\t"
715fa74f8a6SMohammed Gamal 		      "imul %cx\n\t");
716fa74f8a6SMohammed Gamal 
717fa74f8a6SMohammed Gamal 	MK_INSN(imul32_1, "mov $2, %eax\n\t"
718fa74f8a6SMohammed Gamal 		       "mov $-4, %ecx\n\t"
719fa74f8a6SMohammed Gamal 		       "imul %ecx\n\t");
720fa74f8a6SMohammed Gamal 
721fa74f8a6SMohammed Gamal 	MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t"
722fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
723fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
724fa74f8a6SMohammed Gamal 
725fa74f8a6SMohammed Gamal 	MK_INSN(imul16_2, "mov $2, %ax\n\t"
726fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
727fa74f8a6SMohammed Gamal 			"imul %cx\n\t");
728fa74f8a6SMohammed Gamal 
729fa74f8a6SMohammed Gamal 	MK_INSN(imul32_2, "mov $2, %eax\n\t"
730fa74f8a6SMohammed Gamal 			"mov $4, %ecx\n\t"
731fa74f8a6SMohammed Gamal 			"imul %ecx\n\t");
732fa74f8a6SMohammed Gamal 
73318253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
73418253fdeSAvi Kivity 
73518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_1);
7366055ea1fSAvi Kivity 	report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8);
737fa74f8a6SMohammed Gamal 
73818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_1);
7396055ea1fSAvi Kivity 	report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8);
740fa74f8a6SMohammed Gamal 
74118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_1);
7426055ea1fSAvi Kivity 	report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8);
743fa74f8a6SMohammed Gamal 
74418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_2);
7456055ea1fSAvi Kivity 	report("imul 4", R_AX | R_CX | R_DX,
7466055ea1fSAvi Kivity 	       (outregs.eax & 0xffff) == 8
74781050840SAvi Kivity 	       && (outregs.eax & 0xffff0000) == 0x12340000);
748fa74f8a6SMohammed Gamal 
74918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_2);
7506055ea1fSAvi Kivity 	report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8);
751fa74f8a6SMohammed Gamal 
75218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_2);
7536055ea1fSAvi Kivity 	report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8);
754fa74f8a6SMohammed Gamal }
755fa74f8a6SMohammed Gamal 
75659317bd1SMohammed Gamal void test_mul()
75759317bd1SMohammed Gamal {
75859317bd1SMohammed Gamal 	MK_INSN(mul8, "mov $2, %al\n\t"
75959317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
76059317bd1SMohammed Gamal 			"imul %cl\n\t");
76159317bd1SMohammed Gamal 
76259317bd1SMohammed Gamal 	MK_INSN(mul16, "mov $2, %ax\n\t"
76359317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
76459317bd1SMohammed Gamal 			"imul %cx\n\t");
76559317bd1SMohammed Gamal 
76659317bd1SMohammed Gamal 	MK_INSN(mul32, "mov $2, %eax\n\t"
76759317bd1SMohammed Gamal 			"mov $4, %ecx\n\t"
76859317bd1SMohammed Gamal 			"imul %ecx\n\t");
76959317bd1SMohammed Gamal 
77018253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
77118253fdeSAvi Kivity 
77218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul8);
7736055ea1fSAvi Kivity 	report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8);
77459317bd1SMohammed Gamal 
77518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul16);
7766055ea1fSAvi Kivity 	report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8);
77759317bd1SMohammed Gamal 
77818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul32);
7796055ea1fSAvi Kivity 	report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8);
78059317bd1SMohammed Gamal }
78159317bd1SMohammed Gamal 
7820d4c7614SMohammed Gamal void test_div()
7830d4c7614SMohammed Gamal {
7840d4c7614SMohammed Gamal 	MK_INSN(div8, "mov $257, %ax\n\t"
7850d4c7614SMohammed Gamal 			"mov $2, %cl\n\t"
7860d4c7614SMohammed Gamal 			"div %cl\n\t");
7870d4c7614SMohammed Gamal 
7880d4c7614SMohammed Gamal 	MK_INSN(div16, "mov $512, %ax\n\t"
7890d4c7614SMohammed Gamal 			"mov $5, %cx\n\t"
7900d4c7614SMohammed Gamal 			"div %cx\n\t");
7910d4c7614SMohammed Gamal 
7920d4c7614SMohammed Gamal 	MK_INSN(div32, "mov $512, %eax\n\t"
7930d4c7614SMohammed Gamal 			"mov $5, %ecx\n\t"
7940d4c7614SMohammed Gamal 			"div %ecx\n\t");
7950d4c7614SMohammed Gamal 
79618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
79718253fdeSAvi Kivity 
79818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div8);
7996055ea1fSAvi Kivity 	report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384);
8000d4c7614SMohammed Gamal 
80118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div16);
8026055ea1fSAvi Kivity 	report("div 2", R_AX | R_CX | R_DX,
8036055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
8040d4c7614SMohammed Gamal 
80518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div32);
8066055ea1fSAvi Kivity 	report("div 3", R_AX | R_CX | R_DX,
8076055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
8080d4c7614SMohammed Gamal }
8090d4c7614SMohammed Gamal 
8100d4c7614SMohammed Gamal void test_idiv()
8110d4c7614SMohammed Gamal {
8120d4c7614SMohammed Gamal 	MK_INSN(idiv8, "mov $256, %ax\n\t"
8130d4c7614SMohammed Gamal 			"mov $-2, %cl\n\t"
8140d4c7614SMohammed Gamal 			"idiv %cl\n\t");
8150d4c7614SMohammed Gamal 
8160d4c7614SMohammed Gamal 	MK_INSN(idiv16, "mov $512, %ax\n\t"
8170d4c7614SMohammed Gamal 			"mov $-2, %cx\n\t"
8180d4c7614SMohammed Gamal 			"idiv %cx\n\t");
8190d4c7614SMohammed Gamal 
8200d4c7614SMohammed Gamal 	MK_INSN(idiv32, "mov $512, %eax\n\t"
8210d4c7614SMohammed Gamal 			"mov $-2, %ecx\n\t"
8220d4c7614SMohammed Gamal 			"idiv %ecx\n\t");
8230d4c7614SMohammed Gamal 
82418253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
82518253fdeSAvi Kivity 
82618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv8);
8276055ea1fSAvi Kivity 	report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128);
8280d4c7614SMohammed Gamal 
82918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv16);
8306055ea1fSAvi Kivity 	report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256);
8310d4c7614SMohammed Gamal 
83218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv32);
8336055ea1fSAvi Kivity 	report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256);
8340d4c7614SMohammed Gamal }
8350d4c7614SMohammed Gamal 
8366e293cf5SWei Yongjun void test_cbw(void)
8376e293cf5SWei Yongjun {
8386e293cf5SWei Yongjun 	MK_INSN(cbw, "mov $0xFE, %eax \n\t"
8396e293cf5SWei Yongjun 		     "cbw\n\t");
8406e293cf5SWei Yongjun 	MK_INSN(cwde, "mov $0xFFFE, %eax \n\t"
8416e293cf5SWei Yongjun 		      "cwde\n\t");
8426e293cf5SWei Yongjun 
84318253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
84418253fdeSAvi Kivity 
84518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cbw);
8466055ea1fSAvi Kivity 	report("cbq 1", ~0, outregs.eax == 0xFFFE);
8476e293cf5SWei Yongjun 
84818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwde);
8496055ea1fSAvi Kivity 	report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE);
8506e293cf5SWei Yongjun }
8516e293cf5SWei Yongjun 
852eacef4e2SWei Yongjun void test_loopcc(void)
853eacef4e2SWei Yongjun {
854eacef4e2SWei Yongjun 	MK_INSN(loop, "mov $10, %ecx\n\t"
855eacef4e2SWei Yongjun 		      "1: inc %eax\n\t"
856eacef4e2SWei Yongjun 		      "loop 1b\n\t");
857eacef4e2SWei Yongjun 
858eacef4e2SWei Yongjun 	MK_INSN(loope, "mov $10, %ecx\n\t"
859eacef4e2SWei Yongjun 		       "mov $1, %eax\n\t"
860eacef4e2SWei Yongjun 		       "1: dec %eax\n\t"
861eacef4e2SWei Yongjun 		       "loope 1b\n\t");
862eacef4e2SWei Yongjun 
863eacef4e2SWei Yongjun 	MK_INSN(loopne, "mov $10, %ecx\n\t"
864eacef4e2SWei Yongjun 		        "mov $5, %eax\n\t"
865eacef4e2SWei Yongjun 		        "1: dec %eax\n\t"
866eacef4e2SWei Yongjun 			"loopne 1b\n\t");
867eacef4e2SWei Yongjun 
86818253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
869eacef4e2SWei Yongjun 
87018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loop);
8716055ea1fSAvi Kivity 	report("LOOPcc short 1", R_AX, outregs.eax == 10);
87218253fdeSAvi Kivity 
87318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loope);
8746055ea1fSAvi Kivity 	report("LOOPcc short 2", R_AX | R_CX,
8756055ea1fSAvi Kivity 	       outregs.eax == -1 && outregs.ecx == 8);
876eacef4e2SWei Yongjun 
87718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loopne);
8786055ea1fSAvi Kivity 	report("LOOPcc short 3", R_AX | R_CX,
8796055ea1fSAvi Kivity 	       outregs.eax == 0 && outregs.ecx == 5);
880eacef4e2SWei Yongjun }
881eacef4e2SWei Yongjun 
882b274feedSAvi Kivity static void test_das(void)
883b274feedSAvi Kivity {
884b274feedSAvi Kivity     short i;
88581050840SAvi Kivity     u16 nr_fail = 0;
886b274feedSAvi Kivity     static unsigned test_cases[1024] = {
887b274feedSAvi Kivity         0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00,
888b274feedSAvi Kivity         0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01,
889b274feedSAvi Kivity         0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02,
890b274feedSAvi Kivity         0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03,
891b274feedSAvi Kivity         0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04,
892b274feedSAvi Kivity         0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05,
893b274feedSAvi Kivity         0x06000606, 0x8701a606, 0x56100006, 0x9711a006,
894b274feedSAvi Kivity         0x02000707, 0x8301a707, 0x12100107, 0x9311a107,
895b274feedSAvi Kivity         0x02000808, 0x8301a808, 0x12100208, 0x9311a208,
896b274feedSAvi Kivity         0x06000909, 0x8701a909, 0x16100309, 0x9711a309,
897b274feedSAvi Kivity         0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a,
898b274feedSAvi Kivity         0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b,
899b274feedSAvi Kivity         0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c,
900b274feedSAvi Kivity         0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d,
901b274feedSAvi Kivity         0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e,
902b274feedSAvi Kivity         0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f,
903b274feedSAvi Kivity         0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10,
904b274feedSAvi Kivity         0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11,
905b274feedSAvi Kivity         0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12,
906b274feedSAvi Kivity         0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13,
907b274feedSAvi Kivity         0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14,
908b274feedSAvi Kivity         0x02001515, 0x8301b515, 0x16100f15, 0x9711af15,
909b274feedSAvi Kivity         0x02001616, 0x8301b616, 0x12101016, 0x9311b016,
910b274feedSAvi Kivity         0x06001717, 0x8701b717, 0x16101117, 0x9711b117,
911b274feedSAvi Kivity         0x06001818, 0x8701b818, 0x16101218, 0x9711b218,
912b274feedSAvi Kivity         0x02001919, 0x8301b919, 0x12101319, 0x9311b319,
913b274feedSAvi Kivity         0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a,
914b274feedSAvi Kivity         0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b,
915b274feedSAvi Kivity         0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c,
916b274feedSAvi Kivity         0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d,
917b274feedSAvi Kivity         0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e,
918b274feedSAvi Kivity         0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f,
919b274feedSAvi Kivity         0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20,
920b274feedSAvi Kivity         0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21,
921b274feedSAvi Kivity         0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22,
922b274feedSAvi Kivity         0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23,
923b274feedSAvi Kivity         0x06002424, 0x8301c424, 0x16101e24, 0x9711be24,
924b274feedSAvi Kivity         0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25,
925b274feedSAvi Kivity         0x02002626, 0x8701c626, 0x12102026, 0x9711c026,
926b274feedSAvi Kivity         0x06002727, 0x8301c727, 0x16102127, 0x9311c127,
927b274feedSAvi Kivity         0x06002828, 0x8301c828, 0x16102228, 0x9311c228,
928b274feedSAvi Kivity         0x02002929, 0x8701c929, 0x12102329, 0x9711c329,
929b274feedSAvi Kivity         0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a,
930b274feedSAvi Kivity         0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b,
931b274feedSAvi Kivity         0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c,
932b274feedSAvi Kivity         0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d,
933b274feedSAvi Kivity         0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e,
934b274feedSAvi Kivity         0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f,
935b274feedSAvi Kivity         0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30,
936b274feedSAvi Kivity         0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31,
937b274feedSAvi Kivity         0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32,
938b274feedSAvi Kivity         0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33,
939b274feedSAvi Kivity         0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34,
940b274feedSAvi Kivity         0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35,
941b274feedSAvi Kivity         0x06003636, 0x8301d636, 0x16103036, 0x9311d036,
942b274feedSAvi Kivity         0x02003737, 0x8701d737, 0x12103137, 0x9711d137,
943b274feedSAvi Kivity         0x02003838, 0x8701d838, 0x12103238, 0x9711d238,
944b274feedSAvi Kivity         0x06003939, 0x8301d939, 0x16103339, 0x9311d339,
945b274feedSAvi Kivity         0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a,
946b274feedSAvi Kivity         0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b,
947b274feedSAvi Kivity         0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c,
948b274feedSAvi Kivity         0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d,
949b274feedSAvi Kivity         0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e,
950b274feedSAvi Kivity         0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f,
951b274feedSAvi Kivity         0x02004040, 0x8301e040, 0x16103a40, 0x9311da40,
952b274feedSAvi Kivity         0x06004141, 0x8701e141, 0x12103b41, 0x9711db41,
953b274feedSAvi Kivity         0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42,
954b274feedSAvi Kivity         0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43,
955b274feedSAvi Kivity         0x06004444, 0x8701e444, 0x12103e44, 0x9711de44,
956b274feedSAvi Kivity         0x02004545, 0x8301e545, 0x16103f45, 0x9311df45,
957b274feedSAvi Kivity         0x02004646, 0x8301e646, 0x12104046, 0x9311e046,
958b274feedSAvi Kivity         0x06004747, 0x8701e747, 0x16104147, 0x9711e147,
959b274feedSAvi Kivity         0x06004848, 0x8701e848, 0x16104248, 0x9711e248,
960b274feedSAvi Kivity         0x02004949, 0x8301e949, 0x12104349, 0x9311e349,
961b274feedSAvi Kivity         0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a,
962b274feedSAvi Kivity         0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b,
963b274feedSAvi Kivity         0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c,
964b274feedSAvi Kivity         0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d,
965b274feedSAvi Kivity         0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e,
966b274feedSAvi Kivity         0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f,
967b274feedSAvi Kivity         0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50,
968b274feedSAvi Kivity         0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51,
969b274feedSAvi Kivity         0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52,
970b274feedSAvi Kivity         0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53,
971b274feedSAvi Kivity         0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54,
972b274feedSAvi Kivity         0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55,
973b274feedSAvi Kivity         0x06005656, 0x8701f656, 0x16105056, 0x9711f056,
974b274feedSAvi Kivity         0x02005757, 0x8301f757, 0x12105157, 0x9311f157,
975b274feedSAvi Kivity         0x02005858, 0x8301f858, 0x12105258, 0x9311f258,
976b274feedSAvi Kivity         0x06005959, 0x8701f959, 0x16105359, 0x9711f359,
977b274feedSAvi Kivity         0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a,
978b274feedSAvi Kivity         0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b,
979b274feedSAvi Kivity         0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c,
980b274feedSAvi Kivity         0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d,
981b274feedSAvi Kivity         0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e,
982b274feedSAvi Kivity         0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f,
983b274feedSAvi Kivity         0x06006060, 0x47010060, 0x16105a60, 0x9711fa60,
984b274feedSAvi Kivity         0x02006161, 0x03010161, 0x12105b61, 0x9311fb61,
985b274feedSAvi Kivity         0x02006262, 0x03010262, 0x16105c62, 0x9711fc62,
986b274feedSAvi Kivity         0x06006363, 0x07010363, 0x12105d63, 0x9311fd63,
987b274feedSAvi Kivity         0x02006464, 0x03010464, 0x12105e64, 0x9311fe64,
988b274feedSAvi Kivity         0x06006565, 0x07010565, 0x16105f65, 0x9711ff65,
989b274feedSAvi Kivity         0x06006666, 0x07010666, 0x16106066, 0x57110066,
990b274feedSAvi Kivity         0x02006767, 0x03010767, 0x12106167, 0x13110167,
991b274feedSAvi Kivity         0x02006868, 0x03010868, 0x12106268, 0x13110268,
992b274feedSAvi Kivity         0x06006969, 0x07010969, 0x16106369, 0x17110369,
993b274feedSAvi Kivity         0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a,
994b274feedSAvi Kivity         0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b,
995b274feedSAvi Kivity         0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c,
996b274feedSAvi Kivity         0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d,
997b274feedSAvi Kivity         0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e,
998b274feedSAvi Kivity         0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f,
999b274feedSAvi Kivity         0x02007070, 0x03011070, 0x16106a70, 0x17110a70,
1000b274feedSAvi Kivity         0x06007171, 0x07011171, 0x12106b71, 0x13110b71,
1001b274feedSAvi Kivity         0x06007272, 0x07011272, 0x16106c72, 0x17110c72,
1002b274feedSAvi Kivity         0x02007373, 0x03011373, 0x12106d73, 0x13110d73,
1003b274feedSAvi Kivity         0x06007474, 0x07011474, 0x12106e74, 0x13110e74,
1004b274feedSAvi Kivity         0x02007575, 0x03011575, 0x16106f75, 0x17110f75,
1005b274feedSAvi Kivity         0x02007676, 0x03011676, 0x12107076, 0x13111076,
1006b274feedSAvi Kivity         0x06007777, 0x07011777, 0x16107177, 0x17111177,
1007b274feedSAvi Kivity         0x06007878, 0x07011878, 0x16107278, 0x17111278,
1008b274feedSAvi Kivity         0x02007979, 0x03011979, 0x12107379, 0x13111379,
1009b274feedSAvi Kivity         0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a,
1010b274feedSAvi Kivity         0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b,
1011b274feedSAvi Kivity         0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c,
1012b274feedSAvi Kivity         0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d,
1013b274feedSAvi Kivity         0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e,
1014b274feedSAvi Kivity         0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f,
1015b274feedSAvi Kivity         0x82008080, 0x03012080, 0x12107a80, 0x13111a80,
1016b274feedSAvi Kivity         0x86008181, 0x07012181, 0x16107b81, 0x17111b81,
1017b274feedSAvi Kivity         0x86008282, 0x07012282, 0x12107c82, 0x13111c82,
1018b274feedSAvi Kivity         0x82008383, 0x03012383, 0x16107d83, 0x17111d83,
1019b274feedSAvi Kivity         0x86008484, 0x07012484, 0x16107e84, 0x17111e84,
1020b274feedSAvi Kivity         0x82008585, 0x03012585, 0x12107f85, 0x13111f85,
1021b274feedSAvi Kivity         0x82008686, 0x03012686, 0x92108086, 0x13112086,
1022b274feedSAvi Kivity         0x86008787, 0x07012787, 0x96108187, 0x17112187,
1023b274feedSAvi Kivity         0x86008888, 0x07012888, 0x96108288, 0x17112288,
1024b274feedSAvi Kivity         0x82008989, 0x03012989, 0x92108389, 0x13112389,
1025b274feedSAvi Kivity         0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a,
1026b274feedSAvi Kivity         0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b,
1027b274feedSAvi Kivity         0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c,
1028b274feedSAvi Kivity         0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d,
1029b274feedSAvi Kivity         0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e,
1030b274feedSAvi Kivity         0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f,
1031b274feedSAvi Kivity         0x86009090, 0x07013090, 0x92108a90, 0x13112a90,
1032b274feedSAvi Kivity         0x82009191, 0x03013191, 0x96108b91, 0x17112b91,
1033b274feedSAvi Kivity         0x82009292, 0x03013292, 0x92108c92, 0x13112c92,
1034b274feedSAvi Kivity         0x86009393, 0x07013393, 0x96108d93, 0x17112d93,
1035b274feedSAvi Kivity         0x82009494, 0x03013494, 0x96108e94, 0x17112e94,
1036b274feedSAvi Kivity         0x86009595, 0x07013595, 0x92108f95, 0x13112f95,
1037b274feedSAvi Kivity         0x86009696, 0x07013696, 0x96109096, 0x17113096,
1038b274feedSAvi Kivity         0x82009797, 0x03013797, 0x92109197, 0x13113197,
1039b274feedSAvi Kivity         0x82009898, 0x03013898, 0x92109298, 0x13113298,
1040b274feedSAvi Kivity         0x86009999, 0x07013999, 0x96109399, 0x17113399,
1041b274feedSAvi Kivity         0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a,
1042b274feedSAvi Kivity         0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b,
1043b274feedSAvi Kivity         0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c,
1044b274feedSAvi Kivity         0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d,
1045b274feedSAvi Kivity         0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e,
1046b274feedSAvi Kivity         0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f,
1047b274feedSAvi Kivity         0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0,
1048b274feedSAvi Kivity         0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1,
1049b274feedSAvi Kivity         0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2,
1050b274feedSAvi Kivity         0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3,
1051b274feedSAvi Kivity         0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4,
1052b274feedSAvi Kivity         0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5,
1053b274feedSAvi Kivity         0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6,
1054b274feedSAvi Kivity         0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7,
1055b274feedSAvi Kivity         0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8,
1056b274feedSAvi Kivity         0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9,
1057b274feedSAvi Kivity         0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa,
1058b274feedSAvi Kivity         0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab,
1059b274feedSAvi Kivity         0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac,
1060b274feedSAvi Kivity         0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad,
1061b274feedSAvi Kivity         0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae,
1062b274feedSAvi Kivity         0x130049af, 0x130149af, 0x131049af, 0x131149af,
1063b274feedSAvi Kivity         0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0,
1064b274feedSAvi Kivity         0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1,
1065b274feedSAvi Kivity         0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2,
1066b274feedSAvi Kivity         0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3,
1067b274feedSAvi Kivity         0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4,
1068b274feedSAvi Kivity         0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5,
1069b274feedSAvi Kivity         0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6,
1070b274feedSAvi Kivity         0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7,
1071b274feedSAvi Kivity         0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8,
1072b274feedSAvi Kivity         0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9,
1073b274feedSAvi Kivity         0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba,
1074b274feedSAvi Kivity         0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb,
1075b274feedSAvi Kivity         0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc,
1076b274feedSAvi Kivity         0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd,
1077b274feedSAvi Kivity         0x130058be, 0x130158be, 0x131058be, 0x131158be,
1078b274feedSAvi Kivity         0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf,
1079b274feedSAvi Kivity         0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0,
1080b274feedSAvi Kivity         0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1,
1081b274feedSAvi Kivity         0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2,
1082b274feedSAvi Kivity         0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3,
1083b274feedSAvi Kivity         0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4,
1084b274feedSAvi Kivity         0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5,
1085b274feedSAvi Kivity         0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6,
1086b274feedSAvi Kivity         0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7,
1087b274feedSAvi Kivity         0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8,
1088b274feedSAvi Kivity         0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9,
1089b274feedSAvi Kivity         0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca,
1090b274feedSAvi Kivity         0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb,
1091b274feedSAvi Kivity         0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc,
1092b274feedSAvi Kivity         0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd,
1093b274feedSAvi Kivity         0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce,
1094b274feedSAvi Kivity         0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf,
1095b274feedSAvi Kivity         0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0,
1096b274feedSAvi Kivity         0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1,
1097b274feedSAvi Kivity         0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2,
1098b274feedSAvi Kivity         0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3,
1099b274feedSAvi Kivity         0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4,
1100b274feedSAvi Kivity         0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5,
1101b274feedSAvi Kivity         0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6,
1102b274feedSAvi Kivity         0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7,
1103b274feedSAvi Kivity         0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8,
1104b274feedSAvi Kivity         0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9,
1105b274feedSAvi Kivity         0x170074da, 0x170174da, 0x171074da, 0x171174da,
1106b274feedSAvi Kivity         0x130075db, 0x130175db, 0x131075db, 0x131175db,
1107b274feedSAvi Kivity         0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc,
1108b274feedSAvi Kivity         0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd,
1109b274feedSAvi Kivity         0x170078de, 0x170178de, 0x171078de, 0x171178de,
1110b274feedSAvi Kivity         0x130079df, 0x130179df, 0x131079df, 0x131179df,
1111b274feedSAvi Kivity         0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0,
1112b274feedSAvi Kivity         0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1,
1113b274feedSAvi Kivity         0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2,
1114b274feedSAvi Kivity         0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3,
1115b274feedSAvi Kivity         0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4,
1116b274feedSAvi Kivity         0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5,
1117b274feedSAvi Kivity         0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6,
1118b274feedSAvi Kivity         0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7,
1119b274feedSAvi Kivity         0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8,
1120b274feedSAvi Kivity         0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9,
1121b274feedSAvi Kivity         0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea,
1122b274feedSAvi Kivity         0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb,
1123b274feedSAvi Kivity         0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec,
1124b274feedSAvi Kivity         0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed,
1125b274feedSAvi Kivity         0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee,
1126b274feedSAvi Kivity         0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef,
1127b274feedSAvi Kivity         0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0,
1128b274feedSAvi Kivity         0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1,
1129b274feedSAvi Kivity         0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2,
1130b274feedSAvi Kivity         0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3,
1131b274feedSAvi Kivity         0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4,
1132b274feedSAvi Kivity         0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5,
1133b274feedSAvi Kivity         0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6,
1134b274feedSAvi Kivity         0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7,
1135b274feedSAvi Kivity         0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8,
1136b274feedSAvi Kivity         0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9,
1137b274feedSAvi Kivity         0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa,
1138b274feedSAvi Kivity         0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb,
1139b274feedSAvi Kivity         0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc,
1140b274feedSAvi Kivity         0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd,
1141b274feedSAvi Kivity         0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe,
1142b274feedSAvi Kivity         0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff,
1143b274feedSAvi Kivity     };
1144b274feedSAvi Kivity 
1145b274feedSAvi Kivity     MK_INSN(das, "das");
1146b274feedSAvi Kivity 
114718253fdeSAvi Kivity     inregs = (struct regs){ 0 };
114818253fdeSAvi Kivity 
1149b274feedSAvi Kivity     for (i = 0; i < 1024; ++i) {
1150b274feedSAvi Kivity         unsigned tmp = test_cases[i];
1151b274feedSAvi Kivity         inregs.eax = tmp & 0xff;
1152b274feedSAvi Kivity         inregs.eflags = (tmp >> 16) & 0xff;
115318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_das);
115418253fdeSAvi Kivity 	if (!regs_equal(R_AX)
1155b274feedSAvi Kivity             || outregs.eax != ((tmp >> 8) & 0xff)
1156b274feedSAvi Kivity             || (outregs.eflags & 0xff) != (tmp >> 24)) {
115781050840SAvi Kivity 	    ++nr_fail;
115881050840SAvi Kivity 	    break;
1159b274feedSAvi Kivity         }
1160b274feedSAvi Kivity     }
11616055ea1fSAvi Kivity     report("DAS", ~0, nr_fail == 0);
1162b274feedSAvi Kivity }
1163b274feedSAvi Kivity 
11640cbd5b06SMohammed Gamal void test_cwd_cdq()
11650cbd5b06SMohammed Gamal {
11660cbd5b06SMohammed Gamal 	/* Sign-bit set */
11670cbd5b06SMohammed Gamal 	MK_INSN(cwd_1, "mov $0x8000, %ax\n\t"
11680cbd5b06SMohammed Gamal 		       "cwd\n\t");
11690cbd5b06SMohammed Gamal 
11700cbd5b06SMohammed Gamal 	/* Sign-bit not set */
11710cbd5b06SMohammed Gamal 	MK_INSN(cwd_2, "mov $0x1000, %ax\n\t"
11720cbd5b06SMohammed Gamal 		       "cwd\n\t");
11730cbd5b06SMohammed Gamal 
11740cbd5b06SMohammed Gamal 	/* Sign-bit set */
11750cbd5b06SMohammed Gamal 	MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t"
11760cbd5b06SMohammed Gamal 		       "cdq\n\t");
11770cbd5b06SMohammed Gamal 
11780cbd5b06SMohammed Gamal 	/* Sign-bit not set */
11790cbd5b06SMohammed Gamal 	MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t"
11800cbd5b06SMohammed Gamal 		       "cdq\n\t");
11810cbd5b06SMohammed Gamal 
118218253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
118318253fdeSAvi Kivity 
118418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_1);
11856055ea1fSAvi Kivity 	report("cwd 1", R_AX | R_DX,
11866055ea1fSAvi Kivity 	       outregs.eax == 0x8000 && outregs.edx == 0xffff);
11870cbd5b06SMohammed Gamal 
118818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_2);
11896055ea1fSAvi Kivity 	report("cwd 2", R_AX | R_DX,
11906055ea1fSAvi Kivity 	       outregs.eax == 0x1000 && outregs.edx == 0);
11910cbd5b06SMohammed Gamal 
119218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_1);
11936055ea1fSAvi Kivity 	report("cdq 1", R_AX | R_DX,
11946055ea1fSAvi Kivity 	       outregs.eax == 0x80000000 && outregs.edx == 0xffffffff);
11950cbd5b06SMohammed Gamal 
119618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_2);
11976055ea1fSAvi Kivity 	report("cdq 2", R_AX | R_DX,
11986055ea1fSAvi Kivity 	       outregs.eax == 0x10000000 && outregs.edx == 0);
11990cbd5b06SMohammed Gamal }
12000cbd5b06SMohammed Gamal 
120137f51a4aSWei Yongjun static struct {
120237f51a4aSWei Yongjun         void *address;
120337f51a4aSWei Yongjun         unsigned short sel;
120437f51a4aSWei Yongjun } __attribute__((packed)) desc = {
120537f51a4aSWei Yongjun 	(void *)0x1234,
120637f51a4aSWei Yongjun 	0x10,
120737f51a4aSWei Yongjun };
120837f51a4aSWei Yongjun 
120937f51a4aSWei Yongjun void test_lds_lss()
121037f51a4aSWei Yongjun {
121137f51a4aSWei Yongjun 	inregs = (struct regs){ .ebx = (unsigned long)&desc };
121237f51a4aSWei Yongjun 
121337f51a4aSWei Yongjun 	MK_INSN(lds, "push %ds\n\t"
121437f51a4aSWei Yongjun 		     "lds (%ebx), %eax\n\t"
121537f51a4aSWei Yongjun 		     "mov %ds, %ebx\n\t"
121637f51a4aSWei Yongjun 		     "pop %ds\n\t");
121737f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lds);
121837f51a4aSWei Yongjun 	report("lds", R_AX | R_BX,
121937f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
122037f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
122137f51a4aSWei Yongjun 
122237f51a4aSWei Yongjun 	MK_INSN(les, "push %es\n\t"
122337f51a4aSWei Yongjun 		     "les (%ebx), %eax\n\t"
122437f51a4aSWei Yongjun 		     "mov %es, %ebx\n\t"
122537f51a4aSWei Yongjun 		     "pop %es\n\t");
122637f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_les);
122737f51a4aSWei Yongjun 	report("les", R_AX | R_BX,
122837f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
122937f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
123037f51a4aSWei Yongjun 
123137f51a4aSWei Yongjun 	MK_INSN(lfs, "push %fs\n\t"
123237f51a4aSWei Yongjun 		     "lfs (%ebx), %eax\n\t"
123337f51a4aSWei Yongjun 		     "mov %fs, %ebx\n\t"
123437f51a4aSWei Yongjun 		     "pop %fs\n\t");
123537f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lfs);
123637f51a4aSWei Yongjun 	report("lfs", R_AX | R_BX,
123737f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
123837f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
123937f51a4aSWei Yongjun 
124037f51a4aSWei Yongjun 	MK_INSN(lgs, "push %gs\n\t"
124137f51a4aSWei Yongjun 		     "lgs (%ebx), %eax\n\t"
124237f51a4aSWei Yongjun 		     "mov %gs, %ebx\n\t"
124337f51a4aSWei Yongjun 		     "pop %gs\n\t");
124437f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lgs);
124537f51a4aSWei Yongjun 	report("lgs", R_AX | R_BX,
124637f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
124737f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
124837f51a4aSWei Yongjun 
124937f51a4aSWei Yongjun 	MK_INSN(lss, "push %ss\n\t"
125037f51a4aSWei Yongjun 		     "lss (%ebx), %eax\n\t"
125137f51a4aSWei Yongjun 		     "mov %ss, %ebx\n\t"
125237f51a4aSWei Yongjun 		     "pop %ss\n\t");
125337f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lss);
125437f51a4aSWei Yongjun 	report("lss", R_AX | R_BX,
125537f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
125637f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
125737f51a4aSWei Yongjun }
125837f51a4aSWei Yongjun 
1259b1c7c575SWei Yongjun void test_jcxz(void)
1260b1c7c575SWei Yongjun {
1261b1c7c575SWei Yongjun 	MK_INSN(jcxz1, "jcxz 1f\n\t"
1262b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1263b1c7c575SWei Yongjun 		       "1:\n\t");
1264b1c7c575SWei Yongjun 	MK_INSN(jcxz2, "mov $0x100, %ecx\n\t"
1265b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1266b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1267b1c7c575SWei Yongjun 		       "mov $0, %ecx\n\t"
1268b1c7c575SWei Yongjun 		       "1:\n\t");
1269b1c7c575SWei Yongjun 	MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t"
1270b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1271b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1272b1c7c575SWei Yongjun 		       "1:\n\t");
1273b1c7c575SWei Yongjun 	MK_INSN(jecxz1, "jecxz 1f\n\t"
1274b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1275b1c7c575SWei Yongjun 			"1:\n\t");
1276b1c7c575SWei Yongjun 	MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t"
1277b1c7c575SWei Yongjun 			"jecxz 1f\n\t"
1278b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1279b1c7c575SWei Yongjun 			"mov $0, %ecx\n\t"
1280b1c7c575SWei Yongjun 			"1:\n\t");
1281b1c7c575SWei Yongjun 
1282b1c7c575SWei Yongjun 	inregs = (struct regs){ 0 };
1283b1c7c575SWei Yongjun 
1284b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz1);
1285b1c7c575SWei Yongjun 	report("jcxz short 1", 0, 1);
1286b1c7c575SWei Yongjun 
1287b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz2);
1288b1c7c575SWei Yongjun 	report("jcxz short 2", R_AX, outregs.eax == 0x1234);
1289b1c7c575SWei Yongjun 
1290b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz3);
1291b1c7c575SWei Yongjun 	report("jcxz short 3", R_CX, outregs.ecx == 0x10000);
1292b1c7c575SWei Yongjun 
1293b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz1);
1294b1c7c575SWei Yongjun 	report("jecxz short 1", 0, 1);
1295b1c7c575SWei Yongjun 
1296b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz2);
1297b1c7c575SWei Yongjun 	report("jecxz short 2", R_AX, outregs.eax == 0x1234);
1298b1c7c575SWei Yongjun }
1299b1c7c575SWei Yongjun 
13008f578e98SAvi Kivity static void test_cpuid(void)
13018f578e98SAvi Kivity {
13028f578e98SAvi Kivity     MK_INSN(cpuid, "cpuid");
13038f578e98SAvi Kivity     unsigned function = 0x1234;
13048f578e98SAvi Kivity     unsigned eax, ebx, ecx, edx;
13058f578e98SAvi Kivity 
13068f578e98SAvi Kivity     inregs.eax = eax = function;
13078f578e98SAvi Kivity     asm("cpuid" : "+a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx));
13088f578e98SAvi Kivity     exec_in_big_real_mode(&insn_cpuid);
13098f578e98SAvi Kivity     report("cpuid", R_AX|R_BX|R_CX|R_DX,
13108f578e98SAvi Kivity 	   outregs.eax == eax && outregs.ebx == ebx
13118f578e98SAvi Kivity 	   && outregs.ecx == ecx && outregs.edx == edx);
13128f578e98SAvi Kivity }
13138f578e98SAvi Kivity 
1314ed93f43bSAvi Kivity static void test_ss_base_for_esp_ebp(void)
1315ed93f43bSAvi Kivity {
1316ed93f43bSAvi Kivity     MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss");
1317ed93f43bSAvi Kivity     MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss");
1318ed93f43bSAvi Kivity     static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 };
1319ed93f43bSAvi Kivity 
1320ed93f43bSAvi Kivity     inregs.ebx = 1;
1321ed93f43bSAvi Kivity     inregs.ebp = (unsigned)array;
1322ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel1);
1323ed93f43bSAvi Kivity     report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321);
1324ed93f43bSAvi Kivity     inregs.ebx = 1;
1325ed93f43bSAvi Kivity     inregs.ebp = (unsigned)array;
1326ed93f43bSAvi Kivity     inregs.edi = 0;
1327ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel2);
1328ed93f43bSAvi Kivity     report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321);
1329ed93f43bSAvi Kivity }
1330ed93f43bSAvi Kivity 
1331c2281fa4SAvi Kivity static void test_sgdt_sidt(void)
1332c2281fa4SAvi Kivity {
1333c2281fa4SAvi Kivity     MK_INSN(sgdt, "sgdtw (%eax)");
1334c2281fa4SAvi Kivity     MK_INSN(sidt, "sidtw (%eax)");
1335c2281fa4SAvi Kivity     unsigned x, y;
1336c2281fa4SAvi Kivity 
1337c2281fa4SAvi Kivity     inregs.eax = (unsigned)&y;
1338c2281fa4SAvi Kivity     asm volatile("sgdtw %0" : "=m"(x));
1339c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sgdt);
1340c2281fa4SAvi Kivity     report("sgdt", 0, x == y);
1341c2281fa4SAvi Kivity 
1342c2281fa4SAvi Kivity     inregs.eax = (unsigned)&y;
1343c2281fa4SAvi Kivity     asm volatile("sidtw %0" : "=m"(x));
1344c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sidt);
1345c2281fa4SAvi Kivity     report("sidt", 0, x == y);
1346c2281fa4SAvi Kivity }
1347c2281fa4SAvi Kivity 
13487ae3645aSAvi Kivity static void test_lahf(void)
13497ae3645aSAvi Kivity {
13507ae3645aSAvi Kivity     MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf");
13517ae3645aSAvi Kivity 
13527ae3645aSAvi Kivity     inregs.eax = 0xc7;
13537ae3645aSAvi Kivity     exec_in_big_real_mode(&insn_lahf);
13547ae3645aSAvi Kivity     report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax);
13557ae3645aSAvi Kivity }
13567ae3645aSAvi Kivity 
1357fd9ea640SAvi Kivity static void test_movzx_movsx(void)
1358fd9ea640SAvi Kivity {
1359fd9ea640SAvi Kivity     MK_INSN(movsx, "movsx %al, %ebx");
1360fd9ea640SAvi Kivity     MK_INSN(movzx, "movzx %al, %ebx");
13613013e079SGleb Natapov     MK_INSN(movzsah, "movsx %ah, %ebx");
13623013e079SGleb Natapov     MK_INSN(movzxah, "movzx %ah, %ebx");
1363fd9ea640SAvi Kivity 
1364fd9ea640SAvi Kivity     inregs.eax = 0x1234569c;
13653013e079SGleb Natapov     inregs.esp = 0xffff;
1366fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movsx);
1367fd9ea640SAvi Kivity     report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax);
1368fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movzx);
1369fd9ea640SAvi Kivity     report("movzx", R_BX, outregs.ebx == (unsigned char)inregs.eax);
13703013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzsah);
13713013e079SGleb Natapov     report("movsx ah", R_BX, outregs.ebx == (signed char)(inregs.eax>>8));
13723013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzxah);
13733013e079SGleb Natapov     report("movzx ah", R_BX, outregs.ebx == (unsigned char)(inregs.eax >> 8));
1374fd9ea640SAvi Kivity }
1375fd9ea640SAvi Kivity 
1376b493b2e8SAvi Kivity static void test_bswap(void)
1377b493b2e8SAvi Kivity {
1378b493b2e8SAvi Kivity     MK_INSN(bswap, "bswap %ecx");
1379b493b2e8SAvi Kivity 
1380b493b2e8SAvi Kivity     inregs.ecx = 0x12345678;
1381b493b2e8SAvi Kivity     exec_in_big_real_mode(&insn_bswap);
1382b493b2e8SAvi Kivity     report("bswap", R_CX, outregs.ecx == 0x78563412);
1383b493b2e8SAvi Kivity }
1384b493b2e8SAvi Kivity 
13858cd86387SGleb Natapov static void test_aad(void)
13868cd86387SGleb Natapov {
13878cd86387SGleb Natapov     MK_INSN(aad, "aad");
13888cd86387SGleb Natapov 
13898cd86387SGleb Natapov     inregs.eax = 0x12345678;
13908cd86387SGleb Natapov     exec_in_big_real_mode(&insn_aad);
13918cd86387SGleb Natapov     report("aad", R_AX, outregs.eax == 0x123400d4);
13928cd86387SGleb Natapov }
13938cd86387SGleb Natapov 
1394*2a9b5718SPaolo Bonzini static void test_aam(void)
1395*2a9b5718SPaolo Bonzini {
1396*2a9b5718SPaolo Bonzini     MK_INSN(aam, "aam");
1397*2a9b5718SPaolo Bonzini 
1398*2a9b5718SPaolo Bonzini     inregs.eax = 0x76543210;
1399*2a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_aam);
1400*2a9b5718SPaolo Bonzini     report("aam", R_AX, outregs.eax == 0x76540106);
1401*2a9b5718SPaolo Bonzini }
1402*2a9b5718SPaolo Bonzini 
1403*2a9b5718SPaolo Bonzini static void test_xlat(void)
1404*2a9b5718SPaolo Bonzini {
1405*2a9b5718SPaolo Bonzini     MK_INSN(xlat, "xlat");
1406*2a9b5718SPaolo Bonzini     u8 table[256];
1407*2a9b5718SPaolo Bonzini     int i;
1408*2a9b5718SPaolo Bonzini 
1409*2a9b5718SPaolo Bonzini     for (i = 0; i < 256; i++) {
1410*2a9b5718SPaolo Bonzini         table[i] = i + 1;
1411*2a9b5718SPaolo Bonzini     }
1412*2a9b5718SPaolo Bonzini 
1413*2a9b5718SPaolo Bonzini     inregs.eax = 0x89abcdef;
1414*2a9b5718SPaolo Bonzini     inregs.ebx = (u32)table;
1415*2a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_xlat);
1416*2a9b5718SPaolo Bonzini     report("xlat", R_AX, outregs.eax == 0x89abcdf0);
1417*2a9b5718SPaolo Bonzini }
1418*2a9b5718SPaolo Bonzini 
1419*2a9b5718SPaolo Bonzini static void test_salc(void)
1420*2a9b5718SPaolo Bonzini {
1421*2a9b5718SPaolo Bonzini     MK_INSN(clc_salc, "clc; .byte 0xd6");
1422*2a9b5718SPaolo Bonzini     MK_INSN(stc_salc, "stc; .byte 0xd6");
1423*2a9b5718SPaolo Bonzini 
1424*2a9b5718SPaolo Bonzini     inregs.eax = 0x12345678;
1425*2a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_clc_salc);
1426*2a9b5718SPaolo Bonzini     report("salc (1)", R_AX, outregs.eax == 0x12345600);
1427*2a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_stc_salc);
1428*2a9b5718SPaolo Bonzini     report("salc (2)", R_AX, outregs.eax == 0x123456ff);
1429*2a9b5718SPaolo Bonzini }
1430*2a9b5718SPaolo Bonzini 
14310987db7aSGleb Natapov static void test_fninit(void)
14320987db7aSGleb Natapov {
14330987db7aSGleb Natapov 	u16 fcw = -1, fsw = -1;
14340987db7aSGleb Natapov 	MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)");
14350987db7aSGleb Natapov 
14360987db7aSGleb Natapov 	inregs.eax = (u32)&fsw;
14370987db7aSGleb Natapov 	inregs.ebx = (u32)&fcw;
14380987db7aSGleb Natapov 
14390987db7aSGleb Natapov 	exec_in_big_real_mode(&insn_fninit);
14400987db7aSGleb Natapov 	report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f);
14410987db7aSGleb Natapov }
14420987db7aSGleb Natapov 
14437d36db35SAvi Kivity void realmode_start(void)
14447d36db35SAvi Kivity {
14457d36db35SAvi Kivity 	test_null();
14467d36db35SAvi Kivity 
14477d36db35SAvi Kivity 	test_shld();
14487d36db35SAvi Kivity 	test_push_pop();
14497d36db35SAvi Kivity 	test_pusha_popa();
14507d36db35SAvi Kivity 	test_mov_imm();
14517d36db35SAvi Kivity 	test_cmp_imm();
14527d36db35SAvi Kivity 	test_add_imm();
14537d36db35SAvi Kivity 	test_sub_imm();
14547d36db35SAvi Kivity 	test_xor_imm();
14557d36db35SAvi Kivity 	test_io();
14567d36db35SAvi Kivity 	test_eflags_insn();
14577d36db35SAvi Kivity 	test_jcc_short();
14587d36db35SAvi Kivity 	test_jcc_near();
14597d36db35SAvi Kivity 	/* test_call() uses short jump so call it after testing jcc */
14607d36db35SAvi Kivity 	test_call();
14617d36db35SAvi Kivity 	/* long jmp test uses call near so test it after testing call */
14627d36db35SAvi Kivity 	test_long_jmp();
14637d36db35SAvi Kivity 	test_xchg();
14647d36db35SAvi Kivity 	test_iret();
146596b9ca1eSMohammed Gamal 	test_int();
1466fa74f8a6SMohammed Gamal 	test_imul();
146759317bd1SMohammed Gamal 	test_mul();
14680d4c7614SMohammed Gamal 	test_div();
14690d4c7614SMohammed Gamal 	test_idiv();
1470eacef4e2SWei Yongjun 	test_loopcc();
14716e293cf5SWei Yongjun 	test_cbw();
14720cbd5b06SMohammed Gamal 	test_cwd_cdq();
1473b274feedSAvi Kivity 	test_das();
147437f51a4aSWei Yongjun 	test_lds_lss();
1475b1c7c575SWei Yongjun 	test_jcxz();
14768f578e98SAvi Kivity 	test_cpuid();
1477ed93f43bSAvi Kivity 	test_ss_base_for_esp_ebp();
1478c2281fa4SAvi Kivity 	test_sgdt_sidt();
14797ae3645aSAvi Kivity 	test_lahf();
1480fd9ea640SAvi Kivity 	test_movzx_movsx();
1481b493b2e8SAvi Kivity 	test_bswap();
14828cd86387SGleb Natapov 	test_aad();
1483*2a9b5718SPaolo Bonzini 	test_aam();
1484*2a9b5718SPaolo Bonzini 	test_xlat();
1485*2a9b5718SPaolo Bonzini 	test_salc();
14860987db7aSGleb Natapov 	test_fninit();
14877d36db35SAvi Kivity 
14887d36db35SAvi Kivity 	exit(0);
14897d36db35SAvi Kivity }
14907d36db35SAvi Kivity 
14917d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff };
14927d36db35SAvi Kivity 
14937d36db35SAvi Kivity struct __attribute__((packed)) {
14947d36db35SAvi Kivity 	unsigned short limit;
14957d36db35SAvi Kivity 	void *base;
14967d36db35SAvi Kivity } r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt };
14977d36db35SAvi Kivity 
14987d36db35SAvi Kivity asm(
14997d36db35SAvi Kivity 	".section .init \n\t"
15007d36db35SAvi Kivity 
15017d36db35SAvi Kivity 	".code32 \n\t"
15027d36db35SAvi Kivity 
15037d36db35SAvi Kivity 	"mb_magic = 0x1BADB002 \n\t"
15047d36db35SAvi Kivity 	"mb_flags = 0x0 \n\t"
15057d36db35SAvi Kivity 
15067d36db35SAvi Kivity 	"# multiboot header \n\t"
15077d36db35SAvi Kivity 	".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t"
15087d36db35SAvi Kivity 
15097d36db35SAvi Kivity 	".globl start \n\t"
15107d36db35SAvi Kivity 	".data \n\t"
15117d36db35SAvi Kivity 	". = . + 4096 \n\t"
15127d36db35SAvi Kivity 	"stacktop: \n\t"
15137d36db35SAvi Kivity 
15147d36db35SAvi Kivity 	".text \n\t"
15157d36db35SAvi Kivity 	"start: \n\t"
15167d36db35SAvi Kivity 	"lgdt r_gdt_descr \n\t"
15177d36db35SAvi Kivity 	"ljmp $8, $1f; 1: \n\t"
15187d36db35SAvi Kivity 	".code16gcc \n\t"
15197d36db35SAvi Kivity 	"mov $16, %eax \n\t"
15207d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
15217d36db35SAvi Kivity 	"mov %ax, %es \n\t"
15227d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
15237d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
15247d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
15257d36db35SAvi Kivity 	"mov %cr0, %eax \n\t"
15267d36db35SAvi Kivity 	"btc $0, %eax \n\t"
15277d36db35SAvi Kivity 	"mov %eax, %cr0 \n\t"
15287d36db35SAvi Kivity 	"ljmp $0, $realmode_entry \n\t"
15297d36db35SAvi Kivity 
15307d36db35SAvi Kivity 	"realmode_entry: \n\t"
15317d36db35SAvi Kivity 
15327d36db35SAvi Kivity 	"xor %ax, %ax \n\t"
15337d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
15347d36db35SAvi Kivity 	"mov %ax, %es \n\t"
15357d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
15367d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
15377d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
15387d36db35SAvi Kivity 	"mov $stacktop, %esp\n\t"
15397d36db35SAvi Kivity 	"ljmp $0, $realmode_start \n\t"
15407d36db35SAvi Kivity 
15417d36db35SAvi Kivity 	".code16gcc \n\t"
15427d36db35SAvi Kivity 	);
1543