xref: /kvm-unit-tests/x86/realmode.c (revision 975ca0879533f88037fded7eb91d9b2dfe304b41)
1f366255fSPaolo Bonzini #ifndef USE_SERIAL
2f366255fSPaolo Bonzini #define USE_SERIAL
3f366255fSPaolo Bonzini #endif
4f366255fSPaolo Bonzini 
57d36db35SAvi Kivity asm(".code16gcc");
67d36db35SAvi Kivity 
77d36db35SAvi Kivity typedef unsigned char u8;
87d36db35SAvi Kivity typedef unsigned short u16;
97d36db35SAvi Kivity typedef unsigned u32;
107d36db35SAvi Kivity typedef unsigned long long u64;
117d36db35SAvi Kivity 
127d36db35SAvi Kivity void test_function(void);
137d36db35SAvi Kivity 
147d36db35SAvi Kivity asm(
157d36db35SAvi Kivity 	"test_function: \n\t"
167d36db35SAvi Kivity 	"mov $0x1234, %eax \n\t"
177d36db35SAvi Kivity 	"ret"
187d36db35SAvi Kivity    );
197d36db35SAvi Kivity 
207d36db35SAvi Kivity static int strlen(const char *str)
217d36db35SAvi Kivity {
227d36db35SAvi Kivity 	int n;
237d36db35SAvi Kivity 
247d36db35SAvi Kivity 	for (n = 0; *str; ++str)
257d36db35SAvi Kivity 		++n;
267d36db35SAvi Kivity 	return n;
277d36db35SAvi Kivity }
287d36db35SAvi Kivity 
29f366255fSPaolo Bonzini static void outb(u8 data, u16 port)
30f366255fSPaolo Bonzini {
31f366255fSPaolo Bonzini 	asm volatile("out %0, %1" : : "a"(data), "d"(port));
32f366255fSPaolo Bonzini }
33f366255fSPaolo Bonzini 
34f366255fSPaolo Bonzini #ifdef USE_SERIAL
35f366255fSPaolo Bonzini static int serial_iobase = 0x3f8;
36f366255fSPaolo Bonzini static int serial_inited = 0;
37f366255fSPaolo Bonzini 
38f366255fSPaolo Bonzini static u8 inb(u16 port)
39f366255fSPaolo Bonzini {
40f366255fSPaolo Bonzini 	u8 data;
41f366255fSPaolo Bonzini 	asm volatile("in %1, %0" : "=a"(data) : "d"(port));
42f366255fSPaolo Bonzini 	return data;
43f366255fSPaolo Bonzini }
44f366255fSPaolo Bonzini 
45f366255fSPaolo Bonzini static void serial_outb(char ch)
46f366255fSPaolo Bonzini {
47f366255fSPaolo Bonzini 	u8 lsr;
48f366255fSPaolo Bonzini 
49f366255fSPaolo Bonzini 	do {
50f366255fSPaolo Bonzini 		lsr = inb(serial_iobase + 0x05);
51f366255fSPaolo Bonzini 	} while (!(lsr & 0x20));
52f366255fSPaolo Bonzini 
53f366255fSPaolo Bonzini 	outb(ch, serial_iobase + 0x00);
54f366255fSPaolo Bonzini }
55f366255fSPaolo Bonzini 
56f366255fSPaolo Bonzini static void serial_init(void)
57f366255fSPaolo Bonzini {
58f366255fSPaolo Bonzini 	u8 lcr;
59f366255fSPaolo Bonzini 
60f366255fSPaolo Bonzini 	/* set DLAB */
61f366255fSPaolo Bonzini 	lcr = inb(serial_iobase + 0x03);
62f366255fSPaolo Bonzini 	lcr |= 0x80;
63f366255fSPaolo Bonzini 	outb(lcr, serial_iobase + 0x03);
64f366255fSPaolo Bonzini 
65f366255fSPaolo Bonzini 	/* set baud rate to 115200 */
66f366255fSPaolo Bonzini 	outb(0x01, serial_iobase + 0x00);
67f366255fSPaolo Bonzini 	outb(0x00, serial_iobase + 0x01);
68f366255fSPaolo Bonzini 
69f366255fSPaolo Bonzini 	/* clear DLAB */
70f366255fSPaolo Bonzini 	lcr = inb(serial_iobase + 0x03);
71f366255fSPaolo Bonzini 	lcr &= ~0x80;
72f366255fSPaolo Bonzini 	outb(lcr, serial_iobase + 0x03);
73f366255fSPaolo Bonzini }
74f366255fSPaolo Bonzini #endif
75f366255fSPaolo Bonzini 
767d36db35SAvi Kivity static void print_serial(const char *buf)
777d36db35SAvi Kivity {
787d36db35SAvi Kivity 	unsigned long len = strlen(buf);
79f366255fSPaolo Bonzini #ifdef USE_SERIAL
80f366255fSPaolo Bonzini 	unsigned long i;
81f366255fSPaolo Bonzini 	if (!serial_inited) {
82f366255fSPaolo Bonzini 	    serial_init();
83f366255fSPaolo Bonzini 	    serial_inited = 1;
84f366255fSPaolo Bonzini 	}
857d36db35SAvi Kivity 
86f366255fSPaolo Bonzini 	for (i = 0; i < len; i++) {
87f366255fSPaolo Bonzini 	    serial_outb(buf[i]);
88f366255fSPaolo Bonzini 	}
89f366255fSPaolo Bonzini #else
905edbb9aeSPaolo Bonzini 	asm volatile ("addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1));
91f366255fSPaolo Bonzini #endif
927d36db35SAvi Kivity }
937d36db35SAvi Kivity 
94b5105e8bSPaolo Bonzini static void print_serial_u32(u32 value)
95b5105e8bSPaolo Bonzini {
96b5105e8bSPaolo Bonzini 	char n[12], *p;
97b5105e8bSPaolo Bonzini 	p = &n[11];
98b5105e8bSPaolo Bonzini 	*p = 0;
99b5105e8bSPaolo Bonzini 	do {
100b5105e8bSPaolo Bonzini 		*--p = '0' + (value % 10);
101b5105e8bSPaolo Bonzini 		value /= 10;
102b5105e8bSPaolo Bonzini 	} while (value > 0);
103b5105e8bSPaolo Bonzini 	print_serial(p);
104b5105e8bSPaolo Bonzini }
105b5105e8bSPaolo Bonzini 
106b393fe28SNadav Amit static int failed;
107b393fe28SNadav Amit 
1087d36db35SAvi Kivity static void exit(int code)
1097d36db35SAvi Kivity {
110f366255fSPaolo Bonzini 	outb(code, 0xf4);
1117d36db35SAvi Kivity }
1127d36db35SAvi Kivity 
1137d36db35SAvi Kivity struct regs {
1147d36db35SAvi Kivity 	u32 eax, ebx, ecx, edx;
1157d36db35SAvi Kivity 	u32 esi, edi, esp, ebp;
1167d36db35SAvi Kivity 	u32 eip, eflags;
1177d36db35SAvi Kivity };
1187d36db35SAvi Kivity 
119*975ca087SPeter Feiner struct table_descr {
120*975ca087SPeter Feiner 	u16 limit;
121*975ca087SPeter Feiner 	void *base;
122*975ca087SPeter Feiner } __attribute__((packed));
123*975ca087SPeter Feiner 
1247d36db35SAvi Kivity static u64 gdt[] = {
1257d36db35SAvi Kivity 	0,
1267d36db35SAvi Kivity 	0x00cf9b000000ffffull, // flat 32-bit code segment
1277d36db35SAvi Kivity 	0x00cf93000000ffffull, // flat 32-bit data segment
1287d36db35SAvi Kivity };
1297d36db35SAvi Kivity 
130*975ca087SPeter Feiner static struct table_descr gdt_descr = {
1317d36db35SAvi Kivity 	sizeof(gdt) - 1,
1327d36db35SAvi Kivity 	gdt,
1337d36db35SAvi Kivity };
1347d36db35SAvi Kivity 
135d4dc402cSAvi Kivity struct insn_desc {
136d4dc402cSAvi Kivity     u16 ptr;
137d4dc402cSAvi Kivity     u16 len;
138d4dc402cSAvi Kivity };
139d4dc402cSAvi Kivity 
14018253fdeSAvi Kivity static struct regs inregs, outregs;
14118253fdeSAvi Kivity 
14218253fdeSAvi Kivity static void exec_in_big_real_mode(struct insn_desc *insn)
1437d36db35SAvi Kivity {
1447d36db35SAvi Kivity 	unsigned long tmp;
1457d36db35SAvi Kivity 	static struct regs save;
1467d36db35SAvi Kivity 	int i;
1477d36db35SAvi Kivity 	extern u8 test_insn[], test_insn_end[];
1487d36db35SAvi Kivity 
149d4dc402cSAvi Kivity 	for (i = 0; i < insn->len; ++i)
150d4dc402cSAvi Kivity 	    test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i];
1517d36db35SAvi Kivity 	for (; i < test_insn_end - test_insn; ++i)
1527d36db35SAvi Kivity 		test_insn[i] = 0x90; // nop
1537d36db35SAvi Kivity 
15418253fdeSAvi Kivity 	save = inregs;
1557d36db35SAvi Kivity 	asm volatile(
1567d36db35SAvi Kivity 		"lgdtl %[gdt_descr] \n\t"
1577d36db35SAvi Kivity 		"mov %%cr0, %[tmp] \n\t"
1587d36db35SAvi Kivity 		"or $1, %[tmp] \n\t"
1597d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
1607d36db35SAvi Kivity 		"mov %[bigseg], %%gs \n\t"
1617d36db35SAvi Kivity 		"and $-2, %[tmp] \n\t"
1627d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
1637d36db35SAvi Kivity 
16432001692SAvi Kivity                 "pushw %[save]+36; popfw \n\t"
1657d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
1667d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
1677d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
1687d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
1697d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
1707d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
1717d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
1727d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
1737d36db35SAvi Kivity 
1747d36db35SAvi Kivity 		"test_insn: . = . + 32\n\t"
1757d36db35SAvi Kivity 		"test_insn_end: \n\t"
1767d36db35SAvi Kivity 
1777d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
1787d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
1797d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
1807d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
1817d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
1827d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
1837d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
1847d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
1857d36db35SAvi Kivity 
1867d36db35SAvi Kivity 		/* Save EFLAGS in outregs*/
1877d36db35SAvi Kivity 		"pushfl \n\t"
1887d36db35SAvi Kivity 		"popl %[save]+36 \n\t"
1897d36db35SAvi Kivity 
1905edbb9aeSPaolo Bonzini 		/* Restore DF for the harness code */
1915edbb9aeSPaolo Bonzini 		"cld\n\t"
1927d36db35SAvi Kivity 		"xor %[tmp], %[tmp] \n\t"
1937d36db35SAvi Kivity 		"mov %[tmp], %%gs \n\t"
1947d36db35SAvi Kivity 		: [tmp]"=&r"(tmp), [save]"+m"(save)
1957d36db35SAvi Kivity 		: [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16)
1967d36db35SAvi Kivity 		: "cc", "memory"
1977d36db35SAvi Kivity 		);
19818253fdeSAvi Kivity 	outregs = save;
1997d36db35SAvi Kivity }
2007d36db35SAvi Kivity 
2017d36db35SAvi Kivity #define R_AX 1
2027d36db35SAvi Kivity #define R_BX 2
2037d36db35SAvi Kivity #define R_CX 4
2047d36db35SAvi Kivity #define R_DX 8
2057d36db35SAvi Kivity #define R_SI 16
2067d36db35SAvi Kivity #define R_DI 32
2077d36db35SAvi Kivity #define R_SP 64
2087d36db35SAvi Kivity #define R_BP 128
2097d36db35SAvi Kivity 
21018253fdeSAvi Kivity int regs_equal(int ignore)
2117d36db35SAvi Kivity {
21218253fdeSAvi Kivity 	const u32 *p1 = &inregs.eax, *p2 = &outregs.eax;  // yuck
2137d36db35SAvi Kivity 	int i;
2147d36db35SAvi Kivity 
2157d36db35SAvi Kivity 	for (i = 0; i < 8; ++i)
2167d36db35SAvi Kivity 		if (!(ignore & (1 << i)) && p1[i] != p2[i])
2177d36db35SAvi Kivity 			return 0;
2187d36db35SAvi Kivity 	return 1;
2197d36db35SAvi Kivity }
2207d36db35SAvi Kivity 
2216055ea1fSAvi Kivity static void report(const char *name, u16 regs_ignore, _Bool ok)
22281050840SAvi Kivity {
2236055ea1fSAvi Kivity     if (!regs_equal(regs_ignore)) {
2246055ea1fSAvi Kivity 	ok = 0;
2256055ea1fSAvi Kivity     }
22681050840SAvi Kivity     print_serial(ok ? "PASS: " : "FAIL: ");
22781050840SAvi Kivity     print_serial(name);
22881050840SAvi Kivity     print_serial("\n");
229b393fe28SNadav Amit     if (!ok)
230b393fe28SNadav Amit 	failed = 1;
23181050840SAvi Kivity }
23281050840SAvi Kivity 
2337d36db35SAvi Kivity #define MK_INSN(name, str)				\
2347d36db35SAvi Kivity     asm (						\
235d4dc402cSAvi Kivity 	 ".pushsection .data.insn  \n\t"		\
236d4dc402cSAvi Kivity 	 "insn_" #name ": \n\t"				\
237d4dc402cSAvi Kivity 	 ".word 1001f, 1002f - 1001f \n\t"		\
238d4dc402cSAvi Kivity 	 ".popsection \n\t"				\
239d4dc402cSAvi Kivity 	 ".pushsection .text.insn, \"ax\" \n\t"		\
240d4dc402cSAvi Kivity 	 "1001: \n\t"					\
241d4dc402cSAvi Kivity 	 "insn_code_" #name ": " str " \n\t"		\
242d4dc402cSAvi Kivity 	 "1002: \n\t"					\
243d4dc402cSAvi Kivity 	 ".popsection"					\
2447d36db35SAvi Kivity     );							\
245d4dc402cSAvi Kivity     extern struct insn_desc insn_##name;
2467d36db35SAvi Kivity 
2477d36db35SAvi Kivity void test_xchg(void)
2487d36db35SAvi Kivity {
2497d36db35SAvi Kivity 	MK_INSN(xchg_test1, "xchg %eax,%eax\n\t");
2507d36db35SAvi Kivity 	MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t");
2517d36db35SAvi Kivity 	MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t");
2527d36db35SAvi Kivity 	MK_INSN(xchg_test4, "xchg %eax,%edx\n\t");
2537d36db35SAvi Kivity 	MK_INSN(xchg_test5, "xchg %eax,%esi\n\t");
2547d36db35SAvi Kivity 	MK_INSN(xchg_test6, "xchg %eax,%edi\n\t");
2557d36db35SAvi Kivity 	MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t");
2567d36db35SAvi Kivity 	MK_INSN(xchg_test8, "xchg %eax,%esp\n\t");
2577d36db35SAvi Kivity 
25818253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7};
2597d36db35SAvi Kivity 
26018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test1);
2616055ea1fSAvi Kivity 	report("xchg 1", 0, 1);
26218253fdeSAvi Kivity 
26318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test2);
2646055ea1fSAvi Kivity 	report("xchg 2", R_AX | R_BX,
2656055ea1fSAvi Kivity 	       outregs.eax == inregs.ebx && outregs.ebx == inregs.eax);
2667d36db35SAvi Kivity 
26718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test3);
2686055ea1fSAvi Kivity 	report("xchg 3", R_AX | R_CX,
2696055ea1fSAvi Kivity 	       outregs.eax == inregs.ecx && outregs.ecx == inregs.eax);
2707d36db35SAvi Kivity 
27118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test4);
2726055ea1fSAvi Kivity 	report("xchg 4", R_AX | R_DX,
2736055ea1fSAvi Kivity 	       outregs.eax == inregs.edx && outregs.edx == inregs.eax);
2747d36db35SAvi Kivity 
27518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test5);
2766055ea1fSAvi Kivity 	report("xchg 5", R_AX | R_SI,
2776055ea1fSAvi Kivity 	       outregs.eax == inregs.esi && outregs.esi == inregs.eax);
2787d36db35SAvi Kivity 
27918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test6);
2806055ea1fSAvi Kivity 	report("xchg 6", R_AX | R_DI,
2816055ea1fSAvi Kivity 	       outregs.eax == inregs.edi && outregs.edi == inregs.eax);
2827d36db35SAvi Kivity 
28318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test7);
2846055ea1fSAvi Kivity 	report("xchg 7", R_AX | R_BP,
2856055ea1fSAvi Kivity 	       outregs.eax == inregs.ebp && outregs.ebp == inregs.eax);
2867d36db35SAvi Kivity 
28718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test8);
2886055ea1fSAvi Kivity 	report("xchg 8", R_AX | R_SP,
2896055ea1fSAvi Kivity 	       outregs.eax == inregs.esp && outregs.esp == inregs.eax);
2907d36db35SAvi Kivity }
2917d36db35SAvi Kivity 
2927d36db35SAvi Kivity void test_shld(void)
2937d36db35SAvi Kivity {
2947d36db35SAvi Kivity 	MK_INSN(shld_test, "shld $8,%edx,%eax\n\t");
2957d36db35SAvi Kivity 
29618253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0xbe, .edx = 0xef000000 };
29718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_shld_test);
2986055ea1fSAvi Kivity 	report("shld", ~0, outregs.eax == 0xbeef);
2997d36db35SAvi Kivity }
3007d36db35SAvi Kivity 
3017d36db35SAvi Kivity void test_mov_imm(void)
3027d36db35SAvi Kivity {
3037d36db35SAvi Kivity 	MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax");
3047d36db35SAvi Kivity 	MK_INSN(mov_r16_imm_1, "mov $1234, %ax");
3057d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_1, "mov $0x12, %ah");
3067d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_2, "mov $0x34, %al");
3077d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t");
3087d36db35SAvi Kivity 
30918253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
31018253fdeSAvi Kivity 
31118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r16_imm_1);
3126055ea1fSAvi Kivity 	report("mov 1", R_AX, outregs.eax == 1234);
3137d36db35SAvi Kivity 
3147d36db35SAvi Kivity 	/* test mov $imm, %eax */
31518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r32_imm_1);
3166055ea1fSAvi Kivity 	report("mov 2", R_AX, outregs.eax == 1234567890);
3177d36db35SAvi Kivity 
3187d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
31918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_1);
3206055ea1fSAvi Kivity 	report("mov 3", R_AX, outregs.eax == 0x1200);
3217d36db35SAvi Kivity 
32218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_2);
3236055ea1fSAvi Kivity 	report("mov 4", R_AX, outregs.eax == 0x34);
3247d36db35SAvi Kivity 
32518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_3);
3266055ea1fSAvi Kivity 	report("mov 5", R_AX, outregs.eax == 0x1234);
3277d36db35SAvi Kivity }
3287d36db35SAvi Kivity 
3297d36db35SAvi Kivity void test_sub_imm(void)
3307d36db35SAvi Kivity {
3317d36db35SAvi Kivity 	MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t");
3327d36db35SAvi Kivity 	MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t");
3337d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t");
3347d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t");
3357d36db35SAvi Kivity 
33618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
33718253fdeSAvi Kivity 
33818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r16_imm_1);
3396055ea1fSAvi Kivity 	report("sub 1", R_AX, outregs.eax == 1224);
3407d36db35SAvi Kivity 
3417d36db35SAvi Kivity 	/* test mov $imm, %eax */
34218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r32_imm_1);
3436055ea1fSAvi Kivity 	report("sub 2", R_AX, outregs.eax == 1234567880);
3447d36db35SAvi Kivity 
3457d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
34618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_1);
3476055ea1fSAvi Kivity 	report("sub 3", R_AX, outregs.eax == 0x0200);
3487d36db35SAvi Kivity 
34918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_2);
3506055ea1fSAvi Kivity 	report("sub 4", R_AX, outregs.eax == 0x24);
3517d36db35SAvi Kivity }
3527d36db35SAvi Kivity 
3537d36db35SAvi Kivity void test_xor_imm(void)
3547d36db35SAvi Kivity {
3557d36db35SAvi Kivity 	MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t");
3567d36db35SAvi Kivity 	MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t");
3577d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t");
3587d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t");
3597d36db35SAvi Kivity 
36018253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
36118253fdeSAvi Kivity 
36218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r16_imm_1);
3636055ea1fSAvi Kivity 	report("xor 1", R_AX, outregs.eax == 0);
3647d36db35SAvi Kivity 
3657d36db35SAvi Kivity 	/* test mov $imm, %eax */
36618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r32_imm_1);
3676055ea1fSAvi Kivity 	report("xor 2", R_AX, outregs.eax == 0);
3687d36db35SAvi Kivity 
3697d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
37018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_1);
3716055ea1fSAvi Kivity 	report("xor 3", R_AX, outregs.eax == 0);
3727d36db35SAvi Kivity 
37318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_2);
3746055ea1fSAvi Kivity 	report("xor 4", R_AX, outregs.eax == 0);
3757d36db35SAvi Kivity }
3767d36db35SAvi Kivity 
3777d36db35SAvi Kivity void test_cmp_imm(void)
3787d36db35SAvi Kivity {
3797d36db35SAvi Kivity 	MK_INSN(cmp_test1, "mov $0x34, %al\n\t"
3807d36db35SAvi Kivity 			   "cmp $0x34, %al\n\t");
3817d36db35SAvi Kivity 	MK_INSN(cmp_test2, "mov $0x34, %al\n\t"
3827d36db35SAvi Kivity 			   "cmp $0x39, %al\n\t");
3837d36db35SAvi Kivity 	MK_INSN(cmp_test3, "mov $0x34, %al\n\t"
3847d36db35SAvi Kivity 			   "cmp $0x24, %al\n\t");
3857d36db35SAvi Kivity 
38618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
38718253fdeSAvi Kivity 
3887d36db35SAvi Kivity 	/* test cmp imm8 with AL */
3897d36db35SAvi Kivity 	/* ZF: (bit 6) Zero Flag becomes 1 if an operation results
3907d36db35SAvi Kivity 	 * in a 0 writeback, or 0 register
3917d36db35SAvi Kivity 	 */
39218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test1);
3936055ea1fSAvi Kivity 	report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6));
3947d36db35SAvi Kivity 
39518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test2);
3966055ea1fSAvi Kivity 	report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0);
3977d36db35SAvi Kivity 
39818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test3);
3996055ea1fSAvi Kivity 	report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0);
4007d36db35SAvi Kivity }
4017d36db35SAvi Kivity 
4027d36db35SAvi Kivity void test_add_imm(void)
4037d36db35SAvi Kivity {
4047d36db35SAvi Kivity 	MK_INSN(add_test1, "mov $0x43211234, %eax \n\t"
4057d36db35SAvi Kivity 			   "add $0x12344321, %eax \n\t");
4067d36db35SAvi Kivity 	MK_INSN(add_test2, "mov $0x12, %eax \n\t"
4077d36db35SAvi Kivity 			   "add $0x21, %al\n\t");
4087d36db35SAvi Kivity 
40918253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
41018253fdeSAvi Kivity 
41118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test1);
4126055ea1fSAvi Kivity 	report("add 1", ~0, outregs.eax == 0x55555555);
4137d36db35SAvi Kivity 
41418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test2);
4156055ea1fSAvi Kivity 	report("add 2", ~0, outregs.eax == 0x33);
4167d36db35SAvi Kivity }
4177d36db35SAvi Kivity 
4187d36db35SAvi Kivity void test_eflags_insn(void)
4197d36db35SAvi Kivity {
4207d36db35SAvi Kivity 	MK_INSN(clc, "clc");
421b3261e48SMohammed Gamal 	MK_INSN(stc, "stc");
4227d36db35SAvi Kivity 	MK_INSN(cli, "cli");
4237d36db35SAvi Kivity 	MK_INSN(sti, "sti");
4247d36db35SAvi Kivity 	MK_INSN(cld, "cld");
4257d36db35SAvi Kivity 	MK_INSN(std, "std");
4267d36db35SAvi Kivity 
42718253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
42818253fdeSAvi Kivity 
42918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_clc);
4306055ea1fSAvi Kivity 	report("clc", ~0, (outregs.eflags & 1) == 0);
4317d36db35SAvi Kivity 
43218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_stc);
4336055ea1fSAvi Kivity 	report("stc", ~0, (outregs.eflags & 1) == 1);
434b3261e48SMohammed Gamal 
43518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cli);
4366055ea1fSAvi Kivity 	report("cli", ~0, !(outregs.eflags & (1 << 9)));
4377d36db35SAvi Kivity 
43818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sti);
4396055ea1fSAvi Kivity 	report("sti", ~0, outregs.eflags & (1 << 9));
4407d36db35SAvi Kivity 
44118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cld);
4426055ea1fSAvi Kivity 	report("cld", ~0, !(outregs.eflags & (1 << 10)));
4437d36db35SAvi Kivity 
44418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_std);
4456055ea1fSAvi Kivity 	report("std", ~0, (outregs.eflags & (1 << 10)));
4467d36db35SAvi Kivity }
4477d36db35SAvi Kivity 
4487d36db35SAvi Kivity void test_io(void)
4497d36db35SAvi Kivity {
4507d36db35SAvi Kivity 	MK_INSN(io_test1, "mov $0xff, %al \n\t"
4517d36db35SAvi Kivity 		          "out %al, $0xe0 \n\t"
4527d36db35SAvi Kivity 		          "mov $0x00, %al \n\t"
4537d36db35SAvi Kivity 			  "in $0xe0, %al \n\t");
4547d36db35SAvi Kivity 	MK_INSN(io_test2, "mov $0xffff, %ax \n\t"
4557d36db35SAvi Kivity 			  "out %ax, $0xe0 \n\t"
4567d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
4577d36db35SAvi Kivity 			  "in $0xe0, %ax \n\t");
4587d36db35SAvi Kivity 	MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t"
4597d36db35SAvi Kivity 			  "out %eax, $0xe0 \n\t"
4607d36db35SAvi Kivity 			  "mov $0x000000, %eax \n\t"
4617d36db35SAvi Kivity 			  "in $0xe0, %eax \n\t");
4627d36db35SAvi Kivity 	MK_INSN(io_test4, "mov $0xe0, %dx \n\t"
4637d36db35SAvi Kivity 			  "mov $0xff, %al \n\t"
4647d36db35SAvi Kivity 			  "out %al, %dx \n\t"
4657d36db35SAvi Kivity 			  "mov $0x00, %al \n\t"
4667d36db35SAvi Kivity 			  "in %dx, %al \n\t");
4677d36db35SAvi Kivity 	MK_INSN(io_test5, "mov $0xe0, %dx \n\t"
4687d36db35SAvi Kivity 			  "mov $0xffff, %ax \n\t"
4697d36db35SAvi Kivity 			  "out %ax, %dx \n\t"
4707d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
4717d36db35SAvi Kivity 			  "in %dx, %ax \n\t");
4727d36db35SAvi Kivity 	MK_INSN(io_test6, "mov $0xe0, %dx \n\t"
4737d36db35SAvi Kivity 			  "mov $0xffffffff, %eax \n\t"
4747d36db35SAvi Kivity 			  "out %eax, %dx \n\t"
4757d36db35SAvi Kivity 			  "mov $0x00000000, %eax \n\t"
4767d36db35SAvi Kivity 			  "in %dx, %eax \n\t");
4777d36db35SAvi Kivity 
47818253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
47918253fdeSAvi Kivity 
48018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test1);
4816055ea1fSAvi Kivity 	report("pio 1", R_AX, outregs.eax == 0xff);
4827d36db35SAvi Kivity 
48318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test2);
4846055ea1fSAvi Kivity 	report("pio 2", R_AX, outregs.eax == 0xffff);
4857d36db35SAvi Kivity 
48618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test3);
4876055ea1fSAvi Kivity 	report("pio 3", R_AX, outregs.eax == 0xffffffff);
4887d36db35SAvi Kivity 
48918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test4);
4906055ea1fSAvi Kivity 	report("pio 4", R_AX|R_DX, outregs.eax == 0xff);
4917d36db35SAvi Kivity 
49218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test5);
4936055ea1fSAvi Kivity 	report("pio 5", R_AX|R_DX, outregs.eax == 0xffff);
4947d36db35SAvi Kivity 
49518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test6);
4966055ea1fSAvi Kivity 	report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff);
4977d36db35SAvi Kivity }
4987d36db35SAvi Kivity 
499c0b7268dSAvi Kivity asm ("retf: lretw");
500c0b7268dSAvi Kivity extern void retf();
501c0b7268dSAvi Kivity 
5024f66bc86SBruce Rogers asm ("retf_imm: lretw $10");
5034f66bc86SBruce Rogers extern void retf_imm();
5044f66bc86SBruce Rogers 
5057d36db35SAvi Kivity void test_call(void)
5067d36db35SAvi Kivity {
5077d36db35SAvi Kivity 	u32 esp[16];
508c0b7268dSAvi Kivity 	u32 addr;
5097d36db35SAvi Kivity 
51018253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
5117d36db35SAvi Kivity 	inregs.esp = (u32)esp;
5127d36db35SAvi Kivity 
5137d36db35SAvi Kivity 	MK_INSN(call1, "mov $test_function, %eax \n\t"
5147d36db35SAvi Kivity 		       "call *%eax\n\t");
5157d36db35SAvi Kivity 	MK_INSN(call_near1, "jmp 2f\n\t"
5167d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5177d36db35SAvi Kivity 			    "ret\n\t"
5187d36db35SAvi Kivity 			    "2: call 1b\t");
5197d36db35SAvi Kivity 	MK_INSN(call_near2, "call 1f\n\t"
5207d36db35SAvi Kivity 			    "jmp 2f\n\t"
5217d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5227d36db35SAvi Kivity 			    "ret\n\t"
5237d36db35SAvi Kivity 			    "2:\t");
524c0b7268dSAvi Kivity 	MK_INSN(call_far1,  "lcallw *(%ebx)\n\t");
525556d2680SWei Yongjun 	MK_INSN(call_far2,  "lcallw $0, $retf\n\t");
526c6061817SAvi Kivity 	MK_INSN(ret_imm,    "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b");
5274f66bc86SBruce Rogers 	MK_INSN(retf_imm,   "sub $10, %sp; lcallw $0, $retf_imm");
5287d36db35SAvi Kivity 
52918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call1);
5306055ea1fSAvi Kivity 	report("call 1", R_AX, outregs.eax == 0x1234);
5317d36db35SAvi Kivity 
53218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near1);
5336055ea1fSAvi Kivity 	report("call near 1", R_AX, outregs.eax == 0x1234);
5347d36db35SAvi Kivity 
53518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near2);
5366055ea1fSAvi Kivity 	report("call near 2", R_AX, outregs.eax == 0x1234);
537c0b7268dSAvi Kivity 
538c0b7268dSAvi Kivity 	addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f);
539c0b7268dSAvi Kivity 	inregs.ebx = (unsigned)&addr;
54018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_far1);
5416055ea1fSAvi Kivity 	report("call far 1", 0, 1);
542c6061817SAvi Kivity 
543556d2680SWei Yongjun 	exec_in_big_real_mode(&insn_call_far2);
544556d2680SWei Yongjun 	report("call far 2", 0, 1);
545556d2680SWei Yongjun 
54618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_ret_imm);
5476055ea1fSAvi Kivity 	report("ret imm 1", 0, 1);
5484f66bc86SBruce Rogers 
5494f66bc86SBruce Rogers 	exec_in_big_real_mode(&insn_retf_imm);
5504f66bc86SBruce Rogers 	report("retf imm 1", 0, 1);
5517d36db35SAvi Kivity }
5527d36db35SAvi Kivity 
5537d36db35SAvi Kivity void test_jcc_short(void)
5547d36db35SAvi Kivity {
5557d36db35SAvi Kivity 	MK_INSN(jnz_short1, "jnz 1f\n\t"
5567d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
5577d36db35SAvi Kivity 		            "1:\n\t");
5587d36db35SAvi Kivity 	MK_INSN(jnz_short2, "1:\n\t"
5597d36db35SAvi Kivity 			    "cmp $0x1234, %eax\n\t"
5607d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
5617d36db35SAvi Kivity 		            "jnz 1b\n\t");
5627d36db35SAvi Kivity 	MK_INSN(jmp_short1, "jmp 1f\n\t"
5637d36db35SAvi Kivity 		      "mov $0x1234, %eax\n\t"
5647d36db35SAvi Kivity 		      "1:\n\t");
5657d36db35SAvi Kivity 
56618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
5677d36db35SAvi Kivity 
56818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short1);
5696055ea1fSAvi Kivity 	report("jnz short 1", ~0, 1);
57018253fdeSAvi Kivity 
57118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short2);
5726055ea1fSAvi Kivity 	report("jnz short 2", R_AX, (outregs.eflags & (1 << 6)));
5737d36db35SAvi Kivity 
57418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_short1);
5756055ea1fSAvi Kivity 	report("jmp short 1", ~0, 1);
5767d36db35SAvi Kivity }
5777d36db35SAvi Kivity 
5787d36db35SAvi Kivity void test_jcc_near(void)
5797d36db35SAvi Kivity {
5807d36db35SAvi Kivity 	/* encode near jmp manually. gas will not do it if offsets < 127 byte */
5817d36db35SAvi Kivity 	MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t"
5827d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
5837d36db35SAvi Kivity 	MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t"
5847d36db35SAvi Kivity 			   "mov $0x1234, %eax\n\t"
5857d36db35SAvi Kivity 		           ".byte 0x0f, 0x85, 0xf0, 0xff\n\t");
5867d36db35SAvi Kivity 	MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t"
5877d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
5887d36db35SAvi Kivity 
58918253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
5907d36db35SAvi Kivity 
59118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near1);
5926055ea1fSAvi Kivity 	report("jnz near 1", 0, 1);
59318253fdeSAvi Kivity 
59418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near2);
5956055ea1fSAvi Kivity 	report("jnz near 2", R_AX, outregs.eflags & (1 << 6));
5967d36db35SAvi Kivity 
59718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_near1);
5986055ea1fSAvi Kivity 	report("jmp near 1", 0, 1);
5997d36db35SAvi Kivity }
6007d36db35SAvi Kivity 
6017d36db35SAvi Kivity void test_long_jmp()
6027d36db35SAvi Kivity {
6037d36db35SAvi Kivity 	u32 esp[16];
6047d36db35SAvi Kivity 
60518253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
6064aa22949SAvi Kivity 	inregs.esp = (u32)(esp+16);
6077d36db35SAvi Kivity 	MK_INSN(long_jmp, "call 1f\n\t"
6087d36db35SAvi Kivity 			  "jmp 2f\n\t"
6097d36db35SAvi Kivity 			  "1: jmp $0, $test_function\n\t"
6107d36db35SAvi Kivity 		          "2:\n\t");
61118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_long_jmp);
6126055ea1fSAvi Kivity 	report("jmp far 1", R_AX, outregs.eax == 0x1234);
6137d36db35SAvi Kivity }
614fa74f8a6SMohammed Gamal 
6157d36db35SAvi Kivity void test_push_pop()
6167d36db35SAvi Kivity {
6177d36db35SAvi Kivity 	MK_INSN(push32, "mov $0x12345678, %eax\n\t"
6187d36db35SAvi Kivity 			"push %eax\n\t"
6197d36db35SAvi Kivity 			"pop %ebx\n\t");
6207d36db35SAvi Kivity 	MK_INSN(push16, "mov $0x1234, %ax\n\t"
6217d36db35SAvi Kivity 			"push %ax\n\t"
6227d36db35SAvi Kivity 			"pop %bx\n\t");
6237d36db35SAvi Kivity 
6247d36db35SAvi Kivity 	MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten
6257d36db35SAvi Kivity 			 "mov $0x123, %ax\n\t"
6267d36db35SAvi Kivity 			 "mov %ax, %es\n\t"
6277d36db35SAvi Kivity 			 "push %es\n\t"
6287d36db35SAvi Kivity 			 "pop %bx \n\t"
6297d36db35SAvi Kivity 			 );
6307d36db35SAvi Kivity 	MK_INSN(pop_es, "push %ax\n\t"
6317d36db35SAvi Kivity 			"pop %es\n\t"
6327d36db35SAvi Kivity 			"mov %es, %bx\n\t"
6337d36db35SAvi Kivity 			);
6347d36db35SAvi Kivity 	MK_INSN(push_pop_ss, "push %ss\n\t"
6357d36db35SAvi Kivity 			     "pushw %ax\n\t"
6367d36db35SAvi Kivity 			     "popw %ss\n\t"
6377d36db35SAvi Kivity 			     "mov %ss, %bx\n\t"
6387d36db35SAvi Kivity 			     "pop %ss\n\t"
6397d36db35SAvi Kivity 			);
6407d36db35SAvi Kivity 	MK_INSN(push_pop_fs, "push %fs\n\t"
6417d36db35SAvi Kivity 			     "pushl %eax\n\t"
6427d36db35SAvi Kivity 			     "popl %fs\n\t"
6437d36db35SAvi Kivity 			     "mov %fs, %ebx\n\t"
6447d36db35SAvi Kivity 			     "pop %fs\n\t"
6457d36db35SAvi Kivity 			);
64609b657b6SAvi Kivity 	MK_INSN(push_pop_high_esp_bits,
64709b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
64809b657b6SAvi Kivity 		"push %ax; \n\t"
64909b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
65009b657b6SAvi Kivity 		"pop %bx");
6517d36db35SAvi Kivity 
65218253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
65318253fdeSAvi Kivity 
65418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push32);
6556055ea1fSAvi Kivity 	report("push/pop 1", R_AX|R_BX,
6566055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x12345678);
6577d36db35SAvi Kivity 
65818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push16);
6596055ea1fSAvi Kivity 	report("push/pop 2", R_AX|R_BX,
6606055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x1234);
6617d36db35SAvi Kivity 
66218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_es);
6636055ea1fSAvi Kivity 	report("push/pop 3", R_AX|R_BX,
6646055ea1fSAvi Kivity 	       outregs.ebx == outregs.eax && outregs.eax == 0x123);
6657d36db35SAvi Kivity 
66618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pop_es);
6676055ea1fSAvi Kivity 	report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax);
6687d36db35SAvi Kivity 
66918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_ss);
6706055ea1fSAvi Kivity 	report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax);
6717d36db35SAvi Kivity 
67218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_fs);
6736055ea1fSAvi Kivity 	report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax);
67409b657b6SAvi Kivity 
67509b657b6SAvi Kivity 	inregs.eax = 0x9977;
67609b657b6SAvi Kivity 	inregs.ebx = 0x7799;
67709b657b6SAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_high_esp_bits);
67809b657b6SAvi Kivity 	report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977);
6797d36db35SAvi Kivity }
6807d36db35SAvi Kivity 
6817d36db35SAvi Kivity void test_null(void)
6827d36db35SAvi Kivity {
683d4dc402cSAvi Kivity 	MK_INSN(null, "");
684d4dc402cSAvi Kivity 
68518253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
68618253fdeSAvi Kivity 
68718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_null);
6886055ea1fSAvi Kivity 	report("null", 0, 1);
6897d36db35SAvi Kivity }
6907d36db35SAvi Kivity 
6917d36db35SAvi Kivity struct {
6927d36db35SAvi Kivity     char stack[500];
6937d36db35SAvi Kivity     char top[];
6947d36db35SAvi Kivity } tmp_stack;
6957d36db35SAvi Kivity 
6967d36db35SAvi Kivity void test_pusha_popa()
6977d36db35SAvi Kivity {
6987d36db35SAvi Kivity 	MK_INSN(pusha, "pusha\n\t"
6997d36db35SAvi Kivity 		       "pop %edi\n\t"
7007d36db35SAvi Kivity 		       "pop %esi\n\t"
7017d36db35SAvi Kivity 		       "pop %ebp\n\t"
7027d36db35SAvi Kivity 		       "add $4, %esp\n\t"
7037d36db35SAvi Kivity 		       "pop %ebx\n\t"
7047d36db35SAvi Kivity 		       "pop %edx\n\t"
7057d36db35SAvi Kivity 		       "pop %ecx\n\t"
7067d36db35SAvi Kivity 		       "pop %eax\n\t"
7077d36db35SAvi Kivity 		       );
7087d36db35SAvi Kivity 
7097d36db35SAvi Kivity 	MK_INSN(popa, "push %eax\n\t"
7107d36db35SAvi Kivity 		      "push %ecx\n\t"
7117d36db35SAvi Kivity 		      "push %edx\n\t"
7127d36db35SAvi Kivity 		      "push %ebx\n\t"
7137d36db35SAvi Kivity 		      "push %esp\n\t"
7147d36db35SAvi Kivity 		      "push %ebp\n\t"
7157d36db35SAvi Kivity 		      "push %esi\n\t"
7167d36db35SAvi Kivity 		      "push %edi\n\t"
7177d36db35SAvi Kivity 		      "popa\n\t"
7187d36db35SAvi Kivity 		      );
7197d36db35SAvi Kivity 
72018253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top };
7217d36db35SAvi Kivity 
72218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pusha);
7236055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
72418253fdeSAvi Kivity 
72518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_popa);
7266055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
7277d36db35SAvi Kivity }
7287d36db35SAvi Kivity 
7297d36db35SAvi Kivity void test_iret()
7307d36db35SAvi Kivity {
7317d36db35SAvi Kivity 	MK_INSN(iret32, "pushf\n\t"
7327d36db35SAvi Kivity 			"pushl %cs\n\t"
7337d36db35SAvi Kivity 			"call 1f\n\t" /* a near call will push eip onto the stack */
7347d36db35SAvi Kivity 			"jmp 2f\n\t"
7357d36db35SAvi Kivity 			"1: iret\n\t"
7367d36db35SAvi Kivity 			"2:\n\t"
7377d36db35SAvi Kivity 		     );
7387d36db35SAvi Kivity 
7397d36db35SAvi Kivity 	MK_INSN(iret16, "pushfw\n\t"
7407d36db35SAvi Kivity 			"pushw %cs\n\t"
7417d36db35SAvi Kivity 			"callw 1f\n\t"
7427d36db35SAvi Kivity 			"jmp 2f\n\t"
7437d36db35SAvi Kivity 			"1: iretw\n\t"
7447d36db35SAvi Kivity 			"2:\n\t");
7457d36db35SAvi Kivity 
7467d36db35SAvi Kivity 	MK_INSN(iret_flags32, "pushfl\n\t"
7477d36db35SAvi Kivity 			      "popl %eax\n\t"
7487d36db35SAvi Kivity 			      "andl $~0x2, %eax\n\t"
749964942e8SNadav Amit 			      "orl $0xffc18028, %eax\n\t"
7507d36db35SAvi Kivity 			      "pushl %eax\n\t"
7517d36db35SAvi Kivity 			      "pushl %cs\n\t"
7527d36db35SAvi Kivity 			      "call 1f\n\t"
7537d36db35SAvi Kivity 			      "jmp 2f\n\t"
7547d36db35SAvi Kivity 			      "1: iret\n\t"
7557d36db35SAvi Kivity 			      "2:\n\t");
7567d36db35SAvi Kivity 
7577d36db35SAvi Kivity 	MK_INSN(iret_flags16, "pushfw\n\t"
7587d36db35SAvi Kivity 			      "popw %ax\n\t"
7597d36db35SAvi Kivity 			      "and $~0x2, %ax\n\t"
7607d36db35SAvi Kivity 			      "or $0x8028, %ax\n\t"
7617d36db35SAvi Kivity 			      "pushw %ax\n\t"
7627d36db35SAvi Kivity 			      "pushw %cs\n\t"
7637d36db35SAvi Kivity 			      "callw 1f\n\t"
7647d36db35SAvi Kivity 			      "jmp 2f\n\t"
7657d36db35SAvi Kivity 			      "1: iretw\n\t"
7667d36db35SAvi Kivity 			      "2:\n\t");
7677d36db35SAvi Kivity 
76818253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
7697d36db35SAvi Kivity 
77018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret32);
7716055ea1fSAvi Kivity 	report("iret 1", 0, 1);
7727d36db35SAvi Kivity 
77318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret16);
7746055ea1fSAvi Kivity 	report("iret 2", 0, 1);
7757d36db35SAvi Kivity 
77618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags32);
7776055ea1fSAvi Kivity 	report("iret 3", R_AX, 1);
778964942e8SNadav Amit 	report("rflags.rf", ~0, !(outregs.eflags & (1 << 16)));
77918253fdeSAvi Kivity 
78018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags16);
7816055ea1fSAvi Kivity 	report("iret 4", R_AX, 1);
7827d36db35SAvi Kivity }
7837d36db35SAvi Kivity 
78496b9ca1eSMohammed Gamal void test_int()
78596b9ca1eSMohammed Gamal {
78618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
78796b9ca1eSMohammed Gamal 
78896b9ca1eSMohammed Gamal 	*(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */
78996b9ca1eSMohammed Gamal 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
79096b9ca1eSMohammed Gamal 
79196b9ca1eSMohammed Gamal 	MK_INSN(int11, "int $0x11\n\t");
79296b9ca1eSMohammed Gamal 
79318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_int11);
7946055ea1fSAvi Kivity 	report("int 1", 0, 1);
79596b9ca1eSMohammed Gamal }
79696b9ca1eSMohammed Gamal 
797fa74f8a6SMohammed Gamal void test_imul()
798fa74f8a6SMohammed Gamal {
799fa74f8a6SMohammed Gamal 	MK_INSN(imul8_1, "mov $2, %al\n\t"
800fa74f8a6SMohammed Gamal 			"mov $-4, %cx\n\t"
801fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
802fa74f8a6SMohammed Gamal 
803fa74f8a6SMohammed Gamal 	MK_INSN(imul16_1, "mov $2, %ax\n\t"
804fa74f8a6SMohammed Gamal 		      "mov $-4, %cx\n\t"
805fa74f8a6SMohammed Gamal 		      "imul %cx\n\t");
806fa74f8a6SMohammed Gamal 
807fa74f8a6SMohammed Gamal 	MK_INSN(imul32_1, "mov $2, %eax\n\t"
808fa74f8a6SMohammed Gamal 		       "mov $-4, %ecx\n\t"
809fa74f8a6SMohammed Gamal 		       "imul %ecx\n\t");
810fa74f8a6SMohammed Gamal 
811fa74f8a6SMohammed Gamal 	MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t"
812fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
813fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
814fa74f8a6SMohammed Gamal 
815fa74f8a6SMohammed Gamal 	MK_INSN(imul16_2, "mov $2, %ax\n\t"
816fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
817fa74f8a6SMohammed Gamal 			"imul %cx\n\t");
818fa74f8a6SMohammed Gamal 
819fa74f8a6SMohammed Gamal 	MK_INSN(imul32_2, "mov $2, %eax\n\t"
820fa74f8a6SMohammed Gamal 			"mov $4, %ecx\n\t"
821fa74f8a6SMohammed Gamal 			"imul %ecx\n\t");
822fa74f8a6SMohammed Gamal 
82318253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
82418253fdeSAvi Kivity 
82518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_1);
8266055ea1fSAvi Kivity 	report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8);
827fa74f8a6SMohammed Gamal 
82818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_1);
8296055ea1fSAvi Kivity 	report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8);
830fa74f8a6SMohammed Gamal 
83118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_1);
8326055ea1fSAvi Kivity 	report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8);
833fa74f8a6SMohammed Gamal 
83418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_2);
8356055ea1fSAvi Kivity 	report("imul 4", R_AX | R_CX | R_DX,
8366055ea1fSAvi Kivity 	       (outregs.eax & 0xffff) == 8
83781050840SAvi Kivity 	       && (outregs.eax & 0xffff0000) == 0x12340000);
838fa74f8a6SMohammed Gamal 
83918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_2);
8406055ea1fSAvi Kivity 	report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8);
841fa74f8a6SMohammed Gamal 
84218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_2);
8436055ea1fSAvi Kivity 	report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8);
844fa74f8a6SMohammed Gamal }
845fa74f8a6SMohammed Gamal 
84659317bd1SMohammed Gamal void test_mul()
84759317bd1SMohammed Gamal {
84859317bd1SMohammed Gamal 	MK_INSN(mul8, "mov $2, %al\n\t"
84959317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
85059317bd1SMohammed Gamal 			"imul %cl\n\t");
85159317bd1SMohammed Gamal 
85259317bd1SMohammed Gamal 	MK_INSN(mul16, "mov $2, %ax\n\t"
85359317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
85459317bd1SMohammed Gamal 			"imul %cx\n\t");
85559317bd1SMohammed Gamal 
85659317bd1SMohammed Gamal 	MK_INSN(mul32, "mov $2, %eax\n\t"
85759317bd1SMohammed Gamal 			"mov $4, %ecx\n\t"
85859317bd1SMohammed Gamal 			"imul %ecx\n\t");
85959317bd1SMohammed Gamal 
86018253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
86118253fdeSAvi Kivity 
86218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul8);
8636055ea1fSAvi Kivity 	report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8);
86459317bd1SMohammed Gamal 
86518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul16);
8666055ea1fSAvi Kivity 	report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8);
86759317bd1SMohammed Gamal 
86818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul32);
8696055ea1fSAvi Kivity 	report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8);
87059317bd1SMohammed Gamal }
87159317bd1SMohammed Gamal 
8720d4c7614SMohammed Gamal void test_div()
8730d4c7614SMohammed Gamal {
8740d4c7614SMohammed Gamal 	MK_INSN(div8, "mov $257, %ax\n\t"
8750d4c7614SMohammed Gamal 			"mov $2, %cl\n\t"
8760d4c7614SMohammed Gamal 			"div %cl\n\t");
8770d4c7614SMohammed Gamal 
8780d4c7614SMohammed Gamal 	MK_INSN(div16, "mov $512, %ax\n\t"
8790d4c7614SMohammed Gamal 			"mov $5, %cx\n\t"
8800d4c7614SMohammed Gamal 			"div %cx\n\t");
8810d4c7614SMohammed Gamal 
8820d4c7614SMohammed Gamal 	MK_INSN(div32, "mov $512, %eax\n\t"
8830d4c7614SMohammed Gamal 			"mov $5, %ecx\n\t"
8840d4c7614SMohammed Gamal 			"div %ecx\n\t");
8850d4c7614SMohammed Gamal 
88618253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
88718253fdeSAvi Kivity 
88818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div8);
8896055ea1fSAvi Kivity 	report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384);
8900d4c7614SMohammed Gamal 
89118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div16);
8926055ea1fSAvi Kivity 	report("div 2", R_AX | R_CX | R_DX,
8936055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
8940d4c7614SMohammed Gamal 
89518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div32);
8966055ea1fSAvi Kivity 	report("div 3", R_AX | R_CX | R_DX,
8976055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
8980d4c7614SMohammed Gamal }
8990d4c7614SMohammed Gamal 
9000d4c7614SMohammed Gamal void test_idiv()
9010d4c7614SMohammed Gamal {
9020d4c7614SMohammed Gamal 	MK_INSN(idiv8, "mov $256, %ax\n\t"
9030d4c7614SMohammed Gamal 			"mov $-2, %cl\n\t"
9040d4c7614SMohammed Gamal 			"idiv %cl\n\t");
9050d4c7614SMohammed Gamal 
9060d4c7614SMohammed Gamal 	MK_INSN(idiv16, "mov $512, %ax\n\t"
9070d4c7614SMohammed Gamal 			"mov $-2, %cx\n\t"
9080d4c7614SMohammed Gamal 			"idiv %cx\n\t");
9090d4c7614SMohammed Gamal 
9100d4c7614SMohammed Gamal 	MK_INSN(idiv32, "mov $512, %eax\n\t"
9110d4c7614SMohammed Gamal 			"mov $-2, %ecx\n\t"
9120d4c7614SMohammed Gamal 			"idiv %ecx\n\t");
9130d4c7614SMohammed Gamal 
91418253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
91518253fdeSAvi Kivity 
91618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv8);
9176055ea1fSAvi Kivity 	report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128);
9180d4c7614SMohammed Gamal 
91918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv16);
9206055ea1fSAvi Kivity 	report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256);
9210d4c7614SMohammed Gamal 
92218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv32);
9236055ea1fSAvi Kivity 	report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256);
9240d4c7614SMohammed Gamal }
9250d4c7614SMohammed Gamal 
9266e293cf5SWei Yongjun void test_cbw(void)
9276e293cf5SWei Yongjun {
9286e293cf5SWei Yongjun 	MK_INSN(cbw, "mov $0xFE, %eax \n\t"
9296e293cf5SWei Yongjun 		     "cbw\n\t");
9306e293cf5SWei Yongjun 	MK_INSN(cwde, "mov $0xFFFE, %eax \n\t"
9316e293cf5SWei Yongjun 		      "cwde\n\t");
9326e293cf5SWei Yongjun 
93318253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
93418253fdeSAvi Kivity 
93518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cbw);
9366055ea1fSAvi Kivity 	report("cbq 1", ~0, outregs.eax == 0xFFFE);
9376e293cf5SWei Yongjun 
93818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwde);
9396055ea1fSAvi Kivity 	report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE);
9406e293cf5SWei Yongjun }
9416e293cf5SWei Yongjun 
942eacef4e2SWei Yongjun void test_loopcc(void)
943eacef4e2SWei Yongjun {
944eacef4e2SWei Yongjun 	MK_INSN(loop, "mov $10, %ecx\n\t"
945eacef4e2SWei Yongjun 		      "1: inc %eax\n\t"
946eacef4e2SWei Yongjun 		      "loop 1b\n\t");
947eacef4e2SWei Yongjun 
948eacef4e2SWei Yongjun 	MK_INSN(loope, "mov $10, %ecx\n\t"
949eacef4e2SWei Yongjun 		       "mov $1, %eax\n\t"
950eacef4e2SWei Yongjun 		       "1: dec %eax\n\t"
951eacef4e2SWei Yongjun 		       "loope 1b\n\t");
952eacef4e2SWei Yongjun 
953eacef4e2SWei Yongjun 	MK_INSN(loopne, "mov $10, %ecx\n\t"
954eacef4e2SWei Yongjun 		        "mov $5, %eax\n\t"
955eacef4e2SWei Yongjun 		        "1: dec %eax\n\t"
956eacef4e2SWei Yongjun 			"loopne 1b\n\t");
957eacef4e2SWei Yongjun 
95818253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
959eacef4e2SWei Yongjun 
96018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loop);
9616055ea1fSAvi Kivity 	report("LOOPcc short 1", R_AX, outregs.eax == 10);
96218253fdeSAvi Kivity 
96318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loope);
9646055ea1fSAvi Kivity 	report("LOOPcc short 2", R_AX | R_CX,
9656055ea1fSAvi Kivity 	       outregs.eax == -1 && outregs.ecx == 8);
966eacef4e2SWei Yongjun 
96718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loopne);
9686055ea1fSAvi Kivity 	report("LOOPcc short 3", R_AX | R_CX,
9696055ea1fSAvi Kivity 	       outregs.eax == 0 && outregs.ecx == 5);
970eacef4e2SWei Yongjun }
971eacef4e2SWei Yongjun 
972b274feedSAvi Kivity static void test_das(void)
973b274feedSAvi Kivity {
974b274feedSAvi Kivity     short i;
97581050840SAvi Kivity     u16 nr_fail = 0;
976b274feedSAvi Kivity     static unsigned test_cases[1024] = {
977b274feedSAvi Kivity         0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00,
978b274feedSAvi Kivity         0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01,
979b274feedSAvi Kivity         0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02,
980b274feedSAvi Kivity         0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03,
981b274feedSAvi Kivity         0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04,
982b274feedSAvi Kivity         0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05,
983b274feedSAvi Kivity         0x06000606, 0x8701a606, 0x56100006, 0x9711a006,
984b274feedSAvi Kivity         0x02000707, 0x8301a707, 0x12100107, 0x9311a107,
985b274feedSAvi Kivity         0x02000808, 0x8301a808, 0x12100208, 0x9311a208,
986b274feedSAvi Kivity         0x06000909, 0x8701a909, 0x16100309, 0x9711a309,
987b274feedSAvi Kivity         0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a,
988b274feedSAvi Kivity         0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b,
989b274feedSAvi Kivity         0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c,
990b274feedSAvi Kivity         0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d,
991b274feedSAvi Kivity         0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e,
992b274feedSAvi Kivity         0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f,
993b274feedSAvi Kivity         0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10,
994b274feedSAvi Kivity         0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11,
995b274feedSAvi Kivity         0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12,
996b274feedSAvi Kivity         0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13,
997b274feedSAvi Kivity         0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14,
998b274feedSAvi Kivity         0x02001515, 0x8301b515, 0x16100f15, 0x9711af15,
999b274feedSAvi Kivity         0x02001616, 0x8301b616, 0x12101016, 0x9311b016,
1000b274feedSAvi Kivity         0x06001717, 0x8701b717, 0x16101117, 0x9711b117,
1001b274feedSAvi Kivity         0x06001818, 0x8701b818, 0x16101218, 0x9711b218,
1002b274feedSAvi Kivity         0x02001919, 0x8301b919, 0x12101319, 0x9311b319,
1003b274feedSAvi Kivity         0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a,
1004b274feedSAvi Kivity         0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b,
1005b274feedSAvi Kivity         0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c,
1006b274feedSAvi Kivity         0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d,
1007b274feedSAvi Kivity         0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e,
1008b274feedSAvi Kivity         0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f,
1009b274feedSAvi Kivity         0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20,
1010b274feedSAvi Kivity         0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21,
1011b274feedSAvi Kivity         0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22,
1012b274feedSAvi Kivity         0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23,
1013b274feedSAvi Kivity         0x06002424, 0x8301c424, 0x16101e24, 0x9711be24,
1014b274feedSAvi Kivity         0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25,
1015b274feedSAvi Kivity         0x02002626, 0x8701c626, 0x12102026, 0x9711c026,
1016b274feedSAvi Kivity         0x06002727, 0x8301c727, 0x16102127, 0x9311c127,
1017b274feedSAvi Kivity         0x06002828, 0x8301c828, 0x16102228, 0x9311c228,
1018b274feedSAvi Kivity         0x02002929, 0x8701c929, 0x12102329, 0x9711c329,
1019b274feedSAvi Kivity         0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a,
1020b274feedSAvi Kivity         0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b,
1021b274feedSAvi Kivity         0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c,
1022b274feedSAvi Kivity         0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d,
1023b274feedSAvi Kivity         0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e,
1024b274feedSAvi Kivity         0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f,
1025b274feedSAvi Kivity         0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30,
1026b274feedSAvi Kivity         0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31,
1027b274feedSAvi Kivity         0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32,
1028b274feedSAvi Kivity         0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33,
1029b274feedSAvi Kivity         0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34,
1030b274feedSAvi Kivity         0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35,
1031b274feedSAvi Kivity         0x06003636, 0x8301d636, 0x16103036, 0x9311d036,
1032b274feedSAvi Kivity         0x02003737, 0x8701d737, 0x12103137, 0x9711d137,
1033b274feedSAvi Kivity         0x02003838, 0x8701d838, 0x12103238, 0x9711d238,
1034b274feedSAvi Kivity         0x06003939, 0x8301d939, 0x16103339, 0x9311d339,
1035b274feedSAvi Kivity         0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a,
1036b274feedSAvi Kivity         0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b,
1037b274feedSAvi Kivity         0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c,
1038b274feedSAvi Kivity         0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d,
1039b274feedSAvi Kivity         0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e,
1040b274feedSAvi Kivity         0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f,
1041b274feedSAvi Kivity         0x02004040, 0x8301e040, 0x16103a40, 0x9311da40,
1042b274feedSAvi Kivity         0x06004141, 0x8701e141, 0x12103b41, 0x9711db41,
1043b274feedSAvi Kivity         0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42,
1044b274feedSAvi Kivity         0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43,
1045b274feedSAvi Kivity         0x06004444, 0x8701e444, 0x12103e44, 0x9711de44,
1046b274feedSAvi Kivity         0x02004545, 0x8301e545, 0x16103f45, 0x9311df45,
1047b274feedSAvi Kivity         0x02004646, 0x8301e646, 0x12104046, 0x9311e046,
1048b274feedSAvi Kivity         0x06004747, 0x8701e747, 0x16104147, 0x9711e147,
1049b274feedSAvi Kivity         0x06004848, 0x8701e848, 0x16104248, 0x9711e248,
1050b274feedSAvi Kivity         0x02004949, 0x8301e949, 0x12104349, 0x9311e349,
1051b274feedSAvi Kivity         0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a,
1052b274feedSAvi Kivity         0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b,
1053b274feedSAvi Kivity         0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c,
1054b274feedSAvi Kivity         0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d,
1055b274feedSAvi Kivity         0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e,
1056b274feedSAvi Kivity         0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f,
1057b274feedSAvi Kivity         0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50,
1058b274feedSAvi Kivity         0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51,
1059b274feedSAvi Kivity         0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52,
1060b274feedSAvi Kivity         0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53,
1061b274feedSAvi Kivity         0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54,
1062b274feedSAvi Kivity         0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55,
1063b274feedSAvi Kivity         0x06005656, 0x8701f656, 0x16105056, 0x9711f056,
1064b274feedSAvi Kivity         0x02005757, 0x8301f757, 0x12105157, 0x9311f157,
1065b274feedSAvi Kivity         0x02005858, 0x8301f858, 0x12105258, 0x9311f258,
1066b274feedSAvi Kivity         0x06005959, 0x8701f959, 0x16105359, 0x9711f359,
1067b274feedSAvi Kivity         0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a,
1068b274feedSAvi Kivity         0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b,
1069b274feedSAvi Kivity         0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c,
1070b274feedSAvi Kivity         0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d,
1071b274feedSAvi Kivity         0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e,
1072b274feedSAvi Kivity         0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f,
1073b274feedSAvi Kivity         0x06006060, 0x47010060, 0x16105a60, 0x9711fa60,
1074b274feedSAvi Kivity         0x02006161, 0x03010161, 0x12105b61, 0x9311fb61,
1075b274feedSAvi Kivity         0x02006262, 0x03010262, 0x16105c62, 0x9711fc62,
1076b274feedSAvi Kivity         0x06006363, 0x07010363, 0x12105d63, 0x9311fd63,
1077b274feedSAvi Kivity         0x02006464, 0x03010464, 0x12105e64, 0x9311fe64,
1078b274feedSAvi Kivity         0x06006565, 0x07010565, 0x16105f65, 0x9711ff65,
1079b274feedSAvi Kivity         0x06006666, 0x07010666, 0x16106066, 0x57110066,
1080b274feedSAvi Kivity         0x02006767, 0x03010767, 0x12106167, 0x13110167,
1081b274feedSAvi Kivity         0x02006868, 0x03010868, 0x12106268, 0x13110268,
1082b274feedSAvi Kivity         0x06006969, 0x07010969, 0x16106369, 0x17110369,
1083b274feedSAvi Kivity         0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a,
1084b274feedSAvi Kivity         0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b,
1085b274feedSAvi Kivity         0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c,
1086b274feedSAvi Kivity         0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d,
1087b274feedSAvi Kivity         0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e,
1088b274feedSAvi Kivity         0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f,
1089b274feedSAvi Kivity         0x02007070, 0x03011070, 0x16106a70, 0x17110a70,
1090b274feedSAvi Kivity         0x06007171, 0x07011171, 0x12106b71, 0x13110b71,
1091b274feedSAvi Kivity         0x06007272, 0x07011272, 0x16106c72, 0x17110c72,
1092b274feedSAvi Kivity         0x02007373, 0x03011373, 0x12106d73, 0x13110d73,
1093b274feedSAvi Kivity         0x06007474, 0x07011474, 0x12106e74, 0x13110e74,
1094b274feedSAvi Kivity         0x02007575, 0x03011575, 0x16106f75, 0x17110f75,
1095b274feedSAvi Kivity         0x02007676, 0x03011676, 0x12107076, 0x13111076,
1096b274feedSAvi Kivity         0x06007777, 0x07011777, 0x16107177, 0x17111177,
1097b274feedSAvi Kivity         0x06007878, 0x07011878, 0x16107278, 0x17111278,
1098b274feedSAvi Kivity         0x02007979, 0x03011979, 0x12107379, 0x13111379,
1099b274feedSAvi Kivity         0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a,
1100b274feedSAvi Kivity         0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b,
1101b274feedSAvi Kivity         0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c,
1102b274feedSAvi Kivity         0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d,
1103b274feedSAvi Kivity         0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e,
1104b274feedSAvi Kivity         0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f,
1105b274feedSAvi Kivity         0x82008080, 0x03012080, 0x12107a80, 0x13111a80,
1106b274feedSAvi Kivity         0x86008181, 0x07012181, 0x16107b81, 0x17111b81,
1107b274feedSAvi Kivity         0x86008282, 0x07012282, 0x12107c82, 0x13111c82,
1108b274feedSAvi Kivity         0x82008383, 0x03012383, 0x16107d83, 0x17111d83,
1109b274feedSAvi Kivity         0x86008484, 0x07012484, 0x16107e84, 0x17111e84,
1110b274feedSAvi Kivity         0x82008585, 0x03012585, 0x12107f85, 0x13111f85,
1111b274feedSAvi Kivity         0x82008686, 0x03012686, 0x92108086, 0x13112086,
1112b274feedSAvi Kivity         0x86008787, 0x07012787, 0x96108187, 0x17112187,
1113b274feedSAvi Kivity         0x86008888, 0x07012888, 0x96108288, 0x17112288,
1114b274feedSAvi Kivity         0x82008989, 0x03012989, 0x92108389, 0x13112389,
1115b274feedSAvi Kivity         0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a,
1116b274feedSAvi Kivity         0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b,
1117b274feedSAvi Kivity         0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c,
1118b274feedSAvi Kivity         0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d,
1119b274feedSAvi Kivity         0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e,
1120b274feedSAvi Kivity         0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f,
1121b274feedSAvi Kivity         0x86009090, 0x07013090, 0x92108a90, 0x13112a90,
1122b274feedSAvi Kivity         0x82009191, 0x03013191, 0x96108b91, 0x17112b91,
1123b274feedSAvi Kivity         0x82009292, 0x03013292, 0x92108c92, 0x13112c92,
1124b274feedSAvi Kivity         0x86009393, 0x07013393, 0x96108d93, 0x17112d93,
1125b274feedSAvi Kivity         0x82009494, 0x03013494, 0x96108e94, 0x17112e94,
1126b274feedSAvi Kivity         0x86009595, 0x07013595, 0x92108f95, 0x13112f95,
1127b274feedSAvi Kivity         0x86009696, 0x07013696, 0x96109096, 0x17113096,
1128b274feedSAvi Kivity         0x82009797, 0x03013797, 0x92109197, 0x13113197,
1129b274feedSAvi Kivity         0x82009898, 0x03013898, 0x92109298, 0x13113298,
1130b274feedSAvi Kivity         0x86009999, 0x07013999, 0x96109399, 0x17113399,
1131b274feedSAvi Kivity         0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a,
1132b274feedSAvi Kivity         0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b,
1133b274feedSAvi Kivity         0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c,
1134b274feedSAvi Kivity         0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d,
1135b274feedSAvi Kivity         0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e,
1136b274feedSAvi Kivity         0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f,
1137b274feedSAvi Kivity         0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0,
1138b274feedSAvi Kivity         0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1,
1139b274feedSAvi Kivity         0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2,
1140b274feedSAvi Kivity         0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3,
1141b274feedSAvi Kivity         0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4,
1142b274feedSAvi Kivity         0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5,
1143b274feedSAvi Kivity         0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6,
1144b274feedSAvi Kivity         0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7,
1145b274feedSAvi Kivity         0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8,
1146b274feedSAvi Kivity         0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9,
1147b274feedSAvi Kivity         0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa,
1148b274feedSAvi Kivity         0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab,
1149b274feedSAvi Kivity         0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac,
1150b274feedSAvi Kivity         0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad,
1151b274feedSAvi Kivity         0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae,
1152b274feedSAvi Kivity         0x130049af, 0x130149af, 0x131049af, 0x131149af,
1153b274feedSAvi Kivity         0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0,
1154b274feedSAvi Kivity         0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1,
1155b274feedSAvi Kivity         0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2,
1156b274feedSAvi Kivity         0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3,
1157b274feedSAvi Kivity         0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4,
1158b274feedSAvi Kivity         0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5,
1159b274feedSAvi Kivity         0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6,
1160b274feedSAvi Kivity         0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7,
1161b274feedSAvi Kivity         0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8,
1162b274feedSAvi Kivity         0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9,
1163b274feedSAvi Kivity         0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba,
1164b274feedSAvi Kivity         0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb,
1165b274feedSAvi Kivity         0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc,
1166b274feedSAvi Kivity         0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd,
1167b274feedSAvi Kivity         0x130058be, 0x130158be, 0x131058be, 0x131158be,
1168b274feedSAvi Kivity         0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf,
1169b274feedSAvi Kivity         0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0,
1170b274feedSAvi Kivity         0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1,
1171b274feedSAvi Kivity         0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2,
1172b274feedSAvi Kivity         0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3,
1173b274feedSAvi Kivity         0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4,
1174b274feedSAvi Kivity         0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5,
1175b274feedSAvi Kivity         0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6,
1176b274feedSAvi Kivity         0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7,
1177b274feedSAvi Kivity         0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8,
1178b274feedSAvi Kivity         0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9,
1179b274feedSAvi Kivity         0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca,
1180b274feedSAvi Kivity         0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb,
1181b274feedSAvi Kivity         0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc,
1182b274feedSAvi Kivity         0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd,
1183b274feedSAvi Kivity         0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce,
1184b274feedSAvi Kivity         0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf,
1185b274feedSAvi Kivity         0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0,
1186b274feedSAvi Kivity         0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1,
1187b274feedSAvi Kivity         0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2,
1188b274feedSAvi Kivity         0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3,
1189b274feedSAvi Kivity         0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4,
1190b274feedSAvi Kivity         0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5,
1191b274feedSAvi Kivity         0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6,
1192b274feedSAvi Kivity         0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7,
1193b274feedSAvi Kivity         0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8,
1194b274feedSAvi Kivity         0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9,
1195b274feedSAvi Kivity         0x170074da, 0x170174da, 0x171074da, 0x171174da,
1196b274feedSAvi Kivity         0x130075db, 0x130175db, 0x131075db, 0x131175db,
1197b274feedSAvi Kivity         0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc,
1198b274feedSAvi Kivity         0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd,
1199b274feedSAvi Kivity         0x170078de, 0x170178de, 0x171078de, 0x171178de,
1200b274feedSAvi Kivity         0x130079df, 0x130179df, 0x131079df, 0x131179df,
1201b274feedSAvi Kivity         0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0,
1202b274feedSAvi Kivity         0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1,
1203b274feedSAvi Kivity         0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2,
1204b274feedSAvi Kivity         0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3,
1205b274feedSAvi Kivity         0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4,
1206b274feedSAvi Kivity         0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5,
1207b274feedSAvi Kivity         0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6,
1208b274feedSAvi Kivity         0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7,
1209b274feedSAvi Kivity         0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8,
1210b274feedSAvi Kivity         0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9,
1211b274feedSAvi Kivity         0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea,
1212b274feedSAvi Kivity         0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb,
1213b274feedSAvi Kivity         0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec,
1214b274feedSAvi Kivity         0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed,
1215b274feedSAvi Kivity         0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee,
1216b274feedSAvi Kivity         0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef,
1217b274feedSAvi Kivity         0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0,
1218b274feedSAvi Kivity         0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1,
1219b274feedSAvi Kivity         0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2,
1220b274feedSAvi Kivity         0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3,
1221b274feedSAvi Kivity         0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4,
1222b274feedSAvi Kivity         0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5,
1223b274feedSAvi Kivity         0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6,
1224b274feedSAvi Kivity         0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7,
1225b274feedSAvi Kivity         0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8,
1226b274feedSAvi Kivity         0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9,
1227b274feedSAvi Kivity         0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa,
1228b274feedSAvi Kivity         0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb,
1229b274feedSAvi Kivity         0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc,
1230b274feedSAvi Kivity         0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd,
1231b274feedSAvi Kivity         0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe,
1232b274feedSAvi Kivity         0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff,
1233b274feedSAvi Kivity     };
1234b274feedSAvi Kivity 
1235b274feedSAvi Kivity     MK_INSN(das, "das");
1236b274feedSAvi Kivity 
123718253fdeSAvi Kivity     inregs = (struct regs){ 0 };
123818253fdeSAvi Kivity 
1239b274feedSAvi Kivity     for (i = 0; i < 1024; ++i) {
1240b274feedSAvi Kivity         unsigned tmp = test_cases[i];
1241b274feedSAvi Kivity         inregs.eax = tmp & 0xff;
1242b274feedSAvi Kivity         inregs.eflags = (tmp >> 16) & 0xff;
124318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_das);
124418253fdeSAvi Kivity 	if (!regs_equal(R_AX)
1245b274feedSAvi Kivity             || outregs.eax != ((tmp >> 8) & 0xff)
1246b274feedSAvi Kivity             || (outregs.eflags & 0xff) != (tmp >> 24)) {
124781050840SAvi Kivity 	    ++nr_fail;
124881050840SAvi Kivity 	    break;
1249b274feedSAvi Kivity         }
1250b274feedSAvi Kivity     }
12516055ea1fSAvi Kivity     report("DAS", ~0, nr_fail == 0);
1252b274feedSAvi Kivity }
1253b274feedSAvi Kivity 
12540cbd5b06SMohammed Gamal void test_cwd_cdq()
12550cbd5b06SMohammed Gamal {
12560cbd5b06SMohammed Gamal 	/* Sign-bit set */
12570cbd5b06SMohammed Gamal 	MK_INSN(cwd_1, "mov $0x8000, %ax\n\t"
12580cbd5b06SMohammed Gamal 		       "cwd\n\t");
12590cbd5b06SMohammed Gamal 
12600cbd5b06SMohammed Gamal 	/* Sign-bit not set */
12610cbd5b06SMohammed Gamal 	MK_INSN(cwd_2, "mov $0x1000, %ax\n\t"
12620cbd5b06SMohammed Gamal 		       "cwd\n\t");
12630cbd5b06SMohammed Gamal 
12640cbd5b06SMohammed Gamal 	/* Sign-bit set */
12650cbd5b06SMohammed Gamal 	MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t"
12660cbd5b06SMohammed Gamal 		       "cdq\n\t");
12670cbd5b06SMohammed Gamal 
12680cbd5b06SMohammed Gamal 	/* Sign-bit not set */
12690cbd5b06SMohammed Gamal 	MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t"
12700cbd5b06SMohammed Gamal 		       "cdq\n\t");
12710cbd5b06SMohammed Gamal 
127218253fdeSAvi Kivity 	inregs = (struct regs){ 0 };
127318253fdeSAvi Kivity 
127418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_1);
12756055ea1fSAvi Kivity 	report("cwd 1", R_AX | R_DX,
12766055ea1fSAvi Kivity 	       outregs.eax == 0x8000 && outregs.edx == 0xffff);
12770cbd5b06SMohammed Gamal 
127818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_2);
12796055ea1fSAvi Kivity 	report("cwd 2", R_AX | R_DX,
12806055ea1fSAvi Kivity 	       outregs.eax == 0x1000 && outregs.edx == 0);
12810cbd5b06SMohammed Gamal 
128218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_1);
12836055ea1fSAvi Kivity 	report("cdq 1", R_AX | R_DX,
12846055ea1fSAvi Kivity 	       outregs.eax == 0x80000000 && outregs.edx == 0xffffffff);
12850cbd5b06SMohammed Gamal 
128618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_2);
12876055ea1fSAvi Kivity 	report("cdq 2", R_AX | R_DX,
12886055ea1fSAvi Kivity 	       outregs.eax == 0x10000000 && outregs.edx == 0);
12890cbd5b06SMohammed Gamal }
12900cbd5b06SMohammed Gamal 
129137f51a4aSWei Yongjun static struct {
129237f51a4aSWei Yongjun         void *address;
129337f51a4aSWei Yongjun         unsigned short sel;
129437f51a4aSWei Yongjun } __attribute__((packed)) desc = {
129537f51a4aSWei Yongjun 	(void *)0x1234,
129637f51a4aSWei Yongjun 	0x10,
129737f51a4aSWei Yongjun };
129837f51a4aSWei Yongjun 
129937f51a4aSWei Yongjun void test_lds_lss()
130037f51a4aSWei Yongjun {
130137f51a4aSWei Yongjun 	inregs = (struct regs){ .ebx = (unsigned long)&desc };
130237f51a4aSWei Yongjun 
130337f51a4aSWei Yongjun 	MK_INSN(lds, "push %ds\n\t"
130437f51a4aSWei Yongjun 		     "lds (%ebx), %eax\n\t"
130537f51a4aSWei Yongjun 		     "mov %ds, %ebx\n\t"
130637f51a4aSWei Yongjun 		     "pop %ds\n\t");
130737f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lds);
130837f51a4aSWei Yongjun 	report("lds", R_AX | R_BX,
130937f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
131037f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
131137f51a4aSWei Yongjun 
131237f51a4aSWei Yongjun 	MK_INSN(les, "push %es\n\t"
131337f51a4aSWei Yongjun 		     "les (%ebx), %eax\n\t"
131437f51a4aSWei Yongjun 		     "mov %es, %ebx\n\t"
131537f51a4aSWei Yongjun 		     "pop %es\n\t");
131637f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_les);
131737f51a4aSWei Yongjun 	report("les", R_AX | R_BX,
131837f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
131937f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
132037f51a4aSWei Yongjun 
132137f51a4aSWei Yongjun 	MK_INSN(lfs, "push %fs\n\t"
132237f51a4aSWei Yongjun 		     "lfs (%ebx), %eax\n\t"
132337f51a4aSWei Yongjun 		     "mov %fs, %ebx\n\t"
132437f51a4aSWei Yongjun 		     "pop %fs\n\t");
132537f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lfs);
132637f51a4aSWei Yongjun 	report("lfs", R_AX | R_BX,
132737f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
132837f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
132937f51a4aSWei Yongjun 
133037f51a4aSWei Yongjun 	MK_INSN(lgs, "push %gs\n\t"
133137f51a4aSWei Yongjun 		     "lgs (%ebx), %eax\n\t"
133237f51a4aSWei Yongjun 		     "mov %gs, %ebx\n\t"
133337f51a4aSWei Yongjun 		     "pop %gs\n\t");
133437f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lgs);
133537f51a4aSWei Yongjun 	report("lgs", R_AX | R_BX,
133637f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
133737f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
133837f51a4aSWei Yongjun 
133937f51a4aSWei Yongjun 	MK_INSN(lss, "push %ss\n\t"
134037f51a4aSWei Yongjun 		     "lss (%ebx), %eax\n\t"
134137f51a4aSWei Yongjun 		     "mov %ss, %ebx\n\t"
134237f51a4aSWei Yongjun 		     "pop %ss\n\t");
134337f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lss);
134437f51a4aSWei Yongjun 	report("lss", R_AX | R_BX,
134537f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
134637f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
134737f51a4aSWei Yongjun }
134837f51a4aSWei Yongjun 
1349b1c7c575SWei Yongjun void test_jcxz(void)
1350b1c7c575SWei Yongjun {
1351b1c7c575SWei Yongjun 	MK_INSN(jcxz1, "jcxz 1f\n\t"
1352b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1353b1c7c575SWei Yongjun 		       "1:\n\t");
1354b1c7c575SWei Yongjun 	MK_INSN(jcxz2, "mov $0x100, %ecx\n\t"
1355b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1356b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1357b1c7c575SWei Yongjun 		       "mov $0, %ecx\n\t"
1358b1c7c575SWei Yongjun 		       "1:\n\t");
1359b1c7c575SWei Yongjun 	MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t"
1360b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1361b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1362b1c7c575SWei Yongjun 		       "1:\n\t");
1363b1c7c575SWei Yongjun 	MK_INSN(jecxz1, "jecxz 1f\n\t"
1364b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1365b1c7c575SWei Yongjun 			"1:\n\t");
1366b1c7c575SWei Yongjun 	MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t"
1367b1c7c575SWei Yongjun 			"jecxz 1f\n\t"
1368b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1369b1c7c575SWei Yongjun 			"mov $0, %ecx\n\t"
1370b1c7c575SWei Yongjun 			"1:\n\t");
1371b1c7c575SWei Yongjun 
1372b1c7c575SWei Yongjun 	inregs = (struct regs){ 0 };
1373b1c7c575SWei Yongjun 
1374b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz1);
1375b1c7c575SWei Yongjun 	report("jcxz short 1", 0, 1);
1376b1c7c575SWei Yongjun 
1377b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz2);
1378b1c7c575SWei Yongjun 	report("jcxz short 2", R_AX, outregs.eax == 0x1234);
1379b1c7c575SWei Yongjun 
1380b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz3);
1381b1c7c575SWei Yongjun 	report("jcxz short 3", R_CX, outregs.ecx == 0x10000);
1382b1c7c575SWei Yongjun 
1383b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz1);
1384b1c7c575SWei Yongjun 	report("jecxz short 1", 0, 1);
1385b1c7c575SWei Yongjun 
1386b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz2);
1387b1c7c575SWei Yongjun 	report("jecxz short 2", R_AX, outregs.eax == 0x1234);
1388b1c7c575SWei Yongjun }
1389b1c7c575SWei Yongjun 
13908f578e98SAvi Kivity static void test_cpuid(void)
13918f578e98SAvi Kivity {
13928f578e98SAvi Kivity     MK_INSN(cpuid, "cpuid");
13938f578e98SAvi Kivity     unsigned function = 0x1234;
13948f578e98SAvi Kivity     unsigned eax, ebx, ecx, edx;
13958f578e98SAvi Kivity 
13968f578e98SAvi Kivity     inregs.eax = eax = function;
139718ba9083SGleb Natapov     inregs.ecx = ecx = 0;
1398674d2dbeSPaolo Bonzini     asm("cpuid" : "+a"(eax), "=b"(ebx), "+c"(ecx), "=d"(edx));
13998f578e98SAvi Kivity     exec_in_big_real_mode(&insn_cpuid);
14008f578e98SAvi Kivity     report("cpuid", R_AX|R_BX|R_CX|R_DX,
14018f578e98SAvi Kivity 	   outregs.eax == eax && outregs.ebx == ebx
14028f578e98SAvi Kivity 	   && outregs.ecx == ecx && outregs.edx == edx);
14038f578e98SAvi Kivity }
14048f578e98SAvi Kivity 
1405ed93f43bSAvi Kivity static void test_ss_base_for_esp_ebp(void)
1406ed93f43bSAvi Kivity {
1407ed93f43bSAvi Kivity     MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss");
1408ed93f43bSAvi Kivity     MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss");
1409ed93f43bSAvi Kivity     static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 };
1410ed93f43bSAvi Kivity 
1411ed93f43bSAvi Kivity     inregs.ebx = 1;
1412ed93f43bSAvi Kivity     inregs.ebp = (unsigned)array;
1413ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel1);
1414ed93f43bSAvi Kivity     report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321);
1415ed93f43bSAvi Kivity     inregs.ebx = 1;
1416ed93f43bSAvi Kivity     inregs.ebp = (unsigned)array;
1417ed93f43bSAvi Kivity     inregs.edi = 0;
1418ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel2);
1419ed93f43bSAvi Kivity     report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321);
1420ed93f43bSAvi Kivity }
1421ed93f43bSAvi Kivity 
1422*975ca087SPeter Feiner extern unsigned long long r_gdt[];
1423*975ca087SPeter Feiner 
1424c2281fa4SAvi Kivity static void test_sgdt_sidt(void)
1425c2281fa4SAvi Kivity {
1426c2281fa4SAvi Kivity     MK_INSN(sgdt, "sgdtw (%eax)");
1427c2281fa4SAvi Kivity     MK_INSN(sidt, "sidtw (%eax)");
1428*975ca087SPeter Feiner     struct table_descr x, y;
1429c2281fa4SAvi Kivity 
1430c2281fa4SAvi Kivity     inregs.eax = (unsigned)&y;
1431c2281fa4SAvi Kivity     asm volatile("sgdtw %0" : "=m"(x));
1432c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sgdt);
1433*975ca087SPeter Feiner     report("sgdt", 0, x.limit == y.limit && x.base == y.base);
1434c2281fa4SAvi Kivity 
1435c2281fa4SAvi Kivity     inregs.eax = (unsigned)&y;
1436c2281fa4SAvi Kivity     asm volatile("sidtw %0" : "=m"(x));
1437c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sidt);
1438*975ca087SPeter Feiner     report("sidt", 0, x.limit == y.limit && x.base == y.base);
1439c2281fa4SAvi Kivity }
1440c2281fa4SAvi Kivity 
144188b6dac4SPaolo Bonzini static void test_sahf(void)
144288b6dac4SPaolo Bonzini {
144388b6dac4SPaolo Bonzini     MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw");
144488b6dac4SPaolo Bonzini 
144588b6dac4SPaolo Bonzini     inregs.eax = 0xfd00;
144688b6dac4SPaolo Bonzini     exec_in_big_real_mode(&insn_sahf);
144788b6dac4SPaolo Bonzini     report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7));
144888b6dac4SPaolo Bonzini }
144988b6dac4SPaolo Bonzini 
14507ae3645aSAvi Kivity static void test_lahf(void)
14517ae3645aSAvi Kivity {
14527ae3645aSAvi Kivity     MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf");
14537ae3645aSAvi Kivity 
14547ae3645aSAvi Kivity     inregs.eax = 0xc7;
14557ae3645aSAvi Kivity     exec_in_big_real_mode(&insn_lahf);
14567ae3645aSAvi Kivity     report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax);
14577ae3645aSAvi Kivity }
14587ae3645aSAvi Kivity 
1459fd9ea640SAvi Kivity static void test_movzx_movsx(void)
1460fd9ea640SAvi Kivity {
1461fd9ea640SAvi Kivity     MK_INSN(movsx, "movsx %al, %ebx");
1462fd9ea640SAvi Kivity     MK_INSN(movzx, "movzx %al, %ebx");
14633013e079SGleb Natapov     MK_INSN(movzsah, "movsx %ah, %ebx");
14643013e079SGleb Natapov     MK_INSN(movzxah, "movzx %ah, %ebx");
1465fd9ea640SAvi Kivity 
1466fd9ea640SAvi Kivity     inregs.eax = 0x1234569c;
14673013e079SGleb Natapov     inregs.esp = 0xffff;
1468fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movsx);
1469fd9ea640SAvi Kivity     report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax);
1470fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movzx);
1471fd9ea640SAvi Kivity     report("movzx", R_BX, outregs.ebx == (unsigned char)inregs.eax);
14723013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzsah);
14733013e079SGleb Natapov     report("movsx ah", R_BX, outregs.ebx == (signed char)(inregs.eax>>8));
14743013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzxah);
14753013e079SGleb Natapov     report("movzx ah", R_BX, outregs.ebx == (unsigned char)(inregs.eax >> 8));
1476fd9ea640SAvi Kivity }
1477fd9ea640SAvi Kivity 
1478b493b2e8SAvi Kivity static void test_bswap(void)
1479b493b2e8SAvi Kivity {
1480b493b2e8SAvi Kivity     MK_INSN(bswap, "bswap %ecx");
1481b493b2e8SAvi Kivity 
1482b493b2e8SAvi Kivity     inregs.ecx = 0x12345678;
1483b493b2e8SAvi Kivity     exec_in_big_real_mode(&insn_bswap);
1484b493b2e8SAvi Kivity     report("bswap", R_CX, outregs.ecx == 0x78563412);
1485b493b2e8SAvi Kivity }
1486b493b2e8SAvi Kivity 
14878cd86387SGleb Natapov static void test_aad(void)
14888cd86387SGleb Natapov {
14898cd86387SGleb Natapov     MK_INSN(aad, "aad");
14908cd86387SGleb Natapov 
14918cd86387SGleb Natapov     inregs.eax = 0x12345678;
14928cd86387SGleb Natapov     exec_in_big_real_mode(&insn_aad);
14938cd86387SGleb Natapov     report("aad", R_AX, outregs.eax == 0x123400d4);
14948cd86387SGleb Natapov }
14958cd86387SGleb Natapov 
14962a9b5718SPaolo Bonzini static void test_aam(void)
14972a9b5718SPaolo Bonzini {
14982a9b5718SPaolo Bonzini     MK_INSN(aam, "aam");
14992a9b5718SPaolo Bonzini 
15002a9b5718SPaolo Bonzini     inregs.eax = 0x76543210;
15012a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_aam);
15022a9b5718SPaolo Bonzini     report("aam", R_AX, outregs.eax == 0x76540106);
15032a9b5718SPaolo Bonzini }
15042a9b5718SPaolo Bonzini 
15052a9b5718SPaolo Bonzini static void test_xlat(void)
15062a9b5718SPaolo Bonzini {
15072a9b5718SPaolo Bonzini     MK_INSN(xlat, "xlat");
15082a9b5718SPaolo Bonzini     u8 table[256];
15092a9b5718SPaolo Bonzini     int i;
15102a9b5718SPaolo Bonzini 
15112a9b5718SPaolo Bonzini     for (i = 0; i < 256; i++) {
15122a9b5718SPaolo Bonzini         table[i] = i + 1;
15132a9b5718SPaolo Bonzini     }
15142a9b5718SPaolo Bonzini 
15152a9b5718SPaolo Bonzini     inregs.eax = 0x89abcdef;
15162a9b5718SPaolo Bonzini     inregs.ebx = (u32)table;
15172a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_xlat);
15182a9b5718SPaolo Bonzini     report("xlat", R_AX, outregs.eax == 0x89abcdf0);
15192a9b5718SPaolo Bonzini }
15202a9b5718SPaolo Bonzini 
15212a9b5718SPaolo Bonzini static void test_salc(void)
15222a9b5718SPaolo Bonzini {
15232a9b5718SPaolo Bonzini     MK_INSN(clc_salc, "clc; .byte 0xd6");
15242a9b5718SPaolo Bonzini     MK_INSN(stc_salc, "stc; .byte 0xd6");
15252a9b5718SPaolo Bonzini 
15262a9b5718SPaolo Bonzini     inregs.eax = 0x12345678;
15272a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_clc_salc);
15282a9b5718SPaolo Bonzini     report("salc (1)", R_AX, outregs.eax == 0x12345600);
15292a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_stc_salc);
15302a9b5718SPaolo Bonzini     report("salc (2)", R_AX, outregs.eax == 0x123456ff);
15312a9b5718SPaolo Bonzini }
15322a9b5718SPaolo Bonzini 
15330987db7aSGleb Natapov static void test_fninit(void)
15340987db7aSGleb Natapov {
15350987db7aSGleb Natapov 	u16 fcw = -1, fsw = -1;
15360987db7aSGleb Natapov 	MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)");
15370987db7aSGleb Natapov 
15380987db7aSGleb Natapov 	inregs.eax = (u32)&fsw;
15390987db7aSGleb Natapov 	inregs.ebx = (u32)&fcw;
15400987db7aSGleb Natapov 
15410987db7aSGleb Natapov 	exec_in_big_real_mode(&insn_fninit);
15420987db7aSGleb Natapov 	report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f);
15430987db7aSGleb Natapov }
15440987db7aSGleb Natapov 
15451a4c03a0SArthur Chunqi Li static void test_nopl(void)
15461a4c03a0SArthur Chunqi Li {
15471a4c03a0SArthur Chunqi Li 	MK_INSN(nopl1, ".byte 0x90\n\r"); // 1 byte nop
15481a4c03a0SArthur Chunqi Li 	MK_INSN(nopl2, ".byte 0x66, 0x90\n\r"); // 2 bytes nop
15491a4c03a0SArthur Chunqi Li 	MK_INSN(nopl3, ".byte 0x0f, 0x1f, 0x00\n\r"); // 3 bytes nop
15501a4c03a0SArthur Chunqi Li 	MK_INSN(nopl4, ".byte 0x0f, 0x1f, 0x40, 0x00\n\r"); // 4 bytes nop
15511a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl1);
15521a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl2);
15531a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl3);
15541a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl4);
15551a4c03a0SArthur Chunqi Li 	report("nopl", 0, 1);
15561a4c03a0SArthur Chunqi Li }
15571a4c03a0SArthur Chunqi Li 
1558b5105e8bSPaolo Bonzini static u32 perf_baseline;
1559b5105e8bSPaolo Bonzini 
15607505ea23SPaolo Bonzini #define PERF_COUNT 1000000
1561b5105e8bSPaolo Bonzini 
1562b5105e8bSPaolo Bonzini #define MK_INSN_PERF(name, insn)                                \
1563b5105e8bSPaolo Bonzini 	MK_INSN(name, "rdtsc; mov %eax, %ebx; mov %edx, %esi\n" \
1564b5105e8bSPaolo Bonzini 		      "1:" insn "\n"                            \
15657505ea23SPaolo Bonzini 		      ".byte 0x67; loop 1b\n"                   \
1566b5105e8bSPaolo Bonzini 		      "rdtsc");
1567b5105e8bSPaolo Bonzini 
1568b5105e8bSPaolo Bonzini static u32 cycles_in_big_real_mode(struct insn_desc *insn)
1569b5105e8bSPaolo Bonzini {
1570b5105e8bSPaolo Bonzini 	u64 start, end;
1571b5105e8bSPaolo Bonzini 
1572b5105e8bSPaolo Bonzini 	inregs.ecx = PERF_COUNT;
1573b5105e8bSPaolo Bonzini 	exec_in_big_real_mode(insn);
1574b5105e8bSPaolo Bonzini 	start = ((u64)outregs.esi << 32) | outregs.ebx;
1575b5105e8bSPaolo Bonzini 	end = ((u64)outregs.edx << 32) | outregs.eax;
1576b5105e8bSPaolo Bonzini 
1577b5105e8bSPaolo Bonzini 	return end - start;
1578b5105e8bSPaolo Bonzini }
1579b5105e8bSPaolo Bonzini 
1580b5105e8bSPaolo Bonzini static void test_perf_loop(void)
1581b5105e8bSPaolo Bonzini {
1582b5105e8bSPaolo Bonzini 	/*
1583b5105e8bSPaolo Bonzini 	 * This test runs simple instructions that should roughly take the
1584b5105e8bSPaolo Bonzini 	 * the same time to emulate: PERF_COUNT iterations of "loop" and 3
1585b5105e8bSPaolo Bonzini 	 * setup instructions.  Other performance tests can run PERF_COUNT
1586b5105e8bSPaolo Bonzini 	 * iterations of the same instruction and subtract the cycle count
1587b5105e8bSPaolo Bonzini 	 * of this test.
1588b5105e8bSPaolo Bonzini 	 */
1589b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_loop, "");
1590b5105e8bSPaolo Bonzini 	perf_baseline = cycles_in_big_real_mode(&insn_perf_loop);
1591b5105e8bSPaolo Bonzini 	print_serial_u32(perf_baseline / (PERF_COUNT + 3));
1592b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated jump instruction\n");
1593b5105e8bSPaolo Bonzini }
1594b5105e8bSPaolo Bonzini 
1595b5105e8bSPaolo Bonzini static void test_perf_mov(void)
1596b5105e8bSPaolo Bonzini {
1597b5105e8bSPaolo Bonzini 	u32 cyc;
1598b5105e8bSPaolo Bonzini 
1599b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_move, "mov %esi, %edi");
1600b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_move);
1601b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1602b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated move instruction\n");
1603b5105e8bSPaolo Bonzini }
1604b5105e8bSPaolo Bonzini 
1605b5105e8bSPaolo Bonzini static void test_perf_arith(void)
1606b5105e8bSPaolo Bonzini {
1607b5105e8bSPaolo Bonzini 	u32 cyc;
1608b5105e8bSPaolo Bonzini 
1609b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_arith, "add $4, %edi");
1610b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_arith);
1611b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1612b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated arithmetic instruction\n");
1613b5105e8bSPaolo Bonzini }
1614b5105e8bSPaolo Bonzini 
1615b5105e8bSPaolo Bonzini static void test_perf_memory_load(void)
1616b5105e8bSPaolo Bonzini {
1617b5105e8bSPaolo Bonzini 	u32 cyc, tmp;
1618b5105e8bSPaolo Bonzini 
1619b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_memory_load, "cmp $0, (%edi)");
1620b5105e8bSPaolo Bonzini 	inregs.edi = (u32)&tmp;
1621b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_load);
1622b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1623b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated memory load instruction\n");
1624b5105e8bSPaolo Bonzini }
1625b5105e8bSPaolo Bonzini 
16269306cb8eSPaolo Bonzini static void test_perf_memory_store(void)
16279306cb8eSPaolo Bonzini {
16289306cb8eSPaolo Bonzini 	u32 cyc, tmp;
16299306cb8eSPaolo Bonzini 
16309306cb8eSPaolo Bonzini 	MK_INSN_PERF(perf_memory_store, "mov %ax, (%edi)");
16319306cb8eSPaolo Bonzini 	inregs.edi = (u32)&tmp;
16329306cb8eSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_store);
16339306cb8eSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
16349306cb8eSPaolo Bonzini 	print_serial(" cycles/emulated memory store instruction\n");
16359306cb8eSPaolo Bonzini }
16369306cb8eSPaolo Bonzini 
1637b5105e8bSPaolo Bonzini static void test_perf_memory_rmw(void)
1638b5105e8bSPaolo Bonzini {
1639b5105e8bSPaolo Bonzini 	u32 cyc, tmp;
1640b5105e8bSPaolo Bonzini 
1641b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_memory_rmw, "add $1, (%edi)");
1642b5105e8bSPaolo Bonzini 	inregs.edi = (u32)&tmp;
1643b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_rmw);
1644b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1645b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated memory RMW instruction\n");
1646b5105e8bSPaolo Bonzini }
1647b5105e8bSPaolo Bonzini 
16480a5701edSNadav Amit void test_dr_mod(void)
16490a5701edSNadav Amit {
16500a5701edSNadav Amit 	MK_INSN(drmod, "movl %ebx, %dr0\n\t"
16510a5701edSNadav Amit 		       ".byte 0x0f \n\t .byte 0x21 \n\t .byte 0x0\n\t");
16520a5701edSNadav Amit 	inregs.eax = 0xdead;
16530a5701edSNadav Amit 	inregs.ebx = 0xaced;
16540a5701edSNadav Amit 	exec_in_big_real_mode(&insn_drmod);
16550a5701edSNadav Amit 	report("mov dr with mod bits", R_AX | R_BX, outregs.eax == 0xaced);
16560a5701edSNadav Amit }
16570a5701edSNadav Amit 
165899ee878cSNadav Amit void test_smsw(void)
165999ee878cSNadav Amit {
166099ee878cSNadav Amit 	MK_INSN(smsw, "movl %cr0, %ebx\n\t"
166199ee878cSNadav Amit 		      "movl %ebx, %ecx\n\t"
166299ee878cSNadav Amit 		      "or $0x40000000, %ebx\n\t"
166399ee878cSNadav Amit 		      "movl %ebx, %cr0\n\t"
166499ee878cSNadav Amit 		      "smswl %eax\n\t"
166599ee878cSNadav Amit 		      "movl %ecx, %cr0\n\t");
166699ee878cSNadav Amit 	inregs.eax = 0x12345678;
166799ee878cSNadav Amit 	exec_in_big_real_mode(&insn_smsw);
166899ee878cSNadav Amit 	report("smsw", R_AX | R_BX | R_CX, outregs.eax == outregs.ebx);
166999ee878cSNadav Amit }
167099ee878cSNadav Amit 
16717bee560dSNadav Amit void test_xadd(void)
16727bee560dSNadav Amit {
16737bee560dSNadav Amit 	MK_INSN(xadd, "xaddl %eax, %eax\n\t");
16747bee560dSNadav Amit 	inregs.eax = 0x12345678;
16757bee560dSNadav Amit 	exec_in_big_real_mode(&insn_xadd);
16767bee560dSNadav Amit 	report("xadd", R_AX, outregs.eax == inregs.eax * 2);
16777bee560dSNadav Amit }
16787bee560dSNadav Amit 
167999ee878cSNadav Amit 
16807d36db35SAvi Kivity void realmode_start(void)
16817d36db35SAvi Kivity {
16827d36db35SAvi Kivity 	test_null();
16837d36db35SAvi Kivity 
16847d36db35SAvi Kivity 	test_shld();
16857d36db35SAvi Kivity 	test_push_pop();
16867d36db35SAvi Kivity 	test_pusha_popa();
16877d36db35SAvi Kivity 	test_mov_imm();
16887d36db35SAvi Kivity 	test_cmp_imm();
16897d36db35SAvi Kivity 	test_add_imm();
16907d36db35SAvi Kivity 	test_sub_imm();
16917d36db35SAvi Kivity 	test_xor_imm();
16927d36db35SAvi Kivity 	test_io();
16937d36db35SAvi Kivity 	test_eflags_insn();
16947d36db35SAvi Kivity 	test_jcc_short();
16957d36db35SAvi Kivity 	test_jcc_near();
16967d36db35SAvi Kivity 	/* test_call() uses short jump so call it after testing jcc */
16977d36db35SAvi Kivity 	test_call();
16987d36db35SAvi Kivity 	/* long jmp test uses call near so test it after testing call */
16997d36db35SAvi Kivity 	test_long_jmp();
17007d36db35SAvi Kivity 	test_xchg();
17017d36db35SAvi Kivity 	test_iret();
170296b9ca1eSMohammed Gamal 	test_int();
1703fa74f8a6SMohammed Gamal 	test_imul();
170459317bd1SMohammed Gamal 	test_mul();
17050d4c7614SMohammed Gamal 	test_div();
17060d4c7614SMohammed Gamal 	test_idiv();
1707eacef4e2SWei Yongjun 	test_loopcc();
17086e293cf5SWei Yongjun 	test_cbw();
17090cbd5b06SMohammed Gamal 	test_cwd_cdq();
1710b274feedSAvi Kivity 	test_das();
171137f51a4aSWei Yongjun 	test_lds_lss();
1712b1c7c575SWei Yongjun 	test_jcxz();
17138f578e98SAvi Kivity 	test_cpuid();
1714ed93f43bSAvi Kivity 	test_ss_base_for_esp_ebp();
1715c2281fa4SAvi Kivity 	test_sgdt_sidt();
17167ae3645aSAvi Kivity 	test_lahf();
171788b6dac4SPaolo Bonzini 	test_sahf();
1718fd9ea640SAvi Kivity 	test_movzx_movsx();
1719b493b2e8SAvi Kivity 	test_bswap();
17208cd86387SGleb Natapov 	test_aad();
17212a9b5718SPaolo Bonzini 	test_aam();
17222a9b5718SPaolo Bonzini 	test_xlat();
17232a9b5718SPaolo Bonzini 	test_salc();
17240987db7aSGleb Natapov 	test_fninit();
17250a5701edSNadav Amit 	test_dr_mod();
172699ee878cSNadav Amit 	test_smsw();
17271a4c03a0SArthur Chunqi Li 	test_nopl();
17287bee560dSNadav Amit 	test_xadd();
1729b5105e8bSPaolo Bonzini 	test_perf_loop();
1730b5105e8bSPaolo Bonzini 	test_perf_mov();
1731b5105e8bSPaolo Bonzini 	test_perf_arith();
1732b5105e8bSPaolo Bonzini 	test_perf_memory_load();
17339306cb8eSPaolo Bonzini 	test_perf_memory_store();
1734b5105e8bSPaolo Bonzini 	test_perf_memory_rmw();
17357d36db35SAvi Kivity 
1736b393fe28SNadav Amit 	exit(failed);
17377d36db35SAvi Kivity }
17387d36db35SAvi Kivity 
17397d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff };
17407d36db35SAvi Kivity 
1741*975ca087SPeter Feiner struct table_descr r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt };
17427d36db35SAvi Kivity 
17437d36db35SAvi Kivity asm(
17447d36db35SAvi Kivity 	".section .init \n\t"
17457d36db35SAvi Kivity 
17467d36db35SAvi Kivity 	".code32 \n\t"
17477d36db35SAvi Kivity 
17487d36db35SAvi Kivity 	"mb_magic = 0x1BADB002 \n\t"
17497d36db35SAvi Kivity 	"mb_flags = 0x0 \n\t"
17507d36db35SAvi Kivity 
17517d36db35SAvi Kivity 	"# multiboot header \n\t"
17527d36db35SAvi Kivity 	".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t"
17537d36db35SAvi Kivity 
17547d36db35SAvi Kivity 	".globl start \n\t"
17557d36db35SAvi Kivity 	".data \n\t"
17567d36db35SAvi Kivity 	". = . + 4096 \n\t"
17577d36db35SAvi Kivity 	"stacktop: \n\t"
17587d36db35SAvi Kivity 
17597d36db35SAvi Kivity 	".text \n\t"
17607d36db35SAvi Kivity 	"start: \n\t"
17617d36db35SAvi Kivity 	"lgdt r_gdt_descr \n\t"
17627d36db35SAvi Kivity 	"ljmp $8, $1f; 1: \n\t"
17637d36db35SAvi Kivity 	".code16gcc \n\t"
17647d36db35SAvi Kivity 	"mov $16, %eax \n\t"
17657d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
17667d36db35SAvi Kivity 	"mov %ax, %es \n\t"
17677d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
17687d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
17697d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
17707d36db35SAvi Kivity 	"mov %cr0, %eax \n\t"
17717d36db35SAvi Kivity 	"btc $0, %eax \n\t"
17727d36db35SAvi Kivity 	"mov %eax, %cr0 \n\t"
17737d36db35SAvi Kivity 	"ljmp $0, $realmode_entry \n\t"
17747d36db35SAvi Kivity 
17757d36db35SAvi Kivity 	"realmode_entry: \n\t"
17767d36db35SAvi Kivity 
17777d36db35SAvi Kivity 	"xor %ax, %ax \n\t"
17787d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
17797d36db35SAvi Kivity 	"mov %ax, %es \n\t"
17807d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
17817d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
17827d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
17837d36db35SAvi Kivity 	"mov $stacktop, %esp\n\t"
17847d36db35SAvi Kivity 	"ljmp $0, $realmode_start \n\t"
17857d36db35SAvi Kivity 
17867d36db35SAvi Kivity 	".code16gcc \n\t"
17877d36db35SAvi Kivity 	);
1788