xref: /kvm-unit-tests/x86/realmode.c (revision 2e3f9f1f983708407ed961c62226d7d8e6a32850)
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 
12*2e3f9f1fSThomas Huth void realmode_start(void);
137d36db35SAvi Kivity void test_function(void);
147d36db35SAvi Kivity 
157d36db35SAvi Kivity asm(
167d36db35SAvi Kivity 	"test_function: \n\t"
177d36db35SAvi Kivity 	"mov $0x1234, %eax \n\t"
187d36db35SAvi Kivity 	"ret"
197d36db35SAvi Kivity    );
207d36db35SAvi Kivity 
217d36db35SAvi Kivity static int strlen(const char *str)
227d36db35SAvi Kivity {
237d36db35SAvi Kivity 	int n;
247d36db35SAvi Kivity 
257d36db35SAvi Kivity 	for (n = 0; *str; ++str)
267d36db35SAvi Kivity 		++n;
277d36db35SAvi Kivity 	return n;
287d36db35SAvi Kivity }
297d36db35SAvi Kivity 
30f366255fSPaolo Bonzini static void outb(u8 data, u16 port)
31f366255fSPaolo Bonzini {
32f366255fSPaolo Bonzini 	asm volatile("out %0, %1" : : "a"(data), "d"(port));
33f366255fSPaolo Bonzini }
34f366255fSPaolo Bonzini 
35f366255fSPaolo Bonzini #ifdef USE_SERIAL
36f366255fSPaolo Bonzini static int serial_iobase = 0x3f8;
37f366255fSPaolo Bonzini static int serial_inited = 0;
38f366255fSPaolo Bonzini 
39f366255fSPaolo Bonzini static u8 inb(u16 port)
40f366255fSPaolo Bonzini {
41f366255fSPaolo Bonzini 	u8 data;
42f366255fSPaolo Bonzini 	asm volatile("in %1, %0" : "=a"(data) : "d"(port));
43f366255fSPaolo Bonzini 	return data;
44f366255fSPaolo Bonzini }
45f366255fSPaolo Bonzini 
46f366255fSPaolo Bonzini static void serial_outb(char ch)
47f366255fSPaolo Bonzini {
48f366255fSPaolo Bonzini 	u8 lsr;
49f366255fSPaolo Bonzini 
50f366255fSPaolo Bonzini 	do {
51f366255fSPaolo Bonzini 		lsr = inb(serial_iobase + 0x05);
52f366255fSPaolo Bonzini 	} while (!(lsr & 0x20));
53f366255fSPaolo Bonzini 
54f366255fSPaolo Bonzini 	outb(ch, serial_iobase + 0x00);
55f366255fSPaolo Bonzini }
56f366255fSPaolo Bonzini 
57f366255fSPaolo Bonzini static void serial_init(void)
58f366255fSPaolo Bonzini {
59f366255fSPaolo Bonzini 	u8 lcr;
60f366255fSPaolo Bonzini 
61f366255fSPaolo Bonzini 	/* set DLAB */
62f366255fSPaolo Bonzini 	lcr = inb(serial_iobase + 0x03);
63f366255fSPaolo Bonzini 	lcr |= 0x80;
64f366255fSPaolo Bonzini 	outb(lcr, serial_iobase + 0x03);
65f366255fSPaolo Bonzini 
66f366255fSPaolo Bonzini 	/* set baud rate to 115200 */
67f366255fSPaolo Bonzini 	outb(0x01, serial_iobase + 0x00);
68f366255fSPaolo Bonzini 	outb(0x00, serial_iobase + 0x01);
69f366255fSPaolo Bonzini 
70f366255fSPaolo Bonzini 	/* clear DLAB */
71f366255fSPaolo Bonzini 	lcr = inb(serial_iobase + 0x03);
72f366255fSPaolo Bonzini 	lcr &= ~0x80;
73f366255fSPaolo Bonzini 	outb(lcr, serial_iobase + 0x03);
74f366255fSPaolo Bonzini }
75f366255fSPaolo Bonzini #endif
76f366255fSPaolo Bonzini 
777d36db35SAvi Kivity static void print_serial(const char *buf)
787d36db35SAvi Kivity {
797d36db35SAvi Kivity 	unsigned long len = strlen(buf);
80f366255fSPaolo Bonzini #ifdef USE_SERIAL
81f366255fSPaolo Bonzini 	unsigned long i;
82f366255fSPaolo Bonzini 	if (!serial_inited) {
83f366255fSPaolo Bonzini 	    serial_init();
84f366255fSPaolo Bonzini 	    serial_inited = 1;
85f366255fSPaolo Bonzini 	}
867d36db35SAvi Kivity 
87f366255fSPaolo Bonzini 	for (i = 0; i < len; i++) {
88f366255fSPaolo Bonzini 	    serial_outb(buf[i]);
89f366255fSPaolo Bonzini 	}
90f366255fSPaolo Bonzini #else
915edbb9aeSPaolo Bonzini 	asm volatile ("addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1));
92f366255fSPaolo Bonzini #endif
937d36db35SAvi Kivity }
947d36db35SAvi Kivity 
95b5105e8bSPaolo Bonzini static void print_serial_u32(u32 value)
96b5105e8bSPaolo Bonzini {
97b5105e8bSPaolo Bonzini 	char n[12], *p;
98b5105e8bSPaolo Bonzini 	p = &n[11];
99b5105e8bSPaolo Bonzini 	*p = 0;
100b5105e8bSPaolo Bonzini 	do {
101b5105e8bSPaolo Bonzini 		*--p = '0' + (value % 10);
102b5105e8bSPaolo Bonzini 		value /= 10;
103b5105e8bSPaolo Bonzini 	} while (value > 0);
104b5105e8bSPaolo Bonzini 	print_serial(p);
105b5105e8bSPaolo Bonzini }
106b5105e8bSPaolo Bonzini 
107b393fe28SNadav Amit static int failed;
108b393fe28SNadav Amit 
1097d36db35SAvi Kivity static void exit(int code)
1107d36db35SAvi Kivity {
111f366255fSPaolo Bonzini 	outb(code, 0xf4);
1127d36db35SAvi Kivity }
1137d36db35SAvi Kivity 
1147d36db35SAvi Kivity struct regs {
1157d36db35SAvi Kivity 	u32 eax, ebx, ecx, edx;
1167d36db35SAvi Kivity 	u32 esi, edi, esp, ebp;
1177d36db35SAvi Kivity 	u32 eip, eflags;
1187d36db35SAvi Kivity };
1197d36db35SAvi Kivity 
120975ca087SPeter Feiner struct table_descr {
121975ca087SPeter Feiner 	u16 limit;
122975ca087SPeter Feiner 	void *base;
123975ca087SPeter Feiner } __attribute__((packed));
124975ca087SPeter Feiner 
1257d36db35SAvi Kivity static u64 gdt[] = {
1267d36db35SAvi Kivity 	0,
1277d36db35SAvi Kivity 	0x00cf9b000000ffffull, // flat 32-bit code segment
1287d36db35SAvi Kivity 	0x00cf93000000ffffull, // flat 32-bit data segment
1297d36db35SAvi Kivity };
1307d36db35SAvi Kivity 
131975ca087SPeter Feiner static struct table_descr gdt_descr = {
1327d36db35SAvi Kivity 	sizeof(gdt) - 1,
1337d36db35SAvi Kivity 	gdt,
1347d36db35SAvi Kivity };
1357d36db35SAvi Kivity 
136d4dc402cSAvi Kivity struct insn_desc {
137d4dc402cSAvi Kivity     u16 ptr;
138d4dc402cSAvi Kivity     u16 len;
139d4dc402cSAvi Kivity };
140d4dc402cSAvi Kivity 
14118253fdeSAvi Kivity static struct regs inregs, outregs;
14218253fdeSAvi Kivity 
14318253fdeSAvi Kivity static void exec_in_big_real_mode(struct insn_desc *insn)
1447d36db35SAvi Kivity {
1457d36db35SAvi Kivity 	unsigned long tmp;
1467d36db35SAvi Kivity 	static struct regs save;
1477d36db35SAvi Kivity 	int i;
1487d36db35SAvi Kivity 	extern u8 test_insn[], test_insn_end[];
1497d36db35SAvi Kivity 
150d4dc402cSAvi Kivity 	for (i = 0; i < insn->len; ++i)
151d4dc402cSAvi Kivity 	    test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i];
1527d36db35SAvi Kivity 	for (; i < test_insn_end - test_insn; ++i)
1537d36db35SAvi Kivity 		test_insn[i] = 0x90; // nop
1547d36db35SAvi Kivity 
15518253fdeSAvi Kivity 	save = inregs;
1567d36db35SAvi Kivity 	asm volatile(
1577d36db35SAvi Kivity 		"lgdtl %[gdt_descr] \n\t"
1587d36db35SAvi Kivity 		"mov %%cr0, %[tmp] \n\t"
1597d36db35SAvi Kivity 		"or $1, %[tmp] \n\t"
1607d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
1617d36db35SAvi Kivity 		"mov %[bigseg], %%gs \n\t"
1627d36db35SAvi Kivity 		"and $-2, %[tmp] \n\t"
1637d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
1647d36db35SAvi Kivity 
16532001692SAvi Kivity                 "pushw %[save]+36; popfw \n\t"
1667d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
1677d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
1687d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
1697d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
1707d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
1717d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
1727d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
1737d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
1747d36db35SAvi Kivity 
1757d36db35SAvi Kivity 		"test_insn: . = . + 32\n\t"
1767d36db35SAvi Kivity 		"test_insn_end: \n\t"
1777d36db35SAvi Kivity 
1787d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
1797d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
1807d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
1817d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
1827d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
1837d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
1847d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
1857d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
1867d36db35SAvi Kivity 
1877d36db35SAvi Kivity 		/* Save EFLAGS in outregs*/
1887d36db35SAvi Kivity 		"pushfl \n\t"
1897d36db35SAvi Kivity 		"popl %[save]+36 \n\t"
1907d36db35SAvi Kivity 
1915edbb9aeSPaolo Bonzini 		/* Restore DF for the harness code */
1925edbb9aeSPaolo Bonzini 		"cld\n\t"
1937d36db35SAvi Kivity 		"xor %[tmp], %[tmp] \n\t"
1947d36db35SAvi Kivity 		"mov %[tmp], %%gs \n\t"
1957d36db35SAvi Kivity 		: [tmp]"=&r"(tmp), [save]"+m"(save)
1967d36db35SAvi Kivity 		: [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16)
1977d36db35SAvi Kivity 		: "cc", "memory"
1987d36db35SAvi Kivity 		);
19918253fdeSAvi Kivity 	outregs = save;
2007d36db35SAvi Kivity }
2017d36db35SAvi Kivity 
2027d36db35SAvi Kivity #define R_AX 1
2037d36db35SAvi Kivity #define R_BX 2
2047d36db35SAvi Kivity #define R_CX 4
2057d36db35SAvi Kivity #define R_DX 8
2067d36db35SAvi Kivity #define R_SI 16
2077d36db35SAvi Kivity #define R_DI 32
2087d36db35SAvi Kivity #define R_SP 64
2097d36db35SAvi Kivity #define R_BP 128
2107d36db35SAvi Kivity 
211*2e3f9f1fSThomas Huth static int regs_equal(int ignore)
2127d36db35SAvi Kivity {
21318253fdeSAvi Kivity 	const u32 *p1 = &inregs.eax, *p2 = &outregs.eax;  // yuck
2147d36db35SAvi Kivity 	int i;
2157d36db35SAvi Kivity 
2167d36db35SAvi Kivity 	for (i = 0; i < 8; ++i)
2177d36db35SAvi Kivity 		if (!(ignore & (1 << i)) && p1[i] != p2[i])
2187d36db35SAvi Kivity 			return 0;
2197d36db35SAvi Kivity 	return 1;
2207d36db35SAvi Kivity }
2217d36db35SAvi Kivity 
2226055ea1fSAvi Kivity static void report(const char *name, u16 regs_ignore, _Bool ok)
22381050840SAvi Kivity {
2246055ea1fSAvi Kivity     if (!regs_equal(regs_ignore)) {
2256055ea1fSAvi Kivity 	ok = 0;
2266055ea1fSAvi Kivity     }
22781050840SAvi Kivity     print_serial(ok ? "PASS: " : "FAIL: ");
22881050840SAvi Kivity     print_serial(name);
22981050840SAvi Kivity     print_serial("\n");
230b393fe28SNadav Amit     if (!ok)
231b393fe28SNadav Amit 	failed = 1;
23281050840SAvi Kivity }
23381050840SAvi Kivity 
2347d36db35SAvi Kivity #define MK_INSN(name, str)				\
2357d36db35SAvi Kivity     asm (						\
236d4dc402cSAvi Kivity 	 ".pushsection .data.insn  \n\t"		\
237d4dc402cSAvi Kivity 	 "insn_" #name ": \n\t"				\
238d4dc402cSAvi Kivity 	 ".word 1001f, 1002f - 1001f \n\t"		\
239d4dc402cSAvi Kivity 	 ".popsection \n\t"				\
240d4dc402cSAvi Kivity 	 ".pushsection .text.insn, \"ax\" \n\t"		\
241d4dc402cSAvi Kivity 	 "1001: \n\t"					\
242d4dc402cSAvi Kivity 	 "insn_code_" #name ": " str " \n\t"		\
243d4dc402cSAvi Kivity 	 "1002: \n\t"					\
244d4dc402cSAvi Kivity 	 ".popsection"					\
2457d36db35SAvi Kivity     );							\
246d4dc402cSAvi Kivity     extern struct insn_desc insn_##name;
2477d36db35SAvi Kivity 
248*2e3f9f1fSThomas Huth static void test_xchg(void)
2497d36db35SAvi Kivity {
2507d36db35SAvi Kivity 	MK_INSN(xchg_test1, "xchg %eax,%eax\n\t");
2517d36db35SAvi Kivity 	MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t");
2527d36db35SAvi Kivity 	MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t");
2537d36db35SAvi Kivity 	MK_INSN(xchg_test4, "xchg %eax,%edx\n\t");
2547d36db35SAvi Kivity 	MK_INSN(xchg_test5, "xchg %eax,%esi\n\t");
2557d36db35SAvi Kivity 	MK_INSN(xchg_test6, "xchg %eax,%edi\n\t");
2567d36db35SAvi Kivity 	MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t");
2577d36db35SAvi Kivity 	MK_INSN(xchg_test8, "xchg %eax,%esp\n\t");
2587d36db35SAvi Kivity 
25918253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7};
2607d36db35SAvi Kivity 
26118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test1);
2626055ea1fSAvi Kivity 	report("xchg 1", 0, 1);
26318253fdeSAvi Kivity 
26418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test2);
2656055ea1fSAvi Kivity 	report("xchg 2", R_AX | R_BX,
2666055ea1fSAvi Kivity 	       outregs.eax == inregs.ebx && outregs.ebx == inregs.eax);
2677d36db35SAvi Kivity 
26818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test3);
2696055ea1fSAvi Kivity 	report("xchg 3", R_AX | R_CX,
2706055ea1fSAvi Kivity 	       outregs.eax == inregs.ecx && outregs.ecx == inregs.eax);
2717d36db35SAvi Kivity 
27218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test4);
2736055ea1fSAvi Kivity 	report("xchg 4", R_AX | R_DX,
2746055ea1fSAvi Kivity 	       outregs.eax == inregs.edx && outregs.edx == inregs.eax);
2757d36db35SAvi Kivity 
27618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test5);
2776055ea1fSAvi Kivity 	report("xchg 5", R_AX | R_SI,
2786055ea1fSAvi Kivity 	       outregs.eax == inregs.esi && outregs.esi == inregs.eax);
2797d36db35SAvi Kivity 
28018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test6);
2816055ea1fSAvi Kivity 	report("xchg 6", R_AX | R_DI,
2826055ea1fSAvi Kivity 	       outregs.eax == inregs.edi && outregs.edi == inregs.eax);
2837d36db35SAvi Kivity 
28418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test7);
2856055ea1fSAvi Kivity 	report("xchg 7", R_AX | R_BP,
2866055ea1fSAvi Kivity 	       outregs.eax == inregs.ebp && outregs.ebp == inregs.eax);
2877d36db35SAvi Kivity 
28818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test8);
2896055ea1fSAvi Kivity 	report("xchg 8", R_AX | R_SP,
2906055ea1fSAvi Kivity 	       outregs.eax == inregs.esp && outregs.esp == inregs.eax);
2917d36db35SAvi Kivity }
2927d36db35SAvi Kivity 
293*2e3f9f1fSThomas Huth static void test_shld(void)
2947d36db35SAvi Kivity {
2957d36db35SAvi Kivity 	MK_INSN(shld_test, "shld $8,%edx,%eax\n\t");
2967d36db35SAvi Kivity 
29718253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0xbe, .edx = 0xef000000 };
29818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_shld_test);
2996055ea1fSAvi Kivity 	report("shld", ~0, outregs.eax == 0xbeef);
3007d36db35SAvi Kivity }
3017d36db35SAvi Kivity 
302*2e3f9f1fSThomas Huth static void test_mov_imm(void)
3037d36db35SAvi Kivity {
3047d36db35SAvi Kivity 	MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax");
3057d36db35SAvi Kivity 	MK_INSN(mov_r16_imm_1, "mov $1234, %ax");
3067d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_1, "mov $0x12, %ah");
3077d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_2, "mov $0x34, %al");
3087d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t");
3097d36db35SAvi Kivity 
31018253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
31118253fdeSAvi Kivity 
31218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r16_imm_1);
3136055ea1fSAvi Kivity 	report("mov 1", R_AX, outregs.eax == 1234);
3147d36db35SAvi Kivity 
3157d36db35SAvi Kivity 	/* test mov $imm, %eax */
31618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r32_imm_1);
3176055ea1fSAvi Kivity 	report("mov 2", R_AX, outregs.eax == 1234567890);
3187d36db35SAvi Kivity 
3197d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
32018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_1);
3216055ea1fSAvi Kivity 	report("mov 3", R_AX, outregs.eax == 0x1200);
3227d36db35SAvi Kivity 
32318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_2);
3246055ea1fSAvi Kivity 	report("mov 4", R_AX, outregs.eax == 0x34);
3257d36db35SAvi Kivity 
32618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_3);
3276055ea1fSAvi Kivity 	report("mov 5", R_AX, outregs.eax == 0x1234);
3287d36db35SAvi Kivity }
3297d36db35SAvi Kivity 
330*2e3f9f1fSThomas Huth static void test_sub_imm(void)
3317d36db35SAvi Kivity {
3327d36db35SAvi Kivity 	MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t");
3337d36db35SAvi Kivity 	MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t");
3347d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t");
3357d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t");
3367d36db35SAvi Kivity 
33718253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
33818253fdeSAvi Kivity 
33918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r16_imm_1);
3406055ea1fSAvi Kivity 	report("sub 1", R_AX, outregs.eax == 1224);
3417d36db35SAvi Kivity 
3427d36db35SAvi Kivity 	/* test mov $imm, %eax */
34318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r32_imm_1);
3446055ea1fSAvi Kivity 	report("sub 2", R_AX, outregs.eax == 1234567880);
3457d36db35SAvi Kivity 
3467d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
34718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_1);
3486055ea1fSAvi Kivity 	report("sub 3", R_AX, outregs.eax == 0x0200);
3497d36db35SAvi Kivity 
35018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_2);
3516055ea1fSAvi Kivity 	report("sub 4", R_AX, outregs.eax == 0x24);
3527d36db35SAvi Kivity }
3537d36db35SAvi Kivity 
354*2e3f9f1fSThomas Huth static void test_xor_imm(void)
3557d36db35SAvi Kivity {
3567d36db35SAvi Kivity 	MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t");
3577d36db35SAvi Kivity 	MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t");
3587d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t");
3597d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t");
3607d36db35SAvi Kivity 
36118253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
36218253fdeSAvi Kivity 
36318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r16_imm_1);
3646055ea1fSAvi Kivity 	report("xor 1", R_AX, outregs.eax == 0);
3657d36db35SAvi Kivity 
3667d36db35SAvi Kivity 	/* test mov $imm, %eax */
36718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r32_imm_1);
3686055ea1fSAvi Kivity 	report("xor 2", R_AX, outregs.eax == 0);
3697d36db35SAvi Kivity 
3707d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
37118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_1);
3726055ea1fSAvi Kivity 	report("xor 3", R_AX, outregs.eax == 0);
3737d36db35SAvi Kivity 
37418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_2);
3756055ea1fSAvi Kivity 	report("xor 4", R_AX, outregs.eax == 0);
3767d36db35SAvi Kivity }
3777d36db35SAvi Kivity 
378*2e3f9f1fSThomas Huth static void test_cmp_imm(void)
3797d36db35SAvi Kivity {
3807d36db35SAvi Kivity 	MK_INSN(cmp_test1, "mov $0x34, %al\n\t"
3817d36db35SAvi Kivity 			   "cmp $0x34, %al\n\t");
3827d36db35SAvi Kivity 	MK_INSN(cmp_test2, "mov $0x34, %al\n\t"
3837d36db35SAvi Kivity 			   "cmp $0x39, %al\n\t");
3847d36db35SAvi Kivity 	MK_INSN(cmp_test3, "mov $0x34, %al\n\t"
3857d36db35SAvi Kivity 			   "cmp $0x24, %al\n\t");
3867d36db35SAvi Kivity 
38718253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
38818253fdeSAvi Kivity 
3897d36db35SAvi Kivity 	/* test cmp imm8 with AL */
3907d36db35SAvi Kivity 	/* ZF: (bit 6) Zero Flag becomes 1 if an operation results
3917d36db35SAvi Kivity 	 * in a 0 writeback, or 0 register
3927d36db35SAvi Kivity 	 */
39318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test1);
3946055ea1fSAvi Kivity 	report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6));
3957d36db35SAvi Kivity 
39618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test2);
3976055ea1fSAvi Kivity 	report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0);
3987d36db35SAvi Kivity 
39918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test3);
4006055ea1fSAvi Kivity 	report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0);
4017d36db35SAvi Kivity }
4027d36db35SAvi Kivity 
403*2e3f9f1fSThomas Huth static void test_add_imm(void)
4047d36db35SAvi Kivity {
4057d36db35SAvi Kivity 	MK_INSN(add_test1, "mov $0x43211234, %eax \n\t"
4067d36db35SAvi Kivity 			   "add $0x12344321, %eax \n\t");
4077d36db35SAvi Kivity 	MK_INSN(add_test2, "mov $0x12, %eax \n\t"
4087d36db35SAvi Kivity 			   "add $0x21, %al\n\t");
4097d36db35SAvi Kivity 
41018253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
41118253fdeSAvi Kivity 
41218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test1);
4136055ea1fSAvi Kivity 	report("add 1", ~0, outregs.eax == 0x55555555);
4147d36db35SAvi Kivity 
41518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test2);
4166055ea1fSAvi Kivity 	report("add 2", ~0, outregs.eax == 0x33);
4177d36db35SAvi Kivity }
4187d36db35SAvi Kivity 
419*2e3f9f1fSThomas Huth static void test_eflags_insn(void)
4207d36db35SAvi Kivity {
4217d36db35SAvi Kivity 	MK_INSN(clc, "clc");
422b3261e48SMohammed Gamal 	MK_INSN(stc, "stc");
4237d36db35SAvi Kivity 	MK_INSN(cli, "cli");
4247d36db35SAvi Kivity 	MK_INSN(sti, "sti");
4257d36db35SAvi Kivity 	MK_INSN(cld, "cld");
4267d36db35SAvi Kivity 	MK_INSN(std, "std");
4277d36db35SAvi Kivity 
42818253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
42918253fdeSAvi Kivity 
43018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_clc);
4316055ea1fSAvi Kivity 	report("clc", ~0, (outregs.eflags & 1) == 0);
4327d36db35SAvi Kivity 
43318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_stc);
4346055ea1fSAvi Kivity 	report("stc", ~0, (outregs.eflags & 1) == 1);
435b3261e48SMohammed Gamal 
43618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cli);
4376055ea1fSAvi Kivity 	report("cli", ~0, !(outregs.eflags & (1 << 9)));
4387d36db35SAvi Kivity 
43918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sti);
4406055ea1fSAvi Kivity 	report("sti", ~0, outregs.eflags & (1 << 9));
4417d36db35SAvi Kivity 
44218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cld);
4436055ea1fSAvi Kivity 	report("cld", ~0, !(outregs.eflags & (1 << 10)));
4447d36db35SAvi Kivity 
44518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_std);
4466055ea1fSAvi Kivity 	report("std", ~0, (outregs.eflags & (1 << 10)));
4477d36db35SAvi Kivity }
4487d36db35SAvi Kivity 
449*2e3f9f1fSThomas Huth static void test_io(void)
4507d36db35SAvi Kivity {
4517d36db35SAvi Kivity 	MK_INSN(io_test1, "mov $0xff, %al \n\t"
4527d36db35SAvi Kivity 		          "out %al, $0xe0 \n\t"
4537d36db35SAvi Kivity 		          "mov $0x00, %al \n\t"
4547d36db35SAvi Kivity 			  "in $0xe0, %al \n\t");
4557d36db35SAvi Kivity 	MK_INSN(io_test2, "mov $0xffff, %ax \n\t"
4567d36db35SAvi Kivity 			  "out %ax, $0xe0 \n\t"
4577d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
4587d36db35SAvi Kivity 			  "in $0xe0, %ax \n\t");
4597d36db35SAvi Kivity 	MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t"
4607d36db35SAvi Kivity 			  "out %eax, $0xe0 \n\t"
4617d36db35SAvi Kivity 			  "mov $0x000000, %eax \n\t"
4627d36db35SAvi Kivity 			  "in $0xe0, %eax \n\t");
4637d36db35SAvi Kivity 	MK_INSN(io_test4, "mov $0xe0, %dx \n\t"
4647d36db35SAvi Kivity 			  "mov $0xff, %al \n\t"
4657d36db35SAvi Kivity 			  "out %al, %dx \n\t"
4667d36db35SAvi Kivity 			  "mov $0x00, %al \n\t"
4677d36db35SAvi Kivity 			  "in %dx, %al \n\t");
4687d36db35SAvi Kivity 	MK_INSN(io_test5, "mov $0xe0, %dx \n\t"
4697d36db35SAvi Kivity 			  "mov $0xffff, %ax \n\t"
4707d36db35SAvi Kivity 			  "out %ax, %dx \n\t"
4717d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
4727d36db35SAvi Kivity 			  "in %dx, %ax \n\t");
4737d36db35SAvi Kivity 	MK_INSN(io_test6, "mov $0xe0, %dx \n\t"
4747d36db35SAvi Kivity 			  "mov $0xffffffff, %eax \n\t"
4757d36db35SAvi Kivity 			  "out %eax, %dx \n\t"
4767d36db35SAvi Kivity 			  "mov $0x00000000, %eax \n\t"
4777d36db35SAvi Kivity 			  "in %dx, %eax \n\t");
4787d36db35SAvi Kivity 
47918253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
48018253fdeSAvi Kivity 
48118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test1);
4826055ea1fSAvi Kivity 	report("pio 1", R_AX, outregs.eax == 0xff);
4837d36db35SAvi Kivity 
48418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test2);
4856055ea1fSAvi Kivity 	report("pio 2", R_AX, outregs.eax == 0xffff);
4867d36db35SAvi Kivity 
48718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test3);
4886055ea1fSAvi Kivity 	report("pio 3", R_AX, outregs.eax == 0xffffffff);
4897d36db35SAvi Kivity 
49018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test4);
4916055ea1fSAvi Kivity 	report("pio 4", R_AX|R_DX, outregs.eax == 0xff);
4927d36db35SAvi Kivity 
49318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test5);
4946055ea1fSAvi Kivity 	report("pio 5", R_AX|R_DX, outregs.eax == 0xffff);
4957d36db35SAvi Kivity 
49618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test6);
4976055ea1fSAvi Kivity 	report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff);
4987d36db35SAvi Kivity }
4997d36db35SAvi Kivity 
500c0b7268dSAvi Kivity asm ("retf: lretw");
501*2e3f9f1fSThomas Huth extern void retf(void);
502c0b7268dSAvi Kivity 
5034f66bc86SBruce Rogers asm ("retf_imm: lretw $10");
504*2e3f9f1fSThomas Huth extern void retf_imm(void);
5054f66bc86SBruce Rogers 
506*2e3f9f1fSThomas Huth static void test_call(void)
5077d36db35SAvi Kivity {
5087d36db35SAvi Kivity 	u32 esp[16];
509c0b7268dSAvi Kivity 	u32 addr;
5107d36db35SAvi Kivity 
51118253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
5127d36db35SAvi Kivity 	inregs.esp = (u32)esp;
5137d36db35SAvi Kivity 
5147d36db35SAvi Kivity 	MK_INSN(call1, "mov $test_function, %eax \n\t"
5157d36db35SAvi Kivity 		       "call *%eax\n\t");
5167d36db35SAvi Kivity 	MK_INSN(call_near1, "jmp 2f\n\t"
5177d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5187d36db35SAvi Kivity 			    "ret\n\t"
5197d36db35SAvi Kivity 			    "2: call 1b\t");
5207d36db35SAvi Kivity 	MK_INSN(call_near2, "call 1f\n\t"
5217d36db35SAvi Kivity 			    "jmp 2f\n\t"
5227d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5237d36db35SAvi Kivity 			    "ret\n\t"
5247d36db35SAvi Kivity 			    "2:\t");
525c0b7268dSAvi Kivity 	MK_INSN(call_far1,  "lcallw *(%ebx)\n\t");
526556d2680SWei Yongjun 	MK_INSN(call_far2,  "lcallw $0, $retf\n\t");
527c6061817SAvi Kivity 	MK_INSN(ret_imm,    "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b");
5284f66bc86SBruce Rogers 	MK_INSN(retf_imm,   "sub $10, %sp; lcallw $0, $retf_imm");
5297d36db35SAvi Kivity 
53018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call1);
5316055ea1fSAvi Kivity 	report("call 1", R_AX, outregs.eax == 0x1234);
5327d36db35SAvi Kivity 
53318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near1);
5346055ea1fSAvi Kivity 	report("call near 1", R_AX, outregs.eax == 0x1234);
5357d36db35SAvi Kivity 
53618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near2);
5376055ea1fSAvi Kivity 	report("call near 2", R_AX, outregs.eax == 0x1234);
538c0b7268dSAvi Kivity 
539c0b7268dSAvi Kivity 	addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f);
540c0b7268dSAvi Kivity 	inregs.ebx = (unsigned)&addr;
54118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_far1);
5426055ea1fSAvi Kivity 	report("call far 1", 0, 1);
543c6061817SAvi Kivity 
544556d2680SWei Yongjun 	exec_in_big_real_mode(&insn_call_far2);
545556d2680SWei Yongjun 	report("call far 2", 0, 1);
546556d2680SWei Yongjun 
54718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_ret_imm);
5486055ea1fSAvi Kivity 	report("ret imm 1", 0, 1);
5494f66bc86SBruce Rogers 
5504f66bc86SBruce Rogers 	exec_in_big_real_mode(&insn_retf_imm);
5514f66bc86SBruce Rogers 	report("retf imm 1", 0, 1);
5527d36db35SAvi Kivity }
5537d36db35SAvi Kivity 
554*2e3f9f1fSThomas Huth static void test_jcc_short(void)
5557d36db35SAvi Kivity {
5567d36db35SAvi Kivity 	MK_INSN(jnz_short1, "jnz 1f\n\t"
5577d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
5587d36db35SAvi Kivity 		            "1:\n\t");
5597d36db35SAvi Kivity 	MK_INSN(jnz_short2, "1:\n\t"
5607d36db35SAvi Kivity 			    "cmp $0x1234, %eax\n\t"
5617d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
5627d36db35SAvi Kivity 		            "jnz 1b\n\t");
5637d36db35SAvi Kivity 	MK_INSN(jmp_short1, "jmp 1f\n\t"
5647d36db35SAvi Kivity 		      "mov $0x1234, %eax\n\t"
5657d36db35SAvi Kivity 		      "1:\n\t");
5667d36db35SAvi Kivity 
56718253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
5687d36db35SAvi Kivity 
56918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short1);
5706055ea1fSAvi Kivity 	report("jnz short 1", ~0, 1);
57118253fdeSAvi Kivity 
57218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short2);
5736055ea1fSAvi Kivity 	report("jnz short 2", R_AX, (outregs.eflags & (1 << 6)));
5747d36db35SAvi Kivity 
57518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_short1);
5766055ea1fSAvi Kivity 	report("jmp short 1", ~0, 1);
5777d36db35SAvi Kivity }
5787d36db35SAvi Kivity 
579*2e3f9f1fSThomas Huth static void test_jcc_near(void)
5807d36db35SAvi Kivity {
5817d36db35SAvi Kivity 	/* encode near jmp manually. gas will not do it if offsets < 127 byte */
5827d36db35SAvi Kivity 	MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t"
5837d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
5847d36db35SAvi Kivity 	MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t"
5857d36db35SAvi Kivity 			   "mov $0x1234, %eax\n\t"
5867d36db35SAvi Kivity 		           ".byte 0x0f, 0x85, 0xf0, 0xff\n\t");
5877d36db35SAvi Kivity 	MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t"
5887d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
5897d36db35SAvi Kivity 
59018253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
5917d36db35SAvi Kivity 
59218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near1);
5936055ea1fSAvi Kivity 	report("jnz near 1", 0, 1);
59418253fdeSAvi Kivity 
59518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near2);
5966055ea1fSAvi Kivity 	report("jnz near 2", R_AX, outregs.eflags & (1 << 6));
5977d36db35SAvi Kivity 
59818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_near1);
5996055ea1fSAvi Kivity 	report("jmp near 1", 0, 1);
6007d36db35SAvi Kivity }
6017d36db35SAvi Kivity 
602*2e3f9f1fSThomas Huth static void test_long_jmp(void)
6037d36db35SAvi Kivity {
6047d36db35SAvi Kivity 	u32 esp[16];
6057d36db35SAvi Kivity 
60618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
6074aa22949SAvi Kivity 	inregs.esp = (u32)(esp+16);
6087d36db35SAvi Kivity 	MK_INSN(long_jmp, "call 1f\n\t"
6097d36db35SAvi Kivity 			  "jmp 2f\n\t"
6107d36db35SAvi Kivity 			  "1: jmp $0, $test_function\n\t"
6117d36db35SAvi Kivity 		          "2:\n\t");
61218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_long_jmp);
6136055ea1fSAvi Kivity 	report("jmp far 1", R_AX, outregs.eax == 0x1234);
6147d36db35SAvi Kivity }
615fa74f8a6SMohammed Gamal 
616*2e3f9f1fSThomas Huth static void test_push_pop(void)
6177d36db35SAvi Kivity {
6187d36db35SAvi Kivity 	MK_INSN(push32, "mov $0x12345678, %eax\n\t"
6197d36db35SAvi Kivity 			"push %eax\n\t"
6207d36db35SAvi Kivity 			"pop %ebx\n\t");
6217d36db35SAvi Kivity 	MK_INSN(push16, "mov $0x1234, %ax\n\t"
6227d36db35SAvi Kivity 			"push %ax\n\t"
6237d36db35SAvi Kivity 			"pop %bx\n\t");
6247d36db35SAvi Kivity 
6257d36db35SAvi Kivity 	MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten
6267d36db35SAvi Kivity 			 "mov $0x123, %ax\n\t"
6277d36db35SAvi Kivity 			 "mov %ax, %es\n\t"
6287d36db35SAvi Kivity 			 "push %es\n\t"
6297d36db35SAvi Kivity 			 "pop %bx \n\t"
6307d36db35SAvi Kivity 			 );
6317d36db35SAvi Kivity 	MK_INSN(pop_es, "push %ax\n\t"
6327d36db35SAvi Kivity 			"pop %es\n\t"
6337d36db35SAvi Kivity 			"mov %es, %bx\n\t"
6347d36db35SAvi Kivity 			);
6357d36db35SAvi Kivity 	MK_INSN(push_pop_ss, "push %ss\n\t"
6367d36db35SAvi Kivity 			     "pushw %ax\n\t"
6377d36db35SAvi Kivity 			     "popw %ss\n\t"
6387d36db35SAvi Kivity 			     "mov %ss, %bx\n\t"
6397d36db35SAvi Kivity 			     "pop %ss\n\t"
6407d36db35SAvi Kivity 			);
6417d36db35SAvi Kivity 	MK_INSN(push_pop_fs, "push %fs\n\t"
6427d36db35SAvi Kivity 			     "pushl %eax\n\t"
6437d36db35SAvi Kivity 			     "popl %fs\n\t"
6447d36db35SAvi Kivity 			     "mov %fs, %ebx\n\t"
6457d36db35SAvi Kivity 			     "pop %fs\n\t"
6467d36db35SAvi Kivity 			);
64709b657b6SAvi Kivity 	MK_INSN(push_pop_high_esp_bits,
64809b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
64909b657b6SAvi Kivity 		"push %ax; \n\t"
65009b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
65109b657b6SAvi Kivity 		"pop %bx");
6527d36db35SAvi Kivity 
65318253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
65418253fdeSAvi Kivity 
65518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push32);
6566055ea1fSAvi Kivity 	report("push/pop 1", R_AX|R_BX,
6576055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x12345678);
6587d36db35SAvi Kivity 
65918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push16);
6606055ea1fSAvi Kivity 	report("push/pop 2", R_AX|R_BX,
6616055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x1234);
6627d36db35SAvi Kivity 
66318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_es);
6646055ea1fSAvi Kivity 	report("push/pop 3", R_AX|R_BX,
6656055ea1fSAvi Kivity 	       outregs.ebx == outregs.eax && outregs.eax == 0x123);
6667d36db35SAvi Kivity 
66718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pop_es);
6686055ea1fSAvi Kivity 	report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax);
6697d36db35SAvi Kivity 
67018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_ss);
6716055ea1fSAvi Kivity 	report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax);
6727d36db35SAvi Kivity 
67318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_fs);
6746055ea1fSAvi Kivity 	report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax);
67509b657b6SAvi Kivity 
67609b657b6SAvi Kivity 	inregs.eax = 0x9977;
67709b657b6SAvi Kivity 	inregs.ebx = 0x7799;
67809b657b6SAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_high_esp_bits);
67909b657b6SAvi Kivity 	report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977);
6807d36db35SAvi Kivity }
6817d36db35SAvi Kivity 
682*2e3f9f1fSThomas Huth static void test_null(void)
6837d36db35SAvi Kivity {
684d4dc402cSAvi Kivity 	MK_INSN(null, "");
685d4dc402cSAvi Kivity 
68618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
68718253fdeSAvi Kivity 
68818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_null);
6896055ea1fSAvi Kivity 	report("null", 0, 1);
6907d36db35SAvi Kivity }
6917d36db35SAvi Kivity 
6927d36db35SAvi Kivity struct {
6937d36db35SAvi Kivity     char stack[500];
6947d36db35SAvi Kivity     char top[];
6957d36db35SAvi Kivity } tmp_stack;
6967d36db35SAvi Kivity 
697*2e3f9f1fSThomas Huth static void test_pusha_popa(void)
6987d36db35SAvi Kivity {
6997d36db35SAvi Kivity 	MK_INSN(pusha, "pusha\n\t"
7007d36db35SAvi Kivity 		       "pop %edi\n\t"
7017d36db35SAvi Kivity 		       "pop %esi\n\t"
7027d36db35SAvi Kivity 		       "pop %ebp\n\t"
7037d36db35SAvi Kivity 		       "add $4, %esp\n\t"
7047d36db35SAvi Kivity 		       "pop %ebx\n\t"
7057d36db35SAvi Kivity 		       "pop %edx\n\t"
7067d36db35SAvi Kivity 		       "pop %ecx\n\t"
7077d36db35SAvi Kivity 		       "pop %eax\n\t"
7087d36db35SAvi Kivity 		       );
7097d36db35SAvi Kivity 
7107d36db35SAvi Kivity 	MK_INSN(popa, "push %eax\n\t"
7117d36db35SAvi Kivity 		      "push %ecx\n\t"
7127d36db35SAvi Kivity 		      "push %edx\n\t"
7137d36db35SAvi Kivity 		      "push %ebx\n\t"
7147d36db35SAvi Kivity 		      "push %esp\n\t"
7157d36db35SAvi Kivity 		      "push %ebp\n\t"
7167d36db35SAvi Kivity 		      "push %esi\n\t"
7177d36db35SAvi Kivity 		      "push %edi\n\t"
7187d36db35SAvi Kivity 		      "popa\n\t"
7197d36db35SAvi Kivity 		      );
7207d36db35SAvi Kivity 
72118253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top };
7227d36db35SAvi Kivity 
72318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pusha);
7246055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
72518253fdeSAvi Kivity 
72618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_popa);
7276055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
7287d36db35SAvi Kivity }
7297d36db35SAvi Kivity 
730*2e3f9f1fSThomas Huth static void test_iret(void)
7317d36db35SAvi Kivity {
7327d36db35SAvi Kivity 	MK_INSN(iret32, "pushf\n\t"
7337d36db35SAvi Kivity 			"pushl %cs\n\t"
7347d36db35SAvi Kivity 			"call 1f\n\t" /* a near call will push eip onto the stack */
7357d36db35SAvi Kivity 			"jmp 2f\n\t"
7367d36db35SAvi Kivity 			"1: iret\n\t"
7377d36db35SAvi Kivity 			"2:\n\t"
7387d36db35SAvi Kivity 		     );
7397d36db35SAvi Kivity 
7407d36db35SAvi Kivity 	MK_INSN(iret16, "pushfw\n\t"
7417d36db35SAvi Kivity 			"pushw %cs\n\t"
7427d36db35SAvi Kivity 			"callw 1f\n\t"
7437d36db35SAvi Kivity 			"jmp 2f\n\t"
7447d36db35SAvi Kivity 			"1: iretw\n\t"
7457d36db35SAvi Kivity 			"2:\n\t");
7467d36db35SAvi Kivity 
7477d36db35SAvi Kivity 	MK_INSN(iret_flags32, "pushfl\n\t"
7487d36db35SAvi Kivity 			      "popl %eax\n\t"
7497d36db35SAvi Kivity 			      "andl $~0x2, %eax\n\t"
750964942e8SNadav Amit 			      "orl $0xffc18028, %eax\n\t"
7517d36db35SAvi Kivity 			      "pushl %eax\n\t"
7527d36db35SAvi Kivity 			      "pushl %cs\n\t"
7537d36db35SAvi Kivity 			      "call 1f\n\t"
7547d36db35SAvi Kivity 			      "jmp 2f\n\t"
7557d36db35SAvi Kivity 			      "1: iret\n\t"
7567d36db35SAvi Kivity 			      "2:\n\t");
7577d36db35SAvi Kivity 
7587d36db35SAvi Kivity 	MK_INSN(iret_flags16, "pushfw\n\t"
7597d36db35SAvi Kivity 			      "popw %ax\n\t"
7607d36db35SAvi Kivity 			      "and $~0x2, %ax\n\t"
7617d36db35SAvi Kivity 			      "or $0x8028, %ax\n\t"
7627d36db35SAvi Kivity 			      "pushw %ax\n\t"
7637d36db35SAvi Kivity 			      "pushw %cs\n\t"
7647d36db35SAvi Kivity 			      "callw 1f\n\t"
7657d36db35SAvi Kivity 			      "jmp 2f\n\t"
7667d36db35SAvi Kivity 			      "1: iretw\n\t"
7677d36db35SAvi Kivity 			      "2:\n\t");
7687d36db35SAvi Kivity 
76918253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
7707d36db35SAvi Kivity 
77118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret32);
7726055ea1fSAvi Kivity 	report("iret 1", 0, 1);
7737d36db35SAvi Kivity 
77418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret16);
7756055ea1fSAvi Kivity 	report("iret 2", 0, 1);
7767d36db35SAvi Kivity 
77718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags32);
7786055ea1fSAvi Kivity 	report("iret 3", R_AX, 1);
779964942e8SNadav Amit 	report("rflags.rf", ~0, !(outregs.eflags & (1 << 16)));
78018253fdeSAvi Kivity 
78118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags16);
7826055ea1fSAvi Kivity 	report("iret 4", R_AX, 1);
7837d36db35SAvi Kivity }
7847d36db35SAvi Kivity 
785*2e3f9f1fSThomas Huth static void test_int(void)
78696b9ca1eSMohammed Gamal {
78718253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
78896b9ca1eSMohammed Gamal 
78996b9ca1eSMohammed Gamal 	*(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */
79096b9ca1eSMohammed Gamal 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
79196b9ca1eSMohammed Gamal 
79296b9ca1eSMohammed Gamal 	MK_INSN(int11, "int $0x11\n\t");
79396b9ca1eSMohammed Gamal 
79418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_int11);
7956055ea1fSAvi Kivity 	report("int 1", 0, 1);
79696b9ca1eSMohammed Gamal }
79796b9ca1eSMohammed Gamal 
798*2e3f9f1fSThomas Huth static void test_imul(void)
799fa74f8a6SMohammed Gamal {
800fa74f8a6SMohammed Gamal 	MK_INSN(imul8_1, "mov $2, %al\n\t"
801fa74f8a6SMohammed Gamal 			"mov $-4, %cx\n\t"
802fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
803fa74f8a6SMohammed Gamal 
804fa74f8a6SMohammed Gamal 	MK_INSN(imul16_1, "mov $2, %ax\n\t"
805fa74f8a6SMohammed Gamal 		      "mov $-4, %cx\n\t"
806fa74f8a6SMohammed Gamal 		      "imul %cx\n\t");
807fa74f8a6SMohammed Gamal 
808fa74f8a6SMohammed Gamal 	MK_INSN(imul32_1, "mov $2, %eax\n\t"
809fa74f8a6SMohammed Gamal 		       "mov $-4, %ecx\n\t"
810fa74f8a6SMohammed Gamal 		       "imul %ecx\n\t");
811fa74f8a6SMohammed Gamal 
812fa74f8a6SMohammed Gamal 	MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t"
813fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
814fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
815fa74f8a6SMohammed Gamal 
816fa74f8a6SMohammed Gamal 	MK_INSN(imul16_2, "mov $2, %ax\n\t"
817fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
818fa74f8a6SMohammed Gamal 			"imul %cx\n\t");
819fa74f8a6SMohammed Gamal 
820fa74f8a6SMohammed Gamal 	MK_INSN(imul32_2, "mov $2, %eax\n\t"
821fa74f8a6SMohammed Gamal 			"mov $4, %ecx\n\t"
822fa74f8a6SMohammed Gamal 			"imul %ecx\n\t");
823fa74f8a6SMohammed Gamal 
82418253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
82518253fdeSAvi Kivity 
82618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_1);
8276055ea1fSAvi Kivity 	report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8);
828fa74f8a6SMohammed Gamal 
82918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_1);
8306055ea1fSAvi Kivity 	report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8);
831fa74f8a6SMohammed Gamal 
83218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_1);
8336055ea1fSAvi Kivity 	report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8);
834fa74f8a6SMohammed Gamal 
83518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_2);
8366055ea1fSAvi Kivity 	report("imul 4", R_AX | R_CX | R_DX,
8376055ea1fSAvi Kivity 	       (outregs.eax & 0xffff) == 8
83881050840SAvi Kivity 	       && (outregs.eax & 0xffff0000) == 0x12340000);
839fa74f8a6SMohammed Gamal 
84018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_2);
8416055ea1fSAvi Kivity 	report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8);
842fa74f8a6SMohammed Gamal 
84318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_2);
8446055ea1fSAvi Kivity 	report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8);
845fa74f8a6SMohammed Gamal }
846fa74f8a6SMohammed Gamal 
847*2e3f9f1fSThomas Huth static void test_mul(void)
84859317bd1SMohammed Gamal {
84959317bd1SMohammed Gamal 	MK_INSN(mul8, "mov $2, %al\n\t"
85059317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
85159317bd1SMohammed Gamal 			"imul %cl\n\t");
85259317bd1SMohammed Gamal 
85359317bd1SMohammed Gamal 	MK_INSN(mul16, "mov $2, %ax\n\t"
85459317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
85559317bd1SMohammed Gamal 			"imul %cx\n\t");
85659317bd1SMohammed Gamal 
85759317bd1SMohammed Gamal 	MK_INSN(mul32, "mov $2, %eax\n\t"
85859317bd1SMohammed Gamal 			"mov $4, %ecx\n\t"
85959317bd1SMohammed Gamal 			"imul %ecx\n\t");
86059317bd1SMohammed Gamal 
86118253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
86218253fdeSAvi Kivity 
86318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul8);
8646055ea1fSAvi Kivity 	report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8);
86559317bd1SMohammed Gamal 
86618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul16);
8676055ea1fSAvi Kivity 	report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8);
86859317bd1SMohammed Gamal 
86918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul32);
8706055ea1fSAvi Kivity 	report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8);
87159317bd1SMohammed Gamal }
87259317bd1SMohammed Gamal 
873*2e3f9f1fSThomas Huth static void test_div(void)
8740d4c7614SMohammed Gamal {
8750d4c7614SMohammed Gamal 	MK_INSN(div8, "mov $257, %ax\n\t"
8760d4c7614SMohammed Gamal 			"mov $2, %cl\n\t"
8770d4c7614SMohammed Gamal 			"div %cl\n\t");
8780d4c7614SMohammed Gamal 
8790d4c7614SMohammed Gamal 	MK_INSN(div16, "mov $512, %ax\n\t"
8800d4c7614SMohammed Gamal 			"mov $5, %cx\n\t"
8810d4c7614SMohammed Gamal 			"div %cx\n\t");
8820d4c7614SMohammed Gamal 
8830d4c7614SMohammed Gamal 	MK_INSN(div32, "mov $512, %eax\n\t"
8840d4c7614SMohammed Gamal 			"mov $5, %ecx\n\t"
8850d4c7614SMohammed Gamal 			"div %ecx\n\t");
8860d4c7614SMohammed Gamal 
88718253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
88818253fdeSAvi Kivity 
88918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div8);
8906055ea1fSAvi Kivity 	report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384);
8910d4c7614SMohammed Gamal 
89218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div16);
8936055ea1fSAvi Kivity 	report("div 2", R_AX | R_CX | R_DX,
8946055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
8950d4c7614SMohammed Gamal 
89618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div32);
8976055ea1fSAvi Kivity 	report("div 3", R_AX | R_CX | R_DX,
8986055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
8990d4c7614SMohammed Gamal }
9000d4c7614SMohammed Gamal 
901*2e3f9f1fSThomas Huth static void test_idiv(void)
9020d4c7614SMohammed Gamal {
9030d4c7614SMohammed Gamal 	MK_INSN(idiv8, "mov $256, %ax\n\t"
9040d4c7614SMohammed Gamal 			"mov $-2, %cl\n\t"
9050d4c7614SMohammed Gamal 			"idiv %cl\n\t");
9060d4c7614SMohammed Gamal 
9070d4c7614SMohammed Gamal 	MK_INSN(idiv16, "mov $512, %ax\n\t"
9080d4c7614SMohammed Gamal 			"mov $-2, %cx\n\t"
9090d4c7614SMohammed Gamal 			"idiv %cx\n\t");
9100d4c7614SMohammed Gamal 
9110d4c7614SMohammed Gamal 	MK_INSN(idiv32, "mov $512, %eax\n\t"
9120d4c7614SMohammed Gamal 			"mov $-2, %ecx\n\t"
9130d4c7614SMohammed Gamal 			"idiv %ecx\n\t");
9140d4c7614SMohammed Gamal 
91518253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
91618253fdeSAvi Kivity 
91718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv8);
9186055ea1fSAvi Kivity 	report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128);
9190d4c7614SMohammed Gamal 
92018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv16);
9216055ea1fSAvi Kivity 	report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256);
9220d4c7614SMohammed Gamal 
92318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv32);
9246055ea1fSAvi Kivity 	report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256);
9250d4c7614SMohammed Gamal }
9260d4c7614SMohammed Gamal 
927*2e3f9f1fSThomas Huth static void test_cbw(void)
9286e293cf5SWei Yongjun {
9296e293cf5SWei Yongjun 	MK_INSN(cbw, "mov $0xFE, %eax \n\t"
9306e293cf5SWei Yongjun 		     "cbw\n\t");
9316e293cf5SWei Yongjun 	MK_INSN(cwde, "mov $0xFFFE, %eax \n\t"
9326e293cf5SWei Yongjun 		      "cwde\n\t");
9336e293cf5SWei Yongjun 
93418253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
93518253fdeSAvi Kivity 
93618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cbw);
9376055ea1fSAvi Kivity 	report("cbq 1", ~0, outregs.eax == 0xFFFE);
9386e293cf5SWei Yongjun 
93918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwde);
9406055ea1fSAvi Kivity 	report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE);
9416e293cf5SWei Yongjun }
9426e293cf5SWei Yongjun 
943*2e3f9f1fSThomas Huth static void test_loopcc(void)
944eacef4e2SWei Yongjun {
945eacef4e2SWei Yongjun 	MK_INSN(loop, "mov $10, %ecx\n\t"
946eacef4e2SWei Yongjun 		      "1: inc %eax\n\t"
947eacef4e2SWei Yongjun 		      "loop 1b\n\t");
948eacef4e2SWei Yongjun 
949eacef4e2SWei Yongjun 	MK_INSN(loope, "mov $10, %ecx\n\t"
950eacef4e2SWei Yongjun 		       "mov $1, %eax\n\t"
951eacef4e2SWei Yongjun 		       "1: dec %eax\n\t"
952eacef4e2SWei Yongjun 		       "loope 1b\n\t");
953eacef4e2SWei Yongjun 
954eacef4e2SWei Yongjun 	MK_INSN(loopne, "mov $10, %ecx\n\t"
955eacef4e2SWei Yongjun 		        "mov $5, %eax\n\t"
956eacef4e2SWei Yongjun 		        "1: dec %eax\n\t"
957eacef4e2SWei Yongjun 			"loopne 1b\n\t");
958eacef4e2SWei Yongjun 
95918253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
960eacef4e2SWei Yongjun 
96118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loop);
9626055ea1fSAvi Kivity 	report("LOOPcc short 1", R_AX, outregs.eax == 10);
96318253fdeSAvi Kivity 
96418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loope);
9656055ea1fSAvi Kivity 	report("LOOPcc short 2", R_AX | R_CX,
9666055ea1fSAvi Kivity 	       outregs.eax == -1 && outregs.ecx == 8);
967eacef4e2SWei Yongjun 
96818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loopne);
9696055ea1fSAvi Kivity 	report("LOOPcc short 3", R_AX | R_CX,
9706055ea1fSAvi Kivity 	       outregs.eax == 0 && outregs.ecx == 5);
971eacef4e2SWei Yongjun }
972eacef4e2SWei Yongjun 
973b274feedSAvi Kivity static void test_das(void)
974b274feedSAvi Kivity {
975b274feedSAvi Kivity     short i;
97681050840SAvi Kivity     u16 nr_fail = 0;
977b274feedSAvi Kivity     static unsigned test_cases[1024] = {
978b274feedSAvi Kivity         0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00,
979b274feedSAvi Kivity         0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01,
980b274feedSAvi Kivity         0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02,
981b274feedSAvi Kivity         0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03,
982b274feedSAvi Kivity         0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04,
983b274feedSAvi Kivity         0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05,
984b274feedSAvi Kivity         0x06000606, 0x8701a606, 0x56100006, 0x9711a006,
985b274feedSAvi Kivity         0x02000707, 0x8301a707, 0x12100107, 0x9311a107,
986b274feedSAvi Kivity         0x02000808, 0x8301a808, 0x12100208, 0x9311a208,
987b274feedSAvi Kivity         0x06000909, 0x8701a909, 0x16100309, 0x9711a309,
988b274feedSAvi Kivity         0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a,
989b274feedSAvi Kivity         0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b,
990b274feedSAvi Kivity         0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c,
991b274feedSAvi Kivity         0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d,
992b274feedSAvi Kivity         0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e,
993b274feedSAvi Kivity         0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f,
994b274feedSAvi Kivity         0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10,
995b274feedSAvi Kivity         0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11,
996b274feedSAvi Kivity         0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12,
997b274feedSAvi Kivity         0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13,
998b274feedSAvi Kivity         0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14,
999b274feedSAvi Kivity         0x02001515, 0x8301b515, 0x16100f15, 0x9711af15,
1000b274feedSAvi Kivity         0x02001616, 0x8301b616, 0x12101016, 0x9311b016,
1001b274feedSAvi Kivity         0x06001717, 0x8701b717, 0x16101117, 0x9711b117,
1002b274feedSAvi Kivity         0x06001818, 0x8701b818, 0x16101218, 0x9711b218,
1003b274feedSAvi Kivity         0x02001919, 0x8301b919, 0x12101319, 0x9311b319,
1004b274feedSAvi Kivity         0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a,
1005b274feedSAvi Kivity         0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b,
1006b274feedSAvi Kivity         0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c,
1007b274feedSAvi Kivity         0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d,
1008b274feedSAvi Kivity         0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e,
1009b274feedSAvi Kivity         0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f,
1010b274feedSAvi Kivity         0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20,
1011b274feedSAvi Kivity         0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21,
1012b274feedSAvi Kivity         0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22,
1013b274feedSAvi Kivity         0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23,
1014b274feedSAvi Kivity         0x06002424, 0x8301c424, 0x16101e24, 0x9711be24,
1015b274feedSAvi Kivity         0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25,
1016b274feedSAvi Kivity         0x02002626, 0x8701c626, 0x12102026, 0x9711c026,
1017b274feedSAvi Kivity         0x06002727, 0x8301c727, 0x16102127, 0x9311c127,
1018b274feedSAvi Kivity         0x06002828, 0x8301c828, 0x16102228, 0x9311c228,
1019b274feedSAvi Kivity         0x02002929, 0x8701c929, 0x12102329, 0x9711c329,
1020b274feedSAvi Kivity         0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a,
1021b274feedSAvi Kivity         0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b,
1022b274feedSAvi Kivity         0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c,
1023b274feedSAvi Kivity         0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d,
1024b274feedSAvi Kivity         0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e,
1025b274feedSAvi Kivity         0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f,
1026b274feedSAvi Kivity         0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30,
1027b274feedSAvi Kivity         0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31,
1028b274feedSAvi Kivity         0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32,
1029b274feedSAvi Kivity         0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33,
1030b274feedSAvi Kivity         0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34,
1031b274feedSAvi Kivity         0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35,
1032b274feedSAvi Kivity         0x06003636, 0x8301d636, 0x16103036, 0x9311d036,
1033b274feedSAvi Kivity         0x02003737, 0x8701d737, 0x12103137, 0x9711d137,
1034b274feedSAvi Kivity         0x02003838, 0x8701d838, 0x12103238, 0x9711d238,
1035b274feedSAvi Kivity         0x06003939, 0x8301d939, 0x16103339, 0x9311d339,
1036b274feedSAvi Kivity         0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a,
1037b274feedSAvi Kivity         0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b,
1038b274feedSAvi Kivity         0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c,
1039b274feedSAvi Kivity         0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d,
1040b274feedSAvi Kivity         0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e,
1041b274feedSAvi Kivity         0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f,
1042b274feedSAvi Kivity         0x02004040, 0x8301e040, 0x16103a40, 0x9311da40,
1043b274feedSAvi Kivity         0x06004141, 0x8701e141, 0x12103b41, 0x9711db41,
1044b274feedSAvi Kivity         0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42,
1045b274feedSAvi Kivity         0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43,
1046b274feedSAvi Kivity         0x06004444, 0x8701e444, 0x12103e44, 0x9711de44,
1047b274feedSAvi Kivity         0x02004545, 0x8301e545, 0x16103f45, 0x9311df45,
1048b274feedSAvi Kivity         0x02004646, 0x8301e646, 0x12104046, 0x9311e046,
1049b274feedSAvi Kivity         0x06004747, 0x8701e747, 0x16104147, 0x9711e147,
1050b274feedSAvi Kivity         0x06004848, 0x8701e848, 0x16104248, 0x9711e248,
1051b274feedSAvi Kivity         0x02004949, 0x8301e949, 0x12104349, 0x9311e349,
1052b274feedSAvi Kivity         0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a,
1053b274feedSAvi Kivity         0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b,
1054b274feedSAvi Kivity         0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c,
1055b274feedSAvi Kivity         0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d,
1056b274feedSAvi Kivity         0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e,
1057b274feedSAvi Kivity         0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f,
1058b274feedSAvi Kivity         0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50,
1059b274feedSAvi Kivity         0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51,
1060b274feedSAvi Kivity         0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52,
1061b274feedSAvi Kivity         0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53,
1062b274feedSAvi Kivity         0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54,
1063b274feedSAvi Kivity         0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55,
1064b274feedSAvi Kivity         0x06005656, 0x8701f656, 0x16105056, 0x9711f056,
1065b274feedSAvi Kivity         0x02005757, 0x8301f757, 0x12105157, 0x9311f157,
1066b274feedSAvi Kivity         0x02005858, 0x8301f858, 0x12105258, 0x9311f258,
1067b274feedSAvi Kivity         0x06005959, 0x8701f959, 0x16105359, 0x9711f359,
1068b274feedSAvi Kivity         0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a,
1069b274feedSAvi Kivity         0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b,
1070b274feedSAvi Kivity         0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c,
1071b274feedSAvi Kivity         0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d,
1072b274feedSAvi Kivity         0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e,
1073b274feedSAvi Kivity         0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f,
1074b274feedSAvi Kivity         0x06006060, 0x47010060, 0x16105a60, 0x9711fa60,
1075b274feedSAvi Kivity         0x02006161, 0x03010161, 0x12105b61, 0x9311fb61,
1076b274feedSAvi Kivity         0x02006262, 0x03010262, 0x16105c62, 0x9711fc62,
1077b274feedSAvi Kivity         0x06006363, 0x07010363, 0x12105d63, 0x9311fd63,
1078b274feedSAvi Kivity         0x02006464, 0x03010464, 0x12105e64, 0x9311fe64,
1079b274feedSAvi Kivity         0x06006565, 0x07010565, 0x16105f65, 0x9711ff65,
1080b274feedSAvi Kivity         0x06006666, 0x07010666, 0x16106066, 0x57110066,
1081b274feedSAvi Kivity         0x02006767, 0x03010767, 0x12106167, 0x13110167,
1082b274feedSAvi Kivity         0x02006868, 0x03010868, 0x12106268, 0x13110268,
1083b274feedSAvi Kivity         0x06006969, 0x07010969, 0x16106369, 0x17110369,
1084b274feedSAvi Kivity         0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a,
1085b274feedSAvi Kivity         0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b,
1086b274feedSAvi Kivity         0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c,
1087b274feedSAvi Kivity         0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d,
1088b274feedSAvi Kivity         0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e,
1089b274feedSAvi Kivity         0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f,
1090b274feedSAvi Kivity         0x02007070, 0x03011070, 0x16106a70, 0x17110a70,
1091b274feedSAvi Kivity         0x06007171, 0x07011171, 0x12106b71, 0x13110b71,
1092b274feedSAvi Kivity         0x06007272, 0x07011272, 0x16106c72, 0x17110c72,
1093b274feedSAvi Kivity         0x02007373, 0x03011373, 0x12106d73, 0x13110d73,
1094b274feedSAvi Kivity         0x06007474, 0x07011474, 0x12106e74, 0x13110e74,
1095b274feedSAvi Kivity         0x02007575, 0x03011575, 0x16106f75, 0x17110f75,
1096b274feedSAvi Kivity         0x02007676, 0x03011676, 0x12107076, 0x13111076,
1097b274feedSAvi Kivity         0x06007777, 0x07011777, 0x16107177, 0x17111177,
1098b274feedSAvi Kivity         0x06007878, 0x07011878, 0x16107278, 0x17111278,
1099b274feedSAvi Kivity         0x02007979, 0x03011979, 0x12107379, 0x13111379,
1100b274feedSAvi Kivity         0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a,
1101b274feedSAvi Kivity         0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b,
1102b274feedSAvi Kivity         0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c,
1103b274feedSAvi Kivity         0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d,
1104b274feedSAvi Kivity         0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e,
1105b274feedSAvi Kivity         0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f,
1106b274feedSAvi Kivity         0x82008080, 0x03012080, 0x12107a80, 0x13111a80,
1107b274feedSAvi Kivity         0x86008181, 0x07012181, 0x16107b81, 0x17111b81,
1108b274feedSAvi Kivity         0x86008282, 0x07012282, 0x12107c82, 0x13111c82,
1109b274feedSAvi Kivity         0x82008383, 0x03012383, 0x16107d83, 0x17111d83,
1110b274feedSAvi Kivity         0x86008484, 0x07012484, 0x16107e84, 0x17111e84,
1111b274feedSAvi Kivity         0x82008585, 0x03012585, 0x12107f85, 0x13111f85,
1112b274feedSAvi Kivity         0x82008686, 0x03012686, 0x92108086, 0x13112086,
1113b274feedSAvi Kivity         0x86008787, 0x07012787, 0x96108187, 0x17112187,
1114b274feedSAvi Kivity         0x86008888, 0x07012888, 0x96108288, 0x17112288,
1115b274feedSAvi Kivity         0x82008989, 0x03012989, 0x92108389, 0x13112389,
1116b274feedSAvi Kivity         0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a,
1117b274feedSAvi Kivity         0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b,
1118b274feedSAvi Kivity         0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c,
1119b274feedSAvi Kivity         0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d,
1120b274feedSAvi Kivity         0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e,
1121b274feedSAvi Kivity         0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f,
1122b274feedSAvi Kivity         0x86009090, 0x07013090, 0x92108a90, 0x13112a90,
1123b274feedSAvi Kivity         0x82009191, 0x03013191, 0x96108b91, 0x17112b91,
1124b274feedSAvi Kivity         0x82009292, 0x03013292, 0x92108c92, 0x13112c92,
1125b274feedSAvi Kivity         0x86009393, 0x07013393, 0x96108d93, 0x17112d93,
1126b274feedSAvi Kivity         0x82009494, 0x03013494, 0x96108e94, 0x17112e94,
1127b274feedSAvi Kivity         0x86009595, 0x07013595, 0x92108f95, 0x13112f95,
1128b274feedSAvi Kivity         0x86009696, 0x07013696, 0x96109096, 0x17113096,
1129b274feedSAvi Kivity         0x82009797, 0x03013797, 0x92109197, 0x13113197,
1130b274feedSAvi Kivity         0x82009898, 0x03013898, 0x92109298, 0x13113298,
1131b274feedSAvi Kivity         0x86009999, 0x07013999, 0x96109399, 0x17113399,
1132b274feedSAvi Kivity         0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a,
1133b274feedSAvi Kivity         0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b,
1134b274feedSAvi Kivity         0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c,
1135b274feedSAvi Kivity         0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d,
1136b274feedSAvi Kivity         0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e,
1137b274feedSAvi Kivity         0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f,
1138b274feedSAvi Kivity         0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0,
1139b274feedSAvi Kivity         0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1,
1140b274feedSAvi Kivity         0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2,
1141b274feedSAvi Kivity         0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3,
1142b274feedSAvi Kivity         0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4,
1143b274feedSAvi Kivity         0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5,
1144b274feedSAvi Kivity         0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6,
1145b274feedSAvi Kivity         0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7,
1146b274feedSAvi Kivity         0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8,
1147b274feedSAvi Kivity         0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9,
1148b274feedSAvi Kivity         0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa,
1149b274feedSAvi Kivity         0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab,
1150b274feedSAvi Kivity         0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac,
1151b274feedSAvi Kivity         0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad,
1152b274feedSAvi Kivity         0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae,
1153b274feedSAvi Kivity         0x130049af, 0x130149af, 0x131049af, 0x131149af,
1154b274feedSAvi Kivity         0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0,
1155b274feedSAvi Kivity         0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1,
1156b274feedSAvi Kivity         0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2,
1157b274feedSAvi Kivity         0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3,
1158b274feedSAvi Kivity         0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4,
1159b274feedSAvi Kivity         0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5,
1160b274feedSAvi Kivity         0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6,
1161b274feedSAvi Kivity         0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7,
1162b274feedSAvi Kivity         0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8,
1163b274feedSAvi Kivity         0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9,
1164b274feedSAvi Kivity         0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba,
1165b274feedSAvi Kivity         0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb,
1166b274feedSAvi Kivity         0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc,
1167b274feedSAvi Kivity         0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd,
1168b274feedSAvi Kivity         0x130058be, 0x130158be, 0x131058be, 0x131158be,
1169b274feedSAvi Kivity         0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf,
1170b274feedSAvi Kivity         0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0,
1171b274feedSAvi Kivity         0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1,
1172b274feedSAvi Kivity         0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2,
1173b274feedSAvi Kivity         0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3,
1174b274feedSAvi Kivity         0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4,
1175b274feedSAvi Kivity         0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5,
1176b274feedSAvi Kivity         0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6,
1177b274feedSAvi Kivity         0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7,
1178b274feedSAvi Kivity         0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8,
1179b274feedSAvi Kivity         0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9,
1180b274feedSAvi Kivity         0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca,
1181b274feedSAvi Kivity         0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb,
1182b274feedSAvi Kivity         0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc,
1183b274feedSAvi Kivity         0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd,
1184b274feedSAvi Kivity         0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce,
1185b274feedSAvi Kivity         0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf,
1186b274feedSAvi Kivity         0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0,
1187b274feedSAvi Kivity         0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1,
1188b274feedSAvi Kivity         0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2,
1189b274feedSAvi Kivity         0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3,
1190b274feedSAvi Kivity         0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4,
1191b274feedSAvi Kivity         0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5,
1192b274feedSAvi Kivity         0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6,
1193b274feedSAvi Kivity         0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7,
1194b274feedSAvi Kivity         0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8,
1195b274feedSAvi Kivity         0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9,
1196b274feedSAvi Kivity         0x170074da, 0x170174da, 0x171074da, 0x171174da,
1197b274feedSAvi Kivity         0x130075db, 0x130175db, 0x131075db, 0x131175db,
1198b274feedSAvi Kivity         0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc,
1199b274feedSAvi Kivity         0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd,
1200b274feedSAvi Kivity         0x170078de, 0x170178de, 0x171078de, 0x171178de,
1201b274feedSAvi Kivity         0x130079df, 0x130179df, 0x131079df, 0x131179df,
1202b274feedSAvi Kivity         0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0,
1203b274feedSAvi Kivity         0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1,
1204b274feedSAvi Kivity         0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2,
1205b274feedSAvi Kivity         0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3,
1206b274feedSAvi Kivity         0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4,
1207b274feedSAvi Kivity         0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5,
1208b274feedSAvi Kivity         0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6,
1209b274feedSAvi Kivity         0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7,
1210b274feedSAvi Kivity         0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8,
1211b274feedSAvi Kivity         0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9,
1212b274feedSAvi Kivity         0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea,
1213b274feedSAvi Kivity         0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb,
1214b274feedSAvi Kivity         0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec,
1215b274feedSAvi Kivity         0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed,
1216b274feedSAvi Kivity         0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee,
1217b274feedSAvi Kivity         0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef,
1218b274feedSAvi Kivity         0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0,
1219b274feedSAvi Kivity         0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1,
1220b274feedSAvi Kivity         0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2,
1221b274feedSAvi Kivity         0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3,
1222b274feedSAvi Kivity         0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4,
1223b274feedSAvi Kivity         0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5,
1224b274feedSAvi Kivity         0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6,
1225b274feedSAvi Kivity         0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7,
1226b274feedSAvi Kivity         0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8,
1227b274feedSAvi Kivity         0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9,
1228b274feedSAvi Kivity         0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa,
1229b274feedSAvi Kivity         0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb,
1230b274feedSAvi Kivity         0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc,
1231b274feedSAvi Kivity         0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd,
1232b274feedSAvi Kivity         0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe,
1233b274feedSAvi Kivity         0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff,
1234b274feedSAvi Kivity     };
1235b274feedSAvi Kivity 
1236b274feedSAvi Kivity     MK_INSN(das, "das");
1237b274feedSAvi Kivity 
123818253fdeSAvi Kivity     inregs = (struct regs){ 0 };
123918253fdeSAvi Kivity 
1240b274feedSAvi Kivity     for (i = 0; i < 1024; ++i) {
1241b274feedSAvi Kivity         unsigned tmp = test_cases[i];
1242b274feedSAvi Kivity         inregs.eax = tmp & 0xff;
1243b274feedSAvi Kivity         inregs.eflags = (tmp >> 16) & 0xff;
124418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_das);
124518253fdeSAvi Kivity 	if (!regs_equal(R_AX)
1246b274feedSAvi Kivity             || outregs.eax != ((tmp >> 8) & 0xff)
1247b274feedSAvi Kivity             || (outregs.eflags & 0xff) != (tmp >> 24)) {
124881050840SAvi Kivity 	    ++nr_fail;
124981050840SAvi Kivity 	    break;
1250b274feedSAvi Kivity         }
1251b274feedSAvi Kivity     }
12526055ea1fSAvi Kivity     report("DAS", ~0, nr_fail == 0);
1253b274feedSAvi Kivity }
1254b274feedSAvi Kivity 
1255*2e3f9f1fSThomas Huth static void test_cwd_cdq(void)
12560cbd5b06SMohammed Gamal {
12570cbd5b06SMohammed Gamal 	/* Sign-bit set */
12580cbd5b06SMohammed Gamal 	MK_INSN(cwd_1, "mov $0x8000, %ax\n\t"
12590cbd5b06SMohammed Gamal 		       "cwd\n\t");
12600cbd5b06SMohammed Gamal 
12610cbd5b06SMohammed Gamal 	/* Sign-bit not set */
12620cbd5b06SMohammed Gamal 	MK_INSN(cwd_2, "mov $0x1000, %ax\n\t"
12630cbd5b06SMohammed Gamal 		       "cwd\n\t");
12640cbd5b06SMohammed Gamal 
12650cbd5b06SMohammed Gamal 	/* Sign-bit set */
12660cbd5b06SMohammed Gamal 	MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t"
12670cbd5b06SMohammed Gamal 		       "cdq\n\t");
12680cbd5b06SMohammed Gamal 
12690cbd5b06SMohammed Gamal 	/* Sign-bit not set */
12700cbd5b06SMohammed Gamal 	MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t"
12710cbd5b06SMohammed Gamal 		       "cdq\n\t");
12720cbd5b06SMohammed Gamal 
127318253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
127418253fdeSAvi Kivity 
127518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_1);
12766055ea1fSAvi Kivity 	report("cwd 1", R_AX | R_DX,
12776055ea1fSAvi Kivity 	       outregs.eax == 0x8000 && outregs.edx == 0xffff);
12780cbd5b06SMohammed Gamal 
127918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_2);
12806055ea1fSAvi Kivity 	report("cwd 2", R_AX | R_DX,
12816055ea1fSAvi Kivity 	       outregs.eax == 0x1000 && outregs.edx == 0);
12820cbd5b06SMohammed Gamal 
128318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_1);
12846055ea1fSAvi Kivity 	report("cdq 1", R_AX | R_DX,
12856055ea1fSAvi Kivity 	       outregs.eax == 0x80000000 && outregs.edx == 0xffffffff);
12860cbd5b06SMohammed Gamal 
128718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_2);
12886055ea1fSAvi Kivity 	report("cdq 2", R_AX | R_DX,
12896055ea1fSAvi Kivity 	       outregs.eax == 0x10000000 && outregs.edx == 0);
12900cbd5b06SMohammed Gamal }
12910cbd5b06SMohammed Gamal 
129237f51a4aSWei Yongjun static struct {
129337f51a4aSWei Yongjun         void *address;
129437f51a4aSWei Yongjun         unsigned short sel;
129537f51a4aSWei Yongjun } __attribute__((packed)) desc = {
129637f51a4aSWei Yongjun 	(void *)0x1234,
129737f51a4aSWei Yongjun 	0x10,
129837f51a4aSWei Yongjun };
129937f51a4aSWei Yongjun 
1300*2e3f9f1fSThomas Huth static void test_lds_lss(void)
130137f51a4aSWei Yongjun {
130237f51a4aSWei Yongjun 	inregs = (struct regs){ .ebx = (unsigned long)&desc };
130337f51a4aSWei Yongjun 
130437f51a4aSWei Yongjun 	MK_INSN(lds, "push %ds\n\t"
130537f51a4aSWei Yongjun 		     "lds (%ebx), %eax\n\t"
130637f51a4aSWei Yongjun 		     "mov %ds, %ebx\n\t"
130737f51a4aSWei Yongjun 		     "pop %ds\n\t");
130837f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lds);
130937f51a4aSWei Yongjun 	report("lds", R_AX | R_BX,
131037f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
131137f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
131237f51a4aSWei Yongjun 
131337f51a4aSWei Yongjun 	MK_INSN(les, "push %es\n\t"
131437f51a4aSWei Yongjun 		     "les (%ebx), %eax\n\t"
131537f51a4aSWei Yongjun 		     "mov %es, %ebx\n\t"
131637f51a4aSWei Yongjun 		     "pop %es\n\t");
131737f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_les);
131837f51a4aSWei Yongjun 	report("les", R_AX | R_BX,
131937f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
132037f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
132137f51a4aSWei Yongjun 
132237f51a4aSWei Yongjun 	MK_INSN(lfs, "push %fs\n\t"
132337f51a4aSWei Yongjun 		     "lfs (%ebx), %eax\n\t"
132437f51a4aSWei Yongjun 		     "mov %fs, %ebx\n\t"
132537f51a4aSWei Yongjun 		     "pop %fs\n\t");
132637f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lfs);
132737f51a4aSWei Yongjun 	report("lfs", R_AX | R_BX,
132837f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
132937f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
133037f51a4aSWei Yongjun 
133137f51a4aSWei Yongjun 	MK_INSN(lgs, "push %gs\n\t"
133237f51a4aSWei Yongjun 		     "lgs (%ebx), %eax\n\t"
133337f51a4aSWei Yongjun 		     "mov %gs, %ebx\n\t"
133437f51a4aSWei Yongjun 		     "pop %gs\n\t");
133537f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lgs);
133637f51a4aSWei Yongjun 	report("lgs", R_AX | R_BX,
133737f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
133837f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
133937f51a4aSWei Yongjun 
134037f51a4aSWei Yongjun 	MK_INSN(lss, "push %ss\n\t"
134137f51a4aSWei Yongjun 		     "lss (%ebx), %eax\n\t"
134237f51a4aSWei Yongjun 		     "mov %ss, %ebx\n\t"
134337f51a4aSWei Yongjun 		     "pop %ss\n\t");
134437f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lss);
134537f51a4aSWei Yongjun 	report("lss", R_AX | R_BX,
134637f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
134737f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
134837f51a4aSWei Yongjun }
134937f51a4aSWei Yongjun 
1350*2e3f9f1fSThomas Huth static void test_jcxz(void)
1351b1c7c575SWei Yongjun {
1352b1c7c575SWei Yongjun 	MK_INSN(jcxz1, "jcxz 1f\n\t"
1353b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1354b1c7c575SWei Yongjun 		       "1:\n\t");
1355b1c7c575SWei Yongjun 	MK_INSN(jcxz2, "mov $0x100, %ecx\n\t"
1356b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1357b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1358b1c7c575SWei Yongjun 		       "mov $0, %ecx\n\t"
1359b1c7c575SWei Yongjun 		       "1:\n\t");
1360b1c7c575SWei Yongjun 	MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t"
1361b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1362b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1363b1c7c575SWei Yongjun 		       "1:\n\t");
1364b1c7c575SWei Yongjun 	MK_INSN(jecxz1, "jecxz 1f\n\t"
1365b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1366b1c7c575SWei Yongjun 			"1:\n\t");
1367b1c7c575SWei Yongjun 	MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t"
1368b1c7c575SWei Yongjun 			"jecxz 1f\n\t"
1369b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1370b1c7c575SWei Yongjun 			"mov $0, %ecx\n\t"
1371b1c7c575SWei Yongjun 			"1:\n\t");
1372b1c7c575SWei Yongjun 
1373b1c7c575SWei Yongjun 	inregs = (struct regs){ 0 };
1374b1c7c575SWei Yongjun 
1375b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz1);
1376b1c7c575SWei Yongjun 	report("jcxz short 1", 0, 1);
1377b1c7c575SWei Yongjun 
1378b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz2);
1379b1c7c575SWei Yongjun 	report("jcxz short 2", R_AX, outregs.eax == 0x1234);
1380b1c7c575SWei Yongjun 
1381b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz3);
1382b1c7c575SWei Yongjun 	report("jcxz short 3", R_CX, outregs.ecx == 0x10000);
1383b1c7c575SWei Yongjun 
1384b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz1);
1385b1c7c575SWei Yongjun 	report("jecxz short 1", 0, 1);
1386b1c7c575SWei Yongjun 
1387b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz2);
1388b1c7c575SWei Yongjun 	report("jecxz short 2", R_AX, outregs.eax == 0x1234);
1389b1c7c575SWei Yongjun }
1390b1c7c575SWei Yongjun 
13918f578e98SAvi Kivity static void test_cpuid(void)
13928f578e98SAvi Kivity {
13938f578e98SAvi Kivity     MK_INSN(cpuid, "cpuid");
13948f578e98SAvi Kivity     unsigned function = 0x1234;
13958f578e98SAvi Kivity     unsigned eax, ebx, ecx, edx;
13968f578e98SAvi Kivity 
13978f578e98SAvi Kivity     inregs.eax = eax = function;
139818ba9083SGleb Natapov     inregs.ecx = ecx = 0;
1399674d2dbeSPaolo Bonzini     asm("cpuid" : "+a"(eax), "=b"(ebx), "+c"(ecx), "=d"(edx));
14008f578e98SAvi Kivity     exec_in_big_real_mode(&insn_cpuid);
14018f578e98SAvi Kivity     report("cpuid", R_AX|R_BX|R_CX|R_DX,
14028f578e98SAvi Kivity 	   outregs.eax == eax && outregs.ebx == ebx
14038f578e98SAvi Kivity 	   && outregs.ecx == ecx && outregs.edx == edx);
14048f578e98SAvi Kivity }
14058f578e98SAvi Kivity 
1406ed93f43bSAvi Kivity static void test_ss_base_for_esp_ebp(void)
1407ed93f43bSAvi Kivity {
1408ed93f43bSAvi Kivity     MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss");
1409ed93f43bSAvi Kivity     MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss");
1410ed93f43bSAvi Kivity     static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 };
1411ed93f43bSAvi Kivity 
1412ed93f43bSAvi Kivity     inregs.ebx = 1;
1413ed93f43bSAvi Kivity     inregs.ebp = (unsigned)array;
1414ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel1);
1415ed93f43bSAvi Kivity     report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321);
1416ed93f43bSAvi Kivity     inregs.ebx = 1;
1417ed93f43bSAvi Kivity     inregs.ebp = (unsigned)array;
1418ed93f43bSAvi Kivity     inregs.edi = 0;
1419ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel2);
1420ed93f43bSAvi Kivity     report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321);
1421ed93f43bSAvi Kivity }
1422ed93f43bSAvi Kivity 
1423975ca087SPeter Feiner extern unsigned long long r_gdt[];
1424975ca087SPeter Feiner 
1425c2281fa4SAvi Kivity static void test_sgdt_sidt(void)
1426c2281fa4SAvi Kivity {
1427c2281fa4SAvi Kivity     MK_INSN(sgdt, "sgdtw (%eax)");
1428c2281fa4SAvi Kivity     MK_INSN(sidt, "sidtw (%eax)");
1429975ca087SPeter Feiner     struct table_descr x, y;
1430c2281fa4SAvi Kivity 
1431c2281fa4SAvi Kivity     inregs.eax = (unsigned)&y;
1432c2281fa4SAvi Kivity     asm volatile("sgdtw %0" : "=m"(x));
1433c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sgdt);
1434975ca087SPeter Feiner     report("sgdt", 0, x.limit == y.limit && x.base == y.base);
1435c2281fa4SAvi Kivity 
1436c2281fa4SAvi Kivity     inregs.eax = (unsigned)&y;
1437c2281fa4SAvi Kivity     asm volatile("sidtw %0" : "=m"(x));
1438c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sidt);
1439975ca087SPeter Feiner     report("sidt", 0, x.limit == y.limit && x.base == y.base);
1440c2281fa4SAvi Kivity }
1441c2281fa4SAvi Kivity 
144288b6dac4SPaolo Bonzini static void test_sahf(void)
144388b6dac4SPaolo Bonzini {
144488b6dac4SPaolo Bonzini     MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw");
144588b6dac4SPaolo Bonzini 
144688b6dac4SPaolo Bonzini     inregs.eax = 0xfd00;
144788b6dac4SPaolo Bonzini     exec_in_big_real_mode(&insn_sahf);
144888b6dac4SPaolo Bonzini     report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7));
144988b6dac4SPaolo Bonzini }
145088b6dac4SPaolo Bonzini 
14517ae3645aSAvi Kivity static void test_lahf(void)
14527ae3645aSAvi Kivity {
14537ae3645aSAvi Kivity     MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf");
14547ae3645aSAvi Kivity 
14557ae3645aSAvi Kivity     inregs.eax = 0xc7;
14567ae3645aSAvi Kivity     exec_in_big_real_mode(&insn_lahf);
14577ae3645aSAvi Kivity     report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax);
14587ae3645aSAvi Kivity }
14597ae3645aSAvi Kivity 
1460fd9ea640SAvi Kivity static void test_movzx_movsx(void)
1461fd9ea640SAvi Kivity {
1462fd9ea640SAvi Kivity     MK_INSN(movsx, "movsx %al, %ebx");
1463fd9ea640SAvi Kivity     MK_INSN(movzx, "movzx %al, %ebx");
14643013e079SGleb Natapov     MK_INSN(movzsah, "movsx %ah, %ebx");
14653013e079SGleb Natapov     MK_INSN(movzxah, "movzx %ah, %ebx");
1466fd9ea640SAvi Kivity 
1467fd9ea640SAvi Kivity     inregs.eax = 0x1234569c;
14683013e079SGleb Natapov     inregs.esp = 0xffff;
1469fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movsx);
1470fd9ea640SAvi Kivity     report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax);
1471fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movzx);
1472fd9ea640SAvi Kivity     report("movzx", R_BX, outregs.ebx == (unsigned char)inregs.eax);
14733013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzsah);
14743013e079SGleb Natapov     report("movsx ah", R_BX, outregs.ebx == (signed char)(inregs.eax>>8));
14753013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzxah);
14763013e079SGleb Natapov     report("movzx ah", R_BX, outregs.ebx == (unsigned char)(inregs.eax >> 8));
1477fd9ea640SAvi Kivity }
1478fd9ea640SAvi Kivity 
1479b493b2e8SAvi Kivity static void test_bswap(void)
1480b493b2e8SAvi Kivity {
1481b493b2e8SAvi Kivity     MK_INSN(bswap, "bswap %ecx");
1482b493b2e8SAvi Kivity 
1483b493b2e8SAvi Kivity     inregs.ecx = 0x12345678;
1484b493b2e8SAvi Kivity     exec_in_big_real_mode(&insn_bswap);
1485b493b2e8SAvi Kivity     report("bswap", R_CX, outregs.ecx == 0x78563412);
1486b493b2e8SAvi Kivity }
1487b493b2e8SAvi Kivity 
14888cd86387SGleb Natapov static void test_aad(void)
14898cd86387SGleb Natapov {
14908cd86387SGleb Natapov     MK_INSN(aad, "aad");
14918cd86387SGleb Natapov 
14928cd86387SGleb Natapov     inregs.eax = 0x12345678;
14938cd86387SGleb Natapov     exec_in_big_real_mode(&insn_aad);
14948cd86387SGleb Natapov     report("aad", R_AX, outregs.eax == 0x123400d4);
14958cd86387SGleb Natapov }
14968cd86387SGleb Natapov 
14972a9b5718SPaolo Bonzini static void test_aam(void)
14982a9b5718SPaolo Bonzini {
14992a9b5718SPaolo Bonzini     MK_INSN(aam, "aam");
15002a9b5718SPaolo Bonzini 
15012a9b5718SPaolo Bonzini     inregs.eax = 0x76543210;
15022a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_aam);
15032a9b5718SPaolo Bonzini     report("aam", R_AX, outregs.eax == 0x76540106);
15042a9b5718SPaolo Bonzini }
15052a9b5718SPaolo Bonzini 
15062a9b5718SPaolo Bonzini static void test_xlat(void)
15072a9b5718SPaolo Bonzini {
15082a9b5718SPaolo Bonzini     MK_INSN(xlat, "xlat");
15092a9b5718SPaolo Bonzini     u8 table[256];
15102a9b5718SPaolo Bonzini     int i;
15112a9b5718SPaolo Bonzini 
15122a9b5718SPaolo Bonzini     for (i = 0; i < 256; i++) {
15132a9b5718SPaolo Bonzini         table[i] = i + 1;
15142a9b5718SPaolo Bonzini     }
15152a9b5718SPaolo Bonzini 
15162a9b5718SPaolo Bonzini     inregs.eax = 0x89abcdef;
15172a9b5718SPaolo Bonzini     inregs.ebx = (u32)table;
15182a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_xlat);
15192a9b5718SPaolo Bonzini     report("xlat", R_AX, outregs.eax == 0x89abcdf0);
15202a9b5718SPaolo Bonzini }
15212a9b5718SPaolo Bonzini 
15222a9b5718SPaolo Bonzini static void test_salc(void)
15232a9b5718SPaolo Bonzini {
15242a9b5718SPaolo Bonzini     MK_INSN(clc_salc, "clc; .byte 0xd6");
15252a9b5718SPaolo Bonzini     MK_INSN(stc_salc, "stc; .byte 0xd6");
15262a9b5718SPaolo Bonzini 
15272a9b5718SPaolo Bonzini     inregs.eax = 0x12345678;
15282a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_clc_salc);
15292a9b5718SPaolo Bonzini     report("salc (1)", R_AX, outregs.eax == 0x12345600);
15302a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_stc_salc);
15312a9b5718SPaolo Bonzini     report("salc (2)", R_AX, outregs.eax == 0x123456ff);
15322a9b5718SPaolo Bonzini }
15332a9b5718SPaolo Bonzini 
15340987db7aSGleb Natapov static void test_fninit(void)
15350987db7aSGleb Natapov {
15360987db7aSGleb Natapov 	u16 fcw = -1, fsw = -1;
15370987db7aSGleb Natapov 	MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)");
15380987db7aSGleb Natapov 
15390987db7aSGleb Natapov 	inregs.eax = (u32)&fsw;
15400987db7aSGleb Natapov 	inregs.ebx = (u32)&fcw;
15410987db7aSGleb Natapov 
15420987db7aSGleb Natapov 	exec_in_big_real_mode(&insn_fninit);
15430987db7aSGleb Natapov 	report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f);
15440987db7aSGleb Natapov }
15450987db7aSGleb Natapov 
15461a4c03a0SArthur Chunqi Li static void test_nopl(void)
15471a4c03a0SArthur Chunqi Li {
15481a4c03a0SArthur Chunqi Li 	MK_INSN(nopl1, ".byte 0x90\n\r"); // 1 byte nop
15491a4c03a0SArthur Chunqi Li 	MK_INSN(nopl2, ".byte 0x66, 0x90\n\r"); // 2 bytes nop
15501a4c03a0SArthur Chunqi Li 	MK_INSN(nopl3, ".byte 0x0f, 0x1f, 0x00\n\r"); // 3 bytes nop
15511a4c03a0SArthur Chunqi Li 	MK_INSN(nopl4, ".byte 0x0f, 0x1f, 0x40, 0x00\n\r"); // 4 bytes nop
15521a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl1);
15531a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl2);
15541a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl3);
15551a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl4);
15561a4c03a0SArthur Chunqi Li 	report("nopl", 0, 1);
15571a4c03a0SArthur Chunqi Li }
15581a4c03a0SArthur Chunqi Li 
1559b5105e8bSPaolo Bonzini static u32 perf_baseline;
1560b5105e8bSPaolo Bonzini 
15617505ea23SPaolo Bonzini #define PERF_COUNT 1000000
1562b5105e8bSPaolo Bonzini 
1563b5105e8bSPaolo Bonzini #define MK_INSN_PERF(name, insn)                                \
1564b5105e8bSPaolo Bonzini 	MK_INSN(name, "rdtsc; mov %eax, %ebx; mov %edx, %esi\n" \
1565b5105e8bSPaolo Bonzini 		      "1:" insn "\n"                            \
15667505ea23SPaolo Bonzini 		      ".byte 0x67; loop 1b\n"                   \
1567b5105e8bSPaolo Bonzini 		      "rdtsc");
1568b5105e8bSPaolo Bonzini 
1569b5105e8bSPaolo Bonzini static u32 cycles_in_big_real_mode(struct insn_desc *insn)
1570b5105e8bSPaolo Bonzini {
1571b5105e8bSPaolo Bonzini 	u64 start, end;
1572b5105e8bSPaolo Bonzini 
1573b5105e8bSPaolo Bonzini 	inregs.ecx = PERF_COUNT;
1574b5105e8bSPaolo Bonzini 	exec_in_big_real_mode(insn);
1575b5105e8bSPaolo Bonzini 	start = ((u64)outregs.esi << 32) | outregs.ebx;
1576b5105e8bSPaolo Bonzini 	end = ((u64)outregs.edx << 32) | outregs.eax;
1577b5105e8bSPaolo Bonzini 
1578b5105e8bSPaolo Bonzini 	return end - start;
1579b5105e8bSPaolo Bonzini }
1580b5105e8bSPaolo Bonzini 
1581b5105e8bSPaolo Bonzini static void test_perf_loop(void)
1582b5105e8bSPaolo Bonzini {
1583b5105e8bSPaolo Bonzini 	/*
1584b5105e8bSPaolo Bonzini 	 * This test runs simple instructions that should roughly take the
1585b5105e8bSPaolo Bonzini 	 * the same time to emulate: PERF_COUNT iterations of "loop" and 3
1586b5105e8bSPaolo Bonzini 	 * setup instructions.  Other performance tests can run PERF_COUNT
1587b5105e8bSPaolo Bonzini 	 * iterations of the same instruction and subtract the cycle count
1588b5105e8bSPaolo Bonzini 	 * of this test.
1589b5105e8bSPaolo Bonzini 	 */
1590b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_loop, "");
1591b5105e8bSPaolo Bonzini 	perf_baseline = cycles_in_big_real_mode(&insn_perf_loop);
1592b5105e8bSPaolo Bonzini 	print_serial_u32(perf_baseline / (PERF_COUNT + 3));
1593b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated jump instruction\n");
1594b5105e8bSPaolo Bonzini }
1595b5105e8bSPaolo Bonzini 
1596b5105e8bSPaolo Bonzini static void test_perf_mov(void)
1597b5105e8bSPaolo Bonzini {
1598b5105e8bSPaolo Bonzini 	u32 cyc;
1599b5105e8bSPaolo Bonzini 
1600b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_move, "mov %esi, %edi");
1601b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_move);
1602b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1603b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated move instruction\n");
1604b5105e8bSPaolo Bonzini }
1605b5105e8bSPaolo Bonzini 
1606b5105e8bSPaolo Bonzini static void test_perf_arith(void)
1607b5105e8bSPaolo Bonzini {
1608b5105e8bSPaolo Bonzini 	u32 cyc;
1609b5105e8bSPaolo Bonzini 
1610b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_arith, "add $4, %edi");
1611b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_arith);
1612b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1613b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated arithmetic instruction\n");
1614b5105e8bSPaolo Bonzini }
1615b5105e8bSPaolo Bonzini 
1616b5105e8bSPaolo Bonzini static void test_perf_memory_load(void)
1617b5105e8bSPaolo Bonzini {
1618b5105e8bSPaolo Bonzini 	u32 cyc, tmp;
1619b5105e8bSPaolo Bonzini 
1620b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_memory_load, "cmp $0, (%edi)");
1621b5105e8bSPaolo Bonzini 	inregs.edi = (u32)&tmp;
1622b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_load);
1623b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1624b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated memory load instruction\n");
1625b5105e8bSPaolo Bonzini }
1626b5105e8bSPaolo Bonzini 
16279306cb8eSPaolo Bonzini static void test_perf_memory_store(void)
16289306cb8eSPaolo Bonzini {
16299306cb8eSPaolo Bonzini 	u32 cyc, tmp;
16309306cb8eSPaolo Bonzini 
16319306cb8eSPaolo Bonzini 	MK_INSN_PERF(perf_memory_store, "mov %ax, (%edi)");
16329306cb8eSPaolo Bonzini 	inregs.edi = (u32)&tmp;
16339306cb8eSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_store);
16349306cb8eSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
16359306cb8eSPaolo Bonzini 	print_serial(" cycles/emulated memory store instruction\n");
16369306cb8eSPaolo Bonzini }
16379306cb8eSPaolo Bonzini 
1638b5105e8bSPaolo Bonzini static void test_perf_memory_rmw(void)
1639b5105e8bSPaolo Bonzini {
1640b5105e8bSPaolo Bonzini 	u32 cyc, tmp;
1641b5105e8bSPaolo Bonzini 
1642b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_memory_rmw, "add $1, (%edi)");
1643b5105e8bSPaolo Bonzini 	inregs.edi = (u32)&tmp;
1644b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_rmw);
1645b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1646b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated memory RMW instruction\n");
1647b5105e8bSPaolo Bonzini }
1648b5105e8bSPaolo Bonzini 
1649*2e3f9f1fSThomas Huth static void test_dr_mod(void)
16500a5701edSNadav Amit {
16510a5701edSNadav Amit 	MK_INSN(drmod, "movl %ebx, %dr0\n\t"
16520a5701edSNadav Amit 		       ".byte 0x0f \n\t .byte 0x21 \n\t .byte 0x0\n\t");
16530a5701edSNadav Amit 	inregs.eax = 0xdead;
16540a5701edSNadav Amit 	inregs.ebx = 0xaced;
16550a5701edSNadav Amit 	exec_in_big_real_mode(&insn_drmod);
16560a5701edSNadav Amit 	report("mov dr with mod bits", R_AX | R_BX, outregs.eax == 0xaced);
16570a5701edSNadav Amit }
16580a5701edSNadav Amit 
1659*2e3f9f1fSThomas Huth static void test_smsw(void)
166099ee878cSNadav Amit {
166199ee878cSNadav Amit 	MK_INSN(smsw, "movl %cr0, %ebx\n\t"
166299ee878cSNadav Amit 		      "movl %ebx, %ecx\n\t"
166399ee878cSNadav Amit 		      "or $0x40000000, %ebx\n\t"
166499ee878cSNadav Amit 		      "movl %ebx, %cr0\n\t"
166599ee878cSNadav Amit 		      "smswl %eax\n\t"
166699ee878cSNadav Amit 		      "movl %ecx, %cr0\n\t");
166799ee878cSNadav Amit 	inregs.eax = 0x12345678;
166899ee878cSNadav Amit 	exec_in_big_real_mode(&insn_smsw);
166999ee878cSNadav Amit 	report("smsw", R_AX | R_BX | R_CX, outregs.eax == outregs.ebx);
167099ee878cSNadav Amit }
167199ee878cSNadav Amit 
1672*2e3f9f1fSThomas Huth static void test_xadd(void)
16737bee560dSNadav Amit {
16747bee560dSNadav Amit 	MK_INSN(xadd, "xaddl %eax, %eax\n\t");
16757bee560dSNadav Amit 	inregs.eax = 0x12345678;
16767bee560dSNadav Amit 	exec_in_big_real_mode(&insn_xadd);
16777bee560dSNadav Amit 	report("xadd", R_AX, outregs.eax == inregs.eax * 2);
16787bee560dSNadav Amit }
16797bee560dSNadav Amit 
168099ee878cSNadav Amit 
16817d36db35SAvi Kivity void realmode_start(void)
16827d36db35SAvi Kivity {
16837d36db35SAvi Kivity 	test_null();
16847d36db35SAvi Kivity 
16857d36db35SAvi Kivity 	test_shld();
16867d36db35SAvi Kivity 	test_push_pop();
16877d36db35SAvi Kivity 	test_pusha_popa();
16887d36db35SAvi Kivity 	test_mov_imm();
16897d36db35SAvi Kivity 	test_cmp_imm();
16907d36db35SAvi Kivity 	test_add_imm();
16917d36db35SAvi Kivity 	test_sub_imm();
16927d36db35SAvi Kivity 	test_xor_imm();
16937d36db35SAvi Kivity 	test_io();
16947d36db35SAvi Kivity 	test_eflags_insn();
16957d36db35SAvi Kivity 	test_jcc_short();
16967d36db35SAvi Kivity 	test_jcc_near();
16977d36db35SAvi Kivity 	/* test_call() uses short jump so call it after testing jcc */
16987d36db35SAvi Kivity 	test_call();
16997d36db35SAvi Kivity 	/* long jmp test uses call near so test it after testing call */
17007d36db35SAvi Kivity 	test_long_jmp();
17017d36db35SAvi Kivity 	test_xchg();
17027d36db35SAvi Kivity 	test_iret();
170396b9ca1eSMohammed Gamal 	test_int();
1704fa74f8a6SMohammed Gamal 	test_imul();
170559317bd1SMohammed Gamal 	test_mul();
17060d4c7614SMohammed Gamal 	test_div();
17070d4c7614SMohammed Gamal 	test_idiv();
1708eacef4e2SWei Yongjun 	test_loopcc();
17096e293cf5SWei Yongjun 	test_cbw();
17100cbd5b06SMohammed Gamal 	test_cwd_cdq();
1711b274feedSAvi Kivity 	test_das();
171237f51a4aSWei Yongjun 	test_lds_lss();
1713b1c7c575SWei Yongjun 	test_jcxz();
17148f578e98SAvi Kivity 	test_cpuid();
1715ed93f43bSAvi Kivity 	test_ss_base_for_esp_ebp();
1716c2281fa4SAvi Kivity 	test_sgdt_sidt();
17177ae3645aSAvi Kivity 	test_lahf();
171888b6dac4SPaolo Bonzini 	test_sahf();
1719fd9ea640SAvi Kivity 	test_movzx_movsx();
1720b493b2e8SAvi Kivity 	test_bswap();
17218cd86387SGleb Natapov 	test_aad();
17222a9b5718SPaolo Bonzini 	test_aam();
17232a9b5718SPaolo Bonzini 	test_xlat();
17242a9b5718SPaolo Bonzini 	test_salc();
17250987db7aSGleb Natapov 	test_fninit();
17260a5701edSNadav Amit 	test_dr_mod();
172799ee878cSNadav Amit 	test_smsw();
17281a4c03a0SArthur Chunqi Li 	test_nopl();
17297bee560dSNadav Amit 	test_xadd();
1730b5105e8bSPaolo Bonzini 	test_perf_loop();
1731b5105e8bSPaolo Bonzini 	test_perf_mov();
1732b5105e8bSPaolo Bonzini 	test_perf_arith();
1733b5105e8bSPaolo Bonzini 	test_perf_memory_load();
17349306cb8eSPaolo Bonzini 	test_perf_memory_store();
1735b5105e8bSPaolo Bonzini 	test_perf_memory_rmw();
17367d36db35SAvi Kivity 
1737b393fe28SNadav Amit 	exit(failed);
17387d36db35SAvi Kivity }
17397d36db35SAvi Kivity 
17407d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff };
17417d36db35SAvi Kivity 
1742975ca087SPeter Feiner struct table_descr r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt };
17437d36db35SAvi Kivity 
17447d36db35SAvi Kivity asm(
17457d36db35SAvi Kivity 	".section .init \n\t"
17467d36db35SAvi Kivity 
17477d36db35SAvi Kivity 	".code32 \n\t"
17487d36db35SAvi Kivity 
17497d36db35SAvi Kivity 	"mb_magic = 0x1BADB002 \n\t"
17507d36db35SAvi Kivity 	"mb_flags = 0x0 \n\t"
17517d36db35SAvi Kivity 
17527d36db35SAvi Kivity 	"# multiboot header \n\t"
17537d36db35SAvi Kivity 	".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t"
17547d36db35SAvi Kivity 
17557d36db35SAvi Kivity 	".globl start \n\t"
17567d36db35SAvi Kivity 	".data \n\t"
17577d36db35SAvi Kivity 	". = . + 4096 \n\t"
17587d36db35SAvi Kivity 	"stacktop: \n\t"
17597d36db35SAvi Kivity 
17607d36db35SAvi Kivity 	".text \n\t"
17617d36db35SAvi Kivity 	"start: \n\t"
17627d36db35SAvi Kivity 	"lgdt r_gdt_descr \n\t"
17637d36db35SAvi Kivity 	"ljmp $8, $1f; 1: \n\t"
17647d36db35SAvi Kivity 	".code16gcc \n\t"
17657d36db35SAvi Kivity 	"mov $16, %eax \n\t"
17667d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
17677d36db35SAvi Kivity 	"mov %ax, %es \n\t"
17687d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
17697d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
17707d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
17717d36db35SAvi Kivity 	"mov %cr0, %eax \n\t"
17727d36db35SAvi Kivity 	"btc $0, %eax \n\t"
17737d36db35SAvi Kivity 	"mov %eax, %cr0 \n\t"
17747d36db35SAvi Kivity 	"ljmp $0, $realmode_entry \n\t"
17757d36db35SAvi Kivity 
17767d36db35SAvi Kivity 	"realmode_entry: \n\t"
17777d36db35SAvi Kivity 
17787d36db35SAvi Kivity 	"xor %ax, %ax \n\t"
17797d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
17807d36db35SAvi Kivity 	"mov %ax, %es \n\t"
17817d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
17827d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
17837d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
17847d36db35SAvi Kivity 	"mov $stacktop, %esp\n\t"
17857d36db35SAvi Kivity 	"ljmp $0, $realmode_start \n\t"
17867d36db35SAvi Kivity 
17877d36db35SAvi Kivity 	".code16gcc \n\t"
17887d36db35SAvi Kivity 	);
1789