xref: /kvm-unit-tests/x86/realmode.c (revision b5105e8b489b626bae2c1fc45e4ab1263b626eb9)
1f366255fSPaolo Bonzini #ifndef USE_SERIAL
2f366255fSPaolo Bonzini #define USE_SERIAL
3f366255fSPaolo Bonzini #endif
4f366255fSPaolo Bonzini 
57d36db35SAvi Kivity asm(".code16gcc");
67d36db35SAvi Kivity 
77d36db35SAvi Kivity typedef unsigned char u8;
87d36db35SAvi Kivity typedef unsigned short u16;
97d36db35SAvi Kivity typedef unsigned u32;
107d36db35SAvi Kivity typedef unsigned long long u64;
117d36db35SAvi Kivity 
127d36db35SAvi Kivity void test_function(void);
137d36db35SAvi Kivity 
147d36db35SAvi Kivity asm(
157d36db35SAvi Kivity 	"test_function: \n\t"
167d36db35SAvi Kivity 	"mov $0x1234, %eax \n\t"
177d36db35SAvi Kivity 	"ret"
187d36db35SAvi Kivity    );
197d36db35SAvi Kivity 
207d36db35SAvi Kivity static int strlen(const char *str)
217d36db35SAvi Kivity {
227d36db35SAvi Kivity 	int n;
237d36db35SAvi Kivity 
247d36db35SAvi Kivity 	for (n = 0; *str; ++str)
257d36db35SAvi Kivity 		++n;
267d36db35SAvi Kivity 	return n;
277d36db35SAvi Kivity }
287d36db35SAvi Kivity 
29f366255fSPaolo Bonzini static void outb(u8 data, u16 port)
30f366255fSPaolo Bonzini {
31f366255fSPaolo Bonzini 	asm volatile("out %0, %1" : : "a"(data), "d"(port));
32f366255fSPaolo Bonzini }
33f366255fSPaolo Bonzini 
34f366255fSPaolo Bonzini #ifdef USE_SERIAL
35f366255fSPaolo Bonzini static int serial_iobase = 0x3f8;
36f366255fSPaolo Bonzini static int serial_inited = 0;
37f366255fSPaolo Bonzini 
38f366255fSPaolo Bonzini static u8 inb(u16 port)
39f366255fSPaolo Bonzini {
40f366255fSPaolo Bonzini 	u8 data;
41f366255fSPaolo Bonzini 	asm volatile("in %1, %0" : "=a"(data) : "d"(port));
42f366255fSPaolo Bonzini 	return data;
43f366255fSPaolo Bonzini }
44f366255fSPaolo Bonzini 
45f366255fSPaolo Bonzini static void serial_outb(char ch)
46f366255fSPaolo Bonzini {
47f366255fSPaolo Bonzini 	u8 lsr;
48f366255fSPaolo Bonzini 
49f366255fSPaolo Bonzini 	do {
50f366255fSPaolo Bonzini 		lsr = inb(serial_iobase + 0x05);
51f366255fSPaolo Bonzini 	} while (!(lsr & 0x20));
52f366255fSPaolo Bonzini 
53f366255fSPaolo Bonzini 	outb(ch, serial_iobase + 0x00);
54f366255fSPaolo Bonzini }
55f366255fSPaolo Bonzini 
56f366255fSPaolo Bonzini static void serial_init(void)
57f366255fSPaolo Bonzini {
58f366255fSPaolo Bonzini 	u8 lcr;
59f366255fSPaolo Bonzini 
60f366255fSPaolo Bonzini 	/* set DLAB */
61f366255fSPaolo Bonzini 	lcr = inb(serial_iobase + 0x03);
62f366255fSPaolo Bonzini 	lcr |= 0x80;
63f366255fSPaolo Bonzini 	outb(lcr, serial_iobase + 0x03);
64f366255fSPaolo Bonzini 
65f366255fSPaolo Bonzini 	/* set baud rate to 115200 */
66f366255fSPaolo Bonzini 	outb(0x01, serial_iobase + 0x00);
67f366255fSPaolo Bonzini 	outb(0x00, serial_iobase + 0x01);
68f366255fSPaolo Bonzini 
69f366255fSPaolo Bonzini 	/* clear DLAB */
70f366255fSPaolo Bonzini 	lcr = inb(serial_iobase + 0x03);
71f366255fSPaolo Bonzini 	lcr &= ~0x80;
72f366255fSPaolo Bonzini 	outb(lcr, serial_iobase + 0x03);
73f366255fSPaolo Bonzini }
74f366255fSPaolo Bonzini #endif
75f366255fSPaolo Bonzini 
767d36db35SAvi Kivity static void print_serial(const char *buf)
777d36db35SAvi Kivity {
787d36db35SAvi Kivity 	unsigned long len = strlen(buf);
79f366255fSPaolo Bonzini #ifdef USE_SERIAL
80f366255fSPaolo Bonzini 	unsigned long i;
81f366255fSPaolo Bonzini 	if (!serial_inited) {
82f366255fSPaolo Bonzini 	    serial_init();
83f366255fSPaolo Bonzini 	    serial_inited = 1;
84f366255fSPaolo Bonzini 	}
857d36db35SAvi Kivity 
86f366255fSPaolo Bonzini 	for (i = 0; i < len; i++) {
87f366255fSPaolo Bonzini 	    serial_outb(buf[i]);
88f366255fSPaolo Bonzini 	}
89f366255fSPaolo Bonzini #else
905edbb9aeSPaolo Bonzini 	asm volatile ("addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1));
91f366255fSPaolo Bonzini #endif
927d36db35SAvi Kivity }
937d36db35SAvi Kivity 
94*b5105e8bSPaolo Bonzini static void print_serial_u32(u32 value)
95*b5105e8bSPaolo Bonzini {
96*b5105e8bSPaolo Bonzini 	char n[12], *p;
97*b5105e8bSPaolo Bonzini 	p = &n[11];
98*b5105e8bSPaolo Bonzini 	*p = 0;
99*b5105e8bSPaolo Bonzini 	do {
100*b5105e8bSPaolo Bonzini 		*--p = '0' + (value % 10);
101*b5105e8bSPaolo Bonzini 		value /= 10;
102*b5105e8bSPaolo Bonzini 	} while (value > 0);
103*b5105e8bSPaolo Bonzini 	print_serial(p);
104*b5105e8bSPaolo Bonzini }
105*b5105e8bSPaolo Bonzini 
1067d36db35SAvi Kivity static void exit(int code)
1077d36db35SAvi Kivity {
108f366255fSPaolo Bonzini 	outb(code, 0xf4);
1097d36db35SAvi Kivity }
1107d36db35SAvi Kivity 
1117d36db35SAvi Kivity struct regs {
1127d36db35SAvi Kivity 	u32 eax, ebx, ecx, edx;
1137d36db35SAvi Kivity 	u32 esi, edi, esp, ebp;
1147d36db35SAvi Kivity 	u32 eip, eflags;
1157d36db35SAvi Kivity };
1167d36db35SAvi Kivity 
1177d36db35SAvi Kivity static u64 gdt[] = {
1187d36db35SAvi Kivity 	0,
1197d36db35SAvi Kivity 	0x00cf9b000000ffffull, // flat 32-bit code segment
1207d36db35SAvi Kivity 	0x00cf93000000ffffull, // flat 32-bit data segment
1217d36db35SAvi Kivity };
1227d36db35SAvi Kivity 
1237d36db35SAvi Kivity static struct {
1247d36db35SAvi Kivity 	u16 limit;
1257d36db35SAvi Kivity 	void *base;
1267d36db35SAvi Kivity } __attribute__((packed)) gdt_descr = {
1277d36db35SAvi Kivity 	sizeof(gdt) - 1,
1287d36db35SAvi Kivity 	gdt,
1297d36db35SAvi Kivity };
1307d36db35SAvi Kivity 
131d4dc402cSAvi Kivity struct insn_desc {
132d4dc402cSAvi Kivity     u16 ptr;
133d4dc402cSAvi Kivity     u16 len;
134d4dc402cSAvi Kivity };
135d4dc402cSAvi Kivity 
13618253fdeSAvi Kivity static struct regs inregs, outregs;
13718253fdeSAvi Kivity 
13818253fdeSAvi Kivity static void exec_in_big_real_mode(struct insn_desc *insn)
1397d36db35SAvi Kivity {
1407d36db35SAvi Kivity 	unsigned long tmp;
1417d36db35SAvi Kivity 	static struct regs save;
1427d36db35SAvi Kivity 	int i;
1437d36db35SAvi Kivity 	extern u8 test_insn[], test_insn_end[];
1447d36db35SAvi Kivity 
145d4dc402cSAvi Kivity 	for (i = 0; i < insn->len; ++i)
146d4dc402cSAvi Kivity 	    test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i];
1477d36db35SAvi Kivity 	for (; i < test_insn_end - test_insn; ++i)
1487d36db35SAvi Kivity 		test_insn[i] = 0x90; // nop
1497d36db35SAvi Kivity 
15018253fdeSAvi Kivity 	save = inregs;
1517d36db35SAvi Kivity 	asm volatile(
1527d36db35SAvi Kivity 		"lgdtl %[gdt_descr] \n\t"
1537d36db35SAvi Kivity 		"mov %%cr0, %[tmp] \n\t"
1547d36db35SAvi Kivity 		"or $1, %[tmp] \n\t"
1557d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
1567d36db35SAvi Kivity 		"mov %[bigseg], %%gs \n\t"
1577d36db35SAvi Kivity 		"and $-2, %[tmp] \n\t"
1587d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
1597d36db35SAvi Kivity 
16032001692SAvi Kivity                 "pushw %[save]+36; popfw \n\t"
1617d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
1627d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
1637d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
1647d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
1657d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
1667d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
1677d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
1687d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
1697d36db35SAvi Kivity 
1707d36db35SAvi Kivity 		"test_insn: . = . + 32\n\t"
1717d36db35SAvi Kivity 		"test_insn_end: \n\t"
1727d36db35SAvi Kivity 
1737d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
1747d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
1757d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
1767d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
1777d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
1787d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
1797d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
1807d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
1817d36db35SAvi Kivity 
1827d36db35SAvi Kivity 		/* Save EFLAGS in outregs*/
1837d36db35SAvi Kivity 		"pushfl \n\t"
1847d36db35SAvi Kivity 		"popl %[save]+36 \n\t"
1857d36db35SAvi Kivity 
1865edbb9aeSPaolo Bonzini 		/* Restore DF for the harness code */
1875edbb9aeSPaolo Bonzini 		"cld\n\t"
1887d36db35SAvi Kivity 		"xor %[tmp], %[tmp] \n\t"
1897d36db35SAvi Kivity 		"mov %[tmp], %%gs \n\t"
1907d36db35SAvi Kivity 		: [tmp]"=&r"(tmp), [save]"+m"(save)
1917d36db35SAvi Kivity 		: [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16)
1927d36db35SAvi Kivity 		: "cc", "memory"
1937d36db35SAvi Kivity 		);
19418253fdeSAvi Kivity 	outregs = save;
1957d36db35SAvi Kivity }
1967d36db35SAvi Kivity 
1977d36db35SAvi Kivity #define R_AX 1
1987d36db35SAvi Kivity #define R_BX 2
1997d36db35SAvi Kivity #define R_CX 4
2007d36db35SAvi Kivity #define R_DX 8
2017d36db35SAvi Kivity #define R_SI 16
2027d36db35SAvi Kivity #define R_DI 32
2037d36db35SAvi Kivity #define R_SP 64
2047d36db35SAvi Kivity #define R_BP 128
2057d36db35SAvi Kivity 
20618253fdeSAvi Kivity int regs_equal(int ignore)
2077d36db35SAvi Kivity {
20818253fdeSAvi Kivity 	const u32 *p1 = &inregs.eax, *p2 = &outregs.eax;  // yuck
2097d36db35SAvi Kivity 	int i;
2107d36db35SAvi Kivity 
2117d36db35SAvi Kivity 	for (i = 0; i < 8; ++i)
2127d36db35SAvi Kivity 		if (!(ignore & (1 << i)) && p1[i] != p2[i])
2137d36db35SAvi Kivity 			return 0;
2147d36db35SAvi Kivity 	return 1;
2157d36db35SAvi Kivity }
2167d36db35SAvi Kivity 
2176055ea1fSAvi Kivity static void report(const char *name, u16 regs_ignore, _Bool ok)
21881050840SAvi Kivity {
2196055ea1fSAvi Kivity     if (!regs_equal(regs_ignore)) {
2206055ea1fSAvi Kivity 	ok = 0;
2216055ea1fSAvi Kivity     }
22281050840SAvi Kivity     print_serial(ok ? "PASS: " : "FAIL: ");
22381050840SAvi Kivity     print_serial(name);
22481050840SAvi Kivity     print_serial("\n");
22581050840SAvi Kivity }
22681050840SAvi Kivity 
2277d36db35SAvi Kivity #define MK_INSN(name, str)				\
2287d36db35SAvi Kivity     asm (						\
229d4dc402cSAvi Kivity 	 ".pushsection .data.insn  \n\t"		\
230d4dc402cSAvi Kivity 	 "insn_" #name ": \n\t"				\
231d4dc402cSAvi Kivity 	 ".word 1001f, 1002f - 1001f \n\t"		\
232d4dc402cSAvi Kivity 	 ".popsection \n\t"				\
233d4dc402cSAvi Kivity 	 ".pushsection .text.insn, \"ax\" \n\t"		\
234d4dc402cSAvi Kivity 	 "1001: \n\t"					\
235d4dc402cSAvi Kivity 	 "insn_code_" #name ": " str " \n\t"		\
236d4dc402cSAvi Kivity 	 "1002: \n\t"					\
237d4dc402cSAvi Kivity 	 ".popsection"					\
2387d36db35SAvi Kivity     );							\
239d4dc402cSAvi Kivity     extern struct insn_desc insn_##name;
2407d36db35SAvi Kivity 
2417d36db35SAvi Kivity void test_xchg(void)
2427d36db35SAvi Kivity {
2437d36db35SAvi Kivity 	MK_INSN(xchg_test1, "xchg %eax,%eax\n\t");
2447d36db35SAvi Kivity 	MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t");
2457d36db35SAvi Kivity 	MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t");
2467d36db35SAvi Kivity 	MK_INSN(xchg_test4, "xchg %eax,%edx\n\t");
2477d36db35SAvi Kivity 	MK_INSN(xchg_test5, "xchg %eax,%esi\n\t");
2487d36db35SAvi Kivity 	MK_INSN(xchg_test6, "xchg %eax,%edi\n\t");
2497d36db35SAvi Kivity 	MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t");
2507d36db35SAvi Kivity 	MK_INSN(xchg_test8, "xchg %eax,%esp\n\t");
2517d36db35SAvi Kivity 
25218253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7};
2537d36db35SAvi Kivity 
25418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test1);
2556055ea1fSAvi Kivity 	report("xchg 1", 0, 1);
25618253fdeSAvi Kivity 
25718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test2);
2586055ea1fSAvi Kivity 	report("xchg 2", R_AX | R_BX,
2596055ea1fSAvi Kivity 	       outregs.eax == inregs.ebx && outregs.ebx == inregs.eax);
2607d36db35SAvi Kivity 
26118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test3);
2626055ea1fSAvi Kivity 	report("xchg 3", R_AX | R_CX,
2636055ea1fSAvi Kivity 	       outregs.eax == inregs.ecx && outregs.ecx == inregs.eax);
2647d36db35SAvi Kivity 
26518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test4);
2666055ea1fSAvi Kivity 	report("xchg 4", R_AX | R_DX,
2676055ea1fSAvi Kivity 	       outregs.eax == inregs.edx && outregs.edx == inregs.eax);
2687d36db35SAvi Kivity 
26918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test5);
2706055ea1fSAvi Kivity 	report("xchg 5", R_AX | R_SI,
2716055ea1fSAvi Kivity 	       outregs.eax == inregs.esi && outregs.esi == inregs.eax);
2727d36db35SAvi Kivity 
27318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test6);
2746055ea1fSAvi Kivity 	report("xchg 6", R_AX | R_DI,
2756055ea1fSAvi Kivity 	       outregs.eax == inregs.edi && outregs.edi == inregs.eax);
2767d36db35SAvi Kivity 
27718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test7);
2786055ea1fSAvi Kivity 	report("xchg 7", R_AX | R_BP,
2796055ea1fSAvi Kivity 	       outregs.eax == inregs.ebp && outregs.ebp == inregs.eax);
2807d36db35SAvi Kivity 
28118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test8);
2826055ea1fSAvi Kivity 	report("xchg 8", R_AX | R_SP,
2836055ea1fSAvi Kivity 	       outregs.eax == inregs.esp && outregs.esp == inregs.eax);
2847d36db35SAvi Kivity }
2857d36db35SAvi Kivity 
2867d36db35SAvi Kivity void test_shld(void)
2877d36db35SAvi Kivity {
2887d36db35SAvi Kivity 	MK_INSN(shld_test, "shld $8,%edx,%eax\n\t");
2897d36db35SAvi Kivity 
29018253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0xbe, .edx = 0xef000000 };
29118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_shld_test);
2926055ea1fSAvi Kivity 	report("shld", ~0, outregs.eax == 0xbeef);
2937d36db35SAvi Kivity }
2947d36db35SAvi Kivity 
2957d36db35SAvi Kivity void test_mov_imm(void)
2967d36db35SAvi Kivity {
2977d36db35SAvi Kivity 	MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax");
2987d36db35SAvi Kivity 	MK_INSN(mov_r16_imm_1, "mov $1234, %ax");
2997d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_1, "mov $0x12, %ah");
3007d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_2, "mov $0x34, %al");
3017d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t");
3027d36db35SAvi Kivity 
30318253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
30418253fdeSAvi Kivity 
30518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r16_imm_1);
3066055ea1fSAvi Kivity 	report("mov 1", R_AX, outregs.eax == 1234);
3077d36db35SAvi Kivity 
3087d36db35SAvi Kivity 	/* test mov $imm, %eax */
30918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r32_imm_1);
3106055ea1fSAvi Kivity 	report("mov 2", R_AX, outregs.eax == 1234567890);
3117d36db35SAvi Kivity 
3127d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
31318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_1);
3146055ea1fSAvi Kivity 	report("mov 3", R_AX, outregs.eax == 0x1200);
3157d36db35SAvi Kivity 
31618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_2);
3176055ea1fSAvi Kivity 	report("mov 4", R_AX, outregs.eax == 0x34);
3187d36db35SAvi Kivity 
31918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_3);
3206055ea1fSAvi Kivity 	report("mov 5", R_AX, outregs.eax == 0x1234);
3217d36db35SAvi Kivity }
3227d36db35SAvi Kivity 
3237d36db35SAvi Kivity void test_sub_imm(void)
3247d36db35SAvi Kivity {
3257d36db35SAvi Kivity 	MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t");
3267d36db35SAvi Kivity 	MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t");
3277d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t");
3287d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t");
3297d36db35SAvi Kivity 
33018253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
33118253fdeSAvi Kivity 
33218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r16_imm_1);
3336055ea1fSAvi Kivity 	report("sub 1", R_AX, outregs.eax == 1224);
3347d36db35SAvi Kivity 
3357d36db35SAvi Kivity 	/* test mov $imm, %eax */
33618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r32_imm_1);
3376055ea1fSAvi Kivity 	report("sub 2", R_AX, outregs.eax == 1234567880);
3387d36db35SAvi Kivity 
3397d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
34018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_1);
3416055ea1fSAvi Kivity 	report("sub 3", R_AX, outregs.eax == 0x0200);
3427d36db35SAvi Kivity 
34318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_2);
3446055ea1fSAvi Kivity 	report("sub 4", R_AX, outregs.eax == 0x24);
3457d36db35SAvi Kivity }
3467d36db35SAvi Kivity 
3477d36db35SAvi Kivity void test_xor_imm(void)
3487d36db35SAvi Kivity {
3497d36db35SAvi Kivity 	MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t");
3507d36db35SAvi Kivity 	MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t");
3517d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t");
3527d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t");
3537d36db35SAvi Kivity 
35418253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
35518253fdeSAvi Kivity 
35618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r16_imm_1);
3576055ea1fSAvi Kivity 	report("xor 1", R_AX, outregs.eax == 0);
3587d36db35SAvi Kivity 
3597d36db35SAvi Kivity 	/* test mov $imm, %eax */
36018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r32_imm_1);
3616055ea1fSAvi Kivity 	report("xor 2", R_AX, outregs.eax == 0);
3627d36db35SAvi Kivity 
3637d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
36418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_1);
3656055ea1fSAvi Kivity 	report("xor 3", R_AX, outregs.eax == 0);
3667d36db35SAvi Kivity 
36718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_2);
3686055ea1fSAvi Kivity 	report("xor 4", R_AX, outregs.eax == 0);
3697d36db35SAvi Kivity }
3707d36db35SAvi Kivity 
3717d36db35SAvi Kivity void test_cmp_imm(void)
3727d36db35SAvi Kivity {
3737d36db35SAvi Kivity 	MK_INSN(cmp_test1, "mov $0x34, %al\n\t"
3747d36db35SAvi Kivity 			   "cmp $0x34, %al\n\t");
3757d36db35SAvi Kivity 	MK_INSN(cmp_test2, "mov $0x34, %al\n\t"
3767d36db35SAvi Kivity 			   "cmp $0x39, %al\n\t");
3777d36db35SAvi Kivity 	MK_INSN(cmp_test3, "mov $0x34, %al\n\t"
3787d36db35SAvi Kivity 			   "cmp $0x24, %al\n\t");
3797d36db35SAvi Kivity 
38018253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
38118253fdeSAvi Kivity 
3827d36db35SAvi Kivity 	/* test cmp imm8 with AL */
3837d36db35SAvi Kivity 	/* ZF: (bit 6) Zero Flag becomes 1 if an operation results
3847d36db35SAvi Kivity 	 * in a 0 writeback, or 0 register
3857d36db35SAvi Kivity 	 */
38618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test1);
3876055ea1fSAvi Kivity 	report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6));
3887d36db35SAvi Kivity 
38918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test2);
3906055ea1fSAvi Kivity 	report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0);
3917d36db35SAvi Kivity 
39218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test3);
3936055ea1fSAvi Kivity 	report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0);
3947d36db35SAvi Kivity }
3957d36db35SAvi Kivity 
3967d36db35SAvi Kivity void test_add_imm(void)
3977d36db35SAvi Kivity {
3987d36db35SAvi Kivity 	MK_INSN(add_test1, "mov $0x43211234, %eax \n\t"
3997d36db35SAvi Kivity 			   "add $0x12344321, %eax \n\t");
4007d36db35SAvi Kivity 	MK_INSN(add_test2, "mov $0x12, %eax \n\t"
4017d36db35SAvi Kivity 			   "add $0x21, %al\n\t");
4027d36db35SAvi Kivity 
40318253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
40418253fdeSAvi Kivity 
40518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test1);
4066055ea1fSAvi Kivity 	report("add 1", ~0, outregs.eax == 0x55555555);
4077d36db35SAvi Kivity 
40818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test2);
4096055ea1fSAvi Kivity 	report("add 2", ~0, outregs.eax == 0x33);
4107d36db35SAvi Kivity }
4117d36db35SAvi Kivity 
4127d36db35SAvi Kivity void test_eflags_insn(void)
4137d36db35SAvi Kivity {
4147d36db35SAvi Kivity 	MK_INSN(clc, "clc");
415b3261e48SMohammed Gamal 	MK_INSN(stc, "stc");
4167d36db35SAvi Kivity 	MK_INSN(cli, "cli");
4177d36db35SAvi Kivity 	MK_INSN(sti, "sti");
4187d36db35SAvi Kivity 	MK_INSN(cld, "cld");
4197d36db35SAvi Kivity 	MK_INSN(std, "std");
4207d36db35SAvi Kivity 
42118253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
42218253fdeSAvi Kivity 
42318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_clc);
4246055ea1fSAvi Kivity 	report("clc", ~0, (outregs.eflags & 1) == 0);
4257d36db35SAvi Kivity 
42618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_stc);
4276055ea1fSAvi Kivity 	report("stc", ~0, (outregs.eflags & 1) == 1);
428b3261e48SMohammed Gamal 
42918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cli);
4306055ea1fSAvi Kivity 	report("cli", ~0, !(outregs.eflags & (1 << 9)));
4317d36db35SAvi Kivity 
43218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sti);
4336055ea1fSAvi Kivity 	report("sti", ~0, outregs.eflags & (1 << 9));
4347d36db35SAvi Kivity 
43518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cld);
4366055ea1fSAvi Kivity 	report("cld", ~0, !(outregs.eflags & (1 << 10)));
4377d36db35SAvi Kivity 
43818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_std);
4396055ea1fSAvi Kivity 	report("std", ~0, (outregs.eflags & (1 << 10)));
4407d36db35SAvi Kivity }
4417d36db35SAvi Kivity 
4427d36db35SAvi Kivity void test_io(void)
4437d36db35SAvi Kivity {
4447d36db35SAvi Kivity 	MK_INSN(io_test1, "mov $0xff, %al \n\t"
4457d36db35SAvi Kivity 		          "out %al, $0xe0 \n\t"
4467d36db35SAvi Kivity 		          "mov $0x00, %al \n\t"
4477d36db35SAvi Kivity 			  "in $0xe0, %al \n\t");
4487d36db35SAvi Kivity 	MK_INSN(io_test2, "mov $0xffff, %ax \n\t"
4497d36db35SAvi Kivity 			  "out %ax, $0xe0 \n\t"
4507d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
4517d36db35SAvi Kivity 			  "in $0xe0, %ax \n\t");
4527d36db35SAvi Kivity 	MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t"
4537d36db35SAvi Kivity 			  "out %eax, $0xe0 \n\t"
4547d36db35SAvi Kivity 			  "mov $0x000000, %eax \n\t"
4557d36db35SAvi Kivity 			  "in $0xe0, %eax \n\t");
4567d36db35SAvi Kivity 	MK_INSN(io_test4, "mov $0xe0, %dx \n\t"
4577d36db35SAvi Kivity 			  "mov $0xff, %al \n\t"
4587d36db35SAvi Kivity 			  "out %al, %dx \n\t"
4597d36db35SAvi Kivity 			  "mov $0x00, %al \n\t"
4607d36db35SAvi Kivity 			  "in %dx, %al \n\t");
4617d36db35SAvi Kivity 	MK_INSN(io_test5, "mov $0xe0, %dx \n\t"
4627d36db35SAvi Kivity 			  "mov $0xffff, %ax \n\t"
4637d36db35SAvi Kivity 			  "out %ax, %dx \n\t"
4647d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
4657d36db35SAvi Kivity 			  "in %dx, %ax \n\t");
4667d36db35SAvi Kivity 	MK_INSN(io_test6, "mov $0xe0, %dx \n\t"
4677d36db35SAvi Kivity 			  "mov $0xffffffff, %eax \n\t"
4687d36db35SAvi Kivity 			  "out %eax, %dx \n\t"
4697d36db35SAvi Kivity 			  "mov $0x00000000, %eax \n\t"
4707d36db35SAvi Kivity 			  "in %dx, %eax \n\t");
4717d36db35SAvi Kivity 
47218253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
47318253fdeSAvi Kivity 
47418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test1);
4756055ea1fSAvi Kivity 	report("pio 1", R_AX, outregs.eax == 0xff);
4767d36db35SAvi Kivity 
47718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test2);
4786055ea1fSAvi Kivity 	report("pio 2", R_AX, outregs.eax == 0xffff);
4797d36db35SAvi Kivity 
48018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test3);
4816055ea1fSAvi Kivity 	report("pio 3", R_AX, outregs.eax == 0xffffffff);
4827d36db35SAvi Kivity 
48318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test4);
4846055ea1fSAvi Kivity 	report("pio 4", R_AX|R_DX, outregs.eax == 0xff);
4857d36db35SAvi Kivity 
48618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test5);
4876055ea1fSAvi Kivity 	report("pio 5", R_AX|R_DX, outregs.eax == 0xffff);
4887d36db35SAvi Kivity 
48918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test6);
4906055ea1fSAvi Kivity 	report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff);
4917d36db35SAvi Kivity }
4927d36db35SAvi Kivity 
493c0b7268dSAvi Kivity asm ("retf: lretw");
494c0b7268dSAvi Kivity extern void retf();
495c0b7268dSAvi Kivity 
4964f66bc86SBruce Rogers asm ("retf_imm: lretw $10");
4974f66bc86SBruce Rogers extern void retf_imm();
4984f66bc86SBruce Rogers 
4997d36db35SAvi Kivity void test_call(void)
5007d36db35SAvi Kivity {
5017d36db35SAvi Kivity 	u32 esp[16];
502c0b7268dSAvi Kivity 	u32 addr;
5037d36db35SAvi Kivity 
50418253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
5057d36db35SAvi Kivity 	inregs.esp = (u32)esp;
5067d36db35SAvi Kivity 
5077d36db35SAvi Kivity 	MK_INSN(call1, "mov $test_function, %eax \n\t"
5087d36db35SAvi Kivity 		       "call *%eax\n\t");
5097d36db35SAvi Kivity 	MK_INSN(call_near1, "jmp 2f\n\t"
5107d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5117d36db35SAvi Kivity 			    "ret\n\t"
5127d36db35SAvi Kivity 			    "2: call 1b\t");
5137d36db35SAvi Kivity 	MK_INSN(call_near2, "call 1f\n\t"
5147d36db35SAvi Kivity 			    "jmp 2f\n\t"
5157d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5167d36db35SAvi Kivity 			    "ret\n\t"
5177d36db35SAvi Kivity 			    "2:\t");
518c0b7268dSAvi Kivity 	MK_INSN(call_far1,  "lcallw *(%ebx)\n\t");
519556d2680SWei Yongjun 	MK_INSN(call_far2,  "lcallw $0, $retf\n\t");
520c6061817SAvi Kivity 	MK_INSN(ret_imm,    "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b");
5214f66bc86SBruce Rogers 	MK_INSN(retf_imm,   "sub $10, %sp; lcallw $0, $retf_imm");
5227d36db35SAvi Kivity 
52318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call1);
5246055ea1fSAvi Kivity 	report("call 1", R_AX, outregs.eax == 0x1234);
5257d36db35SAvi Kivity 
52618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near1);
5276055ea1fSAvi Kivity 	report("call near 1", R_AX, outregs.eax == 0x1234);
5287d36db35SAvi Kivity 
52918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near2);
5306055ea1fSAvi Kivity 	report("call near 2", R_AX, outregs.eax == 0x1234);
531c0b7268dSAvi Kivity 
532c0b7268dSAvi Kivity 	addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f);
533c0b7268dSAvi Kivity 	inregs.ebx = (unsigned)&addr;
53418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_far1);
5356055ea1fSAvi Kivity 	report("call far 1", 0, 1);
536c6061817SAvi Kivity 
537556d2680SWei Yongjun 	exec_in_big_real_mode(&insn_call_far2);
538556d2680SWei Yongjun 	report("call far 2", 0, 1);
539556d2680SWei Yongjun 
54018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_ret_imm);
5416055ea1fSAvi Kivity 	report("ret imm 1", 0, 1);
5424f66bc86SBruce Rogers 
5434f66bc86SBruce Rogers 	exec_in_big_real_mode(&insn_retf_imm);
5444f66bc86SBruce Rogers 	report("retf imm 1", 0, 1);
5457d36db35SAvi Kivity }
5467d36db35SAvi Kivity 
5477d36db35SAvi Kivity void test_jcc_short(void)
5487d36db35SAvi Kivity {
5497d36db35SAvi Kivity 	MK_INSN(jnz_short1, "jnz 1f\n\t"
5507d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
5517d36db35SAvi Kivity 		            "1:\n\t");
5527d36db35SAvi Kivity 	MK_INSN(jnz_short2, "1:\n\t"
5537d36db35SAvi Kivity 			    "cmp $0x1234, %eax\n\t"
5547d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
5557d36db35SAvi Kivity 		            "jnz 1b\n\t");
5567d36db35SAvi Kivity 	MK_INSN(jmp_short1, "jmp 1f\n\t"
5577d36db35SAvi Kivity 		      "mov $0x1234, %eax\n\t"
5587d36db35SAvi Kivity 		      "1:\n\t");
5597d36db35SAvi Kivity 
56018253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
5617d36db35SAvi Kivity 
56218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short1);
5636055ea1fSAvi Kivity 	report("jnz short 1", ~0, 1);
56418253fdeSAvi Kivity 
56518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short2);
5666055ea1fSAvi Kivity 	report("jnz short 2", R_AX, (outregs.eflags & (1 << 6)));
5677d36db35SAvi Kivity 
56818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_short1);
5696055ea1fSAvi Kivity 	report("jmp short 1", ~0, 1);
5707d36db35SAvi Kivity }
5717d36db35SAvi Kivity 
5727d36db35SAvi Kivity void test_jcc_near(void)
5737d36db35SAvi Kivity {
5747d36db35SAvi Kivity 	/* encode near jmp manually. gas will not do it if offsets < 127 byte */
5757d36db35SAvi Kivity 	MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t"
5767d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
5777d36db35SAvi Kivity 	MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t"
5787d36db35SAvi Kivity 			   "mov $0x1234, %eax\n\t"
5797d36db35SAvi Kivity 		           ".byte 0x0f, 0x85, 0xf0, 0xff\n\t");
5807d36db35SAvi Kivity 	MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t"
5817d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
5827d36db35SAvi Kivity 
58318253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
5847d36db35SAvi Kivity 
58518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near1);
5866055ea1fSAvi Kivity 	report("jnz near 1", 0, 1);
58718253fdeSAvi Kivity 
58818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near2);
5896055ea1fSAvi Kivity 	report("jnz near 2", R_AX, outregs.eflags & (1 << 6));
5907d36db35SAvi Kivity 
59118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_near1);
5926055ea1fSAvi Kivity 	report("jmp near 1", 0, 1);
5937d36db35SAvi Kivity }
5947d36db35SAvi Kivity 
5957d36db35SAvi Kivity void test_long_jmp()
5967d36db35SAvi Kivity {
5977d36db35SAvi Kivity 	u32 esp[16];
5987d36db35SAvi Kivity 
59918253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
6004aa22949SAvi Kivity 	inregs.esp = (u32)(esp+16);
6017d36db35SAvi Kivity 	MK_INSN(long_jmp, "call 1f\n\t"
6027d36db35SAvi Kivity 			  "jmp 2f\n\t"
6037d36db35SAvi Kivity 			  "1: jmp $0, $test_function\n\t"
6047d36db35SAvi Kivity 		          "2:\n\t");
60518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_long_jmp);
6066055ea1fSAvi Kivity 	report("jmp far 1", R_AX, outregs.eax == 0x1234);
6077d36db35SAvi Kivity }
608fa74f8a6SMohammed Gamal 
6097d36db35SAvi Kivity void test_push_pop()
6107d36db35SAvi Kivity {
6117d36db35SAvi Kivity 	MK_INSN(push32, "mov $0x12345678, %eax\n\t"
6127d36db35SAvi Kivity 			"push %eax\n\t"
6137d36db35SAvi Kivity 			"pop %ebx\n\t");
6147d36db35SAvi Kivity 	MK_INSN(push16, "mov $0x1234, %ax\n\t"
6157d36db35SAvi Kivity 			"push %ax\n\t"
6167d36db35SAvi Kivity 			"pop %bx\n\t");
6177d36db35SAvi Kivity 
6187d36db35SAvi Kivity 	MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten
6197d36db35SAvi Kivity 			 "mov $0x123, %ax\n\t"
6207d36db35SAvi Kivity 			 "mov %ax, %es\n\t"
6217d36db35SAvi Kivity 			 "push %es\n\t"
6227d36db35SAvi Kivity 			 "pop %bx \n\t"
6237d36db35SAvi Kivity 			 );
6247d36db35SAvi Kivity 	MK_INSN(pop_es, "push %ax\n\t"
6257d36db35SAvi Kivity 			"pop %es\n\t"
6267d36db35SAvi Kivity 			"mov %es, %bx\n\t"
6277d36db35SAvi Kivity 			);
6287d36db35SAvi Kivity 	MK_INSN(push_pop_ss, "push %ss\n\t"
6297d36db35SAvi Kivity 			     "pushw %ax\n\t"
6307d36db35SAvi Kivity 			     "popw %ss\n\t"
6317d36db35SAvi Kivity 			     "mov %ss, %bx\n\t"
6327d36db35SAvi Kivity 			     "pop %ss\n\t"
6337d36db35SAvi Kivity 			);
6347d36db35SAvi Kivity 	MK_INSN(push_pop_fs, "push %fs\n\t"
6357d36db35SAvi Kivity 			     "pushl %eax\n\t"
6367d36db35SAvi Kivity 			     "popl %fs\n\t"
6377d36db35SAvi Kivity 			     "mov %fs, %ebx\n\t"
6387d36db35SAvi Kivity 			     "pop %fs\n\t"
6397d36db35SAvi Kivity 			);
64009b657b6SAvi Kivity 	MK_INSN(push_pop_high_esp_bits,
64109b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
64209b657b6SAvi Kivity 		"push %ax; \n\t"
64309b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
64409b657b6SAvi Kivity 		"pop %bx");
6457d36db35SAvi Kivity 
64618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
64718253fdeSAvi Kivity 
64818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push32);
6496055ea1fSAvi Kivity 	report("push/pop 1", R_AX|R_BX,
6506055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x12345678);
6517d36db35SAvi Kivity 
65218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push16);
6536055ea1fSAvi Kivity 	report("push/pop 2", R_AX|R_BX,
6546055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x1234);
6557d36db35SAvi Kivity 
65618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_es);
6576055ea1fSAvi Kivity 	report("push/pop 3", R_AX|R_BX,
6586055ea1fSAvi Kivity 	       outregs.ebx == outregs.eax && outregs.eax == 0x123);
6597d36db35SAvi Kivity 
66018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pop_es);
6616055ea1fSAvi Kivity 	report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax);
6627d36db35SAvi Kivity 
66318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_ss);
6646055ea1fSAvi Kivity 	report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax);
6657d36db35SAvi Kivity 
66618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_fs);
6676055ea1fSAvi Kivity 	report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax);
66809b657b6SAvi Kivity 
66909b657b6SAvi Kivity 	inregs.eax = 0x9977;
67009b657b6SAvi Kivity 	inregs.ebx = 0x7799;
67109b657b6SAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_high_esp_bits);
67209b657b6SAvi Kivity 	report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977);
6737d36db35SAvi Kivity }
6747d36db35SAvi Kivity 
6757d36db35SAvi Kivity void test_null(void)
6767d36db35SAvi Kivity {
677d4dc402cSAvi Kivity 	MK_INSN(null, "");
678d4dc402cSAvi Kivity 
67918253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
68018253fdeSAvi Kivity 
68118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_null);
6826055ea1fSAvi Kivity 	report("null", 0, 1);
6837d36db35SAvi Kivity }
6847d36db35SAvi Kivity 
6857d36db35SAvi Kivity struct {
6867d36db35SAvi Kivity     char stack[500];
6877d36db35SAvi Kivity     char top[];
6887d36db35SAvi Kivity } tmp_stack;
6897d36db35SAvi Kivity 
6907d36db35SAvi Kivity void test_pusha_popa()
6917d36db35SAvi Kivity {
6927d36db35SAvi Kivity 	MK_INSN(pusha, "pusha\n\t"
6937d36db35SAvi Kivity 		       "pop %edi\n\t"
6947d36db35SAvi Kivity 		       "pop %esi\n\t"
6957d36db35SAvi Kivity 		       "pop %ebp\n\t"
6967d36db35SAvi Kivity 		       "add $4, %esp\n\t"
6977d36db35SAvi Kivity 		       "pop %ebx\n\t"
6987d36db35SAvi Kivity 		       "pop %edx\n\t"
6997d36db35SAvi Kivity 		       "pop %ecx\n\t"
7007d36db35SAvi Kivity 		       "pop %eax\n\t"
7017d36db35SAvi Kivity 		       );
7027d36db35SAvi Kivity 
7037d36db35SAvi Kivity 	MK_INSN(popa, "push %eax\n\t"
7047d36db35SAvi Kivity 		      "push %ecx\n\t"
7057d36db35SAvi Kivity 		      "push %edx\n\t"
7067d36db35SAvi Kivity 		      "push %ebx\n\t"
7077d36db35SAvi Kivity 		      "push %esp\n\t"
7087d36db35SAvi Kivity 		      "push %ebp\n\t"
7097d36db35SAvi Kivity 		      "push %esi\n\t"
7107d36db35SAvi Kivity 		      "push %edi\n\t"
7117d36db35SAvi Kivity 		      "popa\n\t"
7127d36db35SAvi Kivity 		      );
7137d36db35SAvi Kivity 
71418253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top };
7157d36db35SAvi Kivity 
71618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pusha);
7176055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
71818253fdeSAvi Kivity 
71918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_popa);
7206055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
7217d36db35SAvi Kivity }
7227d36db35SAvi Kivity 
7237d36db35SAvi Kivity void test_iret()
7247d36db35SAvi Kivity {
7257d36db35SAvi Kivity 	MK_INSN(iret32, "pushf\n\t"
7267d36db35SAvi Kivity 			"pushl %cs\n\t"
7277d36db35SAvi Kivity 			"call 1f\n\t" /* a near call will push eip onto the stack */
7287d36db35SAvi Kivity 			"jmp 2f\n\t"
7297d36db35SAvi Kivity 			"1: iret\n\t"
7307d36db35SAvi Kivity 			"2:\n\t"
7317d36db35SAvi Kivity 		     );
7327d36db35SAvi Kivity 
7337d36db35SAvi Kivity 	MK_INSN(iret16, "pushfw\n\t"
7347d36db35SAvi Kivity 			"pushw %cs\n\t"
7357d36db35SAvi Kivity 			"callw 1f\n\t"
7367d36db35SAvi Kivity 			"jmp 2f\n\t"
7377d36db35SAvi Kivity 			"1: iretw\n\t"
7387d36db35SAvi Kivity 			"2:\n\t");
7397d36db35SAvi Kivity 
7407d36db35SAvi Kivity 	MK_INSN(iret_flags32, "pushfl\n\t"
7417d36db35SAvi Kivity 			      "popl %eax\n\t"
7427d36db35SAvi Kivity 			      "andl $~0x2, %eax\n\t"
7437d36db35SAvi Kivity 			      "orl $0xffc08028, %eax\n\t"
7447d36db35SAvi Kivity 			      "pushl %eax\n\t"
7457d36db35SAvi Kivity 			      "pushl %cs\n\t"
7467d36db35SAvi Kivity 			      "call 1f\n\t"
7477d36db35SAvi Kivity 			      "jmp 2f\n\t"
7487d36db35SAvi Kivity 			      "1: iret\n\t"
7497d36db35SAvi Kivity 			      "2:\n\t");
7507d36db35SAvi Kivity 
7517d36db35SAvi Kivity 	MK_INSN(iret_flags16, "pushfw\n\t"
7527d36db35SAvi Kivity 			      "popw %ax\n\t"
7537d36db35SAvi Kivity 			      "and $~0x2, %ax\n\t"
7547d36db35SAvi Kivity 			      "or $0x8028, %ax\n\t"
7557d36db35SAvi Kivity 			      "pushw %ax\n\t"
7567d36db35SAvi Kivity 			      "pushw %cs\n\t"
7577d36db35SAvi Kivity 			      "callw 1f\n\t"
7587d36db35SAvi Kivity 			      "jmp 2f\n\t"
7597d36db35SAvi Kivity 			      "1: iretw\n\t"
7607d36db35SAvi Kivity 			      "2:\n\t");
7617d36db35SAvi Kivity 
76218253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
7637d36db35SAvi Kivity 
76418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret32);
7656055ea1fSAvi Kivity 	report("iret 1", 0, 1);
7667d36db35SAvi Kivity 
76718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret16);
7686055ea1fSAvi Kivity 	report("iret 2", 0, 1);
7697d36db35SAvi Kivity 
77018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags32);
7716055ea1fSAvi Kivity 	report("iret 3", R_AX, 1);
77218253fdeSAvi Kivity 
77318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags16);
7746055ea1fSAvi Kivity 	report("iret 4", R_AX, 1);
7757d36db35SAvi Kivity }
7767d36db35SAvi Kivity 
77796b9ca1eSMohammed Gamal void test_int()
77896b9ca1eSMohammed Gamal {
77918253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
78096b9ca1eSMohammed Gamal 
78196b9ca1eSMohammed Gamal 	*(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */
78296b9ca1eSMohammed Gamal 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
78396b9ca1eSMohammed Gamal 
78496b9ca1eSMohammed Gamal 	MK_INSN(int11, "int $0x11\n\t");
78596b9ca1eSMohammed Gamal 
78618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_int11);
7876055ea1fSAvi Kivity 	report("int 1", 0, 1);
78896b9ca1eSMohammed Gamal }
78996b9ca1eSMohammed Gamal 
790fa74f8a6SMohammed Gamal void test_imul()
791fa74f8a6SMohammed Gamal {
792fa74f8a6SMohammed Gamal 	MK_INSN(imul8_1, "mov $2, %al\n\t"
793fa74f8a6SMohammed Gamal 			"mov $-4, %cx\n\t"
794fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
795fa74f8a6SMohammed Gamal 
796fa74f8a6SMohammed Gamal 	MK_INSN(imul16_1, "mov $2, %ax\n\t"
797fa74f8a6SMohammed Gamal 		      "mov $-4, %cx\n\t"
798fa74f8a6SMohammed Gamal 		      "imul %cx\n\t");
799fa74f8a6SMohammed Gamal 
800fa74f8a6SMohammed Gamal 	MK_INSN(imul32_1, "mov $2, %eax\n\t"
801fa74f8a6SMohammed Gamal 		       "mov $-4, %ecx\n\t"
802fa74f8a6SMohammed Gamal 		       "imul %ecx\n\t");
803fa74f8a6SMohammed Gamal 
804fa74f8a6SMohammed Gamal 	MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t"
805fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
806fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
807fa74f8a6SMohammed Gamal 
808fa74f8a6SMohammed Gamal 	MK_INSN(imul16_2, "mov $2, %ax\n\t"
809fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
810fa74f8a6SMohammed Gamal 			"imul %cx\n\t");
811fa74f8a6SMohammed Gamal 
812fa74f8a6SMohammed Gamal 	MK_INSN(imul32_2, "mov $2, %eax\n\t"
813fa74f8a6SMohammed Gamal 			"mov $4, %ecx\n\t"
814fa74f8a6SMohammed Gamal 			"imul %ecx\n\t");
815fa74f8a6SMohammed Gamal 
81618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
81718253fdeSAvi Kivity 
81818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_1);
8196055ea1fSAvi Kivity 	report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8);
820fa74f8a6SMohammed Gamal 
82118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_1);
8226055ea1fSAvi Kivity 	report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8);
823fa74f8a6SMohammed Gamal 
82418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_1);
8256055ea1fSAvi Kivity 	report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8);
826fa74f8a6SMohammed Gamal 
82718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_2);
8286055ea1fSAvi Kivity 	report("imul 4", R_AX | R_CX | R_DX,
8296055ea1fSAvi Kivity 	       (outregs.eax & 0xffff) == 8
83081050840SAvi Kivity 	       && (outregs.eax & 0xffff0000) == 0x12340000);
831fa74f8a6SMohammed Gamal 
83218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_2);
8336055ea1fSAvi Kivity 	report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8);
834fa74f8a6SMohammed Gamal 
83518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_2);
8366055ea1fSAvi Kivity 	report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8);
837fa74f8a6SMohammed Gamal }
838fa74f8a6SMohammed Gamal 
83959317bd1SMohammed Gamal void test_mul()
84059317bd1SMohammed Gamal {
84159317bd1SMohammed Gamal 	MK_INSN(mul8, "mov $2, %al\n\t"
84259317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
84359317bd1SMohammed Gamal 			"imul %cl\n\t");
84459317bd1SMohammed Gamal 
84559317bd1SMohammed Gamal 	MK_INSN(mul16, "mov $2, %ax\n\t"
84659317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
84759317bd1SMohammed Gamal 			"imul %cx\n\t");
84859317bd1SMohammed Gamal 
84959317bd1SMohammed Gamal 	MK_INSN(mul32, "mov $2, %eax\n\t"
85059317bd1SMohammed Gamal 			"mov $4, %ecx\n\t"
85159317bd1SMohammed Gamal 			"imul %ecx\n\t");
85259317bd1SMohammed Gamal 
85318253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
85418253fdeSAvi Kivity 
85518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul8);
8566055ea1fSAvi Kivity 	report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8);
85759317bd1SMohammed Gamal 
85818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul16);
8596055ea1fSAvi Kivity 	report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8);
86059317bd1SMohammed Gamal 
86118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul32);
8626055ea1fSAvi Kivity 	report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8);
86359317bd1SMohammed Gamal }
86459317bd1SMohammed Gamal 
8650d4c7614SMohammed Gamal void test_div()
8660d4c7614SMohammed Gamal {
8670d4c7614SMohammed Gamal 	MK_INSN(div8, "mov $257, %ax\n\t"
8680d4c7614SMohammed Gamal 			"mov $2, %cl\n\t"
8690d4c7614SMohammed Gamal 			"div %cl\n\t");
8700d4c7614SMohammed Gamal 
8710d4c7614SMohammed Gamal 	MK_INSN(div16, "mov $512, %ax\n\t"
8720d4c7614SMohammed Gamal 			"mov $5, %cx\n\t"
8730d4c7614SMohammed Gamal 			"div %cx\n\t");
8740d4c7614SMohammed Gamal 
8750d4c7614SMohammed Gamal 	MK_INSN(div32, "mov $512, %eax\n\t"
8760d4c7614SMohammed Gamal 			"mov $5, %ecx\n\t"
8770d4c7614SMohammed Gamal 			"div %ecx\n\t");
8780d4c7614SMohammed Gamal 
87918253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
88018253fdeSAvi Kivity 
88118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div8);
8826055ea1fSAvi Kivity 	report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384);
8830d4c7614SMohammed Gamal 
88418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div16);
8856055ea1fSAvi Kivity 	report("div 2", R_AX | R_CX | R_DX,
8866055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
8870d4c7614SMohammed Gamal 
88818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div32);
8896055ea1fSAvi Kivity 	report("div 3", R_AX | R_CX | R_DX,
8906055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
8910d4c7614SMohammed Gamal }
8920d4c7614SMohammed Gamal 
8930d4c7614SMohammed Gamal void test_idiv()
8940d4c7614SMohammed Gamal {
8950d4c7614SMohammed Gamal 	MK_INSN(idiv8, "mov $256, %ax\n\t"
8960d4c7614SMohammed Gamal 			"mov $-2, %cl\n\t"
8970d4c7614SMohammed Gamal 			"idiv %cl\n\t");
8980d4c7614SMohammed Gamal 
8990d4c7614SMohammed Gamal 	MK_INSN(idiv16, "mov $512, %ax\n\t"
9000d4c7614SMohammed Gamal 			"mov $-2, %cx\n\t"
9010d4c7614SMohammed Gamal 			"idiv %cx\n\t");
9020d4c7614SMohammed Gamal 
9030d4c7614SMohammed Gamal 	MK_INSN(idiv32, "mov $512, %eax\n\t"
9040d4c7614SMohammed Gamal 			"mov $-2, %ecx\n\t"
9050d4c7614SMohammed Gamal 			"idiv %ecx\n\t");
9060d4c7614SMohammed Gamal 
90718253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
90818253fdeSAvi Kivity 
90918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv8);
9106055ea1fSAvi Kivity 	report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128);
9110d4c7614SMohammed Gamal 
91218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv16);
9136055ea1fSAvi Kivity 	report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256);
9140d4c7614SMohammed Gamal 
91518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv32);
9166055ea1fSAvi Kivity 	report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256);
9170d4c7614SMohammed Gamal }
9180d4c7614SMohammed Gamal 
9196e293cf5SWei Yongjun void test_cbw(void)
9206e293cf5SWei Yongjun {
9216e293cf5SWei Yongjun 	MK_INSN(cbw, "mov $0xFE, %eax \n\t"
9226e293cf5SWei Yongjun 		     "cbw\n\t");
9236e293cf5SWei Yongjun 	MK_INSN(cwde, "mov $0xFFFE, %eax \n\t"
9246e293cf5SWei Yongjun 		      "cwde\n\t");
9256e293cf5SWei Yongjun 
92618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
92718253fdeSAvi Kivity 
92818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cbw);
9296055ea1fSAvi Kivity 	report("cbq 1", ~0, outregs.eax == 0xFFFE);
9306e293cf5SWei Yongjun 
93118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwde);
9326055ea1fSAvi Kivity 	report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE);
9336e293cf5SWei Yongjun }
9346e293cf5SWei Yongjun 
935eacef4e2SWei Yongjun void test_loopcc(void)
936eacef4e2SWei Yongjun {
937eacef4e2SWei Yongjun 	MK_INSN(loop, "mov $10, %ecx\n\t"
938eacef4e2SWei Yongjun 		      "1: inc %eax\n\t"
939eacef4e2SWei Yongjun 		      "loop 1b\n\t");
940eacef4e2SWei Yongjun 
941eacef4e2SWei Yongjun 	MK_INSN(loope, "mov $10, %ecx\n\t"
942eacef4e2SWei Yongjun 		       "mov $1, %eax\n\t"
943eacef4e2SWei Yongjun 		       "1: dec %eax\n\t"
944eacef4e2SWei Yongjun 		       "loope 1b\n\t");
945eacef4e2SWei Yongjun 
946eacef4e2SWei Yongjun 	MK_INSN(loopne, "mov $10, %ecx\n\t"
947eacef4e2SWei Yongjun 		        "mov $5, %eax\n\t"
948eacef4e2SWei Yongjun 		        "1: dec %eax\n\t"
949eacef4e2SWei Yongjun 			"loopne 1b\n\t");
950eacef4e2SWei Yongjun 
95118253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
952eacef4e2SWei Yongjun 
95318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loop);
9546055ea1fSAvi Kivity 	report("LOOPcc short 1", R_AX, outregs.eax == 10);
95518253fdeSAvi Kivity 
95618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loope);
9576055ea1fSAvi Kivity 	report("LOOPcc short 2", R_AX | R_CX,
9586055ea1fSAvi Kivity 	       outregs.eax == -1 && outregs.ecx == 8);
959eacef4e2SWei Yongjun 
96018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loopne);
9616055ea1fSAvi Kivity 	report("LOOPcc short 3", R_AX | R_CX,
9626055ea1fSAvi Kivity 	       outregs.eax == 0 && outregs.ecx == 5);
963eacef4e2SWei Yongjun }
964eacef4e2SWei Yongjun 
965b274feedSAvi Kivity static void test_das(void)
966b274feedSAvi Kivity {
967b274feedSAvi Kivity     short i;
96881050840SAvi Kivity     u16 nr_fail = 0;
969b274feedSAvi Kivity     static unsigned test_cases[1024] = {
970b274feedSAvi Kivity         0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00,
971b274feedSAvi Kivity         0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01,
972b274feedSAvi Kivity         0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02,
973b274feedSAvi Kivity         0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03,
974b274feedSAvi Kivity         0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04,
975b274feedSAvi Kivity         0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05,
976b274feedSAvi Kivity         0x06000606, 0x8701a606, 0x56100006, 0x9711a006,
977b274feedSAvi Kivity         0x02000707, 0x8301a707, 0x12100107, 0x9311a107,
978b274feedSAvi Kivity         0x02000808, 0x8301a808, 0x12100208, 0x9311a208,
979b274feedSAvi Kivity         0x06000909, 0x8701a909, 0x16100309, 0x9711a309,
980b274feedSAvi Kivity         0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a,
981b274feedSAvi Kivity         0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b,
982b274feedSAvi Kivity         0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c,
983b274feedSAvi Kivity         0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d,
984b274feedSAvi Kivity         0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e,
985b274feedSAvi Kivity         0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f,
986b274feedSAvi Kivity         0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10,
987b274feedSAvi Kivity         0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11,
988b274feedSAvi Kivity         0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12,
989b274feedSAvi Kivity         0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13,
990b274feedSAvi Kivity         0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14,
991b274feedSAvi Kivity         0x02001515, 0x8301b515, 0x16100f15, 0x9711af15,
992b274feedSAvi Kivity         0x02001616, 0x8301b616, 0x12101016, 0x9311b016,
993b274feedSAvi Kivity         0x06001717, 0x8701b717, 0x16101117, 0x9711b117,
994b274feedSAvi Kivity         0x06001818, 0x8701b818, 0x16101218, 0x9711b218,
995b274feedSAvi Kivity         0x02001919, 0x8301b919, 0x12101319, 0x9311b319,
996b274feedSAvi Kivity         0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a,
997b274feedSAvi Kivity         0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b,
998b274feedSAvi Kivity         0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c,
999b274feedSAvi Kivity         0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d,
1000b274feedSAvi Kivity         0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e,
1001b274feedSAvi Kivity         0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f,
1002b274feedSAvi Kivity         0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20,
1003b274feedSAvi Kivity         0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21,
1004b274feedSAvi Kivity         0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22,
1005b274feedSAvi Kivity         0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23,
1006b274feedSAvi Kivity         0x06002424, 0x8301c424, 0x16101e24, 0x9711be24,
1007b274feedSAvi Kivity         0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25,
1008b274feedSAvi Kivity         0x02002626, 0x8701c626, 0x12102026, 0x9711c026,
1009b274feedSAvi Kivity         0x06002727, 0x8301c727, 0x16102127, 0x9311c127,
1010b274feedSAvi Kivity         0x06002828, 0x8301c828, 0x16102228, 0x9311c228,
1011b274feedSAvi Kivity         0x02002929, 0x8701c929, 0x12102329, 0x9711c329,
1012b274feedSAvi Kivity         0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a,
1013b274feedSAvi Kivity         0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b,
1014b274feedSAvi Kivity         0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c,
1015b274feedSAvi Kivity         0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d,
1016b274feedSAvi Kivity         0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e,
1017b274feedSAvi Kivity         0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f,
1018b274feedSAvi Kivity         0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30,
1019b274feedSAvi Kivity         0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31,
1020b274feedSAvi Kivity         0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32,
1021b274feedSAvi Kivity         0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33,
1022b274feedSAvi Kivity         0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34,
1023b274feedSAvi Kivity         0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35,
1024b274feedSAvi Kivity         0x06003636, 0x8301d636, 0x16103036, 0x9311d036,
1025b274feedSAvi Kivity         0x02003737, 0x8701d737, 0x12103137, 0x9711d137,
1026b274feedSAvi Kivity         0x02003838, 0x8701d838, 0x12103238, 0x9711d238,
1027b274feedSAvi Kivity         0x06003939, 0x8301d939, 0x16103339, 0x9311d339,
1028b274feedSAvi Kivity         0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a,
1029b274feedSAvi Kivity         0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b,
1030b274feedSAvi Kivity         0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c,
1031b274feedSAvi Kivity         0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d,
1032b274feedSAvi Kivity         0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e,
1033b274feedSAvi Kivity         0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f,
1034b274feedSAvi Kivity         0x02004040, 0x8301e040, 0x16103a40, 0x9311da40,
1035b274feedSAvi Kivity         0x06004141, 0x8701e141, 0x12103b41, 0x9711db41,
1036b274feedSAvi Kivity         0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42,
1037b274feedSAvi Kivity         0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43,
1038b274feedSAvi Kivity         0x06004444, 0x8701e444, 0x12103e44, 0x9711de44,
1039b274feedSAvi Kivity         0x02004545, 0x8301e545, 0x16103f45, 0x9311df45,
1040b274feedSAvi Kivity         0x02004646, 0x8301e646, 0x12104046, 0x9311e046,
1041b274feedSAvi Kivity         0x06004747, 0x8701e747, 0x16104147, 0x9711e147,
1042b274feedSAvi Kivity         0x06004848, 0x8701e848, 0x16104248, 0x9711e248,
1043b274feedSAvi Kivity         0x02004949, 0x8301e949, 0x12104349, 0x9311e349,
1044b274feedSAvi Kivity         0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a,
1045b274feedSAvi Kivity         0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b,
1046b274feedSAvi Kivity         0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c,
1047b274feedSAvi Kivity         0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d,
1048b274feedSAvi Kivity         0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e,
1049b274feedSAvi Kivity         0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f,
1050b274feedSAvi Kivity         0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50,
1051b274feedSAvi Kivity         0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51,
1052b274feedSAvi Kivity         0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52,
1053b274feedSAvi Kivity         0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53,
1054b274feedSAvi Kivity         0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54,
1055b274feedSAvi Kivity         0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55,
1056b274feedSAvi Kivity         0x06005656, 0x8701f656, 0x16105056, 0x9711f056,
1057b274feedSAvi Kivity         0x02005757, 0x8301f757, 0x12105157, 0x9311f157,
1058b274feedSAvi Kivity         0x02005858, 0x8301f858, 0x12105258, 0x9311f258,
1059b274feedSAvi Kivity         0x06005959, 0x8701f959, 0x16105359, 0x9711f359,
1060b274feedSAvi Kivity         0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a,
1061b274feedSAvi Kivity         0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b,
1062b274feedSAvi Kivity         0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c,
1063b274feedSAvi Kivity         0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d,
1064b274feedSAvi Kivity         0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e,
1065b274feedSAvi Kivity         0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f,
1066b274feedSAvi Kivity         0x06006060, 0x47010060, 0x16105a60, 0x9711fa60,
1067b274feedSAvi Kivity         0x02006161, 0x03010161, 0x12105b61, 0x9311fb61,
1068b274feedSAvi Kivity         0x02006262, 0x03010262, 0x16105c62, 0x9711fc62,
1069b274feedSAvi Kivity         0x06006363, 0x07010363, 0x12105d63, 0x9311fd63,
1070b274feedSAvi Kivity         0x02006464, 0x03010464, 0x12105e64, 0x9311fe64,
1071b274feedSAvi Kivity         0x06006565, 0x07010565, 0x16105f65, 0x9711ff65,
1072b274feedSAvi Kivity         0x06006666, 0x07010666, 0x16106066, 0x57110066,
1073b274feedSAvi Kivity         0x02006767, 0x03010767, 0x12106167, 0x13110167,
1074b274feedSAvi Kivity         0x02006868, 0x03010868, 0x12106268, 0x13110268,
1075b274feedSAvi Kivity         0x06006969, 0x07010969, 0x16106369, 0x17110369,
1076b274feedSAvi Kivity         0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a,
1077b274feedSAvi Kivity         0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b,
1078b274feedSAvi Kivity         0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c,
1079b274feedSAvi Kivity         0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d,
1080b274feedSAvi Kivity         0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e,
1081b274feedSAvi Kivity         0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f,
1082b274feedSAvi Kivity         0x02007070, 0x03011070, 0x16106a70, 0x17110a70,
1083b274feedSAvi Kivity         0x06007171, 0x07011171, 0x12106b71, 0x13110b71,
1084b274feedSAvi Kivity         0x06007272, 0x07011272, 0x16106c72, 0x17110c72,
1085b274feedSAvi Kivity         0x02007373, 0x03011373, 0x12106d73, 0x13110d73,
1086b274feedSAvi Kivity         0x06007474, 0x07011474, 0x12106e74, 0x13110e74,
1087b274feedSAvi Kivity         0x02007575, 0x03011575, 0x16106f75, 0x17110f75,
1088b274feedSAvi Kivity         0x02007676, 0x03011676, 0x12107076, 0x13111076,
1089b274feedSAvi Kivity         0x06007777, 0x07011777, 0x16107177, 0x17111177,
1090b274feedSAvi Kivity         0x06007878, 0x07011878, 0x16107278, 0x17111278,
1091b274feedSAvi Kivity         0x02007979, 0x03011979, 0x12107379, 0x13111379,
1092b274feedSAvi Kivity         0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a,
1093b274feedSAvi Kivity         0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b,
1094b274feedSAvi Kivity         0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c,
1095b274feedSAvi Kivity         0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d,
1096b274feedSAvi Kivity         0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e,
1097b274feedSAvi Kivity         0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f,
1098b274feedSAvi Kivity         0x82008080, 0x03012080, 0x12107a80, 0x13111a80,
1099b274feedSAvi Kivity         0x86008181, 0x07012181, 0x16107b81, 0x17111b81,
1100b274feedSAvi Kivity         0x86008282, 0x07012282, 0x12107c82, 0x13111c82,
1101b274feedSAvi Kivity         0x82008383, 0x03012383, 0x16107d83, 0x17111d83,
1102b274feedSAvi Kivity         0x86008484, 0x07012484, 0x16107e84, 0x17111e84,
1103b274feedSAvi Kivity         0x82008585, 0x03012585, 0x12107f85, 0x13111f85,
1104b274feedSAvi Kivity         0x82008686, 0x03012686, 0x92108086, 0x13112086,
1105b274feedSAvi Kivity         0x86008787, 0x07012787, 0x96108187, 0x17112187,
1106b274feedSAvi Kivity         0x86008888, 0x07012888, 0x96108288, 0x17112288,
1107b274feedSAvi Kivity         0x82008989, 0x03012989, 0x92108389, 0x13112389,
1108b274feedSAvi Kivity         0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a,
1109b274feedSAvi Kivity         0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b,
1110b274feedSAvi Kivity         0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c,
1111b274feedSAvi Kivity         0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d,
1112b274feedSAvi Kivity         0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e,
1113b274feedSAvi Kivity         0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f,
1114b274feedSAvi Kivity         0x86009090, 0x07013090, 0x92108a90, 0x13112a90,
1115b274feedSAvi Kivity         0x82009191, 0x03013191, 0x96108b91, 0x17112b91,
1116b274feedSAvi Kivity         0x82009292, 0x03013292, 0x92108c92, 0x13112c92,
1117b274feedSAvi Kivity         0x86009393, 0x07013393, 0x96108d93, 0x17112d93,
1118b274feedSAvi Kivity         0x82009494, 0x03013494, 0x96108e94, 0x17112e94,
1119b274feedSAvi Kivity         0x86009595, 0x07013595, 0x92108f95, 0x13112f95,
1120b274feedSAvi Kivity         0x86009696, 0x07013696, 0x96109096, 0x17113096,
1121b274feedSAvi Kivity         0x82009797, 0x03013797, 0x92109197, 0x13113197,
1122b274feedSAvi Kivity         0x82009898, 0x03013898, 0x92109298, 0x13113298,
1123b274feedSAvi Kivity         0x86009999, 0x07013999, 0x96109399, 0x17113399,
1124b274feedSAvi Kivity         0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a,
1125b274feedSAvi Kivity         0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b,
1126b274feedSAvi Kivity         0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c,
1127b274feedSAvi Kivity         0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d,
1128b274feedSAvi Kivity         0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e,
1129b274feedSAvi Kivity         0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f,
1130b274feedSAvi Kivity         0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0,
1131b274feedSAvi Kivity         0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1,
1132b274feedSAvi Kivity         0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2,
1133b274feedSAvi Kivity         0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3,
1134b274feedSAvi Kivity         0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4,
1135b274feedSAvi Kivity         0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5,
1136b274feedSAvi Kivity         0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6,
1137b274feedSAvi Kivity         0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7,
1138b274feedSAvi Kivity         0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8,
1139b274feedSAvi Kivity         0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9,
1140b274feedSAvi Kivity         0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa,
1141b274feedSAvi Kivity         0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab,
1142b274feedSAvi Kivity         0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac,
1143b274feedSAvi Kivity         0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad,
1144b274feedSAvi Kivity         0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae,
1145b274feedSAvi Kivity         0x130049af, 0x130149af, 0x131049af, 0x131149af,
1146b274feedSAvi Kivity         0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0,
1147b274feedSAvi Kivity         0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1,
1148b274feedSAvi Kivity         0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2,
1149b274feedSAvi Kivity         0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3,
1150b274feedSAvi Kivity         0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4,
1151b274feedSAvi Kivity         0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5,
1152b274feedSAvi Kivity         0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6,
1153b274feedSAvi Kivity         0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7,
1154b274feedSAvi Kivity         0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8,
1155b274feedSAvi Kivity         0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9,
1156b274feedSAvi Kivity         0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba,
1157b274feedSAvi Kivity         0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb,
1158b274feedSAvi Kivity         0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc,
1159b274feedSAvi Kivity         0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd,
1160b274feedSAvi Kivity         0x130058be, 0x130158be, 0x131058be, 0x131158be,
1161b274feedSAvi Kivity         0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf,
1162b274feedSAvi Kivity         0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0,
1163b274feedSAvi Kivity         0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1,
1164b274feedSAvi Kivity         0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2,
1165b274feedSAvi Kivity         0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3,
1166b274feedSAvi Kivity         0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4,
1167b274feedSAvi Kivity         0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5,
1168b274feedSAvi Kivity         0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6,
1169b274feedSAvi Kivity         0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7,
1170b274feedSAvi Kivity         0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8,
1171b274feedSAvi Kivity         0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9,
1172b274feedSAvi Kivity         0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca,
1173b274feedSAvi Kivity         0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb,
1174b274feedSAvi Kivity         0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc,
1175b274feedSAvi Kivity         0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd,
1176b274feedSAvi Kivity         0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce,
1177b274feedSAvi Kivity         0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf,
1178b274feedSAvi Kivity         0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0,
1179b274feedSAvi Kivity         0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1,
1180b274feedSAvi Kivity         0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2,
1181b274feedSAvi Kivity         0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3,
1182b274feedSAvi Kivity         0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4,
1183b274feedSAvi Kivity         0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5,
1184b274feedSAvi Kivity         0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6,
1185b274feedSAvi Kivity         0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7,
1186b274feedSAvi Kivity         0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8,
1187b274feedSAvi Kivity         0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9,
1188b274feedSAvi Kivity         0x170074da, 0x170174da, 0x171074da, 0x171174da,
1189b274feedSAvi Kivity         0x130075db, 0x130175db, 0x131075db, 0x131175db,
1190b274feedSAvi Kivity         0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc,
1191b274feedSAvi Kivity         0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd,
1192b274feedSAvi Kivity         0x170078de, 0x170178de, 0x171078de, 0x171178de,
1193b274feedSAvi Kivity         0x130079df, 0x130179df, 0x131079df, 0x131179df,
1194b274feedSAvi Kivity         0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0,
1195b274feedSAvi Kivity         0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1,
1196b274feedSAvi Kivity         0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2,
1197b274feedSAvi Kivity         0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3,
1198b274feedSAvi Kivity         0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4,
1199b274feedSAvi Kivity         0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5,
1200b274feedSAvi Kivity         0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6,
1201b274feedSAvi Kivity         0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7,
1202b274feedSAvi Kivity         0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8,
1203b274feedSAvi Kivity         0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9,
1204b274feedSAvi Kivity         0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea,
1205b274feedSAvi Kivity         0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb,
1206b274feedSAvi Kivity         0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec,
1207b274feedSAvi Kivity         0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed,
1208b274feedSAvi Kivity         0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee,
1209b274feedSAvi Kivity         0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef,
1210b274feedSAvi Kivity         0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0,
1211b274feedSAvi Kivity         0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1,
1212b274feedSAvi Kivity         0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2,
1213b274feedSAvi Kivity         0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3,
1214b274feedSAvi Kivity         0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4,
1215b274feedSAvi Kivity         0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5,
1216b274feedSAvi Kivity         0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6,
1217b274feedSAvi Kivity         0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7,
1218b274feedSAvi Kivity         0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8,
1219b274feedSAvi Kivity         0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9,
1220b274feedSAvi Kivity         0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa,
1221b274feedSAvi Kivity         0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb,
1222b274feedSAvi Kivity         0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc,
1223b274feedSAvi Kivity         0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd,
1224b274feedSAvi Kivity         0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe,
1225b274feedSAvi Kivity         0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff,
1226b274feedSAvi Kivity     };
1227b274feedSAvi Kivity 
1228b274feedSAvi Kivity     MK_INSN(das, "das");
1229b274feedSAvi Kivity 
123018253fdeSAvi Kivity     inregs = (struct regs){ 0 };
123118253fdeSAvi Kivity 
1232b274feedSAvi Kivity     for (i = 0; i < 1024; ++i) {
1233b274feedSAvi Kivity         unsigned tmp = test_cases[i];
1234b274feedSAvi Kivity         inregs.eax = tmp & 0xff;
1235b274feedSAvi Kivity         inregs.eflags = (tmp >> 16) & 0xff;
123618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_das);
123718253fdeSAvi Kivity 	if (!regs_equal(R_AX)
1238b274feedSAvi Kivity             || outregs.eax != ((tmp >> 8) & 0xff)
1239b274feedSAvi Kivity             || (outregs.eflags & 0xff) != (tmp >> 24)) {
124081050840SAvi Kivity 	    ++nr_fail;
124181050840SAvi Kivity 	    break;
1242b274feedSAvi Kivity         }
1243b274feedSAvi Kivity     }
12446055ea1fSAvi Kivity     report("DAS", ~0, nr_fail == 0);
1245b274feedSAvi Kivity }
1246b274feedSAvi Kivity 
12470cbd5b06SMohammed Gamal void test_cwd_cdq()
12480cbd5b06SMohammed Gamal {
12490cbd5b06SMohammed Gamal 	/* Sign-bit set */
12500cbd5b06SMohammed Gamal 	MK_INSN(cwd_1, "mov $0x8000, %ax\n\t"
12510cbd5b06SMohammed Gamal 		       "cwd\n\t");
12520cbd5b06SMohammed Gamal 
12530cbd5b06SMohammed Gamal 	/* Sign-bit not set */
12540cbd5b06SMohammed Gamal 	MK_INSN(cwd_2, "mov $0x1000, %ax\n\t"
12550cbd5b06SMohammed Gamal 		       "cwd\n\t");
12560cbd5b06SMohammed Gamal 
12570cbd5b06SMohammed Gamal 	/* Sign-bit set */
12580cbd5b06SMohammed Gamal 	MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t"
12590cbd5b06SMohammed Gamal 		       "cdq\n\t");
12600cbd5b06SMohammed Gamal 
12610cbd5b06SMohammed Gamal 	/* Sign-bit not set */
12620cbd5b06SMohammed Gamal 	MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t"
12630cbd5b06SMohammed Gamal 		       "cdq\n\t");
12640cbd5b06SMohammed Gamal 
126518253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
126618253fdeSAvi Kivity 
126718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_1);
12686055ea1fSAvi Kivity 	report("cwd 1", R_AX | R_DX,
12696055ea1fSAvi Kivity 	       outregs.eax == 0x8000 && outregs.edx == 0xffff);
12700cbd5b06SMohammed Gamal 
127118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_2);
12726055ea1fSAvi Kivity 	report("cwd 2", R_AX | R_DX,
12736055ea1fSAvi Kivity 	       outregs.eax == 0x1000 && outregs.edx == 0);
12740cbd5b06SMohammed Gamal 
127518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_1);
12766055ea1fSAvi Kivity 	report("cdq 1", R_AX | R_DX,
12776055ea1fSAvi Kivity 	       outregs.eax == 0x80000000 && outregs.edx == 0xffffffff);
12780cbd5b06SMohammed Gamal 
127918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_2);
12806055ea1fSAvi Kivity 	report("cdq 2", R_AX | R_DX,
12816055ea1fSAvi Kivity 	       outregs.eax == 0x10000000 && outregs.edx == 0);
12820cbd5b06SMohammed Gamal }
12830cbd5b06SMohammed Gamal 
128437f51a4aSWei Yongjun static struct {
128537f51a4aSWei Yongjun         void *address;
128637f51a4aSWei Yongjun         unsigned short sel;
128737f51a4aSWei Yongjun } __attribute__((packed)) desc = {
128837f51a4aSWei Yongjun 	(void *)0x1234,
128937f51a4aSWei Yongjun 	0x10,
129037f51a4aSWei Yongjun };
129137f51a4aSWei Yongjun 
129237f51a4aSWei Yongjun void test_lds_lss()
129337f51a4aSWei Yongjun {
129437f51a4aSWei Yongjun 	inregs = (struct regs){ .ebx = (unsigned long)&desc };
129537f51a4aSWei Yongjun 
129637f51a4aSWei Yongjun 	MK_INSN(lds, "push %ds\n\t"
129737f51a4aSWei Yongjun 		     "lds (%ebx), %eax\n\t"
129837f51a4aSWei Yongjun 		     "mov %ds, %ebx\n\t"
129937f51a4aSWei Yongjun 		     "pop %ds\n\t");
130037f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lds);
130137f51a4aSWei Yongjun 	report("lds", R_AX | R_BX,
130237f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
130337f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
130437f51a4aSWei Yongjun 
130537f51a4aSWei Yongjun 	MK_INSN(les, "push %es\n\t"
130637f51a4aSWei Yongjun 		     "les (%ebx), %eax\n\t"
130737f51a4aSWei Yongjun 		     "mov %es, %ebx\n\t"
130837f51a4aSWei Yongjun 		     "pop %es\n\t");
130937f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_les);
131037f51a4aSWei Yongjun 	report("les", R_AX | R_BX,
131137f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
131237f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
131337f51a4aSWei Yongjun 
131437f51a4aSWei Yongjun 	MK_INSN(lfs, "push %fs\n\t"
131537f51a4aSWei Yongjun 		     "lfs (%ebx), %eax\n\t"
131637f51a4aSWei Yongjun 		     "mov %fs, %ebx\n\t"
131737f51a4aSWei Yongjun 		     "pop %fs\n\t");
131837f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lfs);
131937f51a4aSWei Yongjun 	report("lfs", R_AX | R_BX,
132037f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
132137f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
132237f51a4aSWei Yongjun 
132337f51a4aSWei Yongjun 	MK_INSN(lgs, "push %gs\n\t"
132437f51a4aSWei Yongjun 		     "lgs (%ebx), %eax\n\t"
132537f51a4aSWei Yongjun 		     "mov %gs, %ebx\n\t"
132637f51a4aSWei Yongjun 		     "pop %gs\n\t");
132737f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lgs);
132837f51a4aSWei Yongjun 	report("lgs", R_AX | R_BX,
132937f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
133037f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
133137f51a4aSWei Yongjun 
133237f51a4aSWei Yongjun 	MK_INSN(lss, "push %ss\n\t"
133337f51a4aSWei Yongjun 		     "lss (%ebx), %eax\n\t"
133437f51a4aSWei Yongjun 		     "mov %ss, %ebx\n\t"
133537f51a4aSWei Yongjun 		     "pop %ss\n\t");
133637f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lss);
133737f51a4aSWei Yongjun 	report("lss", R_AX | R_BX,
133837f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
133937f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
134037f51a4aSWei Yongjun }
134137f51a4aSWei Yongjun 
1342b1c7c575SWei Yongjun void test_jcxz(void)
1343b1c7c575SWei Yongjun {
1344b1c7c575SWei Yongjun 	MK_INSN(jcxz1, "jcxz 1f\n\t"
1345b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1346b1c7c575SWei Yongjun 		       "1:\n\t");
1347b1c7c575SWei Yongjun 	MK_INSN(jcxz2, "mov $0x100, %ecx\n\t"
1348b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1349b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1350b1c7c575SWei Yongjun 		       "mov $0, %ecx\n\t"
1351b1c7c575SWei Yongjun 		       "1:\n\t");
1352b1c7c575SWei Yongjun 	MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t"
1353b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1354b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1355b1c7c575SWei Yongjun 		       "1:\n\t");
1356b1c7c575SWei Yongjun 	MK_INSN(jecxz1, "jecxz 1f\n\t"
1357b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1358b1c7c575SWei Yongjun 			"1:\n\t");
1359b1c7c575SWei Yongjun 	MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t"
1360b1c7c575SWei Yongjun 			"jecxz 1f\n\t"
1361b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1362b1c7c575SWei Yongjun 			"mov $0, %ecx\n\t"
1363b1c7c575SWei Yongjun 			"1:\n\t");
1364b1c7c575SWei Yongjun 
1365b1c7c575SWei Yongjun 	inregs = (struct regs){ 0 };
1366b1c7c575SWei Yongjun 
1367b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz1);
1368b1c7c575SWei Yongjun 	report("jcxz short 1", 0, 1);
1369b1c7c575SWei Yongjun 
1370b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz2);
1371b1c7c575SWei Yongjun 	report("jcxz short 2", R_AX, outregs.eax == 0x1234);
1372b1c7c575SWei Yongjun 
1373b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz3);
1374b1c7c575SWei Yongjun 	report("jcxz short 3", R_CX, outregs.ecx == 0x10000);
1375b1c7c575SWei Yongjun 
1376b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz1);
1377b1c7c575SWei Yongjun 	report("jecxz short 1", 0, 1);
1378b1c7c575SWei Yongjun 
1379b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz2);
1380b1c7c575SWei Yongjun 	report("jecxz short 2", R_AX, outregs.eax == 0x1234);
1381b1c7c575SWei Yongjun }
1382b1c7c575SWei Yongjun 
13838f578e98SAvi Kivity static void test_cpuid(void)
13848f578e98SAvi Kivity {
13858f578e98SAvi Kivity     MK_INSN(cpuid, "cpuid");
13868f578e98SAvi Kivity     unsigned function = 0x1234;
13878f578e98SAvi Kivity     unsigned eax, ebx, ecx, edx;
13888f578e98SAvi Kivity 
13898f578e98SAvi Kivity     inregs.eax = eax = function;
139018ba9083SGleb Natapov     inregs.ecx = ecx = 0;
13918f578e98SAvi Kivity     asm("cpuid" : "+a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx));
13928f578e98SAvi Kivity     exec_in_big_real_mode(&insn_cpuid);
13938f578e98SAvi Kivity     report("cpuid", R_AX|R_BX|R_CX|R_DX,
13948f578e98SAvi Kivity 	   outregs.eax == eax && outregs.ebx == ebx
13958f578e98SAvi Kivity 	   && outregs.ecx == ecx && outregs.edx == edx);
13968f578e98SAvi Kivity }
13978f578e98SAvi Kivity 
1398ed93f43bSAvi Kivity static void test_ss_base_for_esp_ebp(void)
1399ed93f43bSAvi Kivity {
1400ed93f43bSAvi Kivity     MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss");
1401ed93f43bSAvi Kivity     MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss");
1402ed93f43bSAvi Kivity     static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 };
1403ed93f43bSAvi Kivity 
1404ed93f43bSAvi Kivity     inregs.ebx = 1;
1405ed93f43bSAvi Kivity     inregs.ebp = (unsigned)array;
1406ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel1);
1407ed93f43bSAvi Kivity     report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321);
1408ed93f43bSAvi Kivity     inregs.ebx = 1;
1409ed93f43bSAvi Kivity     inregs.ebp = (unsigned)array;
1410ed93f43bSAvi Kivity     inregs.edi = 0;
1411ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel2);
1412ed93f43bSAvi Kivity     report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321);
1413ed93f43bSAvi Kivity }
1414ed93f43bSAvi Kivity 
1415c2281fa4SAvi Kivity static void test_sgdt_sidt(void)
1416c2281fa4SAvi Kivity {
1417c2281fa4SAvi Kivity     MK_INSN(sgdt, "sgdtw (%eax)");
1418c2281fa4SAvi Kivity     MK_INSN(sidt, "sidtw (%eax)");
1419c2281fa4SAvi Kivity     unsigned x, y;
1420c2281fa4SAvi Kivity 
1421c2281fa4SAvi Kivity     inregs.eax = (unsigned)&y;
1422c2281fa4SAvi Kivity     asm volatile("sgdtw %0" : "=m"(x));
1423c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sgdt);
1424c2281fa4SAvi Kivity     report("sgdt", 0, x == y);
1425c2281fa4SAvi Kivity 
1426c2281fa4SAvi Kivity     inregs.eax = (unsigned)&y;
1427c2281fa4SAvi Kivity     asm volatile("sidtw %0" : "=m"(x));
1428c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sidt);
1429c2281fa4SAvi Kivity     report("sidt", 0, x == y);
1430c2281fa4SAvi Kivity }
1431c2281fa4SAvi Kivity 
143288b6dac4SPaolo Bonzini static void test_sahf(void)
143388b6dac4SPaolo Bonzini {
143488b6dac4SPaolo Bonzini     MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw");
143588b6dac4SPaolo Bonzini 
143688b6dac4SPaolo Bonzini     inregs.eax = 0xfd00;
143788b6dac4SPaolo Bonzini     exec_in_big_real_mode(&insn_sahf);
143888b6dac4SPaolo Bonzini     report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7));
143988b6dac4SPaolo Bonzini }
144088b6dac4SPaolo Bonzini 
14417ae3645aSAvi Kivity static void test_lahf(void)
14427ae3645aSAvi Kivity {
14437ae3645aSAvi Kivity     MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf");
14447ae3645aSAvi Kivity 
14457ae3645aSAvi Kivity     inregs.eax = 0xc7;
14467ae3645aSAvi Kivity     exec_in_big_real_mode(&insn_lahf);
14477ae3645aSAvi Kivity     report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax);
14487ae3645aSAvi Kivity }
14497ae3645aSAvi Kivity 
1450fd9ea640SAvi Kivity static void test_movzx_movsx(void)
1451fd9ea640SAvi Kivity {
1452fd9ea640SAvi Kivity     MK_INSN(movsx, "movsx %al, %ebx");
1453fd9ea640SAvi Kivity     MK_INSN(movzx, "movzx %al, %ebx");
14543013e079SGleb Natapov     MK_INSN(movzsah, "movsx %ah, %ebx");
14553013e079SGleb Natapov     MK_INSN(movzxah, "movzx %ah, %ebx");
1456fd9ea640SAvi Kivity 
1457fd9ea640SAvi Kivity     inregs.eax = 0x1234569c;
14583013e079SGleb Natapov     inregs.esp = 0xffff;
1459fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movsx);
1460fd9ea640SAvi Kivity     report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax);
1461fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movzx);
1462fd9ea640SAvi Kivity     report("movzx", R_BX, outregs.ebx == (unsigned char)inregs.eax);
14633013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzsah);
14643013e079SGleb Natapov     report("movsx ah", R_BX, outregs.ebx == (signed char)(inregs.eax>>8));
14653013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzxah);
14663013e079SGleb Natapov     report("movzx ah", R_BX, outregs.ebx == (unsigned char)(inregs.eax >> 8));
1467fd9ea640SAvi Kivity }
1468fd9ea640SAvi Kivity 
1469b493b2e8SAvi Kivity static void test_bswap(void)
1470b493b2e8SAvi Kivity {
1471b493b2e8SAvi Kivity     MK_INSN(bswap, "bswap %ecx");
1472b493b2e8SAvi Kivity 
1473b493b2e8SAvi Kivity     inregs.ecx = 0x12345678;
1474b493b2e8SAvi Kivity     exec_in_big_real_mode(&insn_bswap);
1475b493b2e8SAvi Kivity     report("bswap", R_CX, outregs.ecx == 0x78563412);
1476b493b2e8SAvi Kivity }
1477b493b2e8SAvi Kivity 
14788cd86387SGleb Natapov static void test_aad(void)
14798cd86387SGleb Natapov {
14808cd86387SGleb Natapov     MK_INSN(aad, "aad");
14818cd86387SGleb Natapov 
14828cd86387SGleb Natapov     inregs.eax = 0x12345678;
14838cd86387SGleb Natapov     exec_in_big_real_mode(&insn_aad);
14848cd86387SGleb Natapov     report("aad", R_AX, outregs.eax == 0x123400d4);
14858cd86387SGleb Natapov }
14868cd86387SGleb Natapov 
14872a9b5718SPaolo Bonzini static void test_aam(void)
14882a9b5718SPaolo Bonzini {
14892a9b5718SPaolo Bonzini     MK_INSN(aam, "aam");
14902a9b5718SPaolo Bonzini 
14912a9b5718SPaolo Bonzini     inregs.eax = 0x76543210;
14922a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_aam);
14932a9b5718SPaolo Bonzini     report("aam", R_AX, outregs.eax == 0x76540106);
14942a9b5718SPaolo Bonzini }
14952a9b5718SPaolo Bonzini 
14962a9b5718SPaolo Bonzini static void test_xlat(void)
14972a9b5718SPaolo Bonzini {
14982a9b5718SPaolo Bonzini     MK_INSN(xlat, "xlat");
14992a9b5718SPaolo Bonzini     u8 table[256];
15002a9b5718SPaolo Bonzini     int i;
15012a9b5718SPaolo Bonzini 
15022a9b5718SPaolo Bonzini     for (i = 0; i < 256; i++) {
15032a9b5718SPaolo Bonzini         table[i] = i + 1;
15042a9b5718SPaolo Bonzini     }
15052a9b5718SPaolo Bonzini 
15062a9b5718SPaolo Bonzini     inregs.eax = 0x89abcdef;
15072a9b5718SPaolo Bonzini     inregs.ebx = (u32)table;
15082a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_xlat);
15092a9b5718SPaolo Bonzini     report("xlat", R_AX, outregs.eax == 0x89abcdf0);
15102a9b5718SPaolo Bonzini }
15112a9b5718SPaolo Bonzini 
15122a9b5718SPaolo Bonzini static void test_salc(void)
15132a9b5718SPaolo Bonzini {
15142a9b5718SPaolo Bonzini     MK_INSN(clc_salc, "clc; .byte 0xd6");
15152a9b5718SPaolo Bonzini     MK_INSN(stc_salc, "stc; .byte 0xd6");
15162a9b5718SPaolo Bonzini 
15172a9b5718SPaolo Bonzini     inregs.eax = 0x12345678;
15182a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_clc_salc);
15192a9b5718SPaolo Bonzini     report("salc (1)", R_AX, outregs.eax == 0x12345600);
15202a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_stc_salc);
15212a9b5718SPaolo Bonzini     report("salc (2)", R_AX, outregs.eax == 0x123456ff);
15222a9b5718SPaolo Bonzini }
15232a9b5718SPaolo Bonzini 
15240987db7aSGleb Natapov static void test_fninit(void)
15250987db7aSGleb Natapov {
15260987db7aSGleb Natapov 	u16 fcw = -1, fsw = -1;
15270987db7aSGleb Natapov 	MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)");
15280987db7aSGleb Natapov 
15290987db7aSGleb Natapov 	inregs.eax = (u32)&fsw;
15300987db7aSGleb Natapov 	inregs.ebx = (u32)&fcw;
15310987db7aSGleb Natapov 
15320987db7aSGleb Natapov 	exec_in_big_real_mode(&insn_fninit);
15330987db7aSGleb Natapov 	report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f);
15340987db7aSGleb Natapov }
15350987db7aSGleb Natapov 
15361a4c03a0SArthur Chunqi Li static void test_nopl(void)
15371a4c03a0SArthur Chunqi Li {
15381a4c03a0SArthur Chunqi Li 	MK_INSN(nopl1, ".byte 0x90\n\r"); // 1 byte nop
15391a4c03a0SArthur Chunqi Li 	MK_INSN(nopl2, ".byte 0x66, 0x90\n\r"); // 2 bytes nop
15401a4c03a0SArthur Chunqi Li 	MK_INSN(nopl3, ".byte 0x0f, 0x1f, 0x00\n\r"); // 3 bytes nop
15411a4c03a0SArthur Chunqi Li 	MK_INSN(nopl4, ".byte 0x0f, 0x1f, 0x40, 0x00\n\r"); // 4 bytes nop
15421a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl1);
15431a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl2);
15441a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl3);
15451a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl4);
15461a4c03a0SArthur Chunqi Li 	report("nopl", 0, 1);
15471a4c03a0SArthur Chunqi Li }
15481a4c03a0SArthur Chunqi Li 
1549*b5105e8bSPaolo Bonzini static u32 perf_baseline;
1550*b5105e8bSPaolo Bonzini 
1551*b5105e8bSPaolo Bonzini #define PERF_COUNT 100000
1552*b5105e8bSPaolo Bonzini 
1553*b5105e8bSPaolo Bonzini #define MK_INSN_PERF(name, insn)                                \
1554*b5105e8bSPaolo Bonzini 	MK_INSN(name, "rdtsc; mov %eax, %ebx; mov %edx, %esi\n" \
1555*b5105e8bSPaolo Bonzini 		      "1:" insn "\n"                            \
1556*b5105e8bSPaolo Bonzini 		      "loop 1b\n"                               \
1557*b5105e8bSPaolo Bonzini 		      "rdtsc");
1558*b5105e8bSPaolo Bonzini 
1559*b5105e8bSPaolo Bonzini static u32 cycles_in_big_real_mode(struct insn_desc *insn)
1560*b5105e8bSPaolo Bonzini {
1561*b5105e8bSPaolo Bonzini 	u64 start, end;
1562*b5105e8bSPaolo Bonzini 
1563*b5105e8bSPaolo Bonzini 	inregs.ecx = PERF_COUNT;
1564*b5105e8bSPaolo Bonzini 	exec_in_big_real_mode(insn);
1565*b5105e8bSPaolo Bonzini 	start = ((u64)outregs.esi << 32) | outregs.ebx;
1566*b5105e8bSPaolo Bonzini 	end = ((u64)outregs.edx << 32) | outregs.eax;
1567*b5105e8bSPaolo Bonzini 
1568*b5105e8bSPaolo Bonzini 	return end - start;
1569*b5105e8bSPaolo Bonzini }
1570*b5105e8bSPaolo Bonzini 
1571*b5105e8bSPaolo Bonzini static void test_perf_loop(void)
1572*b5105e8bSPaolo Bonzini {
1573*b5105e8bSPaolo Bonzini 	/*
1574*b5105e8bSPaolo Bonzini 	 * This test runs simple instructions that should roughly take the
1575*b5105e8bSPaolo Bonzini 	 * the same time to emulate: PERF_COUNT iterations of "loop" and 3
1576*b5105e8bSPaolo Bonzini 	 * setup instructions.  Other performance tests can run PERF_COUNT
1577*b5105e8bSPaolo Bonzini 	 * iterations of the same instruction and subtract the cycle count
1578*b5105e8bSPaolo Bonzini 	 * of this test.
1579*b5105e8bSPaolo Bonzini 	 */
1580*b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_loop, "");
1581*b5105e8bSPaolo Bonzini 	perf_baseline = cycles_in_big_real_mode(&insn_perf_loop);
1582*b5105e8bSPaolo Bonzini 	print_serial_u32(perf_baseline / (PERF_COUNT + 3));
1583*b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated jump instruction\n");
1584*b5105e8bSPaolo Bonzini }
1585*b5105e8bSPaolo Bonzini 
1586*b5105e8bSPaolo Bonzini static void test_perf_mov(void)
1587*b5105e8bSPaolo Bonzini {
1588*b5105e8bSPaolo Bonzini 	u32 cyc;
1589*b5105e8bSPaolo Bonzini 
1590*b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_move, "mov %esi, %edi");
1591*b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_move);
1592*b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1593*b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated move instruction\n");
1594*b5105e8bSPaolo Bonzini }
1595*b5105e8bSPaolo Bonzini 
1596*b5105e8bSPaolo Bonzini static void test_perf_arith(void)
1597*b5105e8bSPaolo Bonzini {
1598*b5105e8bSPaolo Bonzini 	u32 cyc;
1599*b5105e8bSPaolo Bonzini 
1600*b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_arith, "add $4, %edi");
1601*b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_arith);
1602*b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1603*b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated arithmetic instruction\n");
1604*b5105e8bSPaolo Bonzini }
1605*b5105e8bSPaolo Bonzini 
1606*b5105e8bSPaolo Bonzini static void test_perf_memory_load(void)
1607*b5105e8bSPaolo Bonzini {
1608*b5105e8bSPaolo Bonzini 	u32 cyc, tmp;
1609*b5105e8bSPaolo Bonzini 
1610*b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_memory_load, "cmp $0, (%edi)");
1611*b5105e8bSPaolo Bonzini 	inregs.edi = (u32)&tmp;
1612*b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_load);
1613*b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1614*b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated memory load instruction\n");
1615*b5105e8bSPaolo Bonzini }
1616*b5105e8bSPaolo Bonzini 
1617*b5105e8bSPaolo Bonzini static void test_perf_memory_rmw(void)
1618*b5105e8bSPaolo Bonzini {
1619*b5105e8bSPaolo Bonzini 	u32 cyc, tmp;
1620*b5105e8bSPaolo Bonzini 
1621*b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_memory_rmw, "add $1, (%edi)");
1622*b5105e8bSPaolo Bonzini 	inregs.edi = (u32)&tmp;
1623*b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_rmw);
1624*b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1625*b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated memory RMW instruction\n");
1626*b5105e8bSPaolo Bonzini }
1627*b5105e8bSPaolo Bonzini 
16287d36db35SAvi Kivity void realmode_start(void)
16297d36db35SAvi Kivity {
16307d36db35SAvi Kivity 	test_null();
16317d36db35SAvi Kivity 
16327d36db35SAvi Kivity 	test_shld();
16337d36db35SAvi Kivity 	test_push_pop();
16347d36db35SAvi Kivity 	test_pusha_popa();
16357d36db35SAvi Kivity 	test_mov_imm();
16367d36db35SAvi Kivity 	test_cmp_imm();
16377d36db35SAvi Kivity 	test_add_imm();
16387d36db35SAvi Kivity 	test_sub_imm();
16397d36db35SAvi Kivity 	test_xor_imm();
16407d36db35SAvi Kivity 	test_io();
16417d36db35SAvi Kivity 	test_eflags_insn();
16427d36db35SAvi Kivity 	test_jcc_short();
16437d36db35SAvi Kivity 	test_jcc_near();
16447d36db35SAvi Kivity 	/* test_call() uses short jump so call it after testing jcc */
16457d36db35SAvi Kivity 	test_call();
16467d36db35SAvi Kivity 	/* long jmp test uses call near so test it after testing call */
16477d36db35SAvi Kivity 	test_long_jmp();
16487d36db35SAvi Kivity 	test_xchg();
16497d36db35SAvi Kivity 	test_iret();
165096b9ca1eSMohammed Gamal 	test_int();
1651fa74f8a6SMohammed Gamal 	test_imul();
165259317bd1SMohammed Gamal 	test_mul();
16530d4c7614SMohammed Gamal 	test_div();
16540d4c7614SMohammed Gamal 	test_idiv();
1655eacef4e2SWei Yongjun 	test_loopcc();
16566e293cf5SWei Yongjun 	test_cbw();
16570cbd5b06SMohammed Gamal 	test_cwd_cdq();
1658b274feedSAvi Kivity 	test_das();
165937f51a4aSWei Yongjun 	test_lds_lss();
1660b1c7c575SWei Yongjun 	test_jcxz();
16618f578e98SAvi Kivity 	test_cpuid();
1662ed93f43bSAvi Kivity 	test_ss_base_for_esp_ebp();
1663c2281fa4SAvi Kivity 	test_sgdt_sidt();
16647ae3645aSAvi Kivity 	test_lahf();
166588b6dac4SPaolo Bonzini 	test_sahf();
1666fd9ea640SAvi Kivity 	test_movzx_movsx();
1667b493b2e8SAvi Kivity 	test_bswap();
16688cd86387SGleb Natapov 	test_aad();
16692a9b5718SPaolo Bonzini 	test_aam();
16702a9b5718SPaolo Bonzini 	test_xlat();
16712a9b5718SPaolo Bonzini 	test_salc();
16720987db7aSGleb Natapov 	test_fninit();
16731a4c03a0SArthur Chunqi Li 	test_nopl();
1674*b5105e8bSPaolo Bonzini 	test_perf_loop();
1675*b5105e8bSPaolo Bonzini 	test_perf_mov();
1676*b5105e8bSPaolo Bonzini 	test_perf_arith();
1677*b5105e8bSPaolo Bonzini 	test_perf_memory_load();
1678*b5105e8bSPaolo Bonzini 	test_perf_memory_rmw();
16797d36db35SAvi Kivity 
16807d36db35SAvi Kivity 	exit(0);
16817d36db35SAvi Kivity }
16827d36db35SAvi Kivity 
16837d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff };
16847d36db35SAvi Kivity 
16857d36db35SAvi Kivity struct __attribute__((packed)) {
16867d36db35SAvi Kivity 	unsigned short limit;
16877d36db35SAvi Kivity 	void *base;
16887d36db35SAvi Kivity } r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt };
16897d36db35SAvi Kivity 
16907d36db35SAvi Kivity asm(
16917d36db35SAvi Kivity 	".section .init \n\t"
16927d36db35SAvi Kivity 
16937d36db35SAvi Kivity 	".code32 \n\t"
16947d36db35SAvi Kivity 
16957d36db35SAvi Kivity 	"mb_magic = 0x1BADB002 \n\t"
16967d36db35SAvi Kivity 	"mb_flags = 0x0 \n\t"
16977d36db35SAvi Kivity 
16987d36db35SAvi Kivity 	"# multiboot header \n\t"
16997d36db35SAvi Kivity 	".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t"
17007d36db35SAvi Kivity 
17017d36db35SAvi Kivity 	".globl start \n\t"
17027d36db35SAvi Kivity 	".data \n\t"
17037d36db35SAvi Kivity 	". = . + 4096 \n\t"
17047d36db35SAvi Kivity 	"stacktop: \n\t"
17057d36db35SAvi Kivity 
17067d36db35SAvi Kivity 	".text \n\t"
17077d36db35SAvi Kivity 	"start: \n\t"
17087d36db35SAvi Kivity 	"lgdt r_gdt_descr \n\t"
17097d36db35SAvi Kivity 	"ljmp $8, $1f; 1: \n\t"
17107d36db35SAvi Kivity 	".code16gcc \n\t"
17117d36db35SAvi Kivity 	"mov $16, %eax \n\t"
17127d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
17137d36db35SAvi Kivity 	"mov %ax, %es \n\t"
17147d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
17157d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
17167d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
17177d36db35SAvi Kivity 	"mov %cr0, %eax \n\t"
17187d36db35SAvi Kivity 	"btc $0, %eax \n\t"
17197d36db35SAvi Kivity 	"mov %eax, %cr0 \n\t"
17207d36db35SAvi Kivity 	"ljmp $0, $realmode_entry \n\t"
17217d36db35SAvi Kivity 
17227d36db35SAvi Kivity 	"realmode_entry: \n\t"
17237d36db35SAvi Kivity 
17247d36db35SAvi Kivity 	"xor %ax, %ax \n\t"
17257d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
17267d36db35SAvi Kivity 	"mov %ax, %es \n\t"
17277d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
17287d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
17297d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
17307d36db35SAvi Kivity 	"mov $stacktop, %esp\n\t"
17317d36db35SAvi Kivity 	"ljmp $0, $realmode_start \n\t"
17327d36db35SAvi Kivity 
17337d36db35SAvi Kivity 	".code16gcc \n\t"
17347d36db35SAvi Kivity 	);
1735