xref: /kvm-unit-tests/x86/realmode.c (revision ed93f43b9ffc8224bd3b4a1369db4d73be4f8fe3)
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 			);
5577d36db35SAvi Kivity 
55818253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
55918253fdeSAvi Kivity 
56018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push32);
5616055ea1fSAvi Kivity 	report("push/pop 1", R_AX|R_BX,
5626055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x12345678);
5637d36db35SAvi Kivity 
56418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push16);
5656055ea1fSAvi Kivity 	report("push/pop 2", R_AX|R_BX,
5666055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x1234);
5677d36db35SAvi Kivity 
56818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_es);
5696055ea1fSAvi Kivity 	report("push/pop 3", R_AX|R_BX,
5706055ea1fSAvi Kivity 	       outregs.ebx == outregs.eax && outregs.eax == 0x123);
5717d36db35SAvi Kivity 
57218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pop_es);
5736055ea1fSAvi Kivity 	report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax);
5747d36db35SAvi Kivity 
57518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_ss);
5766055ea1fSAvi Kivity 	report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax);
5777d36db35SAvi Kivity 
57818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_fs);
5796055ea1fSAvi Kivity 	report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax);
5807d36db35SAvi Kivity }
5817d36db35SAvi Kivity 
5827d36db35SAvi Kivity void test_null(void)
5837d36db35SAvi Kivity {
584d4dc402cSAvi Kivity 	MK_INSN(null, "");
585d4dc402cSAvi Kivity 
58618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
58718253fdeSAvi Kivity 
58818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_null);
5896055ea1fSAvi Kivity 	report("null", 0, 1);
5907d36db35SAvi Kivity }
5917d36db35SAvi Kivity 
5927d36db35SAvi Kivity struct {
5937d36db35SAvi Kivity     char stack[500];
5947d36db35SAvi Kivity     char top[];
5957d36db35SAvi Kivity } tmp_stack;
5967d36db35SAvi Kivity 
5977d36db35SAvi Kivity void test_pusha_popa()
5987d36db35SAvi Kivity {
5997d36db35SAvi Kivity 	MK_INSN(pusha, "pusha\n\t"
6007d36db35SAvi Kivity 		       "pop %edi\n\t"
6017d36db35SAvi Kivity 		       "pop %esi\n\t"
6027d36db35SAvi Kivity 		       "pop %ebp\n\t"
6037d36db35SAvi Kivity 		       "add $4, %esp\n\t"
6047d36db35SAvi Kivity 		       "pop %ebx\n\t"
6057d36db35SAvi Kivity 		       "pop %edx\n\t"
6067d36db35SAvi Kivity 		       "pop %ecx\n\t"
6077d36db35SAvi Kivity 		       "pop %eax\n\t"
6087d36db35SAvi Kivity 		       );
6097d36db35SAvi Kivity 
6107d36db35SAvi Kivity 	MK_INSN(popa, "push %eax\n\t"
6117d36db35SAvi Kivity 		      "push %ecx\n\t"
6127d36db35SAvi Kivity 		      "push %edx\n\t"
6137d36db35SAvi Kivity 		      "push %ebx\n\t"
6147d36db35SAvi Kivity 		      "push %esp\n\t"
6157d36db35SAvi Kivity 		      "push %ebp\n\t"
6167d36db35SAvi Kivity 		      "push %esi\n\t"
6177d36db35SAvi Kivity 		      "push %edi\n\t"
6187d36db35SAvi Kivity 		      "popa\n\t"
6197d36db35SAvi Kivity 		      );
6207d36db35SAvi Kivity 
62118253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top };
6227d36db35SAvi Kivity 
62318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pusha);
6246055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
62518253fdeSAvi Kivity 
62618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_popa);
6276055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
6287d36db35SAvi Kivity }
6297d36db35SAvi Kivity 
6307d36db35SAvi Kivity void test_iret()
6317d36db35SAvi Kivity {
6327d36db35SAvi Kivity 	MK_INSN(iret32, "pushf\n\t"
6337d36db35SAvi Kivity 			"pushl %cs\n\t"
6347d36db35SAvi Kivity 			"call 1f\n\t" /* a near call will push eip onto the stack */
6357d36db35SAvi Kivity 			"jmp 2f\n\t"
6367d36db35SAvi Kivity 			"1: iret\n\t"
6377d36db35SAvi Kivity 			"2:\n\t"
6387d36db35SAvi Kivity 		     );
6397d36db35SAvi Kivity 
6407d36db35SAvi Kivity 	MK_INSN(iret16, "pushfw\n\t"
6417d36db35SAvi Kivity 			"pushw %cs\n\t"
6427d36db35SAvi Kivity 			"callw 1f\n\t"
6437d36db35SAvi Kivity 			"jmp 2f\n\t"
6447d36db35SAvi Kivity 			"1: iretw\n\t"
6457d36db35SAvi Kivity 			"2:\n\t");
6467d36db35SAvi Kivity 
6477d36db35SAvi Kivity 	MK_INSN(iret_flags32, "pushfl\n\t"
6487d36db35SAvi Kivity 			      "popl %eax\n\t"
6497d36db35SAvi Kivity 			      "andl $~0x2, %eax\n\t"
6507d36db35SAvi Kivity 			      "orl $0xffc08028, %eax\n\t"
6517d36db35SAvi Kivity 			      "pushl %eax\n\t"
6527d36db35SAvi Kivity 			      "pushl %cs\n\t"
6537d36db35SAvi Kivity 			      "call 1f\n\t"
6547d36db35SAvi Kivity 			      "jmp 2f\n\t"
6557d36db35SAvi Kivity 			      "1: iret\n\t"
6567d36db35SAvi Kivity 			      "2:\n\t");
6577d36db35SAvi Kivity 
6587d36db35SAvi Kivity 	MK_INSN(iret_flags16, "pushfw\n\t"
6597d36db35SAvi Kivity 			      "popw %ax\n\t"
6607d36db35SAvi Kivity 			      "and $~0x2, %ax\n\t"
6617d36db35SAvi Kivity 			      "or $0x8028, %ax\n\t"
6627d36db35SAvi Kivity 			      "pushw %ax\n\t"
6637d36db35SAvi Kivity 			      "pushw %cs\n\t"
6647d36db35SAvi Kivity 			      "callw 1f\n\t"
6657d36db35SAvi Kivity 			      "jmp 2f\n\t"
6667d36db35SAvi Kivity 			      "1: iretw\n\t"
6677d36db35SAvi Kivity 			      "2:\n\t");
6687d36db35SAvi Kivity 
66918253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
6707d36db35SAvi Kivity 
67118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret32);
6726055ea1fSAvi Kivity 	report("iret 1", 0, 1);
6737d36db35SAvi Kivity 
67418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret16);
6756055ea1fSAvi Kivity 	report("iret 2", 0, 1);
6767d36db35SAvi Kivity 
67718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags32);
6786055ea1fSAvi Kivity 	report("iret 3", R_AX, 1);
67918253fdeSAvi Kivity 
68018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags16);
6816055ea1fSAvi Kivity 	report("iret 4", R_AX, 1);
6827d36db35SAvi Kivity }
6837d36db35SAvi Kivity 
68496b9ca1eSMohammed Gamal void test_int()
68596b9ca1eSMohammed Gamal {
68618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
68796b9ca1eSMohammed Gamal 
68896b9ca1eSMohammed Gamal 	*(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */
68996b9ca1eSMohammed Gamal 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
69096b9ca1eSMohammed Gamal 
69196b9ca1eSMohammed Gamal 	MK_INSN(int11, "int $0x11\n\t");
69296b9ca1eSMohammed Gamal 
69318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_int11);
6946055ea1fSAvi Kivity 	report("int 1", 0, 1);
69596b9ca1eSMohammed Gamal }
69696b9ca1eSMohammed Gamal 
697fa74f8a6SMohammed Gamal void test_imul()
698fa74f8a6SMohammed Gamal {
699fa74f8a6SMohammed Gamal 	MK_INSN(imul8_1, "mov $2, %al\n\t"
700fa74f8a6SMohammed Gamal 			"mov $-4, %cx\n\t"
701fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
702fa74f8a6SMohammed Gamal 
703fa74f8a6SMohammed Gamal 	MK_INSN(imul16_1, "mov $2, %ax\n\t"
704fa74f8a6SMohammed Gamal 		      "mov $-4, %cx\n\t"
705fa74f8a6SMohammed Gamal 		      "imul %cx\n\t");
706fa74f8a6SMohammed Gamal 
707fa74f8a6SMohammed Gamal 	MK_INSN(imul32_1, "mov $2, %eax\n\t"
708fa74f8a6SMohammed Gamal 		       "mov $-4, %ecx\n\t"
709fa74f8a6SMohammed Gamal 		       "imul %ecx\n\t");
710fa74f8a6SMohammed Gamal 
711fa74f8a6SMohammed Gamal 	MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t"
712fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
713fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
714fa74f8a6SMohammed Gamal 
715fa74f8a6SMohammed Gamal 	MK_INSN(imul16_2, "mov $2, %ax\n\t"
716fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
717fa74f8a6SMohammed Gamal 			"imul %cx\n\t");
718fa74f8a6SMohammed Gamal 
719fa74f8a6SMohammed Gamal 	MK_INSN(imul32_2, "mov $2, %eax\n\t"
720fa74f8a6SMohammed Gamal 			"mov $4, %ecx\n\t"
721fa74f8a6SMohammed Gamal 			"imul %ecx\n\t");
722fa74f8a6SMohammed Gamal 
72318253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
72418253fdeSAvi Kivity 
72518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_1);
7266055ea1fSAvi Kivity 	report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8);
727fa74f8a6SMohammed Gamal 
72818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_1);
7296055ea1fSAvi Kivity 	report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8);
730fa74f8a6SMohammed Gamal 
73118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_1);
7326055ea1fSAvi Kivity 	report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8);
733fa74f8a6SMohammed Gamal 
73418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_2);
7356055ea1fSAvi Kivity 	report("imul 4", R_AX | R_CX | R_DX,
7366055ea1fSAvi Kivity 	       (outregs.eax & 0xffff) == 8
73781050840SAvi Kivity 	       && (outregs.eax & 0xffff0000) == 0x12340000);
738fa74f8a6SMohammed Gamal 
73918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_2);
7406055ea1fSAvi Kivity 	report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8);
741fa74f8a6SMohammed Gamal 
74218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_2);
7436055ea1fSAvi Kivity 	report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8);
744fa74f8a6SMohammed Gamal }
745fa74f8a6SMohammed Gamal 
74659317bd1SMohammed Gamal void test_mul()
74759317bd1SMohammed Gamal {
74859317bd1SMohammed Gamal 	MK_INSN(mul8, "mov $2, %al\n\t"
74959317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
75059317bd1SMohammed Gamal 			"imul %cl\n\t");
75159317bd1SMohammed Gamal 
75259317bd1SMohammed Gamal 	MK_INSN(mul16, "mov $2, %ax\n\t"
75359317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
75459317bd1SMohammed Gamal 			"imul %cx\n\t");
75559317bd1SMohammed Gamal 
75659317bd1SMohammed Gamal 	MK_INSN(mul32, "mov $2, %eax\n\t"
75759317bd1SMohammed Gamal 			"mov $4, %ecx\n\t"
75859317bd1SMohammed Gamal 			"imul %ecx\n\t");
75959317bd1SMohammed Gamal 
76018253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
76118253fdeSAvi Kivity 
76218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul8);
7636055ea1fSAvi Kivity 	report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8);
76459317bd1SMohammed Gamal 
76518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul16);
7666055ea1fSAvi Kivity 	report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8);
76759317bd1SMohammed Gamal 
76818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul32);
7696055ea1fSAvi Kivity 	report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8);
77059317bd1SMohammed Gamal }
77159317bd1SMohammed Gamal 
7720d4c7614SMohammed Gamal void test_div()
7730d4c7614SMohammed Gamal {
7740d4c7614SMohammed Gamal 	MK_INSN(div8, "mov $257, %ax\n\t"
7750d4c7614SMohammed Gamal 			"mov $2, %cl\n\t"
7760d4c7614SMohammed Gamal 			"div %cl\n\t");
7770d4c7614SMohammed Gamal 
7780d4c7614SMohammed Gamal 	MK_INSN(div16, "mov $512, %ax\n\t"
7790d4c7614SMohammed Gamal 			"mov $5, %cx\n\t"
7800d4c7614SMohammed Gamal 			"div %cx\n\t");
7810d4c7614SMohammed Gamal 
7820d4c7614SMohammed Gamal 	MK_INSN(div32, "mov $512, %eax\n\t"
7830d4c7614SMohammed Gamal 			"mov $5, %ecx\n\t"
7840d4c7614SMohammed Gamal 			"div %ecx\n\t");
7850d4c7614SMohammed Gamal 
78618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
78718253fdeSAvi Kivity 
78818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div8);
7896055ea1fSAvi Kivity 	report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384);
7900d4c7614SMohammed Gamal 
79118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div16);
7926055ea1fSAvi Kivity 	report("div 2", R_AX | R_CX | R_DX,
7936055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
7940d4c7614SMohammed Gamal 
79518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div32);
7966055ea1fSAvi Kivity 	report("div 3", R_AX | R_CX | R_DX,
7976055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
7980d4c7614SMohammed Gamal }
7990d4c7614SMohammed Gamal 
8000d4c7614SMohammed Gamal void test_idiv()
8010d4c7614SMohammed Gamal {
8020d4c7614SMohammed Gamal 	MK_INSN(idiv8, "mov $256, %ax\n\t"
8030d4c7614SMohammed Gamal 			"mov $-2, %cl\n\t"
8040d4c7614SMohammed Gamal 			"idiv %cl\n\t");
8050d4c7614SMohammed Gamal 
8060d4c7614SMohammed Gamal 	MK_INSN(idiv16, "mov $512, %ax\n\t"
8070d4c7614SMohammed Gamal 			"mov $-2, %cx\n\t"
8080d4c7614SMohammed Gamal 			"idiv %cx\n\t");
8090d4c7614SMohammed Gamal 
8100d4c7614SMohammed Gamal 	MK_INSN(idiv32, "mov $512, %eax\n\t"
8110d4c7614SMohammed Gamal 			"mov $-2, %ecx\n\t"
8120d4c7614SMohammed Gamal 			"idiv %ecx\n\t");
8130d4c7614SMohammed Gamal 
81418253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
81518253fdeSAvi Kivity 
81618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv8);
8176055ea1fSAvi Kivity 	report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128);
8180d4c7614SMohammed Gamal 
81918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv16);
8206055ea1fSAvi Kivity 	report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256);
8210d4c7614SMohammed Gamal 
82218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv32);
8236055ea1fSAvi Kivity 	report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256);
8240d4c7614SMohammed Gamal }
8250d4c7614SMohammed Gamal 
8266e293cf5SWei Yongjun void test_cbw(void)
8276e293cf5SWei Yongjun {
8286e293cf5SWei Yongjun 	MK_INSN(cbw, "mov $0xFE, %eax \n\t"
8296e293cf5SWei Yongjun 		     "cbw\n\t");
8306e293cf5SWei Yongjun 	MK_INSN(cwde, "mov $0xFFFE, %eax \n\t"
8316e293cf5SWei Yongjun 		      "cwde\n\t");
8326e293cf5SWei Yongjun 
83318253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
83418253fdeSAvi Kivity 
83518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cbw);
8366055ea1fSAvi Kivity 	report("cbq 1", ~0, outregs.eax == 0xFFFE);
8376e293cf5SWei Yongjun 
83818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwde);
8396055ea1fSAvi Kivity 	report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE);
8406e293cf5SWei Yongjun }
8416e293cf5SWei Yongjun 
842eacef4e2SWei Yongjun void test_loopcc(void)
843eacef4e2SWei Yongjun {
844eacef4e2SWei Yongjun 	MK_INSN(loop, "mov $10, %ecx\n\t"
845eacef4e2SWei Yongjun 		      "1: inc %eax\n\t"
846eacef4e2SWei Yongjun 		      "loop 1b\n\t");
847eacef4e2SWei Yongjun 
848eacef4e2SWei Yongjun 	MK_INSN(loope, "mov $10, %ecx\n\t"
849eacef4e2SWei Yongjun 		       "mov $1, %eax\n\t"
850eacef4e2SWei Yongjun 		       "1: dec %eax\n\t"
851eacef4e2SWei Yongjun 		       "loope 1b\n\t");
852eacef4e2SWei Yongjun 
853eacef4e2SWei Yongjun 	MK_INSN(loopne, "mov $10, %ecx\n\t"
854eacef4e2SWei Yongjun 		        "mov $5, %eax\n\t"
855eacef4e2SWei Yongjun 		        "1: dec %eax\n\t"
856eacef4e2SWei Yongjun 			"loopne 1b\n\t");
857eacef4e2SWei Yongjun 
85818253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
859eacef4e2SWei Yongjun 
86018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loop);
8616055ea1fSAvi Kivity 	report("LOOPcc short 1", R_AX, outregs.eax == 10);
86218253fdeSAvi Kivity 
86318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loope);
8646055ea1fSAvi Kivity 	report("LOOPcc short 2", R_AX | R_CX,
8656055ea1fSAvi Kivity 	       outregs.eax == -1 && outregs.ecx == 8);
866eacef4e2SWei Yongjun 
86718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loopne);
8686055ea1fSAvi Kivity 	report("LOOPcc short 3", R_AX | R_CX,
8696055ea1fSAvi Kivity 	       outregs.eax == 0 && outregs.ecx == 5);
870eacef4e2SWei Yongjun }
871eacef4e2SWei Yongjun 
872b274feedSAvi Kivity static void test_das(void)
873b274feedSAvi Kivity {
874b274feedSAvi Kivity     short i;
87581050840SAvi Kivity     u16 nr_fail = 0;
876b274feedSAvi Kivity     static unsigned test_cases[1024] = {
877b274feedSAvi Kivity         0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00,
878b274feedSAvi Kivity         0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01,
879b274feedSAvi Kivity         0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02,
880b274feedSAvi Kivity         0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03,
881b274feedSAvi Kivity         0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04,
882b274feedSAvi Kivity         0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05,
883b274feedSAvi Kivity         0x06000606, 0x8701a606, 0x56100006, 0x9711a006,
884b274feedSAvi Kivity         0x02000707, 0x8301a707, 0x12100107, 0x9311a107,
885b274feedSAvi Kivity         0x02000808, 0x8301a808, 0x12100208, 0x9311a208,
886b274feedSAvi Kivity         0x06000909, 0x8701a909, 0x16100309, 0x9711a309,
887b274feedSAvi Kivity         0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a,
888b274feedSAvi Kivity         0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b,
889b274feedSAvi Kivity         0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c,
890b274feedSAvi Kivity         0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d,
891b274feedSAvi Kivity         0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e,
892b274feedSAvi Kivity         0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f,
893b274feedSAvi Kivity         0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10,
894b274feedSAvi Kivity         0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11,
895b274feedSAvi Kivity         0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12,
896b274feedSAvi Kivity         0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13,
897b274feedSAvi Kivity         0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14,
898b274feedSAvi Kivity         0x02001515, 0x8301b515, 0x16100f15, 0x9711af15,
899b274feedSAvi Kivity         0x02001616, 0x8301b616, 0x12101016, 0x9311b016,
900b274feedSAvi Kivity         0x06001717, 0x8701b717, 0x16101117, 0x9711b117,
901b274feedSAvi Kivity         0x06001818, 0x8701b818, 0x16101218, 0x9711b218,
902b274feedSAvi Kivity         0x02001919, 0x8301b919, 0x12101319, 0x9311b319,
903b274feedSAvi Kivity         0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a,
904b274feedSAvi Kivity         0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b,
905b274feedSAvi Kivity         0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c,
906b274feedSAvi Kivity         0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d,
907b274feedSAvi Kivity         0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e,
908b274feedSAvi Kivity         0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f,
909b274feedSAvi Kivity         0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20,
910b274feedSAvi Kivity         0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21,
911b274feedSAvi Kivity         0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22,
912b274feedSAvi Kivity         0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23,
913b274feedSAvi Kivity         0x06002424, 0x8301c424, 0x16101e24, 0x9711be24,
914b274feedSAvi Kivity         0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25,
915b274feedSAvi Kivity         0x02002626, 0x8701c626, 0x12102026, 0x9711c026,
916b274feedSAvi Kivity         0x06002727, 0x8301c727, 0x16102127, 0x9311c127,
917b274feedSAvi Kivity         0x06002828, 0x8301c828, 0x16102228, 0x9311c228,
918b274feedSAvi Kivity         0x02002929, 0x8701c929, 0x12102329, 0x9711c329,
919b274feedSAvi Kivity         0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a,
920b274feedSAvi Kivity         0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b,
921b274feedSAvi Kivity         0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c,
922b274feedSAvi Kivity         0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d,
923b274feedSAvi Kivity         0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e,
924b274feedSAvi Kivity         0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f,
925b274feedSAvi Kivity         0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30,
926b274feedSAvi Kivity         0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31,
927b274feedSAvi Kivity         0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32,
928b274feedSAvi Kivity         0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33,
929b274feedSAvi Kivity         0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34,
930b274feedSAvi Kivity         0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35,
931b274feedSAvi Kivity         0x06003636, 0x8301d636, 0x16103036, 0x9311d036,
932b274feedSAvi Kivity         0x02003737, 0x8701d737, 0x12103137, 0x9711d137,
933b274feedSAvi Kivity         0x02003838, 0x8701d838, 0x12103238, 0x9711d238,
934b274feedSAvi Kivity         0x06003939, 0x8301d939, 0x16103339, 0x9311d339,
935b274feedSAvi Kivity         0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a,
936b274feedSAvi Kivity         0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b,
937b274feedSAvi Kivity         0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c,
938b274feedSAvi Kivity         0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d,
939b274feedSAvi Kivity         0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e,
940b274feedSAvi Kivity         0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f,
941b274feedSAvi Kivity         0x02004040, 0x8301e040, 0x16103a40, 0x9311da40,
942b274feedSAvi Kivity         0x06004141, 0x8701e141, 0x12103b41, 0x9711db41,
943b274feedSAvi Kivity         0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42,
944b274feedSAvi Kivity         0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43,
945b274feedSAvi Kivity         0x06004444, 0x8701e444, 0x12103e44, 0x9711de44,
946b274feedSAvi Kivity         0x02004545, 0x8301e545, 0x16103f45, 0x9311df45,
947b274feedSAvi Kivity         0x02004646, 0x8301e646, 0x12104046, 0x9311e046,
948b274feedSAvi Kivity         0x06004747, 0x8701e747, 0x16104147, 0x9711e147,
949b274feedSAvi Kivity         0x06004848, 0x8701e848, 0x16104248, 0x9711e248,
950b274feedSAvi Kivity         0x02004949, 0x8301e949, 0x12104349, 0x9311e349,
951b274feedSAvi Kivity         0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a,
952b274feedSAvi Kivity         0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b,
953b274feedSAvi Kivity         0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c,
954b274feedSAvi Kivity         0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d,
955b274feedSAvi Kivity         0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e,
956b274feedSAvi Kivity         0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f,
957b274feedSAvi Kivity         0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50,
958b274feedSAvi Kivity         0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51,
959b274feedSAvi Kivity         0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52,
960b274feedSAvi Kivity         0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53,
961b274feedSAvi Kivity         0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54,
962b274feedSAvi Kivity         0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55,
963b274feedSAvi Kivity         0x06005656, 0x8701f656, 0x16105056, 0x9711f056,
964b274feedSAvi Kivity         0x02005757, 0x8301f757, 0x12105157, 0x9311f157,
965b274feedSAvi Kivity         0x02005858, 0x8301f858, 0x12105258, 0x9311f258,
966b274feedSAvi Kivity         0x06005959, 0x8701f959, 0x16105359, 0x9711f359,
967b274feedSAvi Kivity         0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a,
968b274feedSAvi Kivity         0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b,
969b274feedSAvi Kivity         0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c,
970b274feedSAvi Kivity         0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d,
971b274feedSAvi Kivity         0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e,
972b274feedSAvi Kivity         0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f,
973b274feedSAvi Kivity         0x06006060, 0x47010060, 0x16105a60, 0x9711fa60,
974b274feedSAvi Kivity         0x02006161, 0x03010161, 0x12105b61, 0x9311fb61,
975b274feedSAvi Kivity         0x02006262, 0x03010262, 0x16105c62, 0x9711fc62,
976b274feedSAvi Kivity         0x06006363, 0x07010363, 0x12105d63, 0x9311fd63,
977b274feedSAvi Kivity         0x02006464, 0x03010464, 0x12105e64, 0x9311fe64,
978b274feedSAvi Kivity         0x06006565, 0x07010565, 0x16105f65, 0x9711ff65,
979b274feedSAvi Kivity         0x06006666, 0x07010666, 0x16106066, 0x57110066,
980b274feedSAvi Kivity         0x02006767, 0x03010767, 0x12106167, 0x13110167,
981b274feedSAvi Kivity         0x02006868, 0x03010868, 0x12106268, 0x13110268,
982b274feedSAvi Kivity         0x06006969, 0x07010969, 0x16106369, 0x17110369,
983b274feedSAvi Kivity         0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a,
984b274feedSAvi Kivity         0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b,
985b274feedSAvi Kivity         0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c,
986b274feedSAvi Kivity         0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d,
987b274feedSAvi Kivity         0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e,
988b274feedSAvi Kivity         0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f,
989b274feedSAvi Kivity         0x02007070, 0x03011070, 0x16106a70, 0x17110a70,
990b274feedSAvi Kivity         0x06007171, 0x07011171, 0x12106b71, 0x13110b71,
991b274feedSAvi Kivity         0x06007272, 0x07011272, 0x16106c72, 0x17110c72,
992b274feedSAvi Kivity         0x02007373, 0x03011373, 0x12106d73, 0x13110d73,
993b274feedSAvi Kivity         0x06007474, 0x07011474, 0x12106e74, 0x13110e74,
994b274feedSAvi Kivity         0x02007575, 0x03011575, 0x16106f75, 0x17110f75,
995b274feedSAvi Kivity         0x02007676, 0x03011676, 0x12107076, 0x13111076,
996b274feedSAvi Kivity         0x06007777, 0x07011777, 0x16107177, 0x17111177,
997b274feedSAvi Kivity         0x06007878, 0x07011878, 0x16107278, 0x17111278,
998b274feedSAvi Kivity         0x02007979, 0x03011979, 0x12107379, 0x13111379,
999b274feedSAvi Kivity         0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a,
1000b274feedSAvi Kivity         0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b,
1001b274feedSAvi Kivity         0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c,
1002b274feedSAvi Kivity         0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d,
1003b274feedSAvi Kivity         0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e,
1004b274feedSAvi Kivity         0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f,
1005b274feedSAvi Kivity         0x82008080, 0x03012080, 0x12107a80, 0x13111a80,
1006b274feedSAvi Kivity         0x86008181, 0x07012181, 0x16107b81, 0x17111b81,
1007b274feedSAvi Kivity         0x86008282, 0x07012282, 0x12107c82, 0x13111c82,
1008b274feedSAvi Kivity         0x82008383, 0x03012383, 0x16107d83, 0x17111d83,
1009b274feedSAvi Kivity         0x86008484, 0x07012484, 0x16107e84, 0x17111e84,
1010b274feedSAvi Kivity         0x82008585, 0x03012585, 0x12107f85, 0x13111f85,
1011b274feedSAvi Kivity         0x82008686, 0x03012686, 0x92108086, 0x13112086,
1012b274feedSAvi Kivity         0x86008787, 0x07012787, 0x96108187, 0x17112187,
1013b274feedSAvi Kivity         0x86008888, 0x07012888, 0x96108288, 0x17112288,
1014b274feedSAvi Kivity         0x82008989, 0x03012989, 0x92108389, 0x13112389,
1015b274feedSAvi Kivity         0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a,
1016b274feedSAvi Kivity         0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b,
1017b274feedSAvi Kivity         0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c,
1018b274feedSAvi Kivity         0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d,
1019b274feedSAvi Kivity         0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e,
1020b274feedSAvi Kivity         0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f,
1021b274feedSAvi Kivity         0x86009090, 0x07013090, 0x92108a90, 0x13112a90,
1022b274feedSAvi Kivity         0x82009191, 0x03013191, 0x96108b91, 0x17112b91,
1023b274feedSAvi Kivity         0x82009292, 0x03013292, 0x92108c92, 0x13112c92,
1024b274feedSAvi Kivity         0x86009393, 0x07013393, 0x96108d93, 0x17112d93,
1025b274feedSAvi Kivity         0x82009494, 0x03013494, 0x96108e94, 0x17112e94,
1026b274feedSAvi Kivity         0x86009595, 0x07013595, 0x92108f95, 0x13112f95,
1027b274feedSAvi Kivity         0x86009696, 0x07013696, 0x96109096, 0x17113096,
1028b274feedSAvi Kivity         0x82009797, 0x03013797, 0x92109197, 0x13113197,
1029b274feedSAvi Kivity         0x82009898, 0x03013898, 0x92109298, 0x13113298,
1030b274feedSAvi Kivity         0x86009999, 0x07013999, 0x96109399, 0x17113399,
1031b274feedSAvi Kivity         0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a,
1032b274feedSAvi Kivity         0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b,
1033b274feedSAvi Kivity         0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c,
1034b274feedSAvi Kivity         0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d,
1035b274feedSAvi Kivity         0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e,
1036b274feedSAvi Kivity         0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f,
1037b274feedSAvi Kivity         0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0,
1038b274feedSAvi Kivity         0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1,
1039b274feedSAvi Kivity         0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2,
1040b274feedSAvi Kivity         0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3,
1041b274feedSAvi Kivity         0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4,
1042b274feedSAvi Kivity         0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5,
1043b274feedSAvi Kivity         0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6,
1044b274feedSAvi Kivity         0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7,
1045b274feedSAvi Kivity         0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8,
1046b274feedSAvi Kivity         0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9,
1047b274feedSAvi Kivity         0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa,
1048b274feedSAvi Kivity         0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab,
1049b274feedSAvi Kivity         0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac,
1050b274feedSAvi Kivity         0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad,
1051b274feedSAvi Kivity         0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae,
1052b274feedSAvi Kivity         0x130049af, 0x130149af, 0x131049af, 0x131149af,
1053b274feedSAvi Kivity         0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0,
1054b274feedSAvi Kivity         0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1,
1055b274feedSAvi Kivity         0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2,
1056b274feedSAvi Kivity         0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3,
1057b274feedSAvi Kivity         0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4,
1058b274feedSAvi Kivity         0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5,
1059b274feedSAvi Kivity         0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6,
1060b274feedSAvi Kivity         0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7,
1061b274feedSAvi Kivity         0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8,
1062b274feedSAvi Kivity         0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9,
1063b274feedSAvi Kivity         0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba,
1064b274feedSAvi Kivity         0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb,
1065b274feedSAvi Kivity         0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc,
1066b274feedSAvi Kivity         0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd,
1067b274feedSAvi Kivity         0x130058be, 0x130158be, 0x131058be, 0x131158be,
1068b274feedSAvi Kivity         0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf,
1069b274feedSAvi Kivity         0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0,
1070b274feedSAvi Kivity         0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1,
1071b274feedSAvi Kivity         0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2,
1072b274feedSAvi Kivity         0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3,
1073b274feedSAvi Kivity         0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4,
1074b274feedSAvi Kivity         0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5,
1075b274feedSAvi Kivity         0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6,
1076b274feedSAvi Kivity         0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7,
1077b274feedSAvi Kivity         0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8,
1078b274feedSAvi Kivity         0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9,
1079b274feedSAvi Kivity         0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca,
1080b274feedSAvi Kivity         0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb,
1081b274feedSAvi Kivity         0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc,
1082b274feedSAvi Kivity         0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd,
1083b274feedSAvi Kivity         0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce,
1084b274feedSAvi Kivity         0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf,
1085b274feedSAvi Kivity         0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0,
1086b274feedSAvi Kivity         0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1,
1087b274feedSAvi Kivity         0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2,
1088b274feedSAvi Kivity         0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3,
1089b274feedSAvi Kivity         0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4,
1090b274feedSAvi Kivity         0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5,
1091b274feedSAvi Kivity         0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6,
1092b274feedSAvi Kivity         0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7,
1093b274feedSAvi Kivity         0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8,
1094b274feedSAvi Kivity         0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9,
1095b274feedSAvi Kivity         0x170074da, 0x170174da, 0x171074da, 0x171174da,
1096b274feedSAvi Kivity         0x130075db, 0x130175db, 0x131075db, 0x131175db,
1097b274feedSAvi Kivity         0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc,
1098b274feedSAvi Kivity         0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd,
1099b274feedSAvi Kivity         0x170078de, 0x170178de, 0x171078de, 0x171178de,
1100b274feedSAvi Kivity         0x130079df, 0x130179df, 0x131079df, 0x131179df,
1101b274feedSAvi Kivity         0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0,
1102b274feedSAvi Kivity         0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1,
1103b274feedSAvi Kivity         0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2,
1104b274feedSAvi Kivity         0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3,
1105b274feedSAvi Kivity         0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4,
1106b274feedSAvi Kivity         0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5,
1107b274feedSAvi Kivity         0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6,
1108b274feedSAvi Kivity         0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7,
1109b274feedSAvi Kivity         0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8,
1110b274feedSAvi Kivity         0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9,
1111b274feedSAvi Kivity         0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea,
1112b274feedSAvi Kivity         0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb,
1113b274feedSAvi Kivity         0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec,
1114b274feedSAvi Kivity         0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed,
1115b274feedSAvi Kivity         0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee,
1116b274feedSAvi Kivity         0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef,
1117b274feedSAvi Kivity         0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0,
1118b274feedSAvi Kivity         0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1,
1119b274feedSAvi Kivity         0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2,
1120b274feedSAvi Kivity         0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3,
1121b274feedSAvi Kivity         0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4,
1122b274feedSAvi Kivity         0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5,
1123b274feedSAvi Kivity         0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6,
1124b274feedSAvi Kivity         0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7,
1125b274feedSAvi Kivity         0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8,
1126b274feedSAvi Kivity         0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9,
1127b274feedSAvi Kivity         0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa,
1128b274feedSAvi Kivity         0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb,
1129b274feedSAvi Kivity         0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc,
1130b274feedSAvi Kivity         0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd,
1131b274feedSAvi Kivity         0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe,
1132b274feedSAvi Kivity         0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff,
1133b274feedSAvi Kivity     };
1134b274feedSAvi Kivity 
1135b274feedSAvi Kivity     MK_INSN(das, "das");
1136b274feedSAvi Kivity 
113718253fdeSAvi Kivity     inregs = (struct regs){ 0 };
113818253fdeSAvi Kivity 
1139b274feedSAvi Kivity     for (i = 0; i < 1024; ++i) {
1140b274feedSAvi Kivity         unsigned tmp = test_cases[i];
1141b274feedSAvi Kivity         inregs.eax = tmp & 0xff;
1142b274feedSAvi Kivity         inregs.eflags = (tmp >> 16) & 0xff;
114318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_das);
114418253fdeSAvi Kivity 	if (!regs_equal(R_AX)
1145b274feedSAvi Kivity             || outregs.eax != ((tmp >> 8) & 0xff)
1146b274feedSAvi Kivity             || (outregs.eflags & 0xff) != (tmp >> 24)) {
114781050840SAvi Kivity 	    ++nr_fail;
114881050840SAvi Kivity 	    break;
1149b274feedSAvi Kivity         }
1150b274feedSAvi Kivity     }
11516055ea1fSAvi Kivity     report("DAS", ~0, nr_fail == 0);
1152b274feedSAvi Kivity }
1153b274feedSAvi Kivity 
11540cbd5b06SMohammed Gamal void test_cwd_cdq()
11550cbd5b06SMohammed Gamal {
11560cbd5b06SMohammed Gamal 	/* Sign-bit set */
11570cbd5b06SMohammed Gamal 	MK_INSN(cwd_1, "mov $0x8000, %ax\n\t"
11580cbd5b06SMohammed Gamal 		       "cwd\n\t");
11590cbd5b06SMohammed Gamal 
11600cbd5b06SMohammed Gamal 	/* Sign-bit not set */
11610cbd5b06SMohammed Gamal 	MK_INSN(cwd_2, "mov $0x1000, %ax\n\t"
11620cbd5b06SMohammed Gamal 		       "cwd\n\t");
11630cbd5b06SMohammed Gamal 
11640cbd5b06SMohammed Gamal 	/* Sign-bit set */
11650cbd5b06SMohammed Gamal 	MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t"
11660cbd5b06SMohammed Gamal 		       "cdq\n\t");
11670cbd5b06SMohammed Gamal 
11680cbd5b06SMohammed Gamal 	/* Sign-bit not set */
11690cbd5b06SMohammed Gamal 	MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t"
11700cbd5b06SMohammed Gamal 		       "cdq\n\t");
11710cbd5b06SMohammed Gamal 
117218253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
117318253fdeSAvi Kivity 
117418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_1);
11756055ea1fSAvi Kivity 	report("cwd 1", R_AX | R_DX,
11766055ea1fSAvi Kivity 	       outregs.eax == 0x8000 && outregs.edx == 0xffff);
11770cbd5b06SMohammed Gamal 
117818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_2);
11796055ea1fSAvi Kivity 	report("cwd 2", R_AX | R_DX,
11806055ea1fSAvi Kivity 	       outregs.eax == 0x1000 && outregs.edx == 0);
11810cbd5b06SMohammed Gamal 
118218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_1);
11836055ea1fSAvi Kivity 	report("cdq 1", R_AX | R_DX,
11846055ea1fSAvi Kivity 	       outregs.eax == 0x80000000 && outregs.edx == 0xffffffff);
11850cbd5b06SMohammed Gamal 
118618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_2);
11876055ea1fSAvi Kivity 	report("cdq 2", R_AX | R_DX,
11886055ea1fSAvi Kivity 	       outregs.eax == 0x10000000 && outregs.edx == 0);
11890cbd5b06SMohammed Gamal }
11900cbd5b06SMohammed Gamal 
119137f51a4aSWei Yongjun static struct {
119237f51a4aSWei Yongjun         void *address;
119337f51a4aSWei Yongjun         unsigned short sel;
119437f51a4aSWei Yongjun } __attribute__((packed)) desc = {
119537f51a4aSWei Yongjun 	(void *)0x1234,
119637f51a4aSWei Yongjun 	0x10,
119737f51a4aSWei Yongjun };
119837f51a4aSWei Yongjun 
119937f51a4aSWei Yongjun void test_lds_lss()
120037f51a4aSWei Yongjun {
120137f51a4aSWei Yongjun 	inregs = (struct regs){ .ebx = (unsigned long)&desc };
120237f51a4aSWei Yongjun 
120337f51a4aSWei Yongjun 	MK_INSN(lds, "push %ds\n\t"
120437f51a4aSWei Yongjun 		     "lds (%ebx), %eax\n\t"
120537f51a4aSWei Yongjun 		     "mov %ds, %ebx\n\t"
120637f51a4aSWei Yongjun 		     "pop %ds\n\t");
120737f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lds);
120837f51a4aSWei Yongjun 	report("lds", R_AX | R_BX,
120937f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
121037f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
121137f51a4aSWei Yongjun 
121237f51a4aSWei Yongjun 	MK_INSN(les, "push %es\n\t"
121337f51a4aSWei Yongjun 		     "les (%ebx), %eax\n\t"
121437f51a4aSWei Yongjun 		     "mov %es, %ebx\n\t"
121537f51a4aSWei Yongjun 		     "pop %es\n\t");
121637f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_les);
121737f51a4aSWei Yongjun 	report("les", R_AX | R_BX,
121837f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
121937f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
122037f51a4aSWei Yongjun 
122137f51a4aSWei Yongjun 	MK_INSN(lfs, "push %fs\n\t"
122237f51a4aSWei Yongjun 		     "lfs (%ebx), %eax\n\t"
122337f51a4aSWei Yongjun 		     "mov %fs, %ebx\n\t"
122437f51a4aSWei Yongjun 		     "pop %fs\n\t");
122537f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lfs);
122637f51a4aSWei Yongjun 	report("lfs", R_AX | R_BX,
122737f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
122837f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
122937f51a4aSWei Yongjun 
123037f51a4aSWei Yongjun 	MK_INSN(lgs, "push %gs\n\t"
123137f51a4aSWei Yongjun 		     "lgs (%ebx), %eax\n\t"
123237f51a4aSWei Yongjun 		     "mov %gs, %ebx\n\t"
123337f51a4aSWei Yongjun 		     "pop %gs\n\t");
123437f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lgs);
123537f51a4aSWei Yongjun 	report("lgs", R_AX | R_BX,
123637f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
123737f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
123837f51a4aSWei Yongjun 
123937f51a4aSWei Yongjun 	MK_INSN(lss, "push %ss\n\t"
124037f51a4aSWei Yongjun 		     "lss (%ebx), %eax\n\t"
124137f51a4aSWei Yongjun 		     "mov %ss, %ebx\n\t"
124237f51a4aSWei Yongjun 		     "pop %ss\n\t");
124337f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lss);
124437f51a4aSWei Yongjun 	report("lss", R_AX | R_BX,
124537f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
124637f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
124737f51a4aSWei Yongjun }
124837f51a4aSWei Yongjun 
1249b1c7c575SWei Yongjun void test_jcxz(void)
1250b1c7c575SWei Yongjun {
1251b1c7c575SWei Yongjun 	MK_INSN(jcxz1, "jcxz 1f\n\t"
1252b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1253b1c7c575SWei Yongjun 		       "1:\n\t");
1254b1c7c575SWei Yongjun 	MK_INSN(jcxz2, "mov $0x100, %ecx\n\t"
1255b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1256b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1257b1c7c575SWei Yongjun 		       "mov $0, %ecx\n\t"
1258b1c7c575SWei Yongjun 		       "1:\n\t");
1259b1c7c575SWei Yongjun 	MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t"
1260b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1261b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1262b1c7c575SWei Yongjun 		       "1:\n\t");
1263b1c7c575SWei Yongjun 	MK_INSN(jecxz1, "jecxz 1f\n\t"
1264b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1265b1c7c575SWei Yongjun 			"1:\n\t");
1266b1c7c575SWei Yongjun 	MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t"
1267b1c7c575SWei Yongjun 			"jecxz 1f\n\t"
1268b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1269b1c7c575SWei Yongjun 			"mov $0, %ecx\n\t"
1270b1c7c575SWei Yongjun 			"1:\n\t");
1271b1c7c575SWei Yongjun 
1272b1c7c575SWei Yongjun 	inregs = (struct regs){ 0 };
1273b1c7c575SWei Yongjun 
1274b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz1);
1275b1c7c575SWei Yongjun 	report("jcxz short 1", 0, 1);
1276b1c7c575SWei Yongjun 
1277b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz2);
1278b1c7c575SWei Yongjun 	report("jcxz short 2", R_AX, outregs.eax == 0x1234);
1279b1c7c575SWei Yongjun 
1280b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz3);
1281b1c7c575SWei Yongjun 	report("jcxz short 3", R_CX, outregs.ecx == 0x10000);
1282b1c7c575SWei Yongjun 
1283b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz1);
1284b1c7c575SWei Yongjun 	report("jecxz short 1", 0, 1);
1285b1c7c575SWei Yongjun 
1286b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz2);
1287b1c7c575SWei Yongjun 	report("jecxz short 2", R_AX, outregs.eax == 0x1234);
1288b1c7c575SWei Yongjun }
1289b1c7c575SWei Yongjun 
12908f578e98SAvi Kivity static void test_cpuid(void)
12918f578e98SAvi Kivity {
12928f578e98SAvi Kivity     MK_INSN(cpuid, "cpuid");
12938f578e98SAvi Kivity     unsigned function = 0x1234;
12948f578e98SAvi Kivity     unsigned eax, ebx, ecx, edx;
12958f578e98SAvi Kivity 
12968f578e98SAvi Kivity     inregs.eax = eax = function;
12978f578e98SAvi Kivity     asm("cpuid" : "+a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx));
12988f578e98SAvi Kivity     exec_in_big_real_mode(&insn_cpuid);
12998f578e98SAvi Kivity     report("cpuid", R_AX|R_BX|R_CX|R_DX,
13008f578e98SAvi Kivity 	   outregs.eax == eax && outregs.ebx == ebx
13018f578e98SAvi Kivity 	   && outregs.ecx == ecx && outregs.edx == edx);
13028f578e98SAvi Kivity }
13038f578e98SAvi Kivity 
1304*ed93f43bSAvi Kivity static void test_ss_base_for_esp_ebp(void)
1305*ed93f43bSAvi Kivity {
1306*ed93f43bSAvi Kivity     MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss");
1307*ed93f43bSAvi Kivity     MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss");
1308*ed93f43bSAvi Kivity     static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 };
1309*ed93f43bSAvi Kivity 
1310*ed93f43bSAvi Kivity     inregs.ebx = 1;
1311*ed93f43bSAvi Kivity     inregs.ebp = (unsigned)array;
1312*ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel1);
1313*ed93f43bSAvi Kivity     report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321);
1314*ed93f43bSAvi Kivity     inregs.ebx = 1;
1315*ed93f43bSAvi Kivity     inregs.ebp = (unsigned)array;
1316*ed93f43bSAvi Kivity     inregs.edi = 0;
1317*ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel2);
1318*ed93f43bSAvi Kivity     report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321);
1319*ed93f43bSAvi Kivity }
1320*ed93f43bSAvi Kivity 
13217d36db35SAvi Kivity void realmode_start(void)
13227d36db35SAvi Kivity {
13237d36db35SAvi Kivity 	test_null();
13247d36db35SAvi Kivity 
13257d36db35SAvi Kivity 	test_shld();
13267d36db35SAvi Kivity 	test_push_pop();
13277d36db35SAvi Kivity 	test_pusha_popa();
13287d36db35SAvi Kivity 	test_mov_imm();
13297d36db35SAvi Kivity 	test_cmp_imm();
13307d36db35SAvi Kivity 	test_add_imm();
13317d36db35SAvi Kivity 	test_sub_imm();
13327d36db35SAvi Kivity 	test_xor_imm();
13337d36db35SAvi Kivity 	test_io();
13347d36db35SAvi Kivity 	test_eflags_insn();
13357d36db35SAvi Kivity 	test_jcc_short();
13367d36db35SAvi Kivity 	test_jcc_near();
13377d36db35SAvi Kivity 	/* test_call() uses short jump so call it after testing jcc */
13387d36db35SAvi Kivity 	test_call();
13397d36db35SAvi Kivity 	/* long jmp test uses call near so test it after testing call */
13407d36db35SAvi Kivity 	test_long_jmp();
13417d36db35SAvi Kivity 	test_xchg();
13427d36db35SAvi Kivity 	test_iret();
134396b9ca1eSMohammed Gamal 	test_int();
1344fa74f8a6SMohammed Gamal 	test_imul();
134559317bd1SMohammed Gamal 	test_mul();
13460d4c7614SMohammed Gamal 	test_div();
13470d4c7614SMohammed Gamal 	test_idiv();
1348eacef4e2SWei Yongjun 	test_loopcc();
13496e293cf5SWei Yongjun 	test_cbw();
13500cbd5b06SMohammed Gamal 	test_cwd_cdq();
1351b274feedSAvi Kivity 	test_das();
135237f51a4aSWei Yongjun 	test_lds_lss();
1353b1c7c575SWei Yongjun 	test_jcxz();
13548f578e98SAvi Kivity 	test_cpuid();
1355*ed93f43bSAvi Kivity 	test_ss_base_for_esp_ebp();
13567d36db35SAvi Kivity 
13577d36db35SAvi Kivity 	exit(0);
13587d36db35SAvi Kivity }
13597d36db35SAvi Kivity 
13607d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff };
13617d36db35SAvi Kivity 
13627d36db35SAvi Kivity struct __attribute__((packed)) {
13637d36db35SAvi Kivity 	unsigned short limit;
13647d36db35SAvi Kivity 	void *base;
13657d36db35SAvi Kivity } r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt };
13667d36db35SAvi Kivity 
13677d36db35SAvi Kivity asm(
13687d36db35SAvi Kivity 	".section .init \n\t"
13697d36db35SAvi Kivity 
13707d36db35SAvi Kivity 	".code32 \n\t"
13717d36db35SAvi Kivity 
13727d36db35SAvi Kivity 	"mb_magic = 0x1BADB002 \n\t"
13737d36db35SAvi Kivity 	"mb_flags = 0x0 \n\t"
13747d36db35SAvi Kivity 
13757d36db35SAvi Kivity 	"# multiboot header \n\t"
13767d36db35SAvi Kivity 	".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t"
13777d36db35SAvi Kivity 
13787d36db35SAvi Kivity 	".globl start \n\t"
13797d36db35SAvi Kivity 	".data \n\t"
13807d36db35SAvi Kivity 	". = . + 4096 \n\t"
13817d36db35SAvi Kivity 	"stacktop: \n\t"
13827d36db35SAvi Kivity 
13837d36db35SAvi Kivity 	".text \n\t"
13847d36db35SAvi Kivity 	"start: \n\t"
13857d36db35SAvi Kivity 	"lgdt r_gdt_descr \n\t"
13867d36db35SAvi Kivity 	"ljmp $8, $1f; 1: \n\t"
13877d36db35SAvi Kivity 	".code16gcc \n\t"
13887d36db35SAvi Kivity 	"mov $16, %eax \n\t"
13897d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
13907d36db35SAvi Kivity 	"mov %ax, %es \n\t"
13917d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
13927d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
13937d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
13947d36db35SAvi Kivity 	"mov %cr0, %eax \n\t"
13957d36db35SAvi Kivity 	"btc $0, %eax \n\t"
13967d36db35SAvi Kivity 	"mov %eax, %cr0 \n\t"
13977d36db35SAvi Kivity 	"ljmp $0, $realmode_entry \n\t"
13987d36db35SAvi Kivity 
13997d36db35SAvi Kivity 	"realmode_entry: \n\t"
14007d36db35SAvi Kivity 
14017d36db35SAvi Kivity 	"xor %ax, %ax \n\t"
14027d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
14037d36db35SAvi Kivity 	"mov %ax, %es \n\t"
14047d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
14057d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
14067d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
14077d36db35SAvi Kivity 	"mov $stacktop, %esp\n\t"
14087d36db35SAvi Kivity 	"ljmp $0, $realmode_start \n\t"
14097d36db35SAvi Kivity 
14107d36db35SAvi Kivity 	".code16gcc \n\t"
14117d36db35SAvi Kivity 	);
1412