xref: /kvm-unit-tests/x86/realmode.c (revision 074766aea97a4f378a20b38313e255f951b77d50)
1f366255fSPaolo Bonzini #ifndef USE_SERIAL
2f366255fSPaolo Bonzini #define USE_SERIAL
3f366255fSPaolo Bonzini #endif
4f366255fSPaolo Bonzini 
547086996SBill Wendling #define ARRAY_SIZE(_a) (sizeof(_a)/sizeof((_a)[0]))
647086996SBill Wendling 
77d36db35SAvi Kivity asm(".code16gcc");
87d36db35SAvi Kivity 
97d36db35SAvi Kivity typedef unsigned char u8;
107d36db35SAvi Kivity typedef unsigned short u16;
117d36db35SAvi Kivity typedef unsigned u32;
127d36db35SAvi Kivity typedef unsigned long long u64;
137d36db35SAvi Kivity 
142e3f9f1fSThomas Huth void realmode_start(void);
157d36db35SAvi Kivity void test_function(void);
167d36db35SAvi Kivity 
177d36db35SAvi Kivity asm(
187d36db35SAvi Kivity 	"test_function: \n\t"
197d36db35SAvi Kivity 	"mov $0x1234, %eax \n\t"
207d36db35SAvi Kivity 	"ret"
217d36db35SAvi Kivity    );
227d36db35SAvi Kivity 
237d36db35SAvi Kivity static int strlen(const char *str)
247d36db35SAvi Kivity {
257d36db35SAvi Kivity 	int n;
267d36db35SAvi Kivity 
277d36db35SAvi Kivity 	for (n = 0; *str; ++str)
287d36db35SAvi Kivity 		++n;
297d36db35SAvi Kivity 	return n;
307d36db35SAvi Kivity }
317d36db35SAvi Kivity 
32f366255fSPaolo Bonzini static void outb(u8 data, u16 port)
33f366255fSPaolo Bonzini {
34f366255fSPaolo Bonzini 	asm volatile("out %0, %1" : : "a"(data), "d"(port));
35f366255fSPaolo Bonzini }
36f366255fSPaolo Bonzini 
37f366255fSPaolo Bonzini #ifdef USE_SERIAL
38f366255fSPaolo Bonzini static int serial_iobase = 0x3f8;
39f366255fSPaolo Bonzini static int serial_inited = 0;
40f366255fSPaolo Bonzini 
41f366255fSPaolo Bonzini static u8 inb(u16 port)
42f366255fSPaolo Bonzini {
43f366255fSPaolo Bonzini 	u8 data;
44f366255fSPaolo Bonzini 	asm volatile("in %1, %0" : "=a"(data) : "d"(port));
45f366255fSPaolo Bonzini 	return data;
46f366255fSPaolo Bonzini }
47f366255fSPaolo Bonzini 
48f366255fSPaolo Bonzini static void serial_outb(char ch)
49f366255fSPaolo Bonzini {
50f366255fSPaolo Bonzini 	u8 lsr;
51f366255fSPaolo Bonzini 
52f366255fSPaolo Bonzini 	do {
53f366255fSPaolo Bonzini 		lsr = inb(serial_iobase + 0x05);
54f366255fSPaolo Bonzini 	} while (!(lsr & 0x20));
55f366255fSPaolo Bonzini 
56f366255fSPaolo Bonzini 	outb(ch, serial_iobase + 0x00);
57f366255fSPaolo Bonzini }
58f366255fSPaolo Bonzini 
59f366255fSPaolo Bonzini static void serial_init(void)
60f366255fSPaolo Bonzini {
61f366255fSPaolo Bonzini 	u8 lcr;
62f366255fSPaolo Bonzini 
63f366255fSPaolo Bonzini 	/* set DLAB */
64f366255fSPaolo Bonzini 	lcr = inb(serial_iobase + 0x03);
65f366255fSPaolo Bonzini 	lcr |= 0x80;
66f366255fSPaolo Bonzini 	outb(lcr, serial_iobase + 0x03);
67f366255fSPaolo Bonzini 
68f366255fSPaolo Bonzini 	/* set baud rate to 115200 */
69f366255fSPaolo Bonzini 	outb(0x01, serial_iobase + 0x00);
70f366255fSPaolo Bonzini 	outb(0x00, serial_iobase + 0x01);
71f366255fSPaolo Bonzini 
72f366255fSPaolo Bonzini 	/* clear DLAB */
73f366255fSPaolo Bonzini 	lcr = inb(serial_iobase + 0x03);
74f366255fSPaolo Bonzini 	lcr &= ~0x80;
75f366255fSPaolo Bonzini 	outb(lcr, serial_iobase + 0x03);
76f366255fSPaolo Bonzini }
77f366255fSPaolo Bonzini #endif
78f366255fSPaolo Bonzini 
797d36db35SAvi Kivity static void print_serial(const char *buf)
807d36db35SAvi Kivity {
817d36db35SAvi Kivity 	unsigned long len = strlen(buf);
82f366255fSPaolo Bonzini #ifdef USE_SERIAL
83f366255fSPaolo Bonzini 	unsigned long i;
84f366255fSPaolo Bonzini 	if (!serial_inited) {
85f366255fSPaolo Bonzini 	    serial_init();
86f366255fSPaolo Bonzini 	    serial_inited = 1;
87f366255fSPaolo Bonzini 	}
887d36db35SAvi Kivity 
89f366255fSPaolo Bonzini 	for (i = 0; i < len; i++) {
90f366255fSPaolo Bonzini 	    serial_outb(buf[i]);
91f366255fSPaolo Bonzini 	}
92f366255fSPaolo Bonzini #else
935edbb9aeSPaolo Bonzini 	asm volatile ("addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1));
94f366255fSPaolo Bonzini #endif
957d36db35SAvi Kivity }
967d36db35SAvi Kivity 
97b5105e8bSPaolo Bonzini static void print_serial_u32(u32 value)
98b5105e8bSPaolo Bonzini {
99b5105e8bSPaolo Bonzini 	char n[12], *p;
100b5105e8bSPaolo Bonzini 	p = &n[11];
101b5105e8bSPaolo Bonzini 	*p = 0;
102b5105e8bSPaolo Bonzini 	do {
103b5105e8bSPaolo Bonzini 		*--p = '0' + (value % 10);
104b5105e8bSPaolo Bonzini 		value /= 10;
105b5105e8bSPaolo Bonzini 	} while (value > 0);
106b5105e8bSPaolo Bonzini 	print_serial(p);
107b5105e8bSPaolo Bonzini }
108b5105e8bSPaolo Bonzini 
109b393fe28SNadav Amit static int failed;
110b393fe28SNadav Amit 
1117d36db35SAvi Kivity static void exit(int code)
1127d36db35SAvi Kivity {
113f366255fSPaolo Bonzini 	outb(code, 0xf4);
1147d36db35SAvi Kivity }
1157d36db35SAvi Kivity 
1167d36db35SAvi Kivity struct regs {
1177d36db35SAvi Kivity 	u32 eax, ebx, ecx, edx;
1187d36db35SAvi Kivity 	u32 esi, edi, esp, ebp;
1197d36db35SAvi Kivity 	u32 eip, eflags;
1207d36db35SAvi Kivity };
1217d36db35SAvi Kivity 
122975ca087SPeter Feiner struct table_descr {
123975ca087SPeter Feiner 	u16 limit;
124975ca087SPeter Feiner 	void *base;
125975ca087SPeter Feiner } __attribute__((packed));
126975ca087SPeter Feiner 
1277d36db35SAvi Kivity static u64 gdt[] = {
1287d36db35SAvi Kivity 	0,
1297d36db35SAvi Kivity 	0x00cf9b000000ffffull, // flat 32-bit code segment
1307d36db35SAvi Kivity 	0x00cf93000000ffffull, // flat 32-bit data segment
1317d36db35SAvi Kivity };
1327d36db35SAvi Kivity 
133975ca087SPeter Feiner static struct table_descr gdt_descr = {
1347d36db35SAvi Kivity 	sizeof(gdt) - 1,
1357d36db35SAvi Kivity 	gdt,
1367d36db35SAvi Kivity };
1377d36db35SAvi Kivity 
138d4dc402cSAvi Kivity struct insn_desc {
139d4dc402cSAvi Kivity     u16 ptr;
140d4dc402cSAvi Kivity     u16 len;
141d4dc402cSAvi Kivity };
142d4dc402cSAvi Kivity 
14318253fdeSAvi Kivity static struct regs inregs, outregs;
14418253fdeSAvi Kivity 
14518253fdeSAvi Kivity static void exec_in_big_real_mode(struct insn_desc *insn)
1467d36db35SAvi Kivity {
1477d36db35SAvi Kivity 	unsigned long tmp;
1487d36db35SAvi Kivity 	static struct regs save;
1497d36db35SAvi Kivity 	int i;
1507d36db35SAvi Kivity 	extern u8 test_insn[], test_insn_end[];
1517d36db35SAvi Kivity 
152d4dc402cSAvi Kivity 	for (i = 0; i < insn->len; ++i)
153d4dc402cSAvi Kivity 	    test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i];
1547d36db35SAvi Kivity 	for (; i < test_insn_end - test_insn; ++i)
1557d36db35SAvi Kivity 		test_insn[i] = 0x90; // nop
1567d36db35SAvi Kivity 
15718253fdeSAvi Kivity 	save = inregs;
1587d36db35SAvi Kivity 	asm volatile(
1597d36db35SAvi Kivity 		"lgdtl %[gdt_descr] \n\t"
1607d36db35SAvi Kivity 		"mov %%cr0, %[tmp] \n\t"
1617d36db35SAvi Kivity 		"or $1, %[tmp] \n\t"
1627d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
1637d36db35SAvi Kivity 		"mov %[bigseg], %%gs \n\t"
1647d36db35SAvi Kivity 		"and $-2, %[tmp] \n\t"
1657d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
1667d36db35SAvi Kivity 
16732001692SAvi Kivity                 "pushw %[save]+36; popfw \n\t"
1687d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
1697d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
1707d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
1717d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
1727d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
1737d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
1747d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
1757d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
1767d36db35SAvi Kivity 
1777d36db35SAvi Kivity 		"test_insn: . = . + 32\n\t"
1787d36db35SAvi Kivity 		"test_insn_end: \n\t"
1797d36db35SAvi Kivity 
1807d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
1817d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
1827d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
1837d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
1847d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
1857d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
1867d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
1877d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
1887d36db35SAvi Kivity 
1897d36db35SAvi Kivity 		/* Save EFLAGS in outregs*/
1907d36db35SAvi Kivity 		"pushfl \n\t"
1917d36db35SAvi Kivity 		"popl %[save]+36 \n\t"
1927d36db35SAvi Kivity 
1935edbb9aeSPaolo Bonzini 		/* Restore DF for the harness code */
1945edbb9aeSPaolo Bonzini 		"cld\n\t"
1957d36db35SAvi Kivity 		"xor %[tmp], %[tmp] \n\t"
1967d36db35SAvi Kivity 		"mov %[tmp], %%gs \n\t"
1977d36db35SAvi Kivity 		: [tmp]"=&r"(tmp), [save]"+m"(save)
1987d36db35SAvi Kivity 		: [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16)
1997d36db35SAvi Kivity 		: "cc", "memory"
2007d36db35SAvi Kivity 		);
20118253fdeSAvi Kivity 	outregs = save;
2027d36db35SAvi Kivity }
2037d36db35SAvi Kivity 
2047d36db35SAvi Kivity #define R_AX 1
2057d36db35SAvi Kivity #define R_BX 2
2067d36db35SAvi Kivity #define R_CX 4
2077d36db35SAvi Kivity #define R_DX 8
2087d36db35SAvi Kivity #define R_SI 16
2097d36db35SAvi Kivity #define R_DI 32
2107d36db35SAvi Kivity #define R_SP 64
2117d36db35SAvi Kivity #define R_BP 128
2127d36db35SAvi Kivity 
2132e3f9f1fSThomas Huth static int regs_equal(int ignore)
2147d36db35SAvi Kivity {
21518253fdeSAvi Kivity 	const u32 *p1 = &inregs.eax, *p2 = &outregs.eax;  // yuck
2167d36db35SAvi Kivity 	int i;
2177d36db35SAvi Kivity 
2187d36db35SAvi Kivity 	for (i = 0; i < 8; ++i)
2197d36db35SAvi Kivity 		if (!(ignore & (1 << i)) && p1[i] != p2[i])
2207d36db35SAvi Kivity 			return 0;
2217d36db35SAvi Kivity 	return 1;
2227d36db35SAvi Kivity }
2237d36db35SAvi Kivity 
2246055ea1fSAvi Kivity static void report(const char *name, u16 regs_ignore, _Bool ok)
22581050840SAvi Kivity {
2266055ea1fSAvi Kivity     if (!regs_equal(regs_ignore)) {
2276055ea1fSAvi Kivity 	ok = 0;
2286055ea1fSAvi Kivity     }
22981050840SAvi Kivity     print_serial(ok ? "PASS: " : "FAIL: ");
23081050840SAvi Kivity     print_serial(name);
23181050840SAvi Kivity     print_serial("\n");
232b393fe28SNadav Amit     if (!ok)
233b393fe28SNadav Amit 	failed = 1;
23481050840SAvi Kivity }
23581050840SAvi Kivity 
2367d36db35SAvi Kivity #define MK_INSN(name, str)				\
2377d36db35SAvi Kivity     asm (						\
238d4dc402cSAvi Kivity 	 ".pushsection .data.insn  \n\t"		\
239d4dc402cSAvi Kivity 	 "insn_" #name ": \n\t"				\
240d4dc402cSAvi Kivity 	 ".word 1001f, 1002f - 1001f \n\t"		\
241d4dc402cSAvi Kivity 	 ".popsection \n\t"				\
242d4dc402cSAvi Kivity 	 ".pushsection .text.insn, \"ax\" \n\t"		\
243d4dc402cSAvi Kivity 	 "1001: \n\t"					\
244d4dc402cSAvi Kivity 	 "insn_code_" #name ": " str " \n\t"		\
245d4dc402cSAvi Kivity 	 "1002: \n\t"					\
246d4dc402cSAvi Kivity 	 ".popsection"					\
2477d36db35SAvi Kivity     );							\
248d4dc402cSAvi Kivity     extern struct insn_desc insn_##name;
2497d36db35SAvi Kivity 
2502e3f9f1fSThomas Huth static void test_xchg(void)
2517d36db35SAvi Kivity {
2527d36db35SAvi Kivity 	MK_INSN(xchg_test1, "xchg %eax,%eax\n\t");
2537d36db35SAvi Kivity 	MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t");
2547d36db35SAvi Kivity 	MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t");
2557d36db35SAvi Kivity 	MK_INSN(xchg_test4, "xchg %eax,%edx\n\t");
2567d36db35SAvi Kivity 	MK_INSN(xchg_test5, "xchg %eax,%esi\n\t");
2577d36db35SAvi Kivity 	MK_INSN(xchg_test6, "xchg %eax,%edi\n\t");
2587d36db35SAvi Kivity 	MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t");
2597d36db35SAvi Kivity 	MK_INSN(xchg_test8, "xchg %eax,%esp\n\t");
2607d36db35SAvi Kivity 
26118253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7};
2627d36db35SAvi Kivity 
26318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test1);
2646055ea1fSAvi Kivity 	report("xchg 1", 0, 1);
26518253fdeSAvi Kivity 
26618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test2);
2676055ea1fSAvi Kivity 	report("xchg 2", R_AX | R_BX,
2686055ea1fSAvi Kivity 	       outregs.eax == inregs.ebx && outregs.ebx == inregs.eax);
2697d36db35SAvi Kivity 
27018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test3);
2716055ea1fSAvi Kivity 	report("xchg 3", R_AX | R_CX,
2726055ea1fSAvi Kivity 	       outregs.eax == inregs.ecx && outregs.ecx == inregs.eax);
2737d36db35SAvi Kivity 
27418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test4);
2756055ea1fSAvi Kivity 	report("xchg 4", R_AX | R_DX,
2766055ea1fSAvi Kivity 	       outregs.eax == inregs.edx && outregs.edx == inregs.eax);
2777d36db35SAvi Kivity 
27818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test5);
2796055ea1fSAvi Kivity 	report("xchg 5", R_AX | R_SI,
2806055ea1fSAvi Kivity 	       outregs.eax == inregs.esi && outregs.esi == inregs.eax);
2817d36db35SAvi Kivity 
28218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test6);
2836055ea1fSAvi Kivity 	report("xchg 6", R_AX | R_DI,
2846055ea1fSAvi Kivity 	       outregs.eax == inregs.edi && outregs.edi == inregs.eax);
2857d36db35SAvi Kivity 
28618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test7);
2876055ea1fSAvi Kivity 	report("xchg 7", R_AX | R_BP,
2886055ea1fSAvi Kivity 	       outregs.eax == inregs.ebp && outregs.ebp == inregs.eax);
2897d36db35SAvi Kivity 
29018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test8);
2916055ea1fSAvi Kivity 	report("xchg 8", R_AX | R_SP,
2926055ea1fSAvi Kivity 	       outregs.eax == inregs.esp && outregs.esp == inregs.eax);
2937d36db35SAvi Kivity }
2947d36db35SAvi Kivity 
2952e3f9f1fSThomas Huth static void test_shld(void)
2967d36db35SAvi Kivity {
2977d36db35SAvi Kivity 	MK_INSN(shld_test, "shld $8,%edx,%eax\n\t");
2987d36db35SAvi Kivity 
29918253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0xbe, .edx = 0xef000000 };
30018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_shld_test);
3016055ea1fSAvi Kivity 	report("shld", ~0, outregs.eax == 0xbeef);
3027d36db35SAvi Kivity }
3037d36db35SAvi Kivity 
3042e3f9f1fSThomas Huth static void test_mov_imm(void)
3057d36db35SAvi Kivity {
3067d36db35SAvi Kivity 	MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax");
3077d36db35SAvi Kivity 	MK_INSN(mov_r16_imm_1, "mov $1234, %ax");
3087d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_1, "mov $0x12, %ah");
3097d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_2, "mov $0x34, %al");
3107d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t");
3117d36db35SAvi Kivity 
31218253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
31318253fdeSAvi Kivity 
31418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r16_imm_1);
3156055ea1fSAvi Kivity 	report("mov 1", R_AX, outregs.eax == 1234);
3167d36db35SAvi Kivity 
3177d36db35SAvi Kivity 	/* test mov $imm, %eax */
31818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r32_imm_1);
3196055ea1fSAvi Kivity 	report("mov 2", R_AX, outregs.eax == 1234567890);
3207d36db35SAvi Kivity 
3217d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
32218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_1);
3236055ea1fSAvi Kivity 	report("mov 3", R_AX, outregs.eax == 0x1200);
3247d36db35SAvi Kivity 
32518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_2);
3266055ea1fSAvi Kivity 	report("mov 4", R_AX, outregs.eax == 0x34);
3277d36db35SAvi Kivity 
32818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_3);
3296055ea1fSAvi Kivity 	report("mov 5", R_AX, outregs.eax == 0x1234);
3307d36db35SAvi Kivity }
3317d36db35SAvi Kivity 
3322e3f9f1fSThomas Huth static void test_sub_imm(void)
3337d36db35SAvi Kivity {
3347d36db35SAvi Kivity 	MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t");
3357d36db35SAvi Kivity 	MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t");
3367d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t");
3377d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t");
3387d36db35SAvi Kivity 
33918253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
34018253fdeSAvi Kivity 
34118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r16_imm_1);
3426055ea1fSAvi Kivity 	report("sub 1", R_AX, outregs.eax == 1224);
3437d36db35SAvi Kivity 
3447d36db35SAvi Kivity 	/* test mov $imm, %eax */
34518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r32_imm_1);
3466055ea1fSAvi Kivity 	report("sub 2", R_AX, outregs.eax == 1234567880);
3477d36db35SAvi Kivity 
3487d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
34918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_1);
3506055ea1fSAvi Kivity 	report("sub 3", R_AX, outregs.eax == 0x0200);
3517d36db35SAvi Kivity 
35218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_2);
3536055ea1fSAvi Kivity 	report("sub 4", R_AX, outregs.eax == 0x24);
3547d36db35SAvi Kivity }
3557d36db35SAvi Kivity 
3562e3f9f1fSThomas Huth static void test_xor_imm(void)
3577d36db35SAvi Kivity {
3587d36db35SAvi Kivity 	MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t");
3597d36db35SAvi Kivity 	MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t");
3607d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t");
3617d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t");
3627d36db35SAvi Kivity 
36318253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
36418253fdeSAvi Kivity 
36518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r16_imm_1);
3666055ea1fSAvi Kivity 	report("xor 1", R_AX, outregs.eax == 0);
3677d36db35SAvi Kivity 
3687d36db35SAvi Kivity 	/* test mov $imm, %eax */
36918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r32_imm_1);
3706055ea1fSAvi Kivity 	report("xor 2", R_AX, outregs.eax == 0);
3717d36db35SAvi Kivity 
3727d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
37318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_1);
3746055ea1fSAvi Kivity 	report("xor 3", R_AX, outregs.eax == 0);
3757d36db35SAvi Kivity 
37618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_2);
3776055ea1fSAvi Kivity 	report("xor 4", R_AX, outregs.eax == 0);
3787d36db35SAvi Kivity }
3797d36db35SAvi Kivity 
3802e3f9f1fSThomas Huth static void test_cmp_imm(void)
3817d36db35SAvi Kivity {
3827d36db35SAvi Kivity 	MK_INSN(cmp_test1, "mov $0x34, %al\n\t"
3837d36db35SAvi Kivity 			   "cmp $0x34, %al\n\t");
3847d36db35SAvi Kivity 	MK_INSN(cmp_test2, "mov $0x34, %al\n\t"
3857d36db35SAvi Kivity 			   "cmp $0x39, %al\n\t");
3867d36db35SAvi Kivity 	MK_INSN(cmp_test3, "mov $0x34, %al\n\t"
3877d36db35SAvi Kivity 			   "cmp $0x24, %al\n\t");
3887d36db35SAvi Kivity 
38918253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
39018253fdeSAvi Kivity 
3917d36db35SAvi Kivity 	/* test cmp imm8 with AL */
3927d36db35SAvi Kivity 	/* ZF: (bit 6) Zero Flag becomes 1 if an operation results
3937d36db35SAvi Kivity 	 * in a 0 writeback, or 0 register
3947d36db35SAvi Kivity 	 */
39518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test1);
3966055ea1fSAvi Kivity 	report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6));
3977d36db35SAvi Kivity 
39818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test2);
3996055ea1fSAvi Kivity 	report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0);
4007d36db35SAvi Kivity 
40118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test3);
4026055ea1fSAvi Kivity 	report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0);
4037d36db35SAvi Kivity }
4047d36db35SAvi Kivity 
4052e3f9f1fSThomas Huth static void test_add_imm(void)
4067d36db35SAvi Kivity {
4077d36db35SAvi Kivity 	MK_INSN(add_test1, "mov $0x43211234, %eax \n\t"
4087d36db35SAvi Kivity 			   "add $0x12344321, %eax \n\t");
4097d36db35SAvi Kivity 	MK_INSN(add_test2, "mov $0x12, %eax \n\t"
4107d36db35SAvi Kivity 			   "add $0x21, %al\n\t");
4117d36db35SAvi Kivity 
41218253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
41318253fdeSAvi Kivity 
41418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test1);
4156055ea1fSAvi Kivity 	report("add 1", ~0, outregs.eax == 0x55555555);
4167d36db35SAvi Kivity 
41718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test2);
4186055ea1fSAvi Kivity 	report("add 2", ~0, outregs.eax == 0x33);
4197d36db35SAvi Kivity }
4207d36db35SAvi Kivity 
4212e3f9f1fSThomas Huth static void test_eflags_insn(void)
4227d36db35SAvi Kivity {
4237d36db35SAvi Kivity 	MK_INSN(clc, "clc");
424b3261e48SMohammed Gamal 	MK_INSN(stc, "stc");
4257d36db35SAvi Kivity 	MK_INSN(cli, "cli");
4267d36db35SAvi Kivity 	MK_INSN(sti, "sti");
4277d36db35SAvi Kivity 	MK_INSN(cld, "cld");
4287d36db35SAvi Kivity 	MK_INSN(std, "std");
4297d36db35SAvi Kivity 
43018253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
43118253fdeSAvi Kivity 
43218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_clc);
4336055ea1fSAvi Kivity 	report("clc", ~0, (outregs.eflags & 1) == 0);
4347d36db35SAvi Kivity 
43518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_stc);
4366055ea1fSAvi Kivity 	report("stc", ~0, (outregs.eflags & 1) == 1);
437b3261e48SMohammed Gamal 
43818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cli);
4396055ea1fSAvi Kivity 	report("cli", ~0, !(outregs.eflags & (1 << 9)));
4407d36db35SAvi Kivity 
44118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sti);
4426055ea1fSAvi Kivity 	report("sti", ~0, outregs.eflags & (1 << 9));
4437d36db35SAvi Kivity 
44418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cld);
4456055ea1fSAvi Kivity 	report("cld", ~0, !(outregs.eflags & (1 << 10)));
4467d36db35SAvi Kivity 
44718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_std);
4486055ea1fSAvi Kivity 	report("std", ~0, (outregs.eflags & (1 << 10)));
4497d36db35SAvi Kivity }
4507d36db35SAvi Kivity 
4512e3f9f1fSThomas Huth static void test_io(void)
4527d36db35SAvi Kivity {
4537d36db35SAvi Kivity 	MK_INSN(io_test1, "mov $0xff, %al \n\t"
4547d36db35SAvi Kivity 		          "out %al, $0xe0 \n\t"
4557d36db35SAvi Kivity 		          "mov $0x00, %al \n\t"
4567d36db35SAvi Kivity 			  "in $0xe0, %al \n\t");
4577d36db35SAvi Kivity 	MK_INSN(io_test2, "mov $0xffff, %ax \n\t"
4587d36db35SAvi Kivity 			  "out %ax, $0xe0 \n\t"
4597d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
4607d36db35SAvi Kivity 			  "in $0xe0, %ax \n\t");
4617d36db35SAvi Kivity 	MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t"
4627d36db35SAvi Kivity 			  "out %eax, $0xe0 \n\t"
4637d36db35SAvi Kivity 			  "mov $0x000000, %eax \n\t"
4647d36db35SAvi Kivity 			  "in $0xe0, %eax \n\t");
4657d36db35SAvi Kivity 	MK_INSN(io_test4, "mov $0xe0, %dx \n\t"
4667d36db35SAvi Kivity 			  "mov $0xff, %al \n\t"
4677d36db35SAvi Kivity 			  "out %al, %dx \n\t"
4687d36db35SAvi Kivity 			  "mov $0x00, %al \n\t"
4697d36db35SAvi Kivity 			  "in %dx, %al \n\t");
4707d36db35SAvi Kivity 	MK_INSN(io_test5, "mov $0xe0, %dx \n\t"
4717d36db35SAvi Kivity 			  "mov $0xffff, %ax \n\t"
4727d36db35SAvi Kivity 			  "out %ax, %dx \n\t"
4737d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
4747d36db35SAvi Kivity 			  "in %dx, %ax \n\t");
4757d36db35SAvi Kivity 	MK_INSN(io_test6, "mov $0xe0, %dx \n\t"
4767d36db35SAvi Kivity 			  "mov $0xffffffff, %eax \n\t"
4777d36db35SAvi Kivity 			  "out %eax, %dx \n\t"
4787d36db35SAvi Kivity 			  "mov $0x00000000, %eax \n\t"
4797d36db35SAvi Kivity 			  "in %dx, %eax \n\t");
4807d36db35SAvi Kivity 
48118253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
48218253fdeSAvi Kivity 
48318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test1);
4846055ea1fSAvi Kivity 	report("pio 1", R_AX, outregs.eax == 0xff);
4857d36db35SAvi Kivity 
48618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test2);
4876055ea1fSAvi Kivity 	report("pio 2", R_AX, outregs.eax == 0xffff);
4887d36db35SAvi Kivity 
48918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test3);
4906055ea1fSAvi Kivity 	report("pio 3", R_AX, outregs.eax == 0xffffffff);
4917d36db35SAvi Kivity 
49218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test4);
4936055ea1fSAvi Kivity 	report("pio 4", R_AX|R_DX, outregs.eax == 0xff);
4947d36db35SAvi Kivity 
49518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test5);
4966055ea1fSAvi Kivity 	report("pio 5", R_AX|R_DX, outregs.eax == 0xffff);
4977d36db35SAvi Kivity 
49818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test6);
4996055ea1fSAvi Kivity 	report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff);
5007d36db35SAvi Kivity }
5017d36db35SAvi Kivity 
502c0b7268dSAvi Kivity asm ("retf: lretw");
5032e3f9f1fSThomas Huth extern void retf(void);
504c0b7268dSAvi Kivity 
5054f66bc86SBruce Rogers asm ("retf_imm: lretw $10");
5062e3f9f1fSThomas Huth extern void retf_imm(void);
5074f66bc86SBruce Rogers 
5082e3f9f1fSThomas Huth static void test_call(void)
5097d36db35SAvi Kivity {
5107d36db35SAvi Kivity 	u32 esp[16];
511c0b7268dSAvi Kivity 	u32 addr;
5127d36db35SAvi Kivity 
51318253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
51447086996SBill Wendling 	inregs.esp = (u32)&esp[ARRAY_SIZE(esp)];
5157d36db35SAvi Kivity 
5167d36db35SAvi Kivity 	MK_INSN(call1, "mov $test_function, %eax \n\t"
5177d36db35SAvi Kivity 		       "call *%eax\n\t");
5187d36db35SAvi Kivity 	MK_INSN(call_near1, "jmp 2f\n\t"
5197d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5207d36db35SAvi Kivity 			    "ret\n\t"
5217d36db35SAvi Kivity 			    "2: call 1b\t");
5227d36db35SAvi Kivity 	MK_INSN(call_near2, "call 1f\n\t"
5237d36db35SAvi Kivity 			    "jmp 2f\n\t"
5247d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5257d36db35SAvi Kivity 			    "ret\n\t"
5267d36db35SAvi Kivity 			    "2:\t");
527c0b7268dSAvi Kivity 	MK_INSN(call_far1,  "lcallw *(%ebx)\n\t");
528556d2680SWei Yongjun 	MK_INSN(call_far2,  "lcallw $0, $retf\n\t");
529c6061817SAvi Kivity 	MK_INSN(ret_imm,    "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b");
5304f66bc86SBruce Rogers 	MK_INSN(retf_imm,   "sub $10, %sp; lcallw $0, $retf_imm");
5317d36db35SAvi Kivity 
53218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call1);
5336055ea1fSAvi Kivity 	report("call 1", R_AX, outregs.eax == 0x1234);
5347d36db35SAvi Kivity 
53518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near1);
5366055ea1fSAvi Kivity 	report("call near 1", R_AX, outregs.eax == 0x1234);
5377d36db35SAvi Kivity 
53818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near2);
5396055ea1fSAvi Kivity 	report("call near 2", R_AX, outregs.eax == 0x1234);
540c0b7268dSAvi Kivity 
541c0b7268dSAvi Kivity 	addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f);
542c0b7268dSAvi Kivity 	inregs.ebx = (unsigned)&addr;
54318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_far1);
5446055ea1fSAvi Kivity 	report("call far 1", 0, 1);
545c6061817SAvi Kivity 
546556d2680SWei Yongjun 	exec_in_big_real_mode(&insn_call_far2);
547556d2680SWei Yongjun 	report("call far 2", 0, 1);
548556d2680SWei Yongjun 
54918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_ret_imm);
5506055ea1fSAvi Kivity 	report("ret imm 1", 0, 1);
5514f66bc86SBruce Rogers 
5524f66bc86SBruce Rogers 	exec_in_big_real_mode(&insn_retf_imm);
5534f66bc86SBruce Rogers 	report("retf imm 1", 0, 1);
5547d36db35SAvi Kivity }
5557d36db35SAvi Kivity 
5562e3f9f1fSThomas Huth static void test_jcc_short(void)
5577d36db35SAvi Kivity {
5587d36db35SAvi Kivity 	MK_INSN(jnz_short1, "jnz 1f\n\t"
5597d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
5607d36db35SAvi Kivity 		            "1:\n\t");
5617d36db35SAvi Kivity 	MK_INSN(jnz_short2, "1:\n\t"
5627d36db35SAvi Kivity 			    "cmp $0x1234, %eax\n\t"
5637d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
5647d36db35SAvi Kivity 		            "jnz 1b\n\t");
5657d36db35SAvi Kivity 	MK_INSN(jmp_short1, "jmp 1f\n\t"
5667d36db35SAvi Kivity 		      "mov $0x1234, %eax\n\t"
5677d36db35SAvi Kivity 		      "1:\n\t");
5687d36db35SAvi Kivity 
56918253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
5707d36db35SAvi Kivity 
57118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short1);
5726055ea1fSAvi Kivity 	report("jnz short 1", ~0, 1);
57318253fdeSAvi Kivity 
57418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short2);
5756055ea1fSAvi Kivity 	report("jnz short 2", R_AX, (outregs.eflags & (1 << 6)));
5767d36db35SAvi Kivity 
57718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_short1);
5786055ea1fSAvi Kivity 	report("jmp short 1", ~0, 1);
5797d36db35SAvi Kivity }
5807d36db35SAvi Kivity 
5812e3f9f1fSThomas Huth static void test_jcc_near(void)
5827d36db35SAvi Kivity {
5837d36db35SAvi Kivity 	/* encode near jmp manually. gas will not do it if offsets < 127 byte */
5847d36db35SAvi Kivity 	MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t"
5857d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
5867d36db35SAvi Kivity 	MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t"
5877d36db35SAvi Kivity 			   "mov $0x1234, %eax\n\t"
5887d36db35SAvi Kivity 		           ".byte 0x0f, 0x85, 0xf0, 0xff\n\t");
5897d36db35SAvi Kivity 	MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t"
5907d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
5917d36db35SAvi Kivity 
59218253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
5937d36db35SAvi Kivity 
59418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near1);
5956055ea1fSAvi Kivity 	report("jnz near 1", 0, 1);
59618253fdeSAvi Kivity 
59718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near2);
5986055ea1fSAvi Kivity 	report("jnz near 2", R_AX, outregs.eflags & (1 << 6));
5997d36db35SAvi Kivity 
60018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_near1);
6016055ea1fSAvi Kivity 	report("jmp near 1", 0, 1);
6027d36db35SAvi Kivity }
6037d36db35SAvi Kivity 
6042e3f9f1fSThomas Huth static void test_long_jmp(void)
6057d36db35SAvi Kivity {
6067d36db35SAvi Kivity 	u32 esp[16];
6077d36db35SAvi Kivity 
60818253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
609*074766aeSPaolo Bonzini 	inregs.esp = (u32)&esp[ARRAY_SIZE(esp)];
6107d36db35SAvi Kivity 	MK_INSN(long_jmp, "call 1f\n\t"
6117d36db35SAvi Kivity 			  "jmp 2f\n\t"
6127d36db35SAvi Kivity 			  "1: jmp $0, $test_function\n\t"
6137d36db35SAvi Kivity 		          "2:\n\t");
61418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_long_jmp);
6156055ea1fSAvi Kivity 	report("jmp far 1", R_AX, outregs.eax == 0x1234);
6167d36db35SAvi Kivity }
617fa74f8a6SMohammed Gamal 
6182e3f9f1fSThomas Huth static void test_push_pop(void)
6197d36db35SAvi Kivity {
6207d36db35SAvi Kivity 	MK_INSN(push32, "mov $0x12345678, %eax\n\t"
6217d36db35SAvi Kivity 			"push %eax\n\t"
6227d36db35SAvi Kivity 			"pop %ebx\n\t");
6237d36db35SAvi Kivity 	MK_INSN(push16, "mov $0x1234, %ax\n\t"
6247d36db35SAvi Kivity 			"push %ax\n\t"
6257d36db35SAvi Kivity 			"pop %bx\n\t");
6267d36db35SAvi Kivity 
6277d36db35SAvi Kivity 	MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten
6287d36db35SAvi Kivity 			 "mov $0x123, %ax\n\t"
6297d36db35SAvi Kivity 			 "mov %ax, %es\n\t"
6307d36db35SAvi Kivity 			 "push %es\n\t"
6317d36db35SAvi Kivity 			 "pop %bx \n\t"
6327d36db35SAvi Kivity 			 );
6337d36db35SAvi Kivity 	MK_INSN(pop_es, "push %ax\n\t"
6347d36db35SAvi Kivity 			"pop %es\n\t"
6357d36db35SAvi Kivity 			"mov %es, %bx\n\t"
6367d36db35SAvi Kivity 			);
6377d36db35SAvi Kivity 	MK_INSN(push_pop_ss, "push %ss\n\t"
6387d36db35SAvi Kivity 			     "pushw %ax\n\t"
6397d36db35SAvi Kivity 			     "popw %ss\n\t"
6407d36db35SAvi Kivity 			     "mov %ss, %bx\n\t"
6417d36db35SAvi Kivity 			     "pop %ss\n\t"
6427d36db35SAvi Kivity 			);
6437d36db35SAvi Kivity 	MK_INSN(push_pop_fs, "push %fs\n\t"
6447d36db35SAvi Kivity 			     "pushl %eax\n\t"
6457d36db35SAvi Kivity 			     "popl %fs\n\t"
6467d36db35SAvi Kivity 			     "mov %fs, %ebx\n\t"
6477d36db35SAvi Kivity 			     "pop %fs\n\t"
6487d36db35SAvi Kivity 			);
64909b657b6SAvi Kivity 	MK_INSN(push_pop_high_esp_bits,
65009b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
65109b657b6SAvi Kivity 		"push %ax; \n\t"
65209b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
65309b657b6SAvi Kivity 		"pop %bx");
6547d36db35SAvi Kivity 
65518253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
65618253fdeSAvi Kivity 
65718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push32);
6586055ea1fSAvi Kivity 	report("push/pop 1", R_AX|R_BX,
6596055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x12345678);
6607d36db35SAvi Kivity 
66118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push16);
6626055ea1fSAvi Kivity 	report("push/pop 2", R_AX|R_BX,
6636055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x1234);
6647d36db35SAvi Kivity 
66518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_es);
6666055ea1fSAvi Kivity 	report("push/pop 3", R_AX|R_BX,
6676055ea1fSAvi Kivity 	       outregs.ebx == outregs.eax && outregs.eax == 0x123);
6687d36db35SAvi Kivity 
66918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pop_es);
6706055ea1fSAvi Kivity 	report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax);
6717d36db35SAvi Kivity 
67218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_ss);
6736055ea1fSAvi Kivity 	report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax);
6747d36db35SAvi Kivity 
67518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_fs);
6766055ea1fSAvi Kivity 	report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax);
67709b657b6SAvi Kivity 
67809b657b6SAvi Kivity 	inregs.eax = 0x9977;
67909b657b6SAvi Kivity 	inregs.ebx = 0x7799;
68009b657b6SAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_high_esp_bits);
68109b657b6SAvi Kivity 	report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977);
6827d36db35SAvi Kivity }
6837d36db35SAvi Kivity 
6842e3f9f1fSThomas Huth static void test_null(void)
6857d36db35SAvi Kivity {
686d4dc402cSAvi Kivity 	MK_INSN(null, "");
687d4dc402cSAvi Kivity 
68818253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
68918253fdeSAvi Kivity 
69018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_null);
6916055ea1fSAvi Kivity 	report("null", 0, 1);
6927d36db35SAvi Kivity }
6937d36db35SAvi Kivity 
6947d36db35SAvi Kivity struct {
6957d36db35SAvi Kivity     char stack[500];
6967d36db35SAvi Kivity     char top[];
6977d36db35SAvi Kivity } tmp_stack;
6987d36db35SAvi Kivity 
6992e3f9f1fSThomas Huth static void test_pusha_popa(void)
7007d36db35SAvi Kivity {
7017d36db35SAvi Kivity 	MK_INSN(pusha, "pusha\n\t"
7027d36db35SAvi Kivity 		       "pop %edi\n\t"
7037d36db35SAvi Kivity 		       "pop %esi\n\t"
7047d36db35SAvi Kivity 		       "pop %ebp\n\t"
7057d36db35SAvi Kivity 		       "add $4, %esp\n\t"
7067d36db35SAvi Kivity 		       "pop %ebx\n\t"
7077d36db35SAvi Kivity 		       "pop %edx\n\t"
7087d36db35SAvi Kivity 		       "pop %ecx\n\t"
7097d36db35SAvi Kivity 		       "pop %eax\n\t"
7107d36db35SAvi Kivity 		       );
7117d36db35SAvi Kivity 
7127d36db35SAvi Kivity 	MK_INSN(popa, "push %eax\n\t"
7137d36db35SAvi Kivity 		      "push %ecx\n\t"
7147d36db35SAvi Kivity 		      "push %edx\n\t"
7157d36db35SAvi Kivity 		      "push %ebx\n\t"
7167d36db35SAvi Kivity 		      "push %esp\n\t"
7177d36db35SAvi Kivity 		      "push %ebp\n\t"
7187d36db35SAvi Kivity 		      "push %esi\n\t"
7197d36db35SAvi Kivity 		      "push %edi\n\t"
7207d36db35SAvi Kivity 		      "popa\n\t"
7217d36db35SAvi Kivity 		      );
7227d36db35SAvi Kivity 
72318253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top };
7247d36db35SAvi Kivity 
72518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pusha);
7266055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
72718253fdeSAvi Kivity 
72818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_popa);
7296055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
7307d36db35SAvi Kivity }
7317d36db35SAvi Kivity 
7322e3f9f1fSThomas Huth static void test_iret(void)
7337d36db35SAvi Kivity {
7347d36db35SAvi Kivity 	MK_INSN(iret32, "pushf\n\t"
7357d36db35SAvi Kivity 			"pushl %cs\n\t"
7367d36db35SAvi Kivity 			"call 1f\n\t" /* a near call will push eip onto the stack */
7377d36db35SAvi Kivity 			"jmp 2f\n\t"
7387d36db35SAvi Kivity 			"1: iret\n\t"
7397d36db35SAvi Kivity 			"2:\n\t"
7407d36db35SAvi Kivity 		     );
7417d36db35SAvi Kivity 
7427d36db35SAvi Kivity 	MK_INSN(iret16, "pushfw\n\t"
7437d36db35SAvi Kivity 			"pushw %cs\n\t"
7447d36db35SAvi Kivity 			"callw 1f\n\t"
7457d36db35SAvi Kivity 			"jmp 2f\n\t"
7467d36db35SAvi Kivity 			"1: iretw\n\t"
7477d36db35SAvi Kivity 			"2:\n\t");
7487d36db35SAvi Kivity 
7497d36db35SAvi Kivity 	MK_INSN(iret_flags32, "pushfl\n\t"
7507d36db35SAvi Kivity 			      "popl %eax\n\t"
7517d36db35SAvi Kivity 			      "andl $~0x2, %eax\n\t"
752964942e8SNadav Amit 			      "orl $0xffc18028, %eax\n\t"
7537d36db35SAvi Kivity 			      "pushl %eax\n\t"
7547d36db35SAvi Kivity 			      "pushl %cs\n\t"
7557d36db35SAvi Kivity 			      "call 1f\n\t"
7567d36db35SAvi Kivity 			      "jmp 2f\n\t"
7577d36db35SAvi Kivity 			      "1: iret\n\t"
7587d36db35SAvi Kivity 			      "2:\n\t");
7597d36db35SAvi Kivity 
7607d36db35SAvi Kivity 	MK_INSN(iret_flags16, "pushfw\n\t"
7617d36db35SAvi Kivity 			      "popw %ax\n\t"
7627d36db35SAvi Kivity 			      "and $~0x2, %ax\n\t"
7637d36db35SAvi Kivity 			      "or $0x8028, %ax\n\t"
7647d36db35SAvi Kivity 			      "pushw %ax\n\t"
7657d36db35SAvi Kivity 			      "pushw %cs\n\t"
7667d36db35SAvi Kivity 			      "callw 1f\n\t"
7677d36db35SAvi Kivity 			      "jmp 2f\n\t"
7687d36db35SAvi Kivity 			      "1: iretw\n\t"
7697d36db35SAvi Kivity 			      "2:\n\t");
7707d36db35SAvi Kivity 
77118253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
7727d36db35SAvi Kivity 
77318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret32);
7746055ea1fSAvi Kivity 	report("iret 1", 0, 1);
7757d36db35SAvi Kivity 
77618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret16);
7776055ea1fSAvi Kivity 	report("iret 2", 0, 1);
7787d36db35SAvi Kivity 
77918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags32);
7806055ea1fSAvi Kivity 	report("iret 3", R_AX, 1);
781964942e8SNadav Amit 	report("rflags.rf", ~0, !(outregs.eflags & (1 << 16)));
78218253fdeSAvi Kivity 
78318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags16);
7846055ea1fSAvi Kivity 	report("iret 4", R_AX, 1);
7857d36db35SAvi Kivity }
7867d36db35SAvi Kivity 
7872e3f9f1fSThomas Huth static void test_int(void)
78896b9ca1eSMohammed Gamal {
78918253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
79096b9ca1eSMohammed Gamal 
79196b9ca1eSMohammed Gamal 	*(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */
79296b9ca1eSMohammed Gamal 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
79396b9ca1eSMohammed Gamal 
79496b9ca1eSMohammed Gamal 	MK_INSN(int11, "int $0x11\n\t");
79596b9ca1eSMohammed Gamal 
79618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_int11);
7976055ea1fSAvi Kivity 	report("int 1", 0, 1);
79896b9ca1eSMohammed Gamal }
79996b9ca1eSMohammed Gamal 
8002e3f9f1fSThomas Huth static void test_imul(void)
801fa74f8a6SMohammed Gamal {
802fa74f8a6SMohammed Gamal 	MK_INSN(imul8_1, "mov $2, %al\n\t"
803fa74f8a6SMohammed Gamal 			"mov $-4, %cx\n\t"
804fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
805fa74f8a6SMohammed Gamal 
806fa74f8a6SMohammed Gamal 	MK_INSN(imul16_1, "mov $2, %ax\n\t"
807fa74f8a6SMohammed Gamal 		      "mov $-4, %cx\n\t"
808fa74f8a6SMohammed Gamal 		      "imul %cx\n\t");
809fa74f8a6SMohammed Gamal 
810fa74f8a6SMohammed Gamal 	MK_INSN(imul32_1, "mov $2, %eax\n\t"
811fa74f8a6SMohammed Gamal 		       "mov $-4, %ecx\n\t"
812fa74f8a6SMohammed Gamal 		       "imul %ecx\n\t");
813fa74f8a6SMohammed Gamal 
814fa74f8a6SMohammed Gamal 	MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t"
815fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
816fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
817fa74f8a6SMohammed Gamal 
818fa74f8a6SMohammed Gamal 	MK_INSN(imul16_2, "mov $2, %ax\n\t"
819fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
820fa74f8a6SMohammed Gamal 			"imul %cx\n\t");
821fa74f8a6SMohammed Gamal 
822fa74f8a6SMohammed Gamal 	MK_INSN(imul32_2, "mov $2, %eax\n\t"
823fa74f8a6SMohammed Gamal 			"mov $4, %ecx\n\t"
824fa74f8a6SMohammed Gamal 			"imul %ecx\n\t");
825fa74f8a6SMohammed Gamal 
82618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
82718253fdeSAvi Kivity 
82818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_1);
8296055ea1fSAvi Kivity 	report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8);
830fa74f8a6SMohammed Gamal 
83118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_1);
8326055ea1fSAvi Kivity 	report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8);
833fa74f8a6SMohammed Gamal 
83418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_1);
8356055ea1fSAvi Kivity 	report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8);
836fa74f8a6SMohammed Gamal 
83718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_2);
8386055ea1fSAvi Kivity 	report("imul 4", R_AX | R_CX | R_DX,
8396055ea1fSAvi Kivity 	       (outregs.eax & 0xffff) == 8
84081050840SAvi Kivity 	       && (outregs.eax & 0xffff0000) == 0x12340000);
841fa74f8a6SMohammed Gamal 
84218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_2);
8436055ea1fSAvi Kivity 	report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8);
844fa74f8a6SMohammed Gamal 
84518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_2);
8466055ea1fSAvi Kivity 	report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8);
847fa74f8a6SMohammed Gamal }
848fa74f8a6SMohammed Gamal 
8492e3f9f1fSThomas Huth static void test_mul(void)
85059317bd1SMohammed Gamal {
85159317bd1SMohammed Gamal 	MK_INSN(mul8, "mov $2, %al\n\t"
85259317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
85359317bd1SMohammed Gamal 			"imul %cl\n\t");
85459317bd1SMohammed Gamal 
85559317bd1SMohammed Gamal 	MK_INSN(mul16, "mov $2, %ax\n\t"
85659317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
85759317bd1SMohammed Gamal 			"imul %cx\n\t");
85859317bd1SMohammed Gamal 
85959317bd1SMohammed Gamal 	MK_INSN(mul32, "mov $2, %eax\n\t"
86059317bd1SMohammed Gamal 			"mov $4, %ecx\n\t"
86159317bd1SMohammed Gamal 			"imul %ecx\n\t");
86259317bd1SMohammed Gamal 
86318253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
86418253fdeSAvi Kivity 
86518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul8);
8666055ea1fSAvi Kivity 	report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8);
86759317bd1SMohammed Gamal 
86818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul16);
8696055ea1fSAvi Kivity 	report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8);
87059317bd1SMohammed Gamal 
87118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul32);
8726055ea1fSAvi Kivity 	report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8);
87359317bd1SMohammed Gamal }
87459317bd1SMohammed Gamal 
8752e3f9f1fSThomas Huth static void test_div(void)
8760d4c7614SMohammed Gamal {
8770d4c7614SMohammed Gamal 	MK_INSN(div8, "mov $257, %ax\n\t"
8780d4c7614SMohammed Gamal 			"mov $2, %cl\n\t"
8790d4c7614SMohammed Gamal 			"div %cl\n\t");
8800d4c7614SMohammed Gamal 
8810d4c7614SMohammed Gamal 	MK_INSN(div16, "mov $512, %ax\n\t"
8820d4c7614SMohammed Gamal 			"mov $5, %cx\n\t"
8830d4c7614SMohammed Gamal 			"div %cx\n\t");
8840d4c7614SMohammed Gamal 
8850d4c7614SMohammed Gamal 	MK_INSN(div32, "mov $512, %eax\n\t"
8860d4c7614SMohammed Gamal 			"mov $5, %ecx\n\t"
8870d4c7614SMohammed Gamal 			"div %ecx\n\t");
8880d4c7614SMohammed Gamal 
88918253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
89018253fdeSAvi Kivity 
89118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div8);
8926055ea1fSAvi Kivity 	report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384);
8930d4c7614SMohammed Gamal 
89418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div16);
8956055ea1fSAvi Kivity 	report("div 2", R_AX | R_CX | R_DX,
8966055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
8970d4c7614SMohammed Gamal 
89818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div32);
8996055ea1fSAvi Kivity 	report("div 3", R_AX | R_CX | R_DX,
9006055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
9010d4c7614SMohammed Gamal }
9020d4c7614SMohammed Gamal 
9032e3f9f1fSThomas Huth static void test_idiv(void)
9040d4c7614SMohammed Gamal {
9050d4c7614SMohammed Gamal 	MK_INSN(idiv8, "mov $256, %ax\n\t"
9060d4c7614SMohammed Gamal 			"mov $-2, %cl\n\t"
9070d4c7614SMohammed Gamal 			"idiv %cl\n\t");
9080d4c7614SMohammed Gamal 
9090d4c7614SMohammed Gamal 	MK_INSN(idiv16, "mov $512, %ax\n\t"
9100d4c7614SMohammed Gamal 			"mov $-2, %cx\n\t"
9110d4c7614SMohammed Gamal 			"idiv %cx\n\t");
9120d4c7614SMohammed Gamal 
9130d4c7614SMohammed Gamal 	MK_INSN(idiv32, "mov $512, %eax\n\t"
9140d4c7614SMohammed Gamal 			"mov $-2, %ecx\n\t"
9150d4c7614SMohammed Gamal 			"idiv %ecx\n\t");
9160d4c7614SMohammed Gamal 
91718253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
91818253fdeSAvi Kivity 
91918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv8);
9206055ea1fSAvi Kivity 	report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128);
9210d4c7614SMohammed Gamal 
92218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv16);
9236055ea1fSAvi Kivity 	report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256);
9240d4c7614SMohammed Gamal 
92518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv32);
9266055ea1fSAvi Kivity 	report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256);
9270d4c7614SMohammed Gamal }
9280d4c7614SMohammed Gamal 
9292e3f9f1fSThomas Huth static void test_cbw(void)
9306e293cf5SWei Yongjun {
9316e293cf5SWei Yongjun 	MK_INSN(cbw, "mov $0xFE, %eax \n\t"
9326e293cf5SWei Yongjun 		     "cbw\n\t");
9336e293cf5SWei Yongjun 	MK_INSN(cwde, "mov $0xFFFE, %eax \n\t"
9346e293cf5SWei Yongjun 		      "cwde\n\t");
9356e293cf5SWei Yongjun 
93618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
93718253fdeSAvi Kivity 
93818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cbw);
9396055ea1fSAvi Kivity 	report("cbq 1", ~0, outregs.eax == 0xFFFE);
9406e293cf5SWei Yongjun 
94118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwde);
9426055ea1fSAvi Kivity 	report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE);
9436e293cf5SWei Yongjun }
9446e293cf5SWei Yongjun 
9452e3f9f1fSThomas Huth static void test_loopcc(void)
946eacef4e2SWei Yongjun {
947eacef4e2SWei Yongjun 	MK_INSN(loop, "mov $10, %ecx\n\t"
948eacef4e2SWei Yongjun 		      "1: inc %eax\n\t"
949eacef4e2SWei Yongjun 		      "loop 1b\n\t");
950eacef4e2SWei Yongjun 
951eacef4e2SWei Yongjun 	MK_INSN(loope, "mov $10, %ecx\n\t"
952eacef4e2SWei Yongjun 		       "mov $1, %eax\n\t"
953eacef4e2SWei Yongjun 		       "1: dec %eax\n\t"
954eacef4e2SWei Yongjun 		       "loope 1b\n\t");
955eacef4e2SWei Yongjun 
956eacef4e2SWei Yongjun 	MK_INSN(loopne, "mov $10, %ecx\n\t"
957eacef4e2SWei Yongjun 		        "mov $5, %eax\n\t"
958eacef4e2SWei Yongjun 		        "1: dec %eax\n\t"
959eacef4e2SWei Yongjun 			"loopne 1b\n\t");
960eacef4e2SWei Yongjun 
96118253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
962eacef4e2SWei Yongjun 
96318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loop);
9646055ea1fSAvi Kivity 	report("LOOPcc short 1", R_AX, outregs.eax == 10);
96518253fdeSAvi Kivity 
96618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loope);
9676055ea1fSAvi Kivity 	report("LOOPcc short 2", R_AX | R_CX,
9686055ea1fSAvi Kivity 	       outregs.eax == -1 && outregs.ecx == 8);
969eacef4e2SWei Yongjun 
97018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loopne);
9716055ea1fSAvi Kivity 	report("LOOPcc short 3", R_AX | R_CX,
9726055ea1fSAvi Kivity 	       outregs.eax == 0 && outregs.ecx == 5);
973eacef4e2SWei Yongjun }
974eacef4e2SWei Yongjun 
975b274feedSAvi Kivity static void test_das(void)
976b274feedSAvi Kivity {
977b274feedSAvi Kivity     short i;
97881050840SAvi Kivity     u16 nr_fail = 0;
979b274feedSAvi Kivity     static unsigned test_cases[1024] = {
980b274feedSAvi Kivity         0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00,
981b274feedSAvi Kivity         0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01,
982b274feedSAvi Kivity         0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02,
983b274feedSAvi Kivity         0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03,
984b274feedSAvi Kivity         0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04,
985b274feedSAvi Kivity         0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05,
986b274feedSAvi Kivity         0x06000606, 0x8701a606, 0x56100006, 0x9711a006,
987b274feedSAvi Kivity         0x02000707, 0x8301a707, 0x12100107, 0x9311a107,
988b274feedSAvi Kivity         0x02000808, 0x8301a808, 0x12100208, 0x9311a208,
989b274feedSAvi Kivity         0x06000909, 0x8701a909, 0x16100309, 0x9711a309,
990b274feedSAvi Kivity         0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a,
991b274feedSAvi Kivity         0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b,
992b274feedSAvi Kivity         0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c,
993b274feedSAvi Kivity         0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d,
994b274feedSAvi Kivity         0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e,
995b274feedSAvi Kivity         0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f,
996b274feedSAvi Kivity         0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10,
997b274feedSAvi Kivity         0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11,
998b274feedSAvi Kivity         0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12,
999b274feedSAvi Kivity         0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13,
1000b274feedSAvi Kivity         0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14,
1001b274feedSAvi Kivity         0x02001515, 0x8301b515, 0x16100f15, 0x9711af15,
1002b274feedSAvi Kivity         0x02001616, 0x8301b616, 0x12101016, 0x9311b016,
1003b274feedSAvi Kivity         0x06001717, 0x8701b717, 0x16101117, 0x9711b117,
1004b274feedSAvi Kivity         0x06001818, 0x8701b818, 0x16101218, 0x9711b218,
1005b274feedSAvi Kivity         0x02001919, 0x8301b919, 0x12101319, 0x9311b319,
1006b274feedSAvi Kivity         0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a,
1007b274feedSAvi Kivity         0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b,
1008b274feedSAvi Kivity         0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c,
1009b274feedSAvi Kivity         0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d,
1010b274feedSAvi Kivity         0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e,
1011b274feedSAvi Kivity         0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f,
1012b274feedSAvi Kivity         0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20,
1013b274feedSAvi Kivity         0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21,
1014b274feedSAvi Kivity         0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22,
1015b274feedSAvi Kivity         0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23,
1016b274feedSAvi Kivity         0x06002424, 0x8301c424, 0x16101e24, 0x9711be24,
1017b274feedSAvi Kivity         0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25,
1018b274feedSAvi Kivity         0x02002626, 0x8701c626, 0x12102026, 0x9711c026,
1019b274feedSAvi Kivity         0x06002727, 0x8301c727, 0x16102127, 0x9311c127,
1020b274feedSAvi Kivity         0x06002828, 0x8301c828, 0x16102228, 0x9311c228,
1021b274feedSAvi Kivity         0x02002929, 0x8701c929, 0x12102329, 0x9711c329,
1022b274feedSAvi Kivity         0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a,
1023b274feedSAvi Kivity         0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b,
1024b274feedSAvi Kivity         0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c,
1025b274feedSAvi Kivity         0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d,
1026b274feedSAvi Kivity         0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e,
1027b274feedSAvi Kivity         0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f,
1028b274feedSAvi Kivity         0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30,
1029b274feedSAvi Kivity         0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31,
1030b274feedSAvi Kivity         0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32,
1031b274feedSAvi Kivity         0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33,
1032b274feedSAvi Kivity         0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34,
1033b274feedSAvi Kivity         0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35,
1034b274feedSAvi Kivity         0x06003636, 0x8301d636, 0x16103036, 0x9311d036,
1035b274feedSAvi Kivity         0x02003737, 0x8701d737, 0x12103137, 0x9711d137,
1036b274feedSAvi Kivity         0x02003838, 0x8701d838, 0x12103238, 0x9711d238,
1037b274feedSAvi Kivity         0x06003939, 0x8301d939, 0x16103339, 0x9311d339,
1038b274feedSAvi Kivity         0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a,
1039b274feedSAvi Kivity         0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b,
1040b274feedSAvi Kivity         0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c,
1041b274feedSAvi Kivity         0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d,
1042b274feedSAvi Kivity         0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e,
1043b274feedSAvi Kivity         0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f,
1044b274feedSAvi Kivity         0x02004040, 0x8301e040, 0x16103a40, 0x9311da40,
1045b274feedSAvi Kivity         0x06004141, 0x8701e141, 0x12103b41, 0x9711db41,
1046b274feedSAvi Kivity         0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42,
1047b274feedSAvi Kivity         0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43,
1048b274feedSAvi Kivity         0x06004444, 0x8701e444, 0x12103e44, 0x9711de44,
1049b274feedSAvi Kivity         0x02004545, 0x8301e545, 0x16103f45, 0x9311df45,
1050b274feedSAvi Kivity         0x02004646, 0x8301e646, 0x12104046, 0x9311e046,
1051b274feedSAvi Kivity         0x06004747, 0x8701e747, 0x16104147, 0x9711e147,
1052b274feedSAvi Kivity         0x06004848, 0x8701e848, 0x16104248, 0x9711e248,
1053b274feedSAvi Kivity         0x02004949, 0x8301e949, 0x12104349, 0x9311e349,
1054b274feedSAvi Kivity         0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a,
1055b274feedSAvi Kivity         0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b,
1056b274feedSAvi Kivity         0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c,
1057b274feedSAvi Kivity         0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d,
1058b274feedSAvi Kivity         0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e,
1059b274feedSAvi Kivity         0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f,
1060b274feedSAvi Kivity         0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50,
1061b274feedSAvi Kivity         0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51,
1062b274feedSAvi Kivity         0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52,
1063b274feedSAvi Kivity         0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53,
1064b274feedSAvi Kivity         0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54,
1065b274feedSAvi Kivity         0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55,
1066b274feedSAvi Kivity         0x06005656, 0x8701f656, 0x16105056, 0x9711f056,
1067b274feedSAvi Kivity         0x02005757, 0x8301f757, 0x12105157, 0x9311f157,
1068b274feedSAvi Kivity         0x02005858, 0x8301f858, 0x12105258, 0x9311f258,
1069b274feedSAvi Kivity         0x06005959, 0x8701f959, 0x16105359, 0x9711f359,
1070b274feedSAvi Kivity         0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a,
1071b274feedSAvi Kivity         0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b,
1072b274feedSAvi Kivity         0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c,
1073b274feedSAvi Kivity         0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d,
1074b274feedSAvi Kivity         0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e,
1075b274feedSAvi Kivity         0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f,
1076b274feedSAvi Kivity         0x06006060, 0x47010060, 0x16105a60, 0x9711fa60,
1077b274feedSAvi Kivity         0x02006161, 0x03010161, 0x12105b61, 0x9311fb61,
1078b274feedSAvi Kivity         0x02006262, 0x03010262, 0x16105c62, 0x9711fc62,
1079b274feedSAvi Kivity         0x06006363, 0x07010363, 0x12105d63, 0x9311fd63,
1080b274feedSAvi Kivity         0x02006464, 0x03010464, 0x12105e64, 0x9311fe64,
1081b274feedSAvi Kivity         0x06006565, 0x07010565, 0x16105f65, 0x9711ff65,
1082b274feedSAvi Kivity         0x06006666, 0x07010666, 0x16106066, 0x57110066,
1083b274feedSAvi Kivity         0x02006767, 0x03010767, 0x12106167, 0x13110167,
1084b274feedSAvi Kivity         0x02006868, 0x03010868, 0x12106268, 0x13110268,
1085b274feedSAvi Kivity         0x06006969, 0x07010969, 0x16106369, 0x17110369,
1086b274feedSAvi Kivity         0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a,
1087b274feedSAvi Kivity         0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b,
1088b274feedSAvi Kivity         0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c,
1089b274feedSAvi Kivity         0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d,
1090b274feedSAvi Kivity         0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e,
1091b274feedSAvi Kivity         0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f,
1092b274feedSAvi Kivity         0x02007070, 0x03011070, 0x16106a70, 0x17110a70,
1093b274feedSAvi Kivity         0x06007171, 0x07011171, 0x12106b71, 0x13110b71,
1094b274feedSAvi Kivity         0x06007272, 0x07011272, 0x16106c72, 0x17110c72,
1095b274feedSAvi Kivity         0x02007373, 0x03011373, 0x12106d73, 0x13110d73,
1096b274feedSAvi Kivity         0x06007474, 0x07011474, 0x12106e74, 0x13110e74,
1097b274feedSAvi Kivity         0x02007575, 0x03011575, 0x16106f75, 0x17110f75,
1098b274feedSAvi Kivity         0x02007676, 0x03011676, 0x12107076, 0x13111076,
1099b274feedSAvi Kivity         0x06007777, 0x07011777, 0x16107177, 0x17111177,
1100b274feedSAvi Kivity         0x06007878, 0x07011878, 0x16107278, 0x17111278,
1101b274feedSAvi Kivity         0x02007979, 0x03011979, 0x12107379, 0x13111379,
1102b274feedSAvi Kivity         0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a,
1103b274feedSAvi Kivity         0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b,
1104b274feedSAvi Kivity         0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c,
1105b274feedSAvi Kivity         0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d,
1106b274feedSAvi Kivity         0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e,
1107b274feedSAvi Kivity         0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f,
1108b274feedSAvi Kivity         0x82008080, 0x03012080, 0x12107a80, 0x13111a80,
1109b274feedSAvi Kivity         0x86008181, 0x07012181, 0x16107b81, 0x17111b81,
1110b274feedSAvi Kivity         0x86008282, 0x07012282, 0x12107c82, 0x13111c82,
1111b274feedSAvi Kivity         0x82008383, 0x03012383, 0x16107d83, 0x17111d83,
1112b274feedSAvi Kivity         0x86008484, 0x07012484, 0x16107e84, 0x17111e84,
1113b274feedSAvi Kivity         0x82008585, 0x03012585, 0x12107f85, 0x13111f85,
1114b274feedSAvi Kivity         0x82008686, 0x03012686, 0x92108086, 0x13112086,
1115b274feedSAvi Kivity         0x86008787, 0x07012787, 0x96108187, 0x17112187,
1116b274feedSAvi Kivity         0x86008888, 0x07012888, 0x96108288, 0x17112288,
1117b274feedSAvi Kivity         0x82008989, 0x03012989, 0x92108389, 0x13112389,
1118b274feedSAvi Kivity         0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a,
1119b274feedSAvi Kivity         0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b,
1120b274feedSAvi Kivity         0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c,
1121b274feedSAvi Kivity         0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d,
1122b274feedSAvi Kivity         0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e,
1123b274feedSAvi Kivity         0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f,
1124b274feedSAvi Kivity         0x86009090, 0x07013090, 0x92108a90, 0x13112a90,
1125b274feedSAvi Kivity         0x82009191, 0x03013191, 0x96108b91, 0x17112b91,
1126b274feedSAvi Kivity         0x82009292, 0x03013292, 0x92108c92, 0x13112c92,
1127b274feedSAvi Kivity         0x86009393, 0x07013393, 0x96108d93, 0x17112d93,
1128b274feedSAvi Kivity         0x82009494, 0x03013494, 0x96108e94, 0x17112e94,
1129b274feedSAvi Kivity         0x86009595, 0x07013595, 0x92108f95, 0x13112f95,
1130b274feedSAvi Kivity         0x86009696, 0x07013696, 0x96109096, 0x17113096,
1131b274feedSAvi Kivity         0x82009797, 0x03013797, 0x92109197, 0x13113197,
1132b274feedSAvi Kivity         0x82009898, 0x03013898, 0x92109298, 0x13113298,
1133b274feedSAvi Kivity         0x86009999, 0x07013999, 0x96109399, 0x17113399,
1134b274feedSAvi Kivity         0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a,
1135b274feedSAvi Kivity         0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b,
1136b274feedSAvi Kivity         0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c,
1137b274feedSAvi Kivity         0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d,
1138b274feedSAvi Kivity         0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e,
1139b274feedSAvi Kivity         0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f,
1140b274feedSAvi Kivity         0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0,
1141b274feedSAvi Kivity         0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1,
1142b274feedSAvi Kivity         0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2,
1143b274feedSAvi Kivity         0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3,
1144b274feedSAvi Kivity         0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4,
1145b274feedSAvi Kivity         0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5,
1146b274feedSAvi Kivity         0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6,
1147b274feedSAvi Kivity         0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7,
1148b274feedSAvi Kivity         0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8,
1149b274feedSAvi Kivity         0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9,
1150b274feedSAvi Kivity         0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa,
1151b274feedSAvi Kivity         0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab,
1152b274feedSAvi Kivity         0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac,
1153b274feedSAvi Kivity         0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad,
1154b274feedSAvi Kivity         0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae,
1155b274feedSAvi Kivity         0x130049af, 0x130149af, 0x131049af, 0x131149af,
1156b274feedSAvi Kivity         0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0,
1157b274feedSAvi Kivity         0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1,
1158b274feedSAvi Kivity         0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2,
1159b274feedSAvi Kivity         0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3,
1160b274feedSAvi Kivity         0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4,
1161b274feedSAvi Kivity         0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5,
1162b274feedSAvi Kivity         0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6,
1163b274feedSAvi Kivity         0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7,
1164b274feedSAvi Kivity         0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8,
1165b274feedSAvi Kivity         0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9,
1166b274feedSAvi Kivity         0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba,
1167b274feedSAvi Kivity         0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb,
1168b274feedSAvi Kivity         0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc,
1169b274feedSAvi Kivity         0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd,
1170b274feedSAvi Kivity         0x130058be, 0x130158be, 0x131058be, 0x131158be,
1171b274feedSAvi Kivity         0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf,
1172b274feedSAvi Kivity         0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0,
1173b274feedSAvi Kivity         0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1,
1174b274feedSAvi Kivity         0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2,
1175b274feedSAvi Kivity         0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3,
1176b274feedSAvi Kivity         0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4,
1177b274feedSAvi Kivity         0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5,
1178b274feedSAvi Kivity         0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6,
1179b274feedSAvi Kivity         0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7,
1180b274feedSAvi Kivity         0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8,
1181b274feedSAvi Kivity         0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9,
1182b274feedSAvi Kivity         0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca,
1183b274feedSAvi Kivity         0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb,
1184b274feedSAvi Kivity         0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc,
1185b274feedSAvi Kivity         0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd,
1186b274feedSAvi Kivity         0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce,
1187b274feedSAvi Kivity         0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf,
1188b274feedSAvi Kivity         0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0,
1189b274feedSAvi Kivity         0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1,
1190b274feedSAvi Kivity         0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2,
1191b274feedSAvi Kivity         0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3,
1192b274feedSAvi Kivity         0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4,
1193b274feedSAvi Kivity         0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5,
1194b274feedSAvi Kivity         0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6,
1195b274feedSAvi Kivity         0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7,
1196b274feedSAvi Kivity         0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8,
1197b274feedSAvi Kivity         0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9,
1198b274feedSAvi Kivity         0x170074da, 0x170174da, 0x171074da, 0x171174da,
1199b274feedSAvi Kivity         0x130075db, 0x130175db, 0x131075db, 0x131175db,
1200b274feedSAvi Kivity         0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc,
1201b274feedSAvi Kivity         0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd,
1202b274feedSAvi Kivity         0x170078de, 0x170178de, 0x171078de, 0x171178de,
1203b274feedSAvi Kivity         0x130079df, 0x130179df, 0x131079df, 0x131179df,
1204b274feedSAvi Kivity         0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0,
1205b274feedSAvi Kivity         0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1,
1206b274feedSAvi Kivity         0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2,
1207b274feedSAvi Kivity         0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3,
1208b274feedSAvi Kivity         0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4,
1209b274feedSAvi Kivity         0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5,
1210b274feedSAvi Kivity         0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6,
1211b274feedSAvi Kivity         0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7,
1212b274feedSAvi Kivity         0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8,
1213b274feedSAvi Kivity         0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9,
1214b274feedSAvi Kivity         0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea,
1215b274feedSAvi Kivity         0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb,
1216b274feedSAvi Kivity         0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec,
1217b274feedSAvi Kivity         0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed,
1218b274feedSAvi Kivity         0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee,
1219b274feedSAvi Kivity         0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef,
1220b274feedSAvi Kivity         0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0,
1221b274feedSAvi Kivity         0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1,
1222b274feedSAvi Kivity         0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2,
1223b274feedSAvi Kivity         0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3,
1224b274feedSAvi Kivity         0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4,
1225b274feedSAvi Kivity         0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5,
1226b274feedSAvi Kivity         0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6,
1227b274feedSAvi Kivity         0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7,
1228b274feedSAvi Kivity         0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8,
1229b274feedSAvi Kivity         0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9,
1230b274feedSAvi Kivity         0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa,
1231b274feedSAvi Kivity         0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb,
1232b274feedSAvi Kivity         0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc,
1233b274feedSAvi Kivity         0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd,
1234b274feedSAvi Kivity         0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe,
1235b274feedSAvi Kivity         0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff,
1236b274feedSAvi Kivity     };
1237b274feedSAvi Kivity 
1238b274feedSAvi Kivity     MK_INSN(das, "das");
1239b274feedSAvi Kivity 
124018253fdeSAvi Kivity     inregs = (struct regs){ 0 };
124118253fdeSAvi Kivity 
1242b274feedSAvi Kivity     for (i = 0; i < 1024; ++i) {
1243b274feedSAvi Kivity         unsigned tmp = test_cases[i];
1244b274feedSAvi Kivity         inregs.eax = tmp & 0xff;
1245b274feedSAvi Kivity         inregs.eflags = (tmp >> 16) & 0xff;
124618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_das);
124718253fdeSAvi Kivity 	if (!regs_equal(R_AX)
1248b274feedSAvi Kivity             || outregs.eax != ((tmp >> 8) & 0xff)
1249b274feedSAvi Kivity             || (outregs.eflags & 0xff) != (tmp >> 24)) {
125081050840SAvi Kivity 	    ++nr_fail;
125181050840SAvi Kivity 	    break;
1252b274feedSAvi Kivity         }
1253b274feedSAvi Kivity     }
12546055ea1fSAvi Kivity     report("DAS", ~0, nr_fail == 0);
1255b274feedSAvi Kivity }
1256b274feedSAvi Kivity 
12572e3f9f1fSThomas Huth static void test_cwd_cdq(void)
12580cbd5b06SMohammed Gamal {
12590cbd5b06SMohammed Gamal 	/* Sign-bit set */
12600cbd5b06SMohammed Gamal 	MK_INSN(cwd_1, "mov $0x8000, %ax\n\t"
12610cbd5b06SMohammed Gamal 		       "cwd\n\t");
12620cbd5b06SMohammed Gamal 
12630cbd5b06SMohammed Gamal 	/* Sign-bit not set */
12640cbd5b06SMohammed Gamal 	MK_INSN(cwd_2, "mov $0x1000, %ax\n\t"
12650cbd5b06SMohammed Gamal 		       "cwd\n\t");
12660cbd5b06SMohammed Gamal 
12670cbd5b06SMohammed Gamal 	/* Sign-bit set */
12680cbd5b06SMohammed Gamal 	MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t"
12690cbd5b06SMohammed Gamal 		       "cdq\n\t");
12700cbd5b06SMohammed Gamal 
12710cbd5b06SMohammed Gamal 	/* Sign-bit not set */
12720cbd5b06SMohammed Gamal 	MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t"
12730cbd5b06SMohammed Gamal 		       "cdq\n\t");
12740cbd5b06SMohammed Gamal 
127518253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
127618253fdeSAvi Kivity 
127718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_1);
12786055ea1fSAvi Kivity 	report("cwd 1", R_AX | R_DX,
12796055ea1fSAvi Kivity 	       outregs.eax == 0x8000 && outregs.edx == 0xffff);
12800cbd5b06SMohammed Gamal 
128118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_2);
12826055ea1fSAvi Kivity 	report("cwd 2", R_AX | R_DX,
12836055ea1fSAvi Kivity 	       outregs.eax == 0x1000 && outregs.edx == 0);
12840cbd5b06SMohammed Gamal 
128518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_1);
12866055ea1fSAvi Kivity 	report("cdq 1", R_AX | R_DX,
12876055ea1fSAvi Kivity 	       outregs.eax == 0x80000000 && outregs.edx == 0xffffffff);
12880cbd5b06SMohammed Gamal 
128918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_2);
12906055ea1fSAvi Kivity 	report("cdq 2", R_AX | R_DX,
12916055ea1fSAvi Kivity 	       outregs.eax == 0x10000000 && outregs.edx == 0);
12920cbd5b06SMohammed Gamal }
12930cbd5b06SMohammed Gamal 
129437f51a4aSWei Yongjun static struct {
129537f51a4aSWei Yongjun         void *address;
129637f51a4aSWei Yongjun         unsigned short sel;
129737f51a4aSWei Yongjun } __attribute__((packed)) desc = {
129837f51a4aSWei Yongjun 	(void *)0x1234,
129937f51a4aSWei Yongjun 	0x10,
130037f51a4aSWei Yongjun };
130137f51a4aSWei Yongjun 
13022e3f9f1fSThomas Huth static void test_lds_lss(void)
130337f51a4aSWei Yongjun {
130437f51a4aSWei Yongjun 	inregs = (struct regs){ .ebx = (unsigned long)&desc };
130537f51a4aSWei Yongjun 
130637f51a4aSWei Yongjun 	MK_INSN(lds, "push %ds\n\t"
130737f51a4aSWei Yongjun 		     "lds (%ebx), %eax\n\t"
130837f51a4aSWei Yongjun 		     "mov %ds, %ebx\n\t"
130937f51a4aSWei Yongjun 		     "pop %ds\n\t");
131037f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lds);
131137f51a4aSWei Yongjun 	report("lds", R_AX | R_BX,
131237f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
131337f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
131437f51a4aSWei Yongjun 
131537f51a4aSWei Yongjun 	MK_INSN(les, "push %es\n\t"
131637f51a4aSWei Yongjun 		     "les (%ebx), %eax\n\t"
131737f51a4aSWei Yongjun 		     "mov %es, %ebx\n\t"
131837f51a4aSWei Yongjun 		     "pop %es\n\t");
131937f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_les);
132037f51a4aSWei Yongjun 	report("les", R_AX | R_BX,
132137f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
132237f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
132337f51a4aSWei Yongjun 
132437f51a4aSWei Yongjun 	MK_INSN(lfs, "push %fs\n\t"
132537f51a4aSWei Yongjun 		     "lfs (%ebx), %eax\n\t"
132637f51a4aSWei Yongjun 		     "mov %fs, %ebx\n\t"
132737f51a4aSWei Yongjun 		     "pop %fs\n\t");
132837f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lfs);
132937f51a4aSWei Yongjun 	report("lfs", R_AX | R_BX,
133037f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
133137f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
133237f51a4aSWei Yongjun 
133337f51a4aSWei Yongjun 	MK_INSN(lgs, "push %gs\n\t"
133437f51a4aSWei Yongjun 		     "lgs (%ebx), %eax\n\t"
133537f51a4aSWei Yongjun 		     "mov %gs, %ebx\n\t"
133637f51a4aSWei Yongjun 		     "pop %gs\n\t");
133737f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lgs);
133837f51a4aSWei Yongjun 	report("lgs", R_AX | R_BX,
133937f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
134037f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
134137f51a4aSWei Yongjun 
134237f51a4aSWei Yongjun 	MK_INSN(lss, "push %ss\n\t"
134337f51a4aSWei Yongjun 		     "lss (%ebx), %eax\n\t"
134437f51a4aSWei Yongjun 		     "mov %ss, %ebx\n\t"
134537f51a4aSWei Yongjun 		     "pop %ss\n\t");
134637f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lss);
134737f51a4aSWei Yongjun 	report("lss", R_AX | R_BX,
134837f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
134937f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
135037f51a4aSWei Yongjun }
135137f51a4aSWei Yongjun 
13522e3f9f1fSThomas Huth static void test_jcxz(void)
1353b1c7c575SWei Yongjun {
1354b1c7c575SWei Yongjun 	MK_INSN(jcxz1, "jcxz 1f\n\t"
1355b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1356b1c7c575SWei Yongjun 		       "1:\n\t");
1357b1c7c575SWei Yongjun 	MK_INSN(jcxz2, "mov $0x100, %ecx\n\t"
1358b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1359b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1360b1c7c575SWei Yongjun 		       "mov $0, %ecx\n\t"
1361b1c7c575SWei Yongjun 		       "1:\n\t");
1362b1c7c575SWei Yongjun 	MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t"
1363b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1364b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1365b1c7c575SWei Yongjun 		       "1:\n\t");
1366b1c7c575SWei Yongjun 	MK_INSN(jecxz1, "jecxz 1f\n\t"
1367b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1368b1c7c575SWei Yongjun 			"1:\n\t");
1369b1c7c575SWei Yongjun 	MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t"
1370b1c7c575SWei Yongjun 			"jecxz 1f\n\t"
1371b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1372b1c7c575SWei Yongjun 			"mov $0, %ecx\n\t"
1373b1c7c575SWei Yongjun 			"1:\n\t");
1374b1c7c575SWei Yongjun 
1375b1c7c575SWei Yongjun 	inregs = (struct regs){ 0 };
1376b1c7c575SWei Yongjun 
1377b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz1);
1378b1c7c575SWei Yongjun 	report("jcxz short 1", 0, 1);
1379b1c7c575SWei Yongjun 
1380b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz2);
1381b1c7c575SWei Yongjun 	report("jcxz short 2", R_AX, outregs.eax == 0x1234);
1382b1c7c575SWei Yongjun 
1383b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz3);
1384b1c7c575SWei Yongjun 	report("jcxz short 3", R_CX, outregs.ecx == 0x10000);
1385b1c7c575SWei Yongjun 
1386b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz1);
1387b1c7c575SWei Yongjun 	report("jecxz short 1", 0, 1);
1388b1c7c575SWei Yongjun 
1389b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz2);
1390b1c7c575SWei Yongjun 	report("jecxz short 2", R_AX, outregs.eax == 0x1234);
1391b1c7c575SWei Yongjun }
1392b1c7c575SWei Yongjun 
13938f578e98SAvi Kivity static void test_cpuid(void)
13948f578e98SAvi Kivity {
13958f578e98SAvi Kivity     MK_INSN(cpuid, "cpuid");
13968f578e98SAvi Kivity     unsigned function = 0x1234;
13978f578e98SAvi Kivity     unsigned eax, ebx, ecx, edx;
13988f578e98SAvi Kivity 
13998f578e98SAvi Kivity     inregs.eax = eax = function;
140018ba9083SGleb Natapov     inregs.ecx = ecx = 0;
1401674d2dbeSPaolo Bonzini     asm("cpuid" : "+a"(eax), "=b"(ebx), "+c"(ecx), "=d"(edx));
14028f578e98SAvi Kivity     exec_in_big_real_mode(&insn_cpuid);
14038f578e98SAvi Kivity     report("cpuid", R_AX|R_BX|R_CX|R_DX,
14048f578e98SAvi Kivity 	   outregs.eax == eax && outregs.ebx == ebx
14058f578e98SAvi Kivity 	   && outregs.ecx == ecx && outregs.edx == edx);
14068f578e98SAvi Kivity }
14078f578e98SAvi Kivity 
1408ed93f43bSAvi Kivity static void test_ss_base_for_esp_ebp(void)
1409ed93f43bSAvi Kivity {
1410ed93f43bSAvi Kivity     MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss");
1411ed93f43bSAvi Kivity     MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss");
1412ed93f43bSAvi Kivity     static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 };
1413ed93f43bSAvi Kivity 
1414ed93f43bSAvi Kivity     inregs.ebx = 1;
1415ed93f43bSAvi Kivity     inregs.ebp = (unsigned)array;
1416ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel1);
1417ed93f43bSAvi Kivity     report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321);
1418ed93f43bSAvi Kivity     inregs.ebx = 1;
1419ed93f43bSAvi Kivity     inregs.ebp = (unsigned)array;
1420ed93f43bSAvi Kivity     inregs.edi = 0;
1421ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel2);
1422ed93f43bSAvi Kivity     report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321);
1423ed93f43bSAvi Kivity }
1424ed93f43bSAvi Kivity 
1425975ca087SPeter Feiner extern unsigned long long r_gdt[];
1426975ca087SPeter Feiner 
1427c2281fa4SAvi Kivity static void test_sgdt_sidt(void)
1428c2281fa4SAvi Kivity {
1429c2281fa4SAvi Kivity     MK_INSN(sgdt, "sgdtw (%eax)");
1430c2281fa4SAvi Kivity     MK_INSN(sidt, "sidtw (%eax)");
1431975ca087SPeter Feiner     struct table_descr x, y;
1432c2281fa4SAvi Kivity 
1433c2281fa4SAvi Kivity     inregs.eax = (unsigned)&y;
1434c2281fa4SAvi Kivity     asm volatile("sgdtw %0" : "=m"(x));
1435c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sgdt);
1436975ca087SPeter Feiner     report("sgdt", 0, x.limit == y.limit && x.base == y.base);
1437c2281fa4SAvi Kivity 
1438c2281fa4SAvi Kivity     inregs.eax = (unsigned)&y;
1439c2281fa4SAvi Kivity     asm volatile("sidtw %0" : "=m"(x));
1440c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sidt);
1441975ca087SPeter Feiner     report("sidt", 0, x.limit == y.limit && x.base == y.base);
1442c2281fa4SAvi Kivity }
1443c2281fa4SAvi Kivity 
144488b6dac4SPaolo Bonzini static void test_sahf(void)
144588b6dac4SPaolo Bonzini {
144688b6dac4SPaolo Bonzini     MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw");
144788b6dac4SPaolo Bonzini 
144888b6dac4SPaolo Bonzini     inregs.eax = 0xfd00;
144988b6dac4SPaolo Bonzini     exec_in_big_real_mode(&insn_sahf);
145088b6dac4SPaolo Bonzini     report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7));
145188b6dac4SPaolo Bonzini }
145288b6dac4SPaolo Bonzini 
14537ae3645aSAvi Kivity static void test_lahf(void)
14547ae3645aSAvi Kivity {
14557ae3645aSAvi Kivity     MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf");
14567ae3645aSAvi Kivity 
14577ae3645aSAvi Kivity     inregs.eax = 0xc7;
14587ae3645aSAvi Kivity     exec_in_big_real_mode(&insn_lahf);
14597ae3645aSAvi Kivity     report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax);
14607ae3645aSAvi Kivity }
14617ae3645aSAvi Kivity 
1462fd9ea640SAvi Kivity static void test_movzx_movsx(void)
1463fd9ea640SAvi Kivity {
1464fd9ea640SAvi Kivity     MK_INSN(movsx, "movsx %al, %ebx");
1465fd9ea640SAvi Kivity     MK_INSN(movzx, "movzx %al, %ebx");
14663013e079SGleb Natapov     MK_INSN(movzsah, "movsx %ah, %ebx");
14673013e079SGleb Natapov     MK_INSN(movzxah, "movzx %ah, %ebx");
1468fd9ea640SAvi Kivity 
1469fd9ea640SAvi Kivity     inregs.eax = 0x1234569c;
14703013e079SGleb Natapov     inregs.esp = 0xffff;
1471fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movsx);
1472fd9ea640SAvi Kivity     report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax);
1473fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movzx);
1474fd9ea640SAvi Kivity     report("movzx", R_BX, outregs.ebx == (unsigned char)inregs.eax);
14753013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzsah);
14763013e079SGleb Natapov     report("movsx ah", R_BX, outregs.ebx == (signed char)(inregs.eax>>8));
14773013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzxah);
14783013e079SGleb Natapov     report("movzx ah", R_BX, outregs.ebx == (unsigned char)(inregs.eax >> 8));
1479fd9ea640SAvi Kivity }
1480fd9ea640SAvi Kivity 
1481b493b2e8SAvi Kivity static void test_bswap(void)
1482b493b2e8SAvi Kivity {
1483b493b2e8SAvi Kivity     MK_INSN(bswap, "bswap %ecx");
1484b493b2e8SAvi Kivity 
1485b493b2e8SAvi Kivity     inregs.ecx = 0x12345678;
1486b493b2e8SAvi Kivity     exec_in_big_real_mode(&insn_bswap);
1487b493b2e8SAvi Kivity     report("bswap", R_CX, outregs.ecx == 0x78563412);
1488b493b2e8SAvi Kivity }
1489b493b2e8SAvi Kivity 
14908cd86387SGleb Natapov static void test_aad(void)
14918cd86387SGleb Natapov {
14928cd86387SGleb Natapov     MK_INSN(aad, "aad");
14938cd86387SGleb Natapov 
14948cd86387SGleb Natapov     inregs.eax = 0x12345678;
14958cd86387SGleb Natapov     exec_in_big_real_mode(&insn_aad);
14968cd86387SGleb Natapov     report("aad", R_AX, outregs.eax == 0x123400d4);
14978cd86387SGleb Natapov }
14988cd86387SGleb Natapov 
14992a9b5718SPaolo Bonzini static void test_aam(void)
15002a9b5718SPaolo Bonzini {
15012a9b5718SPaolo Bonzini     MK_INSN(aam, "aam");
15022a9b5718SPaolo Bonzini 
15032a9b5718SPaolo Bonzini     inregs.eax = 0x76543210;
15042a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_aam);
15052a9b5718SPaolo Bonzini     report("aam", R_AX, outregs.eax == 0x76540106);
15062a9b5718SPaolo Bonzini }
15072a9b5718SPaolo Bonzini 
15082a9b5718SPaolo Bonzini static void test_xlat(void)
15092a9b5718SPaolo Bonzini {
15102a9b5718SPaolo Bonzini     MK_INSN(xlat, "xlat");
15112a9b5718SPaolo Bonzini     u8 table[256];
15122a9b5718SPaolo Bonzini     int i;
15132a9b5718SPaolo Bonzini 
15142a9b5718SPaolo Bonzini     for (i = 0; i < 256; i++) {
15152a9b5718SPaolo Bonzini         table[i] = i + 1;
15162a9b5718SPaolo Bonzini     }
15172a9b5718SPaolo Bonzini 
15182a9b5718SPaolo Bonzini     inregs.eax = 0x89abcdef;
15192a9b5718SPaolo Bonzini     inregs.ebx = (u32)table;
15202a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_xlat);
15212a9b5718SPaolo Bonzini     report("xlat", R_AX, outregs.eax == 0x89abcdf0);
15222a9b5718SPaolo Bonzini }
15232a9b5718SPaolo Bonzini 
15242a9b5718SPaolo Bonzini static void test_salc(void)
15252a9b5718SPaolo Bonzini {
15262a9b5718SPaolo Bonzini     MK_INSN(clc_salc, "clc; .byte 0xd6");
15272a9b5718SPaolo Bonzini     MK_INSN(stc_salc, "stc; .byte 0xd6");
15282a9b5718SPaolo Bonzini 
15292a9b5718SPaolo Bonzini     inregs.eax = 0x12345678;
15302a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_clc_salc);
15312a9b5718SPaolo Bonzini     report("salc (1)", R_AX, outregs.eax == 0x12345600);
15322a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_stc_salc);
15332a9b5718SPaolo Bonzini     report("salc (2)", R_AX, outregs.eax == 0x123456ff);
15342a9b5718SPaolo Bonzini }
15352a9b5718SPaolo Bonzini 
15360987db7aSGleb Natapov static void test_fninit(void)
15370987db7aSGleb Natapov {
15380987db7aSGleb Natapov 	u16 fcw = -1, fsw = -1;
15390987db7aSGleb Natapov 	MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)");
15400987db7aSGleb Natapov 
15410987db7aSGleb Natapov 	inregs.eax = (u32)&fsw;
15420987db7aSGleb Natapov 	inregs.ebx = (u32)&fcw;
15430987db7aSGleb Natapov 
15440987db7aSGleb Natapov 	exec_in_big_real_mode(&insn_fninit);
15450987db7aSGleb Natapov 	report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f);
15460987db7aSGleb Natapov }
15470987db7aSGleb Natapov 
15481a4c03a0SArthur Chunqi Li static void test_nopl(void)
15491a4c03a0SArthur Chunqi Li {
15501a4c03a0SArthur Chunqi Li 	MK_INSN(nopl1, ".byte 0x90\n\r"); // 1 byte nop
15511a4c03a0SArthur Chunqi Li 	MK_INSN(nopl2, ".byte 0x66, 0x90\n\r"); // 2 bytes nop
15521a4c03a0SArthur Chunqi Li 	MK_INSN(nopl3, ".byte 0x0f, 0x1f, 0x00\n\r"); // 3 bytes nop
15531a4c03a0SArthur Chunqi Li 	MK_INSN(nopl4, ".byte 0x0f, 0x1f, 0x40, 0x00\n\r"); // 4 bytes nop
15541a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl1);
15551a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl2);
15561a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl3);
15571a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl4);
15581a4c03a0SArthur Chunqi Li 	report("nopl", 0, 1);
15591a4c03a0SArthur Chunqi Li }
15601a4c03a0SArthur Chunqi Li 
1561b5105e8bSPaolo Bonzini static u32 perf_baseline;
1562b5105e8bSPaolo Bonzini 
15637505ea23SPaolo Bonzini #define PERF_COUNT 1000000
1564b5105e8bSPaolo Bonzini 
1565b5105e8bSPaolo Bonzini #define MK_INSN_PERF(name, insn)                                \
1566b5105e8bSPaolo Bonzini 	MK_INSN(name, "rdtsc; mov %eax, %ebx; mov %edx, %esi\n" \
1567b5105e8bSPaolo Bonzini 		      "1:" insn "\n"                            \
15687505ea23SPaolo Bonzini 		      ".byte 0x67; loop 1b\n"                   \
1569b5105e8bSPaolo Bonzini 		      "rdtsc");
1570b5105e8bSPaolo Bonzini 
1571b5105e8bSPaolo Bonzini static u32 cycles_in_big_real_mode(struct insn_desc *insn)
1572b5105e8bSPaolo Bonzini {
1573b5105e8bSPaolo Bonzini 	u64 start, end;
1574b5105e8bSPaolo Bonzini 
1575b5105e8bSPaolo Bonzini 	inregs.ecx = PERF_COUNT;
1576b5105e8bSPaolo Bonzini 	exec_in_big_real_mode(insn);
1577b5105e8bSPaolo Bonzini 	start = ((u64)outregs.esi << 32) | outregs.ebx;
1578b5105e8bSPaolo Bonzini 	end = ((u64)outregs.edx << 32) | outregs.eax;
1579b5105e8bSPaolo Bonzini 
1580b5105e8bSPaolo Bonzini 	return end - start;
1581b5105e8bSPaolo Bonzini }
1582b5105e8bSPaolo Bonzini 
1583b5105e8bSPaolo Bonzini static void test_perf_loop(void)
1584b5105e8bSPaolo Bonzini {
1585b5105e8bSPaolo Bonzini 	/*
1586b5105e8bSPaolo Bonzini 	 * This test runs simple instructions that should roughly take the
1587b5105e8bSPaolo Bonzini 	 * the same time to emulate: PERF_COUNT iterations of "loop" and 3
1588b5105e8bSPaolo Bonzini 	 * setup instructions.  Other performance tests can run PERF_COUNT
1589b5105e8bSPaolo Bonzini 	 * iterations of the same instruction and subtract the cycle count
1590b5105e8bSPaolo Bonzini 	 * of this test.
1591b5105e8bSPaolo Bonzini 	 */
1592b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_loop, "");
1593b5105e8bSPaolo Bonzini 	perf_baseline = cycles_in_big_real_mode(&insn_perf_loop);
1594b5105e8bSPaolo Bonzini 	print_serial_u32(perf_baseline / (PERF_COUNT + 3));
1595b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated jump instruction\n");
1596b5105e8bSPaolo Bonzini }
1597b5105e8bSPaolo Bonzini 
1598b5105e8bSPaolo Bonzini static void test_perf_mov(void)
1599b5105e8bSPaolo Bonzini {
1600b5105e8bSPaolo Bonzini 	u32 cyc;
1601b5105e8bSPaolo Bonzini 
1602b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_move, "mov %esi, %edi");
1603b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_move);
1604b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1605b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated move instruction\n");
1606b5105e8bSPaolo Bonzini }
1607b5105e8bSPaolo Bonzini 
1608b5105e8bSPaolo Bonzini static void test_perf_arith(void)
1609b5105e8bSPaolo Bonzini {
1610b5105e8bSPaolo Bonzini 	u32 cyc;
1611b5105e8bSPaolo Bonzini 
1612b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_arith, "add $4, %edi");
1613b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_arith);
1614b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1615b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated arithmetic instruction\n");
1616b5105e8bSPaolo Bonzini }
1617b5105e8bSPaolo Bonzini 
1618b5105e8bSPaolo Bonzini static void test_perf_memory_load(void)
1619b5105e8bSPaolo Bonzini {
1620b5105e8bSPaolo Bonzini 	u32 cyc, tmp;
1621b5105e8bSPaolo Bonzini 
1622b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_memory_load, "cmp $0, (%edi)");
1623b5105e8bSPaolo Bonzini 	inregs.edi = (u32)&tmp;
1624b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_load);
1625b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1626b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated memory load instruction\n");
1627b5105e8bSPaolo Bonzini }
1628b5105e8bSPaolo Bonzini 
16299306cb8eSPaolo Bonzini static void test_perf_memory_store(void)
16309306cb8eSPaolo Bonzini {
16319306cb8eSPaolo Bonzini 	u32 cyc, tmp;
16329306cb8eSPaolo Bonzini 
16339306cb8eSPaolo Bonzini 	MK_INSN_PERF(perf_memory_store, "mov %ax, (%edi)");
16349306cb8eSPaolo Bonzini 	inregs.edi = (u32)&tmp;
16359306cb8eSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_store);
16369306cb8eSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
16379306cb8eSPaolo Bonzini 	print_serial(" cycles/emulated memory store instruction\n");
16389306cb8eSPaolo Bonzini }
16399306cb8eSPaolo Bonzini 
1640b5105e8bSPaolo Bonzini static void test_perf_memory_rmw(void)
1641b5105e8bSPaolo Bonzini {
1642b5105e8bSPaolo Bonzini 	u32 cyc, tmp;
1643b5105e8bSPaolo Bonzini 
1644b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_memory_rmw, "add $1, (%edi)");
1645b5105e8bSPaolo Bonzini 	inregs.edi = (u32)&tmp;
1646b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_rmw);
1647b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1648b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated memory RMW instruction\n");
1649b5105e8bSPaolo Bonzini }
1650b5105e8bSPaolo Bonzini 
16512e3f9f1fSThomas Huth static void test_dr_mod(void)
16520a5701edSNadav Amit {
16530a5701edSNadav Amit 	MK_INSN(drmod, "movl %ebx, %dr0\n\t"
16540a5701edSNadav Amit 		       ".byte 0x0f \n\t .byte 0x21 \n\t .byte 0x0\n\t");
16550a5701edSNadav Amit 	inregs.eax = 0xdead;
16560a5701edSNadav Amit 	inregs.ebx = 0xaced;
16570a5701edSNadav Amit 	exec_in_big_real_mode(&insn_drmod);
16580a5701edSNadav Amit 	report("mov dr with mod bits", R_AX | R_BX, outregs.eax == 0xaced);
16590a5701edSNadav Amit }
16600a5701edSNadav Amit 
16612e3f9f1fSThomas Huth static void test_smsw(void)
166299ee878cSNadav Amit {
166399ee878cSNadav Amit 	MK_INSN(smsw, "movl %cr0, %ebx\n\t"
166499ee878cSNadav Amit 		      "movl %ebx, %ecx\n\t"
166599ee878cSNadav Amit 		      "or $0x40000000, %ebx\n\t"
166699ee878cSNadav Amit 		      "movl %ebx, %cr0\n\t"
166799ee878cSNadav Amit 		      "smswl %eax\n\t"
166899ee878cSNadav Amit 		      "movl %ecx, %cr0\n\t");
166999ee878cSNadav Amit 	inregs.eax = 0x12345678;
167099ee878cSNadav Amit 	exec_in_big_real_mode(&insn_smsw);
167199ee878cSNadav Amit 	report("smsw", R_AX | R_BX | R_CX, outregs.eax == outregs.ebx);
167299ee878cSNadav Amit }
167399ee878cSNadav Amit 
16742e3f9f1fSThomas Huth static void test_xadd(void)
16757bee560dSNadav Amit {
16767bee560dSNadav Amit 	MK_INSN(xadd, "xaddl %eax, %eax\n\t");
16777bee560dSNadav Amit 	inregs.eax = 0x12345678;
16787bee560dSNadav Amit 	exec_in_big_real_mode(&insn_xadd);
16797bee560dSNadav Amit 	report("xadd", R_AX, outregs.eax == inregs.eax * 2);
16807bee560dSNadav Amit }
16817bee560dSNadav Amit 
168299ee878cSNadav Amit 
16837d36db35SAvi Kivity void realmode_start(void)
16847d36db35SAvi Kivity {
16857d36db35SAvi Kivity 	test_null();
16867d36db35SAvi Kivity 
16877d36db35SAvi Kivity 	test_shld();
16887d36db35SAvi Kivity 	test_push_pop();
16897d36db35SAvi Kivity 	test_pusha_popa();
16907d36db35SAvi Kivity 	test_mov_imm();
16917d36db35SAvi Kivity 	test_cmp_imm();
16927d36db35SAvi Kivity 	test_add_imm();
16937d36db35SAvi Kivity 	test_sub_imm();
16947d36db35SAvi Kivity 	test_xor_imm();
16957d36db35SAvi Kivity 	test_io();
16967d36db35SAvi Kivity 	test_eflags_insn();
16977d36db35SAvi Kivity 	test_jcc_short();
16987d36db35SAvi Kivity 	test_jcc_near();
16997d36db35SAvi Kivity 	/* test_call() uses short jump so call it after testing jcc */
17007d36db35SAvi Kivity 	test_call();
17017d36db35SAvi Kivity 	/* long jmp test uses call near so test it after testing call */
17027d36db35SAvi Kivity 	test_long_jmp();
17037d36db35SAvi Kivity 	test_xchg();
17047d36db35SAvi Kivity 	test_iret();
170596b9ca1eSMohammed Gamal 	test_int();
1706fa74f8a6SMohammed Gamal 	test_imul();
170759317bd1SMohammed Gamal 	test_mul();
17080d4c7614SMohammed Gamal 	test_div();
17090d4c7614SMohammed Gamal 	test_idiv();
1710eacef4e2SWei Yongjun 	test_loopcc();
17116e293cf5SWei Yongjun 	test_cbw();
17120cbd5b06SMohammed Gamal 	test_cwd_cdq();
1713b274feedSAvi Kivity 	test_das();
171437f51a4aSWei Yongjun 	test_lds_lss();
1715b1c7c575SWei Yongjun 	test_jcxz();
17168f578e98SAvi Kivity 	test_cpuid();
1717ed93f43bSAvi Kivity 	test_ss_base_for_esp_ebp();
1718c2281fa4SAvi Kivity 	test_sgdt_sidt();
17197ae3645aSAvi Kivity 	test_lahf();
172088b6dac4SPaolo Bonzini 	test_sahf();
1721fd9ea640SAvi Kivity 	test_movzx_movsx();
1722b493b2e8SAvi Kivity 	test_bswap();
17238cd86387SGleb Natapov 	test_aad();
17242a9b5718SPaolo Bonzini 	test_aam();
17252a9b5718SPaolo Bonzini 	test_xlat();
17262a9b5718SPaolo Bonzini 	test_salc();
17270987db7aSGleb Natapov 	test_fninit();
17280a5701edSNadav Amit 	test_dr_mod();
172999ee878cSNadav Amit 	test_smsw();
17301a4c03a0SArthur Chunqi Li 	test_nopl();
17317bee560dSNadav Amit 	test_xadd();
1732b5105e8bSPaolo Bonzini 	test_perf_loop();
1733b5105e8bSPaolo Bonzini 	test_perf_mov();
1734b5105e8bSPaolo Bonzini 	test_perf_arith();
1735b5105e8bSPaolo Bonzini 	test_perf_memory_load();
17369306cb8eSPaolo Bonzini 	test_perf_memory_store();
1737b5105e8bSPaolo Bonzini 	test_perf_memory_rmw();
17387d36db35SAvi Kivity 
1739b393fe28SNadav Amit 	exit(failed);
17407d36db35SAvi Kivity }
17417d36db35SAvi Kivity 
17427d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff };
17437d36db35SAvi Kivity 
1744975ca087SPeter Feiner struct table_descr r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt };
17457d36db35SAvi Kivity 
17467d36db35SAvi Kivity asm(
17477d36db35SAvi Kivity 	".section .init \n\t"
17487d36db35SAvi Kivity 
17497d36db35SAvi Kivity 	".code32 \n\t"
17507d36db35SAvi Kivity 
17517d36db35SAvi Kivity 	"mb_magic = 0x1BADB002 \n\t"
17527d36db35SAvi Kivity 	"mb_flags = 0x0 \n\t"
17537d36db35SAvi Kivity 
17547d36db35SAvi Kivity 	"# multiboot header \n\t"
17557d36db35SAvi Kivity 	".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t"
17567d36db35SAvi Kivity 
17577d36db35SAvi Kivity 	".globl start \n\t"
17587d36db35SAvi Kivity 	".data \n\t"
17597d36db35SAvi Kivity 	". = . + 4096 \n\t"
17607d36db35SAvi Kivity 	"stacktop: \n\t"
17617d36db35SAvi Kivity 
17627d36db35SAvi Kivity 	".text \n\t"
17637d36db35SAvi Kivity 	"start: \n\t"
17647d36db35SAvi Kivity 	"lgdt r_gdt_descr \n\t"
17657d36db35SAvi Kivity 	"ljmp $8, $1f; 1: \n\t"
17667d36db35SAvi Kivity 	".code16gcc \n\t"
17677d36db35SAvi Kivity 	"mov $16, %eax \n\t"
17687d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
17697d36db35SAvi Kivity 	"mov %ax, %es \n\t"
17707d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
17717d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
17727d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
17737d36db35SAvi Kivity 	"mov %cr0, %eax \n\t"
17747d36db35SAvi Kivity 	"btc $0, %eax \n\t"
17757d36db35SAvi Kivity 	"mov %eax, %cr0 \n\t"
17767d36db35SAvi Kivity 	"ljmp $0, $realmode_entry \n\t"
17777d36db35SAvi Kivity 
17787d36db35SAvi Kivity 	"realmode_entry: \n\t"
17797d36db35SAvi Kivity 
17807d36db35SAvi Kivity 	"xor %ax, %ax \n\t"
17817d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
17827d36db35SAvi Kivity 	"mov %ax, %es \n\t"
17837d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
17847d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
17857d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
17867d36db35SAvi Kivity 	"mov $stacktop, %esp\n\t"
17877d36db35SAvi Kivity 	"ljmp $0, $realmode_start \n\t"
17887d36db35SAvi Kivity 
17897d36db35SAvi Kivity 	".code16gcc \n\t"
17907d36db35SAvi Kivity 	);
1791