xref: /kvm-unit-tests/x86/realmode.c (revision d7903be60ba61792d7edb69126e82629ab43e60d)
1f366255fSPaolo Bonzini #ifndef USE_SERIAL
2f366255fSPaolo Bonzini #define USE_SERIAL
3f366255fSPaolo Bonzini #endif
4f366255fSPaolo Bonzini 
547086996SBill Wendling #define ARRAY_SIZE(_a) (sizeof(_a)/sizeof((_a)[0]))
647086996SBill Wendling 
77d36db35SAvi Kivity asm(".code16gcc");
87d36db35SAvi Kivity 
97d36db35SAvi Kivity typedef unsigned char u8;
107d36db35SAvi Kivity typedef unsigned short u16;
117d36db35SAvi Kivity typedef unsigned u32;
127d36db35SAvi Kivity typedef unsigned long long u64;
137d36db35SAvi Kivity 
14bd62e289SBill Wendling #ifndef NULL
15bd62e289SBill Wendling #define NULL ((void*)0)
16bd62e289SBill Wendling #endif
17bd62e289SBill Wendling 
182e3f9f1fSThomas Huth void realmode_start(void);
197d36db35SAvi Kivity void test_function(void);
207d36db35SAvi Kivity 
217d36db35SAvi Kivity asm(
227d36db35SAvi Kivity 	"test_function: \n\t"
237d36db35SAvi Kivity 	"mov $0x1234, %eax \n\t"
247d36db35SAvi Kivity 	"ret"
257d36db35SAvi Kivity    );
267d36db35SAvi Kivity 
277d36db35SAvi Kivity static int strlen(const char *str)
287d36db35SAvi Kivity {
297d36db35SAvi Kivity 	int n;
307d36db35SAvi Kivity 
317d36db35SAvi Kivity 	for (n = 0; *str; ++str)
327d36db35SAvi Kivity 		++n;
337d36db35SAvi Kivity 	return n;
347d36db35SAvi Kivity }
357d36db35SAvi Kivity 
36f366255fSPaolo Bonzini static void outb(u8 data, u16 port)
37f366255fSPaolo Bonzini {
38f366255fSPaolo Bonzini 	asm volatile("out %0, %1" : : "a"(data), "d"(port));
39f366255fSPaolo Bonzini }
40f366255fSPaolo Bonzini 
41f366255fSPaolo Bonzini #ifdef USE_SERIAL
42f366255fSPaolo Bonzini static int serial_iobase = 0x3f8;
43f366255fSPaolo Bonzini static int serial_inited = 0;
44f366255fSPaolo Bonzini 
45f366255fSPaolo Bonzini static u8 inb(u16 port)
46f366255fSPaolo Bonzini {
47f366255fSPaolo Bonzini 	u8 data;
48f366255fSPaolo Bonzini 	asm volatile("in %1, %0" : "=a"(data) : "d"(port));
49f366255fSPaolo Bonzini 	return data;
50f366255fSPaolo Bonzini }
51f366255fSPaolo Bonzini 
52f366255fSPaolo Bonzini static void serial_outb(char ch)
53f366255fSPaolo Bonzini {
54f366255fSPaolo Bonzini 	u8 lsr;
55f366255fSPaolo Bonzini 
56f366255fSPaolo Bonzini 	do {
57f366255fSPaolo Bonzini 		lsr = inb(serial_iobase + 0x05);
58f366255fSPaolo Bonzini 	} while (!(lsr & 0x20));
59f366255fSPaolo Bonzini 
60f366255fSPaolo Bonzini 	outb(ch, serial_iobase + 0x00);
61f366255fSPaolo Bonzini }
62f366255fSPaolo Bonzini 
63f366255fSPaolo Bonzini static void serial_init(void)
64f366255fSPaolo Bonzini {
65f366255fSPaolo Bonzini 	u8 lcr;
66f366255fSPaolo Bonzini 
67f366255fSPaolo Bonzini 	/* set DLAB */
68f366255fSPaolo Bonzini 	lcr = inb(serial_iobase + 0x03);
69f366255fSPaolo Bonzini 	lcr |= 0x80;
70f366255fSPaolo Bonzini 	outb(lcr, serial_iobase + 0x03);
71f366255fSPaolo Bonzini 
72f366255fSPaolo Bonzini 	/* set baud rate to 115200 */
73f366255fSPaolo Bonzini 	outb(0x01, serial_iobase + 0x00);
74f366255fSPaolo Bonzini 	outb(0x00, serial_iobase + 0x01);
75f366255fSPaolo Bonzini 
76f366255fSPaolo Bonzini 	/* clear DLAB */
77f366255fSPaolo Bonzini 	lcr = inb(serial_iobase + 0x03);
78f366255fSPaolo Bonzini 	lcr &= ~0x80;
79f366255fSPaolo Bonzini 	outb(lcr, serial_iobase + 0x03);
80f366255fSPaolo Bonzini }
81f366255fSPaolo Bonzini #endif
82f366255fSPaolo Bonzini 
837d36db35SAvi Kivity static void print_serial(const char *buf)
847d36db35SAvi Kivity {
857d36db35SAvi Kivity 	unsigned long len = strlen(buf);
86f366255fSPaolo Bonzini #ifdef USE_SERIAL
87f366255fSPaolo Bonzini 	unsigned long i;
88f366255fSPaolo Bonzini 	if (!serial_inited) {
89f366255fSPaolo Bonzini 	    serial_init();
90f366255fSPaolo Bonzini 	    serial_inited = 1;
91f366255fSPaolo Bonzini 	}
927d36db35SAvi Kivity 
93f366255fSPaolo Bonzini 	for (i = 0; i < len; i++) {
94f366255fSPaolo Bonzini 	    serial_outb(buf[i]);
95f366255fSPaolo Bonzini 	}
96f366255fSPaolo Bonzini #else
975edbb9aeSPaolo Bonzini 	asm volatile ("addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1));
98f366255fSPaolo Bonzini #endif
997d36db35SAvi Kivity }
1007d36db35SAvi Kivity 
101b5105e8bSPaolo Bonzini static void print_serial_u32(u32 value)
102b5105e8bSPaolo Bonzini {
103b5105e8bSPaolo Bonzini 	char n[12], *p;
104b5105e8bSPaolo Bonzini 	p = &n[11];
105b5105e8bSPaolo Bonzini 	*p = 0;
106b5105e8bSPaolo Bonzini 	do {
107b5105e8bSPaolo Bonzini 		*--p = '0' + (value % 10);
108b5105e8bSPaolo Bonzini 		value /= 10;
109b5105e8bSPaolo Bonzini 	} while (value > 0);
110b5105e8bSPaolo Bonzini 	print_serial(p);
111b5105e8bSPaolo Bonzini }
112b5105e8bSPaolo Bonzini 
113b393fe28SNadav Amit static int failed;
114b393fe28SNadav Amit 
1157d36db35SAvi Kivity static void exit(int code)
1167d36db35SAvi Kivity {
117f366255fSPaolo Bonzini 	outb(code, 0xf4);
1183b9b2d55SNadav Amit 
1193b9b2d55SNadav Amit 	while (1) {
1203b9b2d55SNadav Amit 		asm volatile("hlt" ::: "memory");
1213b9b2d55SNadav Amit 	}
1227d36db35SAvi Kivity }
1237d36db35SAvi Kivity 
1247d36db35SAvi Kivity struct regs {
1257d36db35SAvi Kivity 	u32 eax, ebx, ecx, edx;
1267d36db35SAvi Kivity 	u32 esi, edi, esp, ebp;
1277d36db35SAvi Kivity 	u32 eip, eflags;
1287d36db35SAvi Kivity };
1297d36db35SAvi Kivity 
130975ca087SPeter Feiner struct table_descr {
131975ca087SPeter Feiner 	u16 limit;
132975ca087SPeter Feiner 	void *base;
133975ca087SPeter Feiner } __attribute__((packed));
134975ca087SPeter Feiner 
1357d36db35SAvi Kivity static u64 gdt[] = {
1367d36db35SAvi Kivity 	0,
1377d36db35SAvi Kivity 	0x00cf9b000000ffffull, // flat 32-bit code segment
1387d36db35SAvi Kivity 	0x00cf93000000ffffull, // flat 32-bit data segment
1397d36db35SAvi Kivity };
1407d36db35SAvi Kivity 
141975ca087SPeter Feiner static struct table_descr gdt_descr = {
1427d36db35SAvi Kivity 	sizeof(gdt) - 1,
1437d36db35SAvi Kivity 	gdt,
1447d36db35SAvi Kivity };
1457d36db35SAvi Kivity 
146d4dc402cSAvi Kivity struct insn_desc {
147d4dc402cSAvi Kivity     u16 ptr;
148d4dc402cSAvi Kivity     u16 len;
149d4dc402cSAvi Kivity };
150d4dc402cSAvi Kivity 
151bd62e289SBill Wendling struct {
152bd62e289SBill Wendling 	u32 stack[128];
153bd62e289SBill Wendling 	char top[];
154bd62e289SBill Wendling } tmp_stack;
155bd62e289SBill Wendling 
15618253fdeSAvi Kivity static struct regs inregs, outregs;
15718253fdeSAvi Kivity 
158bd62e289SBill Wendling static inline void init_inregs(struct regs *regs)
159bd62e289SBill Wendling {
160bd62e289SBill Wendling 	inregs = (struct regs){ 0 };
161bd62e289SBill Wendling 	if (regs)
162bd62e289SBill Wendling 		inregs = *regs;
163bd62e289SBill Wendling 	if (!inregs.esp)
164bd62e289SBill Wendling 		inregs.esp = (unsigned long)&tmp_stack.top;
165bd62e289SBill Wendling }
166bd62e289SBill Wendling 
16718253fdeSAvi Kivity static void exec_in_big_real_mode(struct insn_desc *insn)
1687d36db35SAvi Kivity {
1697d36db35SAvi Kivity 	unsigned long tmp;
1707d36db35SAvi Kivity 	static struct regs save;
1717d36db35SAvi Kivity 	int i;
1727d36db35SAvi Kivity 	extern u8 test_insn[], test_insn_end[];
1737d36db35SAvi Kivity 
174d4dc402cSAvi Kivity 	for (i = 0; i < insn->len; ++i)
175d4dc402cSAvi Kivity 	    test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i];
1767d36db35SAvi Kivity 	for (; i < test_insn_end - test_insn; ++i)
1777d36db35SAvi Kivity 		test_insn[i] = 0x90; // nop
1787d36db35SAvi Kivity 
17918253fdeSAvi Kivity 	save = inregs;
1807d36db35SAvi Kivity 	asm volatile(
1817d36db35SAvi Kivity 		"lgdtl %[gdt_descr] \n\t"
1827d36db35SAvi Kivity 		"mov %%cr0, %[tmp] \n\t"
1837d36db35SAvi Kivity 		"or $1, %[tmp] \n\t"
1847d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
1857d36db35SAvi Kivity 		"mov %[bigseg], %%gs \n\t"
1867d36db35SAvi Kivity 		"and $-2, %[tmp] \n\t"
1877d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
1887d36db35SAvi Kivity 
189eb6687a2SBill Wendling 		/* Save ES, because it is clobbered by some tests. */
190eb6687a2SBill Wendling 		"pushw %%es \n\t"
191eb6687a2SBill Wendling 
19232001692SAvi Kivity 		"pushw %[save]+36; popfw \n\t"
1937d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
1947d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
1957d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
1967d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
1977d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
1987d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
1997d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
2007d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
2017d36db35SAvi Kivity 
2027d36db35SAvi Kivity 		"test_insn: . = . + 32\n\t"
2037d36db35SAvi Kivity 		"test_insn_end: \n\t"
2047d36db35SAvi Kivity 
2057d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
2067d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
2077d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
2087d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
2097d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
2107d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
2117d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
2127d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
2137d36db35SAvi Kivity 
2147d36db35SAvi Kivity 		/* Save EFLAGS in outregs*/
2157d36db35SAvi Kivity 		"pushfl \n\t"
2167d36db35SAvi Kivity 		"popl %[save]+36 \n\t"
2177d36db35SAvi Kivity 
218eb6687a2SBill Wendling 		/* Restore ES for future rep string operations. */
219eb6687a2SBill Wendling 		"popw %%es \n\t"
220eb6687a2SBill Wendling 
2215edbb9aeSPaolo Bonzini 		/* Restore DF for the harness code */
2225edbb9aeSPaolo Bonzini 		"cld\n\t"
2237d36db35SAvi Kivity 		"xor %[tmp], %[tmp] \n\t"
2247d36db35SAvi Kivity 		"mov %[tmp], %%gs \n\t"
2257d36db35SAvi Kivity 		: [tmp]"=&r"(tmp), [save]"+m"(save)
2267d36db35SAvi Kivity 		: [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16)
2277d36db35SAvi Kivity 		: "cc", "memory"
2287d36db35SAvi Kivity 		);
22918253fdeSAvi Kivity 	outregs = save;
2307d36db35SAvi Kivity }
2317d36db35SAvi Kivity 
2327d36db35SAvi Kivity #define R_AX 1
2337d36db35SAvi Kivity #define R_BX 2
2347d36db35SAvi Kivity #define R_CX 4
2357d36db35SAvi Kivity #define R_DX 8
2367d36db35SAvi Kivity #define R_SI 16
2377d36db35SAvi Kivity #define R_DI 32
2387d36db35SAvi Kivity #define R_SP 64
2397d36db35SAvi Kivity #define R_BP 128
2407d36db35SAvi Kivity 
2412e3f9f1fSThomas Huth static int regs_equal(int ignore)
2427d36db35SAvi Kivity {
24318253fdeSAvi Kivity 	const u32 *p1 = &inregs.eax, *p2 = &outregs.eax;  // yuck
2447d36db35SAvi Kivity 	int i;
2457d36db35SAvi Kivity 
2467d36db35SAvi Kivity 	for (i = 0; i < 8; ++i)
2477d36db35SAvi Kivity 		if (!(ignore & (1 << i)) && p1[i] != p2[i])
2487d36db35SAvi Kivity 			return 0;
2497d36db35SAvi Kivity 	return 1;
2507d36db35SAvi Kivity }
2517d36db35SAvi Kivity 
2526055ea1fSAvi Kivity static void report(const char *name, u16 regs_ignore, _Bool ok)
25381050840SAvi Kivity {
2546055ea1fSAvi Kivity     if (!regs_equal(regs_ignore)) {
2556055ea1fSAvi Kivity 	ok = 0;
2566055ea1fSAvi Kivity     }
25781050840SAvi Kivity     print_serial(ok ? "PASS: " : "FAIL: ");
25881050840SAvi Kivity     print_serial(name);
25981050840SAvi Kivity     print_serial("\n");
260b393fe28SNadav Amit     if (!ok)
261b393fe28SNadav Amit 	failed = 1;
26281050840SAvi Kivity }
26381050840SAvi Kivity 
2647d36db35SAvi Kivity #define MK_INSN(name, str)				\
2657d36db35SAvi Kivity     asm (						\
266d4dc402cSAvi Kivity 	 ".pushsection .data.insn  \n\t"		\
267d4dc402cSAvi Kivity 	 "insn_" #name ": \n\t"				\
268d4dc402cSAvi Kivity 	 ".word 1001f, 1002f - 1001f \n\t"		\
269d4dc402cSAvi Kivity 	 ".popsection \n\t"				\
270d4dc402cSAvi Kivity 	 ".pushsection .text.insn, \"ax\" \n\t"		\
271d4dc402cSAvi Kivity 	 "1001: \n\t"					\
272d4dc402cSAvi Kivity 	 "insn_code_" #name ": " str " \n\t"		\
273d4dc402cSAvi Kivity 	 "1002: \n\t"					\
274d4dc402cSAvi Kivity 	 ".popsection"					\
2757d36db35SAvi Kivity     );							\
276d4dc402cSAvi Kivity     extern struct insn_desc insn_##name;
2777d36db35SAvi Kivity 
2782e3f9f1fSThomas Huth static void test_xchg(void)
2797d36db35SAvi Kivity {
2807d36db35SAvi Kivity 	MK_INSN(xchg_test1, "xchg %eax,%eax\n\t");
2817d36db35SAvi Kivity 	MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t");
2827d36db35SAvi Kivity 	MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t");
2837d36db35SAvi Kivity 	MK_INSN(xchg_test4, "xchg %eax,%edx\n\t");
2847d36db35SAvi Kivity 	MK_INSN(xchg_test5, "xchg %eax,%esi\n\t");
2857d36db35SAvi Kivity 	MK_INSN(xchg_test6, "xchg %eax,%edi\n\t");
2867d36db35SAvi Kivity 	MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t");
2877d36db35SAvi Kivity 	MK_INSN(xchg_test8, "xchg %eax,%esp\n\t");
2887d36db35SAvi Kivity 
28918253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7};
2907d36db35SAvi Kivity 
29118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test1);
2926055ea1fSAvi Kivity 	report("xchg 1", 0, 1);
29318253fdeSAvi Kivity 
29418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test2);
2956055ea1fSAvi Kivity 	report("xchg 2", R_AX | R_BX,
2966055ea1fSAvi Kivity 	       outregs.eax == inregs.ebx && outregs.ebx == inregs.eax);
2977d36db35SAvi Kivity 
29818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test3);
2996055ea1fSAvi Kivity 	report("xchg 3", R_AX | R_CX,
3006055ea1fSAvi Kivity 	       outregs.eax == inregs.ecx && outregs.ecx == inregs.eax);
3017d36db35SAvi Kivity 
30218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test4);
3036055ea1fSAvi Kivity 	report("xchg 4", R_AX | R_DX,
3046055ea1fSAvi Kivity 	       outregs.eax == inregs.edx && outregs.edx == inregs.eax);
3057d36db35SAvi Kivity 
30618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test5);
3076055ea1fSAvi Kivity 	report("xchg 5", R_AX | R_SI,
3086055ea1fSAvi Kivity 	       outregs.eax == inregs.esi && outregs.esi == inregs.eax);
3097d36db35SAvi Kivity 
31018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test6);
3116055ea1fSAvi Kivity 	report("xchg 6", R_AX | R_DI,
3126055ea1fSAvi Kivity 	       outregs.eax == inregs.edi && outregs.edi == inregs.eax);
3137d36db35SAvi Kivity 
31418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test7);
3156055ea1fSAvi Kivity 	report("xchg 7", R_AX | R_BP,
3166055ea1fSAvi Kivity 	       outregs.eax == inregs.ebp && outregs.ebp == inregs.eax);
3177d36db35SAvi Kivity 
31818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test8);
3196055ea1fSAvi Kivity 	report("xchg 8", R_AX | R_SP,
3206055ea1fSAvi Kivity 	       outregs.eax == inregs.esp && outregs.esp == inregs.eax);
3217d36db35SAvi Kivity }
3227d36db35SAvi Kivity 
3232e3f9f1fSThomas Huth static void test_shld(void)
3247d36db35SAvi Kivity {
3257d36db35SAvi Kivity 	MK_INSN(shld_test, "shld $8,%edx,%eax\n\t");
3267d36db35SAvi Kivity 
327bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0xbe, .edx = 0xef000000 });
328bd62e289SBill Wendling 
32918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_shld_test);
3306055ea1fSAvi Kivity 	report("shld", ~0, outregs.eax == 0xbeef);
3317d36db35SAvi Kivity }
3327d36db35SAvi Kivity 
3332e3f9f1fSThomas Huth static void test_mov_imm(void)
3347d36db35SAvi Kivity {
3357d36db35SAvi Kivity 	MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax");
3367d36db35SAvi Kivity 	MK_INSN(mov_r16_imm_1, "mov $1234, %ax");
3377d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_1, "mov $0x12, %ah");
3387d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_2, "mov $0x34, %al");
3397d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t");
3407d36db35SAvi Kivity 
341bd62e289SBill Wendling 	init_inregs(NULL);
34218253fdeSAvi Kivity 
34318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r16_imm_1);
3446055ea1fSAvi Kivity 	report("mov 1", R_AX, outregs.eax == 1234);
3457d36db35SAvi Kivity 
3467d36db35SAvi Kivity 	/* test mov $imm, %eax */
34718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r32_imm_1);
3486055ea1fSAvi Kivity 	report("mov 2", R_AX, outregs.eax == 1234567890);
3497d36db35SAvi Kivity 
3507d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
35118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_1);
3526055ea1fSAvi Kivity 	report("mov 3", R_AX, outregs.eax == 0x1200);
3537d36db35SAvi Kivity 
35418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_2);
3556055ea1fSAvi Kivity 	report("mov 4", R_AX, outregs.eax == 0x34);
3567d36db35SAvi Kivity 
35718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_3);
3586055ea1fSAvi Kivity 	report("mov 5", R_AX, outregs.eax == 0x1234);
3597d36db35SAvi Kivity }
3607d36db35SAvi Kivity 
3612e3f9f1fSThomas Huth static void test_sub_imm(void)
3627d36db35SAvi Kivity {
3637d36db35SAvi Kivity 	MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t");
3647d36db35SAvi Kivity 	MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t");
3657d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t");
3667d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t");
3677d36db35SAvi Kivity 
368bd62e289SBill Wendling 	init_inregs(NULL);
36918253fdeSAvi Kivity 
37018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r16_imm_1);
3716055ea1fSAvi Kivity 	report("sub 1", R_AX, outregs.eax == 1224);
3727d36db35SAvi Kivity 
3737d36db35SAvi Kivity 	/* test mov $imm, %eax */
37418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r32_imm_1);
3756055ea1fSAvi Kivity 	report("sub 2", R_AX, outregs.eax == 1234567880);
3767d36db35SAvi Kivity 
3777d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
37818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_1);
3796055ea1fSAvi Kivity 	report("sub 3", R_AX, outregs.eax == 0x0200);
3807d36db35SAvi Kivity 
38118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_2);
3826055ea1fSAvi Kivity 	report("sub 4", R_AX, outregs.eax == 0x24);
3837d36db35SAvi Kivity }
3847d36db35SAvi Kivity 
3852e3f9f1fSThomas Huth static void test_xor_imm(void)
3867d36db35SAvi Kivity {
3877d36db35SAvi Kivity 	MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t");
3887d36db35SAvi Kivity 	MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t");
3897d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t");
3907d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t");
3917d36db35SAvi Kivity 
392bd62e289SBill Wendling 	init_inregs(NULL);
39318253fdeSAvi Kivity 
39418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r16_imm_1);
3956055ea1fSAvi Kivity 	report("xor 1", R_AX, outregs.eax == 0);
3967d36db35SAvi Kivity 
3977d36db35SAvi Kivity 	/* test mov $imm, %eax */
39818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r32_imm_1);
3996055ea1fSAvi Kivity 	report("xor 2", R_AX, outregs.eax == 0);
4007d36db35SAvi Kivity 
4017d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
40218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_1);
4036055ea1fSAvi Kivity 	report("xor 3", R_AX, outregs.eax == 0);
4047d36db35SAvi Kivity 
40518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_2);
4066055ea1fSAvi Kivity 	report("xor 4", R_AX, outregs.eax == 0);
4077d36db35SAvi Kivity }
4087d36db35SAvi Kivity 
4092e3f9f1fSThomas Huth static void test_cmp_imm(void)
4107d36db35SAvi Kivity {
4117d36db35SAvi Kivity 	MK_INSN(cmp_test1, "mov $0x34, %al\n\t"
4127d36db35SAvi Kivity 			   "cmp $0x34, %al\n\t");
4137d36db35SAvi Kivity 	MK_INSN(cmp_test2, "mov $0x34, %al\n\t"
4147d36db35SAvi Kivity 			   "cmp $0x39, %al\n\t");
4157d36db35SAvi Kivity 	MK_INSN(cmp_test3, "mov $0x34, %al\n\t"
4167d36db35SAvi Kivity 			   "cmp $0x24, %al\n\t");
4177d36db35SAvi Kivity 
418bd62e289SBill Wendling 	init_inregs(NULL);
41918253fdeSAvi Kivity 
4207d36db35SAvi Kivity 	/* test cmp imm8 with AL */
4217d36db35SAvi Kivity 	/* ZF: (bit 6) Zero Flag becomes 1 if an operation results
4227d36db35SAvi Kivity 	 * in a 0 writeback, or 0 register
4237d36db35SAvi Kivity 	 */
42418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test1);
4256055ea1fSAvi Kivity 	report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6));
4267d36db35SAvi Kivity 
42718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test2);
4286055ea1fSAvi Kivity 	report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0);
4297d36db35SAvi Kivity 
43018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test3);
4316055ea1fSAvi Kivity 	report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0);
4327d36db35SAvi Kivity }
4337d36db35SAvi Kivity 
4342e3f9f1fSThomas Huth static void test_add_imm(void)
4357d36db35SAvi Kivity {
4367d36db35SAvi Kivity 	MK_INSN(add_test1, "mov $0x43211234, %eax \n\t"
4377d36db35SAvi Kivity 			   "add $0x12344321, %eax \n\t");
4387d36db35SAvi Kivity 	MK_INSN(add_test2, "mov $0x12, %eax \n\t"
4397d36db35SAvi Kivity 			   "add $0x21, %al\n\t");
4407d36db35SAvi Kivity 
441bd62e289SBill Wendling 	init_inregs(NULL);
44218253fdeSAvi Kivity 
44318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test1);
4446055ea1fSAvi Kivity 	report("add 1", ~0, outregs.eax == 0x55555555);
4457d36db35SAvi Kivity 
44618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test2);
4476055ea1fSAvi Kivity 	report("add 2", ~0, outregs.eax == 0x33);
4487d36db35SAvi Kivity }
4497d36db35SAvi Kivity 
4502e3f9f1fSThomas Huth static void test_eflags_insn(void)
4517d36db35SAvi Kivity {
4527d36db35SAvi Kivity 	MK_INSN(clc, "clc");
453b3261e48SMohammed Gamal 	MK_INSN(stc, "stc");
4547d36db35SAvi Kivity 	MK_INSN(cli, "cli");
4557d36db35SAvi Kivity 	MK_INSN(sti, "sti");
4567d36db35SAvi Kivity 	MK_INSN(cld, "cld");
4577d36db35SAvi Kivity 	MK_INSN(std, "std");
4587d36db35SAvi Kivity 
459bd62e289SBill Wendling 	init_inregs(NULL);
46018253fdeSAvi Kivity 
46118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_clc);
4626055ea1fSAvi Kivity 	report("clc", ~0, (outregs.eflags & 1) == 0);
4637d36db35SAvi Kivity 
46418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_stc);
4656055ea1fSAvi Kivity 	report("stc", ~0, (outregs.eflags & 1) == 1);
466b3261e48SMohammed Gamal 
46718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cli);
4686055ea1fSAvi Kivity 	report("cli", ~0, !(outregs.eflags & (1 << 9)));
4697d36db35SAvi Kivity 
47018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sti);
4716055ea1fSAvi Kivity 	report("sti", ~0, outregs.eflags & (1 << 9));
4727d36db35SAvi Kivity 
47318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cld);
4746055ea1fSAvi Kivity 	report("cld", ~0, !(outregs.eflags & (1 << 10)));
4757d36db35SAvi Kivity 
47618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_std);
4776055ea1fSAvi Kivity 	report("std", ~0, (outregs.eflags & (1 << 10)));
4787d36db35SAvi Kivity }
4797d36db35SAvi Kivity 
4802e3f9f1fSThomas Huth static void test_io(void)
4817d36db35SAvi Kivity {
4827d36db35SAvi Kivity 	MK_INSN(io_test1, "mov $0xff, %al \n\t"
4837d36db35SAvi Kivity 		          "out %al, $0xe0 \n\t"
4847d36db35SAvi Kivity 		          "mov $0x00, %al \n\t"
4857d36db35SAvi Kivity 			  "in $0xe0, %al \n\t");
4867d36db35SAvi Kivity 	MK_INSN(io_test2, "mov $0xffff, %ax \n\t"
4877d36db35SAvi Kivity 			  "out %ax, $0xe0 \n\t"
4887d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
4897d36db35SAvi Kivity 			  "in $0xe0, %ax \n\t");
4907d36db35SAvi Kivity 	MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t"
4917d36db35SAvi Kivity 			  "out %eax, $0xe0 \n\t"
4927d36db35SAvi Kivity 			  "mov $0x000000, %eax \n\t"
4937d36db35SAvi Kivity 			  "in $0xe0, %eax \n\t");
4947d36db35SAvi Kivity 	MK_INSN(io_test4, "mov $0xe0, %dx \n\t"
4957d36db35SAvi Kivity 			  "mov $0xff, %al \n\t"
4967d36db35SAvi Kivity 			  "out %al, %dx \n\t"
4977d36db35SAvi Kivity 			  "mov $0x00, %al \n\t"
4987d36db35SAvi Kivity 			  "in %dx, %al \n\t");
4997d36db35SAvi Kivity 	MK_INSN(io_test5, "mov $0xe0, %dx \n\t"
5007d36db35SAvi Kivity 			  "mov $0xffff, %ax \n\t"
5017d36db35SAvi Kivity 			  "out %ax, %dx \n\t"
5027d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
5037d36db35SAvi Kivity 			  "in %dx, %ax \n\t");
5047d36db35SAvi Kivity 	MK_INSN(io_test6, "mov $0xe0, %dx \n\t"
5057d36db35SAvi Kivity 			  "mov $0xffffffff, %eax \n\t"
5067d36db35SAvi Kivity 			  "out %eax, %dx \n\t"
5077d36db35SAvi Kivity 			  "mov $0x00000000, %eax \n\t"
5087d36db35SAvi Kivity 			  "in %dx, %eax \n\t");
5097d36db35SAvi Kivity 
510bd62e289SBill Wendling 	init_inregs(NULL);
51118253fdeSAvi Kivity 
51218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test1);
5136055ea1fSAvi Kivity 	report("pio 1", R_AX, outregs.eax == 0xff);
5147d36db35SAvi Kivity 
51518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test2);
5166055ea1fSAvi Kivity 	report("pio 2", R_AX, outregs.eax == 0xffff);
5177d36db35SAvi Kivity 
51818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test3);
5196055ea1fSAvi Kivity 	report("pio 3", R_AX, outregs.eax == 0xffffffff);
5207d36db35SAvi Kivity 
52118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test4);
5226055ea1fSAvi Kivity 	report("pio 4", R_AX|R_DX, outregs.eax == 0xff);
5237d36db35SAvi Kivity 
52418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test5);
5256055ea1fSAvi Kivity 	report("pio 5", R_AX|R_DX, outregs.eax == 0xffff);
5267d36db35SAvi Kivity 
52718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test6);
5286055ea1fSAvi Kivity 	report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff);
5297d36db35SAvi Kivity }
5307d36db35SAvi Kivity 
531c0b7268dSAvi Kivity asm ("retf: lretw");
5322e3f9f1fSThomas Huth extern void retf(void);
533c0b7268dSAvi Kivity 
5344f66bc86SBruce Rogers asm ("retf_imm: lretw $10");
5352e3f9f1fSThomas Huth extern void retf_imm(void);
5364f66bc86SBruce Rogers 
5372e3f9f1fSThomas Huth static void test_call(void)
5387d36db35SAvi Kivity {
539c0b7268dSAvi Kivity 	u32 addr;
5407d36db35SAvi Kivity 
5417d36db35SAvi Kivity 	MK_INSN(call1, "mov $test_function, %eax \n\t"
5427d36db35SAvi Kivity 		       "call *%eax\n\t");
5437d36db35SAvi Kivity 	MK_INSN(call_near1, "jmp 2f\n\t"
5447d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5457d36db35SAvi Kivity 			    "ret\n\t"
5467d36db35SAvi Kivity 			    "2: call 1b\t");
5477d36db35SAvi Kivity 	MK_INSN(call_near2, "call 1f\n\t"
5487d36db35SAvi Kivity 			    "jmp 2f\n\t"
5497d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5507d36db35SAvi Kivity 			    "ret\n\t"
5517d36db35SAvi Kivity 			    "2:\t");
552c0b7268dSAvi Kivity 	MK_INSN(call_far1,  "lcallw *(%ebx)\n\t");
553556d2680SWei Yongjun 	MK_INSN(call_far2,  "lcallw $0, $retf\n\t");
554c6061817SAvi Kivity 	MK_INSN(ret_imm,    "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b");
5554f66bc86SBruce Rogers 	MK_INSN(retf_imm,   "sub $10, %sp; lcallw $0, $retf_imm");
5567d36db35SAvi Kivity 
557bd62e289SBill Wendling 	init_inregs(NULL);
558bd62e289SBill Wendling 
55918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call1);
5606055ea1fSAvi Kivity 	report("call 1", R_AX, outregs.eax == 0x1234);
5617d36db35SAvi Kivity 
56218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near1);
5636055ea1fSAvi Kivity 	report("call near 1", R_AX, outregs.eax == 0x1234);
5647d36db35SAvi Kivity 
56518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near2);
5666055ea1fSAvi Kivity 	report("call near 2", R_AX, outregs.eax == 0x1234);
567c0b7268dSAvi Kivity 
568c0b7268dSAvi Kivity 	addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f);
569c0b7268dSAvi Kivity 	inregs.ebx = (unsigned)&addr;
57018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_far1);
5716055ea1fSAvi Kivity 	report("call far 1", 0, 1);
572c6061817SAvi Kivity 
573556d2680SWei Yongjun 	exec_in_big_real_mode(&insn_call_far2);
574556d2680SWei Yongjun 	report("call far 2", 0, 1);
575556d2680SWei Yongjun 
57618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_ret_imm);
5776055ea1fSAvi Kivity 	report("ret imm 1", 0, 1);
5784f66bc86SBruce Rogers 
5794f66bc86SBruce Rogers 	exec_in_big_real_mode(&insn_retf_imm);
5804f66bc86SBruce Rogers 	report("retf imm 1", 0, 1);
5817d36db35SAvi Kivity }
5827d36db35SAvi Kivity 
5832e3f9f1fSThomas Huth static void test_jcc_short(void)
5847d36db35SAvi Kivity {
5857d36db35SAvi Kivity 	MK_INSN(jnz_short1, "jnz 1f\n\t"
5867d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
5877d36db35SAvi Kivity 		            "1:\n\t");
5887d36db35SAvi Kivity 	MK_INSN(jnz_short2, "1:\n\t"
5897d36db35SAvi Kivity 			    "cmp $0x1234, %eax\n\t"
5907d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
5917d36db35SAvi Kivity 		            "jnz 1b\n\t");
5927d36db35SAvi Kivity 	MK_INSN(jmp_short1, "jmp 1f\n\t"
5937d36db35SAvi Kivity 		      "mov $0x1234, %eax\n\t"
5947d36db35SAvi Kivity 		      "1:\n\t");
5957d36db35SAvi Kivity 
596bd62e289SBill Wendling 	init_inregs(NULL);
5977d36db35SAvi Kivity 
59818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short1);
5996055ea1fSAvi Kivity 	report("jnz short 1", ~0, 1);
60018253fdeSAvi Kivity 
60118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short2);
6026055ea1fSAvi Kivity 	report("jnz short 2", R_AX, (outregs.eflags & (1 << 6)));
6037d36db35SAvi Kivity 
60418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_short1);
6056055ea1fSAvi Kivity 	report("jmp short 1", ~0, 1);
6067d36db35SAvi Kivity }
6077d36db35SAvi Kivity 
6082e3f9f1fSThomas Huth static void test_jcc_near(void)
6097d36db35SAvi Kivity {
6107d36db35SAvi Kivity 	/* encode near jmp manually. gas will not do it if offsets < 127 byte */
6117d36db35SAvi Kivity 	MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t"
6127d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
6137d36db35SAvi Kivity 	MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t"
6147d36db35SAvi Kivity 			   "mov $0x1234, %eax\n\t"
6157d36db35SAvi Kivity 		           ".byte 0x0f, 0x85, 0xf0, 0xff\n\t");
6167d36db35SAvi Kivity 	MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t"
6177d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
6187d36db35SAvi Kivity 
619bd62e289SBill Wendling 	init_inregs(NULL);
6207d36db35SAvi Kivity 
62118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near1);
6226055ea1fSAvi Kivity 	report("jnz near 1", 0, 1);
62318253fdeSAvi Kivity 
62418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near2);
6256055ea1fSAvi Kivity 	report("jnz near 2", R_AX, outregs.eflags & (1 << 6));
6267d36db35SAvi Kivity 
62718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_near1);
6286055ea1fSAvi Kivity 	report("jmp near 1", 0, 1);
6297d36db35SAvi Kivity }
6307d36db35SAvi Kivity 
6312e3f9f1fSThomas Huth static void test_long_jmp(void)
6327d36db35SAvi Kivity {
6337d36db35SAvi Kivity 	MK_INSN(long_jmp, "call 1f\n\t"
6347d36db35SAvi Kivity 			  "jmp 2f\n\t"
6357d36db35SAvi Kivity 			  "1: jmp $0, $test_function\n\t"
6367d36db35SAvi Kivity 		          "2:\n\t");
637bd62e289SBill Wendling 
638bd62e289SBill Wendling 	init_inregs(NULL);
639bd62e289SBill Wendling 
64018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_long_jmp);
6416055ea1fSAvi Kivity 	report("jmp far 1", R_AX, outregs.eax == 0x1234);
6427d36db35SAvi Kivity }
643fa74f8a6SMohammed Gamal 
6442e3f9f1fSThomas Huth static void test_push_pop(void)
6457d36db35SAvi Kivity {
6467d36db35SAvi Kivity 	MK_INSN(push32, "mov $0x12345678, %eax\n\t"
6477d36db35SAvi Kivity 			"push %eax\n\t"
6487d36db35SAvi Kivity 			"pop %ebx\n\t");
6497d36db35SAvi Kivity 	MK_INSN(push16, "mov $0x1234, %ax\n\t"
6507d36db35SAvi Kivity 			"push %ax\n\t"
6517d36db35SAvi Kivity 			"pop %bx\n\t");
6527d36db35SAvi Kivity 
6537d36db35SAvi Kivity 	MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten
6547d36db35SAvi Kivity 			 "mov $0x123, %ax\n\t"
6557d36db35SAvi Kivity 			 "mov %ax, %es\n\t"
656231b4c3bSRoman Bolshakov 			 "pushw %es\n\t"
6577d36db35SAvi Kivity 			 "pop %bx \n\t"
6587d36db35SAvi Kivity 			 );
6597d36db35SAvi Kivity 	MK_INSN(pop_es, "push %ax\n\t"
660231b4c3bSRoman Bolshakov 			"popw %es\n\t"
6617d36db35SAvi Kivity 			"mov %es, %bx\n\t"
6627d36db35SAvi Kivity 			);
663231b4c3bSRoman Bolshakov 	MK_INSN(push_pop_ss, "pushw %ss\n\t"
6647d36db35SAvi Kivity 			     "pushw %ax\n\t"
6657d36db35SAvi Kivity 			     "popw %ss\n\t"
6667d36db35SAvi Kivity 			     "mov %ss, %bx\n\t"
667231b4c3bSRoman Bolshakov 			     "popw %ss\n\t"
6687d36db35SAvi Kivity 			);
669231b4c3bSRoman Bolshakov 	MK_INSN(push_pop_fs, "pushl %fs\n\t"
6707d36db35SAvi Kivity 			     "pushl %eax\n\t"
6717d36db35SAvi Kivity 			     "popl %fs\n\t"
6727d36db35SAvi Kivity 			     "mov %fs, %ebx\n\t"
673231b4c3bSRoman Bolshakov 			     "popl %fs\n\t"
6747d36db35SAvi Kivity 			);
67509b657b6SAvi Kivity 	MK_INSN(push_pop_high_esp_bits,
67609b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
67709b657b6SAvi Kivity 		"push %ax; \n\t"
67809b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
67909b657b6SAvi Kivity 		"pop %bx");
6807d36db35SAvi Kivity 
681bd62e289SBill Wendling 	init_inregs(NULL);
68218253fdeSAvi Kivity 
68318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push32);
6846055ea1fSAvi Kivity 	report("push/pop 1", R_AX|R_BX,
6856055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x12345678);
6867d36db35SAvi Kivity 
68718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push16);
6886055ea1fSAvi Kivity 	report("push/pop 2", R_AX|R_BX,
6896055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x1234);
6907d36db35SAvi Kivity 
69118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_es);
6926055ea1fSAvi Kivity 	report("push/pop 3", R_AX|R_BX,
6936055ea1fSAvi Kivity 	       outregs.ebx == outregs.eax && outregs.eax == 0x123);
6947d36db35SAvi Kivity 
69518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pop_es);
6966055ea1fSAvi Kivity 	report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax);
6977d36db35SAvi Kivity 
69818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_ss);
6996055ea1fSAvi Kivity 	report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax);
7007d36db35SAvi Kivity 
70118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_fs);
7026055ea1fSAvi Kivity 	report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax);
70309b657b6SAvi Kivity 
70409b657b6SAvi Kivity 	inregs.eax = 0x9977;
70509b657b6SAvi Kivity 	inregs.ebx = 0x7799;
70609b657b6SAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_high_esp_bits);
70709b657b6SAvi Kivity 	report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977);
7087d36db35SAvi Kivity }
7097d36db35SAvi Kivity 
7102e3f9f1fSThomas Huth static void test_null(void)
7117d36db35SAvi Kivity {
712d4dc402cSAvi Kivity 	MK_INSN(null, "");
713d4dc402cSAvi Kivity 
714bd62e289SBill Wendling 	init_inregs(NULL);
71518253fdeSAvi Kivity 
71618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_null);
7176055ea1fSAvi Kivity 	report("null", 0, 1);
7187d36db35SAvi Kivity }
7197d36db35SAvi Kivity 
7202e3f9f1fSThomas Huth static void test_pusha_popa(void)
7217d36db35SAvi Kivity {
7227d36db35SAvi Kivity 	MK_INSN(pusha, "pusha\n\t"
7237d36db35SAvi Kivity 		       "pop %edi\n\t"
7247d36db35SAvi Kivity 		       "pop %esi\n\t"
7257d36db35SAvi Kivity 		       "pop %ebp\n\t"
7267d36db35SAvi Kivity 		       "add $4, %esp\n\t"
7277d36db35SAvi Kivity 		       "pop %ebx\n\t"
7287d36db35SAvi Kivity 		       "pop %edx\n\t"
7297d36db35SAvi Kivity 		       "pop %ecx\n\t"
7307d36db35SAvi Kivity 		       "pop %eax\n\t"
7317d36db35SAvi Kivity 		       );
7327d36db35SAvi Kivity 
7337d36db35SAvi Kivity 	MK_INSN(popa, "push %eax\n\t"
7347d36db35SAvi Kivity 		      "push %ecx\n\t"
7357d36db35SAvi Kivity 		      "push %edx\n\t"
7367d36db35SAvi Kivity 		      "push %ebx\n\t"
7377d36db35SAvi Kivity 		      "push %esp\n\t"
7387d36db35SAvi Kivity 		      "push %ebp\n\t"
7397d36db35SAvi Kivity 		      "push %esi\n\t"
7407d36db35SAvi Kivity 		      "push %edi\n\t"
7417d36db35SAvi Kivity 		      "popa\n\t"
7427d36db35SAvi Kivity 		      );
7437d36db35SAvi Kivity 
744bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6 });
7457d36db35SAvi Kivity 
74618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pusha);
7476055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
74818253fdeSAvi Kivity 
74918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_popa);
7506055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
7517d36db35SAvi Kivity }
7527d36db35SAvi Kivity 
7532e3f9f1fSThomas Huth static void test_iret(void)
7547d36db35SAvi Kivity {
7557d36db35SAvi Kivity 	MK_INSN(iret32, "pushf\n\t"
7567d36db35SAvi Kivity 			"pushl %cs\n\t"
7577d36db35SAvi Kivity 			"call 1f\n\t" /* a near call will push eip onto the stack */
7587d36db35SAvi Kivity 			"jmp 2f\n\t"
759231b4c3bSRoman Bolshakov 			"1: iretl\n\t"
7607d36db35SAvi Kivity 			"2:\n\t"
7617d36db35SAvi Kivity 		     );
7627d36db35SAvi Kivity 
7637d36db35SAvi Kivity 	MK_INSN(iret16, "pushfw\n\t"
7647d36db35SAvi Kivity 			"pushw %cs\n\t"
7657d36db35SAvi Kivity 			"callw 1f\n\t"
7667d36db35SAvi Kivity 			"jmp 2f\n\t"
7677d36db35SAvi Kivity 			"1: iretw\n\t"
7687d36db35SAvi Kivity 			"2:\n\t");
7697d36db35SAvi Kivity 
7707d36db35SAvi Kivity 	MK_INSN(iret_flags32, "pushfl\n\t"
7717d36db35SAvi Kivity 			      "popl %eax\n\t"
7727d36db35SAvi Kivity 			      "andl $~0x2, %eax\n\t"
773964942e8SNadav Amit 			      "orl $0xffc18028, %eax\n\t"
7747d36db35SAvi Kivity 			      "pushl %eax\n\t"
7757d36db35SAvi Kivity 			      "pushl %cs\n\t"
7767d36db35SAvi Kivity 			      "call 1f\n\t"
7777d36db35SAvi Kivity 			      "jmp 2f\n\t"
778231b4c3bSRoman Bolshakov 			      "1: iretl\n\t"
7797d36db35SAvi Kivity 			      "2:\n\t");
7807d36db35SAvi Kivity 
7817d36db35SAvi Kivity 	MK_INSN(iret_flags16, "pushfw\n\t"
7827d36db35SAvi Kivity 			      "popw %ax\n\t"
7837d36db35SAvi Kivity 			      "and $~0x2, %ax\n\t"
7847d36db35SAvi Kivity 			      "or $0x8028, %ax\n\t"
7857d36db35SAvi Kivity 			      "pushw %ax\n\t"
7867d36db35SAvi Kivity 			      "pushw %cs\n\t"
7877d36db35SAvi Kivity 			      "callw 1f\n\t"
7887d36db35SAvi Kivity 			      "jmp 2f\n\t"
7897d36db35SAvi Kivity 			      "1: iretw\n\t"
7907d36db35SAvi Kivity 			      "2:\n\t");
7917d36db35SAvi Kivity 
792bd62e289SBill Wendling 	init_inregs(NULL);
7937d36db35SAvi Kivity 
79418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret32);
7956055ea1fSAvi Kivity 	report("iret 1", 0, 1);
7967d36db35SAvi Kivity 
79718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret16);
7986055ea1fSAvi Kivity 	report("iret 2", 0, 1);
7997d36db35SAvi Kivity 
80018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags32);
8016055ea1fSAvi Kivity 	report("iret 3", R_AX, 1);
802964942e8SNadav Amit 	report("rflags.rf", ~0, !(outregs.eflags & (1 << 16)));
80318253fdeSAvi Kivity 
80418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags16);
8056055ea1fSAvi Kivity 	report("iret 4", R_AX, 1);
8067d36db35SAvi Kivity }
8077d36db35SAvi Kivity 
8082e3f9f1fSThomas Huth static void test_int(void)
80996b9ca1eSMohammed Gamal {
810bd62e289SBill Wendling 	init_inregs(NULL);
81196b9ca1eSMohammed Gamal 
81296b9ca1eSMohammed Gamal 	*(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */
81396b9ca1eSMohammed Gamal 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
81496b9ca1eSMohammed Gamal 
81596b9ca1eSMohammed Gamal 	MK_INSN(int11, "int $0x11\n\t");
81696b9ca1eSMohammed Gamal 
81718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_int11);
8186055ea1fSAvi Kivity 	report("int 1", 0, 1);
81996b9ca1eSMohammed Gamal }
82096b9ca1eSMohammed Gamal 
8218202cf84SRoman Bolshakov static void test_sti_inhibit(void)
8228202cf84SRoman Bolshakov {
8238202cf84SRoman Bolshakov 	init_inregs(NULL);
8248202cf84SRoman Bolshakov 
8258202cf84SRoman Bolshakov 	*(u32 *)(0x73 * 4) = 0x1000; /* Store IRQ 11 handler in the IDT */
8268202cf84SRoman Bolshakov 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
8278202cf84SRoman Bolshakov 
8288202cf84SRoman Bolshakov 	MK_INSN(sti_inhibit, "cli\n\t"
8298202cf84SRoman Bolshakov 			     "movw $0x200b, %dx\n\t"
8308202cf84SRoman Bolshakov 			     "movl $1, %eax\n\t"
8318202cf84SRoman Bolshakov 			     "outl %eax, %dx\n\t" /* Set IRQ11 */
8328202cf84SRoman Bolshakov 			     "movl $0, %eax\n\t"
8338202cf84SRoman Bolshakov 			     "outl %eax, %dx\n\t" /* Clear IRQ11 */
8348202cf84SRoman Bolshakov 			     "sti\n\t"
8358202cf84SRoman Bolshakov 			     "hlt\n\t");
8368202cf84SRoman Bolshakov 	exec_in_big_real_mode(&insn_sti_inhibit);
8378202cf84SRoman Bolshakov 
8388202cf84SRoman Bolshakov 	report("sti inhibit", ~0, 1);
8398202cf84SRoman Bolshakov }
8408202cf84SRoman Bolshakov 
8412e3f9f1fSThomas Huth static void test_imul(void)
842fa74f8a6SMohammed Gamal {
843fa74f8a6SMohammed Gamal 	MK_INSN(imul8_1, "mov $2, %al\n\t"
844fa74f8a6SMohammed Gamal 			"mov $-4, %cx\n\t"
845fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
846fa74f8a6SMohammed Gamal 
847fa74f8a6SMohammed Gamal 	MK_INSN(imul16_1, "mov $2, %ax\n\t"
848fa74f8a6SMohammed Gamal 		      "mov $-4, %cx\n\t"
849fa74f8a6SMohammed Gamal 		      "imul %cx\n\t");
850fa74f8a6SMohammed Gamal 
851fa74f8a6SMohammed Gamal 	MK_INSN(imul32_1, "mov $2, %eax\n\t"
852fa74f8a6SMohammed Gamal 		       "mov $-4, %ecx\n\t"
853fa74f8a6SMohammed Gamal 		       "imul %ecx\n\t");
854fa74f8a6SMohammed Gamal 
855fa74f8a6SMohammed Gamal 	MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t"
856fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
857fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
858fa74f8a6SMohammed Gamal 
859fa74f8a6SMohammed Gamal 	MK_INSN(imul16_2, "mov $2, %ax\n\t"
860fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
861fa74f8a6SMohammed Gamal 			"imul %cx\n\t");
862fa74f8a6SMohammed Gamal 
863fa74f8a6SMohammed Gamal 	MK_INSN(imul32_2, "mov $2, %eax\n\t"
864fa74f8a6SMohammed Gamal 			"mov $4, %ecx\n\t"
865fa74f8a6SMohammed Gamal 			"imul %ecx\n\t");
866fa74f8a6SMohammed Gamal 
867bd62e289SBill Wendling 	init_inregs(NULL);
86818253fdeSAvi Kivity 
86918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_1);
8706055ea1fSAvi Kivity 	report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8);
871fa74f8a6SMohammed Gamal 
87218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_1);
8736055ea1fSAvi Kivity 	report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8);
874fa74f8a6SMohammed Gamal 
87518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_1);
8766055ea1fSAvi Kivity 	report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8);
877fa74f8a6SMohammed Gamal 
87818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_2);
8796055ea1fSAvi Kivity 	report("imul 4", R_AX | R_CX | R_DX,
8806055ea1fSAvi Kivity 	       (outregs.eax & 0xffff) == 8
88181050840SAvi Kivity 	       && (outregs.eax & 0xffff0000) == 0x12340000);
882fa74f8a6SMohammed Gamal 
88318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_2);
8846055ea1fSAvi Kivity 	report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8);
885fa74f8a6SMohammed Gamal 
88618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_2);
8876055ea1fSAvi Kivity 	report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8);
888fa74f8a6SMohammed Gamal }
889fa74f8a6SMohammed Gamal 
8902e3f9f1fSThomas Huth static void test_mul(void)
89159317bd1SMohammed Gamal {
89259317bd1SMohammed Gamal 	MK_INSN(mul8, "mov $2, %al\n\t"
89359317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
89459317bd1SMohammed Gamal 			"imul %cl\n\t");
89559317bd1SMohammed Gamal 
89659317bd1SMohammed Gamal 	MK_INSN(mul16, "mov $2, %ax\n\t"
89759317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
89859317bd1SMohammed Gamal 			"imul %cx\n\t");
89959317bd1SMohammed Gamal 
90059317bd1SMohammed Gamal 	MK_INSN(mul32, "mov $2, %eax\n\t"
90159317bd1SMohammed Gamal 			"mov $4, %ecx\n\t"
90259317bd1SMohammed Gamal 			"imul %ecx\n\t");
90359317bd1SMohammed Gamal 
904bd62e289SBill Wendling 	init_inregs(NULL);
90518253fdeSAvi Kivity 
90618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul8);
9076055ea1fSAvi Kivity 	report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8);
90859317bd1SMohammed Gamal 
90918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul16);
9106055ea1fSAvi Kivity 	report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8);
91159317bd1SMohammed Gamal 
91218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul32);
9136055ea1fSAvi Kivity 	report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8);
91459317bd1SMohammed Gamal }
91559317bd1SMohammed Gamal 
9162e3f9f1fSThomas Huth static void test_div(void)
9170d4c7614SMohammed Gamal {
9180d4c7614SMohammed Gamal 	MK_INSN(div8, "mov $257, %ax\n\t"
9190d4c7614SMohammed Gamal 			"mov $2, %cl\n\t"
9200d4c7614SMohammed Gamal 			"div %cl\n\t");
9210d4c7614SMohammed Gamal 
9220d4c7614SMohammed Gamal 	MK_INSN(div16, "mov $512, %ax\n\t"
9230d4c7614SMohammed Gamal 			"mov $5, %cx\n\t"
9240d4c7614SMohammed Gamal 			"div %cx\n\t");
9250d4c7614SMohammed Gamal 
9260d4c7614SMohammed Gamal 	MK_INSN(div32, "mov $512, %eax\n\t"
9270d4c7614SMohammed Gamal 			"mov $5, %ecx\n\t"
9280d4c7614SMohammed Gamal 			"div %ecx\n\t");
9290d4c7614SMohammed Gamal 
930bd62e289SBill Wendling 	init_inregs(NULL);
93118253fdeSAvi Kivity 
93218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div8);
9336055ea1fSAvi Kivity 	report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384);
9340d4c7614SMohammed Gamal 
93518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div16);
9366055ea1fSAvi Kivity 	report("div 2", R_AX | R_CX | R_DX,
9376055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
9380d4c7614SMohammed Gamal 
93918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div32);
9406055ea1fSAvi Kivity 	report("div 3", R_AX | R_CX | R_DX,
9416055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
9420d4c7614SMohammed Gamal }
9430d4c7614SMohammed Gamal 
9442e3f9f1fSThomas Huth static void test_idiv(void)
9450d4c7614SMohammed Gamal {
9460d4c7614SMohammed Gamal 	MK_INSN(idiv8, "mov $256, %ax\n\t"
9470d4c7614SMohammed Gamal 			"mov $-2, %cl\n\t"
9480d4c7614SMohammed Gamal 			"idiv %cl\n\t");
9490d4c7614SMohammed Gamal 
9500d4c7614SMohammed Gamal 	MK_INSN(idiv16, "mov $512, %ax\n\t"
9510d4c7614SMohammed Gamal 			"mov $-2, %cx\n\t"
9520d4c7614SMohammed Gamal 			"idiv %cx\n\t");
9530d4c7614SMohammed Gamal 
9540d4c7614SMohammed Gamal 	MK_INSN(idiv32, "mov $512, %eax\n\t"
9550d4c7614SMohammed Gamal 			"mov $-2, %ecx\n\t"
9560d4c7614SMohammed Gamal 			"idiv %ecx\n\t");
9570d4c7614SMohammed Gamal 
958bd62e289SBill Wendling 	init_inregs(NULL);
95918253fdeSAvi Kivity 
96018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv8);
9616055ea1fSAvi Kivity 	report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128);
9620d4c7614SMohammed Gamal 
96318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv16);
9646055ea1fSAvi Kivity 	report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256);
9650d4c7614SMohammed Gamal 
96618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv32);
9676055ea1fSAvi Kivity 	report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256);
9680d4c7614SMohammed Gamal }
9690d4c7614SMohammed Gamal 
9702e3f9f1fSThomas Huth static void test_cbw(void)
9716e293cf5SWei Yongjun {
9726e293cf5SWei Yongjun 	MK_INSN(cbw, "mov $0xFE, %eax \n\t"
9736e293cf5SWei Yongjun 		     "cbw\n\t");
9746e293cf5SWei Yongjun 	MK_INSN(cwde, "mov $0xFFFE, %eax \n\t"
9756e293cf5SWei Yongjun 		      "cwde\n\t");
9766e293cf5SWei Yongjun 
977bd62e289SBill Wendling 	init_inregs(NULL);
97818253fdeSAvi Kivity 
97918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cbw);
9806055ea1fSAvi Kivity 	report("cbq 1", ~0, outregs.eax == 0xFFFE);
9816e293cf5SWei Yongjun 
98218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwde);
9836055ea1fSAvi Kivity 	report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE);
9846e293cf5SWei Yongjun }
9856e293cf5SWei Yongjun 
9862e3f9f1fSThomas Huth static void test_loopcc(void)
987eacef4e2SWei Yongjun {
988eacef4e2SWei Yongjun 	MK_INSN(loop, "mov $10, %ecx\n\t"
989eacef4e2SWei Yongjun 		      "1: inc %eax\n\t"
990eacef4e2SWei Yongjun 		      "loop 1b\n\t");
991eacef4e2SWei Yongjun 
992eacef4e2SWei Yongjun 	MK_INSN(loope, "mov $10, %ecx\n\t"
993eacef4e2SWei Yongjun 		       "mov $1, %eax\n\t"
994eacef4e2SWei Yongjun 		       "1: dec %eax\n\t"
995eacef4e2SWei Yongjun 		       "loope 1b\n\t");
996eacef4e2SWei Yongjun 
997eacef4e2SWei Yongjun 	MK_INSN(loopne, "mov $10, %ecx\n\t"
998eacef4e2SWei Yongjun 		        "mov $5, %eax\n\t"
999eacef4e2SWei Yongjun 		        "1: dec %eax\n\t"
1000eacef4e2SWei Yongjun 			"loopne 1b\n\t");
1001eacef4e2SWei Yongjun 
1002bd62e289SBill Wendling 	init_inregs(NULL);
1003eacef4e2SWei Yongjun 
100418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loop);
10056055ea1fSAvi Kivity 	report("LOOPcc short 1", R_AX, outregs.eax == 10);
100618253fdeSAvi Kivity 
100718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loope);
10086055ea1fSAvi Kivity 	report("LOOPcc short 2", R_AX | R_CX,
10096055ea1fSAvi Kivity 	       outregs.eax == -1 && outregs.ecx == 8);
1010eacef4e2SWei Yongjun 
101118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loopne);
10126055ea1fSAvi Kivity 	report("LOOPcc short 3", R_AX | R_CX,
10136055ea1fSAvi Kivity 	       outregs.eax == 0 && outregs.ecx == 5);
1014eacef4e2SWei Yongjun }
1015eacef4e2SWei Yongjun 
1016b274feedSAvi Kivity static void test_das(void)
1017b274feedSAvi Kivity {
1018b274feedSAvi Kivity     short i;
101981050840SAvi Kivity     u16 nr_fail = 0;
1020b274feedSAvi Kivity     static unsigned test_cases[1024] = {
1021b274feedSAvi Kivity         0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00,
1022b274feedSAvi Kivity         0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01,
1023b274feedSAvi Kivity         0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02,
1024b274feedSAvi Kivity         0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03,
1025b274feedSAvi Kivity         0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04,
1026b274feedSAvi Kivity         0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05,
1027b274feedSAvi Kivity         0x06000606, 0x8701a606, 0x56100006, 0x9711a006,
1028b274feedSAvi Kivity         0x02000707, 0x8301a707, 0x12100107, 0x9311a107,
1029b274feedSAvi Kivity         0x02000808, 0x8301a808, 0x12100208, 0x9311a208,
1030b274feedSAvi Kivity         0x06000909, 0x8701a909, 0x16100309, 0x9711a309,
1031b274feedSAvi Kivity         0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a,
1032b274feedSAvi Kivity         0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b,
1033b274feedSAvi Kivity         0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c,
1034b274feedSAvi Kivity         0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d,
1035b274feedSAvi Kivity         0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e,
1036b274feedSAvi Kivity         0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f,
1037b274feedSAvi Kivity         0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10,
1038b274feedSAvi Kivity         0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11,
1039b274feedSAvi Kivity         0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12,
1040b274feedSAvi Kivity         0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13,
1041b274feedSAvi Kivity         0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14,
1042b274feedSAvi Kivity         0x02001515, 0x8301b515, 0x16100f15, 0x9711af15,
1043b274feedSAvi Kivity         0x02001616, 0x8301b616, 0x12101016, 0x9311b016,
1044b274feedSAvi Kivity         0x06001717, 0x8701b717, 0x16101117, 0x9711b117,
1045b274feedSAvi Kivity         0x06001818, 0x8701b818, 0x16101218, 0x9711b218,
1046b274feedSAvi Kivity         0x02001919, 0x8301b919, 0x12101319, 0x9311b319,
1047b274feedSAvi Kivity         0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a,
1048b274feedSAvi Kivity         0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b,
1049b274feedSAvi Kivity         0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c,
1050b274feedSAvi Kivity         0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d,
1051b274feedSAvi Kivity         0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e,
1052b274feedSAvi Kivity         0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f,
1053b274feedSAvi Kivity         0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20,
1054b274feedSAvi Kivity         0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21,
1055b274feedSAvi Kivity         0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22,
1056b274feedSAvi Kivity         0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23,
1057b274feedSAvi Kivity         0x06002424, 0x8301c424, 0x16101e24, 0x9711be24,
1058b274feedSAvi Kivity         0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25,
1059b274feedSAvi Kivity         0x02002626, 0x8701c626, 0x12102026, 0x9711c026,
1060b274feedSAvi Kivity         0x06002727, 0x8301c727, 0x16102127, 0x9311c127,
1061b274feedSAvi Kivity         0x06002828, 0x8301c828, 0x16102228, 0x9311c228,
1062b274feedSAvi Kivity         0x02002929, 0x8701c929, 0x12102329, 0x9711c329,
1063b274feedSAvi Kivity         0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a,
1064b274feedSAvi Kivity         0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b,
1065b274feedSAvi Kivity         0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c,
1066b274feedSAvi Kivity         0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d,
1067b274feedSAvi Kivity         0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e,
1068b274feedSAvi Kivity         0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f,
1069b274feedSAvi Kivity         0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30,
1070b274feedSAvi Kivity         0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31,
1071b274feedSAvi Kivity         0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32,
1072b274feedSAvi Kivity         0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33,
1073b274feedSAvi Kivity         0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34,
1074b274feedSAvi Kivity         0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35,
1075b274feedSAvi Kivity         0x06003636, 0x8301d636, 0x16103036, 0x9311d036,
1076b274feedSAvi Kivity         0x02003737, 0x8701d737, 0x12103137, 0x9711d137,
1077b274feedSAvi Kivity         0x02003838, 0x8701d838, 0x12103238, 0x9711d238,
1078b274feedSAvi Kivity         0x06003939, 0x8301d939, 0x16103339, 0x9311d339,
1079b274feedSAvi Kivity         0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a,
1080b274feedSAvi Kivity         0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b,
1081b274feedSAvi Kivity         0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c,
1082b274feedSAvi Kivity         0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d,
1083b274feedSAvi Kivity         0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e,
1084b274feedSAvi Kivity         0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f,
1085b274feedSAvi Kivity         0x02004040, 0x8301e040, 0x16103a40, 0x9311da40,
1086b274feedSAvi Kivity         0x06004141, 0x8701e141, 0x12103b41, 0x9711db41,
1087b274feedSAvi Kivity         0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42,
1088b274feedSAvi Kivity         0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43,
1089b274feedSAvi Kivity         0x06004444, 0x8701e444, 0x12103e44, 0x9711de44,
1090b274feedSAvi Kivity         0x02004545, 0x8301e545, 0x16103f45, 0x9311df45,
1091b274feedSAvi Kivity         0x02004646, 0x8301e646, 0x12104046, 0x9311e046,
1092b274feedSAvi Kivity         0x06004747, 0x8701e747, 0x16104147, 0x9711e147,
1093b274feedSAvi Kivity         0x06004848, 0x8701e848, 0x16104248, 0x9711e248,
1094b274feedSAvi Kivity         0x02004949, 0x8301e949, 0x12104349, 0x9311e349,
1095b274feedSAvi Kivity         0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a,
1096b274feedSAvi Kivity         0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b,
1097b274feedSAvi Kivity         0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c,
1098b274feedSAvi Kivity         0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d,
1099b274feedSAvi Kivity         0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e,
1100b274feedSAvi Kivity         0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f,
1101b274feedSAvi Kivity         0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50,
1102b274feedSAvi Kivity         0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51,
1103b274feedSAvi Kivity         0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52,
1104b274feedSAvi Kivity         0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53,
1105b274feedSAvi Kivity         0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54,
1106b274feedSAvi Kivity         0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55,
1107b274feedSAvi Kivity         0x06005656, 0x8701f656, 0x16105056, 0x9711f056,
1108b274feedSAvi Kivity         0x02005757, 0x8301f757, 0x12105157, 0x9311f157,
1109b274feedSAvi Kivity         0x02005858, 0x8301f858, 0x12105258, 0x9311f258,
1110b274feedSAvi Kivity         0x06005959, 0x8701f959, 0x16105359, 0x9711f359,
1111b274feedSAvi Kivity         0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a,
1112b274feedSAvi Kivity         0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b,
1113b274feedSAvi Kivity         0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c,
1114b274feedSAvi Kivity         0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d,
1115b274feedSAvi Kivity         0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e,
1116b274feedSAvi Kivity         0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f,
1117b274feedSAvi Kivity         0x06006060, 0x47010060, 0x16105a60, 0x9711fa60,
1118b274feedSAvi Kivity         0x02006161, 0x03010161, 0x12105b61, 0x9311fb61,
1119b274feedSAvi Kivity         0x02006262, 0x03010262, 0x16105c62, 0x9711fc62,
1120b274feedSAvi Kivity         0x06006363, 0x07010363, 0x12105d63, 0x9311fd63,
1121b274feedSAvi Kivity         0x02006464, 0x03010464, 0x12105e64, 0x9311fe64,
1122b274feedSAvi Kivity         0x06006565, 0x07010565, 0x16105f65, 0x9711ff65,
1123b274feedSAvi Kivity         0x06006666, 0x07010666, 0x16106066, 0x57110066,
1124b274feedSAvi Kivity         0x02006767, 0x03010767, 0x12106167, 0x13110167,
1125b274feedSAvi Kivity         0x02006868, 0x03010868, 0x12106268, 0x13110268,
1126b274feedSAvi Kivity         0x06006969, 0x07010969, 0x16106369, 0x17110369,
1127b274feedSAvi Kivity         0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a,
1128b274feedSAvi Kivity         0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b,
1129b274feedSAvi Kivity         0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c,
1130b274feedSAvi Kivity         0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d,
1131b274feedSAvi Kivity         0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e,
1132b274feedSAvi Kivity         0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f,
1133b274feedSAvi Kivity         0x02007070, 0x03011070, 0x16106a70, 0x17110a70,
1134b274feedSAvi Kivity         0x06007171, 0x07011171, 0x12106b71, 0x13110b71,
1135b274feedSAvi Kivity         0x06007272, 0x07011272, 0x16106c72, 0x17110c72,
1136b274feedSAvi Kivity         0x02007373, 0x03011373, 0x12106d73, 0x13110d73,
1137b274feedSAvi Kivity         0x06007474, 0x07011474, 0x12106e74, 0x13110e74,
1138b274feedSAvi Kivity         0x02007575, 0x03011575, 0x16106f75, 0x17110f75,
1139b274feedSAvi Kivity         0x02007676, 0x03011676, 0x12107076, 0x13111076,
1140b274feedSAvi Kivity         0x06007777, 0x07011777, 0x16107177, 0x17111177,
1141b274feedSAvi Kivity         0x06007878, 0x07011878, 0x16107278, 0x17111278,
1142b274feedSAvi Kivity         0x02007979, 0x03011979, 0x12107379, 0x13111379,
1143b274feedSAvi Kivity         0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a,
1144b274feedSAvi Kivity         0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b,
1145b274feedSAvi Kivity         0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c,
1146b274feedSAvi Kivity         0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d,
1147b274feedSAvi Kivity         0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e,
1148b274feedSAvi Kivity         0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f,
1149b274feedSAvi Kivity         0x82008080, 0x03012080, 0x12107a80, 0x13111a80,
1150b274feedSAvi Kivity         0x86008181, 0x07012181, 0x16107b81, 0x17111b81,
1151b274feedSAvi Kivity         0x86008282, 0x07012282, 0x12107c82, 0x13111c82,
1152b274feedSAvi Kivity         0x82008383, 0x03012383, 0x16107d83, 0x17111d83,
1153b274feedSAvi Kivity         0x86008484, 0x07012484, 0x16107e84, 0x17111e84,
1154b274feedSAvi Kivity         0x82008585, 0x03012585, 0x12107f85, 0x13111f85,
1155b274feedSAvi Kivity         0x82008686, 0x03012686, 0x92108086, 0x13112086,
1156b274feedSAvi Kivity         0x86008787, 0x07012787, 0x96108187, 0x17112187,
1157b274feedSAvi Kivity         0x86008888, 0x07012888, 0x96108288, 0x17112288,
1158b274feedSAvi Kivity         0x82008989, 0x03012989, 0x92108389, 0x13112389,
1159b274feedSAvi Kivity         0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a,
1160b274feedSAvi Kivity         0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b,
1161b274feedSAvi Kivity         0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c,
1162b274feedSAvi Kivity         0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d,
1163b274feedSAvi Kivity         0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e,
1164b274feedSAvi Kivity         0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f,
1165b274feedSAvi Kivity         0x86009090, 0x07013090, 0x92108a90, 0x13112a90,
1166b274feedSAvi Kivity         0x82009191, 0x03013191, 0x96108b91, 0x17112b91,
1167b274feedSAvi Kivity         0x82009292, 0x03013292, 0x92108c92, 0x13112c92,
1168b274feedSAvi Kivity         0x86009393, 0x07013393, 0x96108d93, 0x17112d93,
1169b274feedSAvi Kivity         0x82009494, 0x03013494, 0x96108e94, 0x17112e94,
1170b274feedSAvi Kivity         0x86009595, 0x07013595, 0x92108f95, 0x13112f95,
1171b274feedSAvi Kivity         0x86009696, 0x07013696, 0x96109096, 0x17113096,
1172b274feedSAvi Kivity         0x82009797, 0x03013797, 0x92109197, 0x13113197,
1173b274feedSAvi Kivity         0x82009898, 0x03013898, 0x92109298, 0x13113298,
1174b274feedSAvi Kivity         0x86009999, 0x07013999, 0x96109399, 0x17113399,
1175b274feedSAvi Kivity         0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a,
1176b274feedSAvi Kivity         0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b,
1177b274feedSAvi Kivity         0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c,
1178b274feedSAvi Kivity         0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d,
1179b274feedSAvi Kivity         0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e,
1180b274feedSAvi Kivity         0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f,
1181b274feedSAvi Kivity         0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0,
1182b274feedSAvi Kivity         0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1,
1183b274feedSAvi Kivity         0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2,
1184b274feedSAvi Kivity         0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3,
1185b274feedSAvi Kivity         0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4,
1186b274feedSAvi Kivity         0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5,
1187b274feedSAvi Kivity         0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6,
1188b274feedSAvi Kivity         0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7,
1189b274feedSAvi Kivity         0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8,
1190b274feedSAvi Kivity         0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9,
1191b274feedSAvi Kivity         0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa,
1192b274feedSAvi Kivity         0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab,
1193b274feedSAvi Kivity         0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac,
1194b274feedSAvi Kivity         0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad,
1195b274feedSAvi Kivity         0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae,
1196b274feedSAvi Kivity         0x130049af, 0x130149af, 0x131049af, 0x131149af,
1197b274feedSAvi Kivity         0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0,
1198b274feedSAvi Kivity         0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1,
1199b274feedSAvi Kivity         0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2,
1200b274feedSAvi Kivity         0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3,
1201b274feedSAvi Kivity         0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4,
1202b274feedSAvi Kivity         0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5,
1203b274feedSAvi Kivity         0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6,
1204b274feedSAvi Kivity         0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7,
1205b274feedSAvi Kivity         0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8,
1206b274feedSAvi Kivity         0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9,
1207b274feedSAvi Kivity         0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba,
1208b274feedSAvi Kivity         0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb,
1209b274feedSAvi Kivity         0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc,
1210b274feedSAvi Kivity         0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd,
1211b274feedSAvi Kivity         0x130058be, 0x130158be, 0x131058be, 0x131158be,
1212b274feedSAvi Kivity         0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf,
1213b274feedSAvi Kivity         0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0,
1214b274feedSAvi Kivity         0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1,
1215b274feedSAvi Kivity         0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2,
1216b274feedSAvi Kivity         0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3,
1217b274feedSAvi Kivity         0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4,
1218b274feedSAvi Kivity         0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5,
1219b274feedSAvi Kivity         0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6,
1220b274feedSAvi Kivity         0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7,
1221b274feedSAvi Kivity         0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8,
1222b274feedSAvi Kivity         0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9,
1223b274feedSAvi Kivity         0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca,
1224b274feedSAvi Kivity         0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb,
1225b274feedSAvi Kivity         0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc,
1226b274feedSAvi Kivity         0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd,
1227b274feedSAvi Kivity         0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce,
1228b274feedSAvi Kivity         0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf,
1229b274feedSAvi Kivity         0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0,
1230b274feedSAvi Kivity         0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1,
1231b274feedSAvi Kivity         0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2,
1232b274feedSAvi Kivity         0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3,
1233b274feedSAvi Kivity         0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4,
1234b274feedSAvi Kivity         0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5,
1235b274feedSAvi Kivity         0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6,
1236b274feedSAvi Kivity         0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7,
1237b274feedSAvi Kivity         0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8,
1238b274feedSAvi Kivity         0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9,
1239b274feedSAvi Kivity         0x170074da, 0x170174da, 0x171074da, 0x171174da,
1240b274feedSAvi Kivity         0x130075db, 0x130175db, 0x131075db, 0x131175db,
1241b274feedSAvi Kivity         0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc,
1242b274feedSAvi Kivity         0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd,
1243b274feedSAvi Kivity         0x170078de, 0x170178de, 0x171078de, 0x171178de,
1244b274feedSAvi Kivity         0x130079df, 0x130179df, 0x131079df, 0x131179df,
1245b274feedSAvi Kivity         0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0,
1246b274feedSAvi Kivity         0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1,
1247b274feedSAvi Kivity         0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2,
1248b274feedSAvi Kivity         0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3,
1249b274feedSAvi Kivity         0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4,
1250b274feedSAvi Kivity         0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5,
1251b274feedSAvi Kivity         0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6,
1252b274feedSAvi Kivity         0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7,
1253b274feedSAvi Kivity         0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8,
1254b274feedSAvi Kivity         0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9,
1255b274feedSAvi Kivity         0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea,
1256b274feedSAvi Kivity         0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb,
1257b274feedSAvi Kivity         0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec,
1258b274feedSAvi Kivity         0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed,
1259b274feedSAvi Kivity         0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee,
1260b274feedSAvi Kivity         0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef,
1261b274feedSAvi Kivity         0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0,
1262b274feedSAvi Kivity         0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1,
1263b274feedSAvi Kivity         0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2,
1264b274feedSAvi Kivity         0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3,
1265b274feedSAvi Kivity         0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4,
1266b274feedSAvi Kivity         0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5,
1267b274feedSAvi Kivity         0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6,
1268b274feedSAvi Kivity         0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7,
1269b274feedSAvi Kivity         0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8,
1270b274feedSAvi Kivity         0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9,
1271b274feedSAvi Kivity         0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa,
1272b274feedSAvi Kivity         0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb,
1273b274feedSAvi Kivity         0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc,
1274b274feedSAvi Kivity         0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd,
1275b274feedSAvi Kivity         0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe,
1276b274feedSAvi Kivity         0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff,
1277b274feedSAvi Kivity     };
1278b274feedSAvi Kivity 
1279b274feedSAvi Kivity     MK_INSN(das, "das");
1280b274feedSAvi Kivity 
1281bd62e289SBill Wendling     init_inregs(NULL);
128218253fdeSAvi Kivity 
1283b274feedSAvi Kivity     for (i = 0; i < 1024; ++i) {
1284b274feedSAvi Kivity         unsigned tmp = test_cases[i];
1285b274feedSAvi Kivity         inregs.eax = tmp & 0xff;
1286b274feedSAvi Kivity         inregs.eflags = (tmp >> 16) & 0xff;
128718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_das);
128818253fdeSAvi Kivity 	if (!regs_equal(R_AX)
1289b274feedSAvi Kivity             || outregs.eax != ((tmp >> 8) & 0xff)
1290b274feedSAvi Kivity             || (outregs.eflags & 0xff) != (tmp >> 24)) {
129181050840SAvi Kivity 	    ++nr_fail;
129281050840SAvi Kivity 	    break;
1293b274feedSAvi Kivity         }
1294b274feedSAvi Kivity     }
12956055ea1fSAvi Kivity     report("DAS", ~0, nr_fail == 0);
1296b274feedSAvi Kivity }
1297b274feedSAvi Kivity 
12982e3f9f1fSThomas Huth static void test_cwd_cdq(void)
12990cbd5b06SMohammed Gamal {
13000cbd5b06SMohammed Gamal 	/* Sign-bit set */
13010cbd5b06SMohammed Gamal 	MK_INSN(cwd_1, "mov $0x8000, %ax\n\t"
13020cbd5b06SMohammed Gamal 		       "cwd\n\t");
13030cbd5b06SMohammed Gamal 
13040cbd5b06SMohammed Gamal 	/* Sign-bit not set */
13050cbd5b06SMohammed Gamal 	MK_INSN(cwd_2, "mov $0x1000, %ax\n\t"
13060cbd5b06SMohammed Gamal 		       "cwd\n\t");
13070cbd5b06SMohammed Gamal 
13080cbd5b06SMohammed Gamal 	/* Sign-bit set */
13090cbd5b06SMohammed Gamal 	MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t"
13100cbd5b06SMohammed Gamal 		       "cdq\n\t");
13110cbd5b06SMohammed Gamal 
13120cbd5b06SMohammed Gamal 	/* Sign-bit not set */
13130cbd5b06SMohammed Gamal 	MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t"
13140cbd5b06SMohammed Gamal 		       "cdq\n\t");
13150cbd5b06SMohammed Gamal 
1316bd62e289SBill Wendling 	init_inregs(NULL);
131718253fdeSAvi Kivity 
131818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_1);
13196055ea1fSAvi Kivity 	report("cwd 1", R_AX | R_DX,
13206055ea1fSAvi Kivity 	       outregs.eax == 0x8000 && outregs.edx == 0xffff);
13210cbd5b06SMohammed Gamal 
132218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_2);
13236055ea1fSAvi Kivity 	report("cwd 2", R_AX | R_DX,
13246055ea1fSAvi Kivity 	       outregs.eax == 0x1000 && outregs.edx == 0);
13250cbd5b06SMohammed Gamal 
132618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_1);
13276055ea1fSAvi Kivity 	report("cdq 1", R_AX | R_DX,
13286055ea1fSAvi Kivity 	       outregs.eax == 0x80000000 && outregs.edx == 0xffffffff);
13290cbd5b06SMohammed Gamal 
133018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_2);
13316055ea1fSAvi Kivity 	report("cdq 2", R_AX | R_DX,
13326055ea1fSAvi Kivity 	       outregs.eax == 0x10000000 && outregs.edx == 0);
13330cbd5b06SMohammed Gamal }
13340cbd5b06SMohammed Gamal 
133537f51a4aSWei Yongjun static struct {
133637f51a4aSWei Yongjun         void *address;
133737f51a4aSWei Yongjun         unsigned short sel;
133837f51a4aSWei Yongjun } __attribute__((packed)) desc = {
133937f51a4aSWei Yongjun 	(void *)0x1234,
134037f51a4aSWei Yongjun 	0x10,
134137f51a4aSWei Yongjun };
134237f51a4aSWei Yongjun 
13432e3f9f1fSThomas Huth static void test_lds_lss(void)
134437f51a4aSWei Yongjun {
1345bd62e289SBill Wendling 	init_inregs(&(struct regs){ .ebx = (unsigned long)&desc });
134637f51a4aSWei Yongjun 
1347231b4c3bSRoman Bolshakov 	MK_INSN(lds, "pushl %ds\n\t"
134837f51a4aSWei Yongjun 		     "lds (%ebx), %eax\n\t"
134937f51a4aSWei Yongjun 		     "mov %ds, %ebx\n\t"
1350231b4c3bSRoman Bolshakov 		     "popl %ds\n\t");
135137f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lds);
135237f51a4aSWei Yongjun 	report("lds", R_AX | R_BX,
135337f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
135437f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
135537f51a4aSWei Yongjun 
1356eb6687a2SBill Wendling 	MK_INSN(les, "les (%ebx), %eax\n\t"
1357eb6687a2SBill Wendling 		     "mov %es, %ebx\n\t");
135837f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_les);
135937f51a4aSWei Yongjun 	report("les", R_AX | R_BX,
136037f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
136137f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
136237f51a4aSWei Yongjun 
1363231b4c3bSRoman Bolshakov 	MK_INSN(lfs, "pushl %fs\n\t"
136437f51a4aSWei Yongjun 		     "lfs (%ebx), %eax\n\t"
136537f51a4aSWei Yongjun 		     "mov %fs, %ebx\n\t"
1366231b4c3bSRoman Bolshakov 		     "popl %fs\n\t");
136737f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lfs);
136837f51a4aSWei Yongjun 	report("lfs", R_AX | R_BX,
136937f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
137037f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
137137f51a4aSWei Yongjun 
1372231b4c3bSRoman Bolshakov 	MK_INSN(lgs, "pushl %gs\n\t"
137337f51a4aSWei Yongjun 		     "lgs (%ebx), %eax\n\t"
137437f51a4aSWei Yongjun 		     "mov %gs, %ebx\n\t"
1375231b4c3bSRoman Bolshakov 		     "popl %gs\n\t");
137637f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lgs);
137737f51a4aSWei Yongjun 	report("lgs", R_AX | R_BX,
137837f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
137937f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
138037f51a4aSWei Yongjun 
1381*d7903be6SNadav Amit 	MK_INSN(lss, "mov %ss, %dx\n\t"
138237f51a4aSWei Yongjun 		     "lss (%ebx), %eax\n\t"
138337f51a4aSWei Yongjun 		     "mov %ss, %ebx\n\t"
1384*d7903be6SNadav Amit 		     "mov %dx, %ss\n\t");
138537f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lss);
138637f51a4aSWei Yongjun 	report("lss", R_AX | R_BX,
138737f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
138837f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
138937f51a4aSWei Yongjun }
139037f51a4aSWei Yongjun 
13912e3f9f1fSThomas Huth static void test_jcxz(void)
1392b1c7c575SWei Yongjun {
1393b1c7c575SWei Yongjun 	MK_INSN(jcxz1, "jcxz 1f\n\t"
1394b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1395b1c7c575SWei Yongjun 		       "1:\n\t");
1396b1c7c575SWei Yongjun 	MK_INSN(jcxz2, "mov $0x100, %ecx\n\t"
1397b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1398b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1399b1c7c575SWei Yongjun 		       "mov $0, %ecx\n\t"
1400b1c7c575SWei Yongjun 		       "1:\n\t");
1401b1c7c575SWei Yongjun 	MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t"
1402b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1403b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1404b1c7c575SWei Yongjun 		       "1:\n\t");
1405b1c7c575SWei Yongjun 	MK_INSN(jecxz1, "jecxz 1f\n\t"
1406b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1407b1c7c575SWei Yongjun 			"1:\n\t");
1408b1c7c575SWei Yongjun 	MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t"
1409b1c7c575SWei Yongjun 			"jecxz 1f\n\t"
1410b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1411b1c7c575SWei Yongjun 			"mov $0, %ecx\n\t"
1412b1c7c575SWei Yongjun 			"1:\n\t");
1413b1c7c575SWei Yongjun 
1414bd62e289SBill Wendling 	init_inregs(NULL);
1415b1c7c575SWei Yongjun 
1416b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz1);
1417b1c7c575SWei Yongjun 	report("jcxz short 1", 0, 1);
1418b1c7c575SWei Yongjun 
1419b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz2);
1420b1c7c575SWei Yongjun 	report("jcxz short 2", R_AX, outregs.eax == 0x1234);
1421b1c7c575SWei Yongjun 
1422b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz3);
1423b1c7c575SWei Yongjun 	report("jcxz short 3", R_CX, outregs.ecx == 0x10000);
1424b1c7c575SWei Yongjun 
1425b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz1);
1426b1c7c575SWei Yongjun 	report("jecxz short 1", 0, 1);
1427b1c7c575SWei Yongjun 
1428b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz2);
1429b1c7c575SWei Yongjun 	report("jecxz short 2", R_AX, outregs.eax == 0x1234);
1430b1c7c575SWei Yongjun }
1431b1c7c575SWei Yongjun 
14328f578e98SAvi Kivity static void test_cpuid(void)
14338f578e98SAvi Kivity {
14348f578e98SAvi Kivity     MK_INSN(cpuid, "cpuid");
14358f578e98SAvi Kivity     unsigned function = 0x1234;
14368f578e98SAvi Kivity     unsigned eax, ebx, ecx, edx;
14378f578e98SAvi Kivity 
1438bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = function });
1439bd62e289SBill Wendling 
1440bd62e289SBill Wendling     eax = inregs.eax;
1441bd62e289SBill Wendling     ecx = inregs.ecx;
1442674d2dbeSPaolo Bonzini     asm("cpuid" : "+a"(eax), "=b"(ebx), "+c"(ecx), "=d"(edx));
14438f578e98SAvi Kivity     exec_in_big_real_mode(&insn_cpuid);
14448f578e98SAvi Kivity     report("cpuid", R_AX|R_BX|R_CX|R_DX,
14458f578e98SAvi Kivity 	   outregs.eax == eax && outregs.ebx == ebx
14468f578e98SAvi Kivity 	   && outregs.ecx == ecx && outregs.edx == edx);
14478f578e98SAvi Kivity }
14488f578e98SAvi Kivity 
1449ed93f43bSAvi Kivity static void test_ss_base_for_esp_ebp(void)
1450ed93f43bSAvi Kivity {
1451ed93f43bSAvi Kivity     MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss");
1452ed93f43bSAvi Kivity     MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss");
1453ed93f43bSAvi Kivity     static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 };
1454ed93f43bSAvi Kivity 
1455bd62e289SBill Wendling     init_inregs(&(struct regs){ .ebx = 1, .ebp = (unsigned)array });
1456bd62e289SBill Wendling 
1457ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel1);
1458ed93f43bSAvi Kivity     report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321);
1459bd62e289SBill Wendling 
1460ed93f43bSAvi Kivity     inregs.ebx = 1;
1461ed93f43bSAvi Kivity     inregs.ebp = (unsigned)array;
1462ed93f43bSAvi Kivity     inregs.edi = 0;
1463ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel2);
1464ed93f43bSAvi Kivity     report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321);
1465ed93f43bSAvi Kivity }
1466ed93f43bSAvi Kivity 
1467975ca087SPeter Feiner extern unsigned long long r_gdt[];
1468975ca087SPeter Feiner 
1469c2281fa4SAvi Kivity static void test_sgdt_sidt(void)
1470c2281fa4SAvi Kivity {
1471c2281fa4SAvi Kivity     MK_INSN(sgdt, "sgdtw (%eax)");
1472c2281fa4SAvi Kivity     MK_INSN(sidt, "sidtw (%eax)");
1473975ca087SPeter Feiner     struct table_descr x, y;
1474c2281fa4SAvi Kivity 
1475bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = (unsigned)&y });
1476bd62e289SBill Wendling 
1477c2281fa4SAvi Kivity     asm volatile("sgdtw %0" : "=m"(x));
1478c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sgdt);
1479975ca087SPeter Feiner     report("sgdt", 0, x.limit == y.limit && x.base == y.base);
1480c2281fa4SAvi Kivity 
1481c2281fa4SAvi Kivity     inregs.eax = (unsigned)&y;
1482c2281fa4SAvi Kivity     asm volatile("sidtw %0" : "=m"(x));
1483c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sidt);
1484975ca087SPeter Feiner     report("sidt", 0, x.limit == y.limit && x.base == y.base);
1485c2281fa4SAvi Kivity }
1486c2281fa4SAvi Kivity 
148788b6dac4SPaolo Bonzini static void test_sahf(void)
148888b6dac4SPaolo Bonzini {
148988b6dac4SPaolo Bonzini     MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw");
149088b6dac4SPaolo Bonzini 
1491bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0xfd00 });
1492bd62e289SBill Wendling 
149388b6dac4SPaolo Bonzini     exec_in_big_real_mode(&insn_sahf);
149488b6dac4SPaolo Bonzini     report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7));
149588b6dac4SPaolo Bonzini }
149688b6dac4SPaolo Bonzini 
14977ae3645aSAvi Kivity static void test_lahf(void)
14987ae3645aSAvi Kivity {
14997ae3645aSAvi Kivity     MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf");
15007ae3645aSAvi Kivity 
1501bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0xc7 });
1502bd62e289SBill Wendling 
15037ae3645aSAvi Kivity     exec_in_big_real_mode(&insn_lahf);
15047ae3645aSAvi Kivity     report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax);
15057ae3645aSAvi Kivity }
15067ae3645aSAvi Kivity 
1507fd9ea640SAvi Kivity static void test_movzx_movsx(void)
1508fd9ea640SAvi Kivity {
1509fd9ea640SAvi Kivity     MK_INSN(movsx, "movsx %al, %ebx");
1510fd9ea640SAvi Kivity     MK_INSN(movzx, "movzx %al, %ebx");
15113013e079SGleb Natapov     MK_INSN(movzsah, "movsx %ah, %ebx");
15123013e079SGleb Natapov     MK_INSN(movzxah, "movzx %ah, %ebx");
1513fd9ea640SAvi Kivity 
1514bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x1234569c });
1515bd62e289SBill Wendling 
1516fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movsx);
1517fd9ea640SAvi Kivity     report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax);
1518fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movzx);
1519fd9ea640SAvi Kivity     report("movzx", R_BX, outregs.ebx == (unsigned char)inregs.eax);
15203013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzsah);
15213013e079SGleb Natapov     report("movsx ah", R_BX, outregs.ebx == (signed char)(inregs.eax>>8));
15223013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzxah);
15233013e079SGleb Natapov     report("movzx ah", R_BX, outregs.ebx == (unsigned char)(inregs.eax >> 8));
1524fd9ea640SAvi Kivity }
1525fd9ea640SAvi Kivity 
1526b493b2e8SAvi Kivity static void test_bswap(void)
1527b493b2e8SAvi Kivity {
1528b493b2e8SAvi Kivity     MK_INSN(bswap, "bswap %ecx");
1529b493b2e8SAvi Kivity 
1530bd62e289SBill Wendling     init_inregs(&(struct regs){ .ecx = 0x12345678 });
1531bd62e289SBill Wendling 
1532b493b2e8SAvi Kivity     exec_in_big_real_mode(&insn_bswap);
1533b493b2e8SAvi Kivity     report("bswap", R_CX, outregs.ecx == 0x78563412);
1534b493b2e8SAvi Kivity }
1535b493b2e8SAvi Kivity 
15368cd86387SGleb Natapov static void test_aad(void)
15378cd86387SGleb Natapov {
15388cd86387SGleb Natapov     MK_INSN(aad, "aad");
15398cd86387SGleb Natapov 
1540bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x12345678 });
1541bd62e289SBill Wendling 
15428cd86387SGleb Natapov     exec_in_big_real_mode(&insn_aad);
15438cd86387SGleb Natapov     report("aad", R_AX, outregs.eax == 0x123400d4);
15448cd86387SGleb Natapov }
15458cd86387SGleb Natapov 
15462a9b5718SPaolo Bonzini static void test_aam(void)
15472a9b5718SPaolo Bonzini {
15482a9b5718SPaolo Bonzini     MK_INSN(aam, "aam");
15492a9b5718SPaolo Bonzini 
1550bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x76543210 });
1551bd62e289SBill Wendling 
15522a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_aam);
15532a9b5718SPaolo Bonzini     report("aam", R_AX, outregs.eax == 0x76540106);
15542a9b5718SPaolo Bonzini }
15552a9b5718SPaolo Bonzini 
15562a9b5718SPaolo Bonzini static void test_xlat(void)
15572a9b5718SPaolo Bonzini {
15582a9b5718SPaolo Bonzini     MK_INSN(xlat, "xlat");
15592a9b5718SPaolo Bonzini     u8 table[256];
15602a9b5718SPaolo Bonzini     int i;
15612a9b5718SPaolo Bonzini 
15622a9b5718SPaolo Bonzini     for (i = 0; i < 256; i++) {
15632a9b5718SPaolo Bonzini         table[i] = i + 1;
15642a9b5718SPaolo Bonzini     }
15652a9b5718SPaolo Bonzini 
1566bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x89abcdef, .ebx = (u32)table });
1567bd62e289SBill Wendling 
15682a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_xlat);
15692a9b5718SPaolo Bonzini     report("xlat", R_AX, outregs.eax == 0x89abcdf0);
15702a9b5718SPaolo Bonzini }
15712a9b5718SPaolo Bonzini 
15722a9b5718SPaolo Bonzini static void test_salc(void)
15732a9b5718SPaolo Bonzini {
15742a9b5718SPaolo Bonzini     MK_INSN(clc_salc, "clc; .byte 0xd6");
15752a9b5718SPaolo Bonzini     MK_INSN(stc_salc, "stc; .byte 0xd6");
15762a9b5718SPaolo Bonzini 
1577bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x12345678 });
1578bd62e289SBill Wendling 
15792a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_clc_salc);
15802a9b5718SPaolo Bonzini     report("salc (1)", R_AX, outregs.eax == 0x12345600);
15812a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_stc_salc);
15822a9b5718SPaolo Bonzini     report("salc (2)", R_AX, outregs.eax == 0x123456ff);
15832a9b5718SPaolo Bonzini }
15842a9b5718SPaolo Bonzini 
15850987db7aSGleb Natapov static void test_fninit(void)
15860987db7aSGleb Natapov {
15870987db7aSGleb Natapov 	u16 fcw = -1, fsw = -1;
15880987db7aSGleb Natapov 	MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)");
15890987db7aSGleb Natapov 
1590bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = (u32)&fsw, .ebx = (u32)&fcw });
15910987db7aSGleb Natapov 
15920987db7aSGleb Natapov 	exec_in_big_real_mode(&insn_fninit);
15930987db7aSGleb Natapov 	report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f);
15940987db7aSGleb Natapov }
15950987db7aSGleb Natapov 
15961a4c03a0SArthur Chunqi Li static void test_nopl(void)
15971a4c03a0SArthur Chunqi Li {
15981a4c03a0SArthur Chunqi Li 	MK_INSN(nopl1, ".byte 0x90\n\r"); // 1 byte nop
15991a4c03a0SArthur Chunqi Li 	MK_INSN(nopl2, ".byte 0x66, 0x90\n\r"); // 2 bytes nop
16001a4c03a0SArthur Chunqi Li 	MK_INSN(nopl3, ".byte 0x0f, 0x1f, 0x00\n\r"); // 3 bytes nop
16011a4c03a0SArthur Chunqi Li 	MK_INSN(nopl4, ".byte 0x0f, 0x1f, 0x40, 0x00\n\r"); // 4 bytes nop
16021a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl1);
16031a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl2);
16041a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl3);
16051a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl4);
16061a4c03a0SArthur Chunqi Li 	report("nopl", 0, 1);
16071a4c03a0SArthur Chunqi Li }
16081a4c03a0SArthur Chunqi Li 
1609b5105e8bSPaolo Bonzini static u32 perf_baseline;
1610b5105e8bSPaolo Bonzini 
16117505ea23SPaolo Bonzini #define PERF_COUNT 1000000
1612b5105e8bSPaolo Bonzini 
1613b5105e8bSPaolo Bonzini #define MK_INSN_PERF(name, insn)                                \
1614b5105e8bSPaolo Bonzini 	MK_INSN(name, "rdtsc; mov %eax, %ebx; mov %edx, %esi\n" \
1615b5105e8bSPaolo Bonzini 		      "1:" insn "\n"                            \
16167505ea23SPaolo Bonzini 		      ".byte 0x67; loop 1b\n"                   \
1617b5105e8bSPaolo Bonzini 		      "rdtsc");
1618b5105e8bSPaolo Bonzini 
1619b5105e8bSPaolo Bonzini static u32 cycles_in_big_real_mode(struct insn_desc *insn)
1620b5105e8bSPaolo Bonzini {
1621b5105e8bSPaolo Bonzini 	u64 start, end;
1622b5105e8bSPaolo Bonzini 
1623bd62e289SBill Wendling 	init_inregs(&(struct regs){ .ecx = PERF_COUNT });
1624bd62e289SBill Wendling 
1625b5105e8bSPaolo Bonzini 	exec_in_big_real_mode(insn);
1626b5105e8bSPaolo Bonzini 	start = ((u64)outregs.esi << 32) | outregs.ebx;
1627b5105e8bSPaolo Bonzini 	end = ((u64)outregs.edx << 32) | outregs.eax;
1628b5105e8bSPaolo Bonzini 
1629b5105e8bSPaolo Bonzini 	return end - start;
1630b5105e8bSPaolo Bonzini }
1631b5105e8bSPaolo Bonzini 
1632b5105e8bSPaolo Bonzini static void test_perf_loop(void)
1633b5105e8bSPaolo Bonzini {
1634b5105e8bSPaolo Bonzini 	/*
1635b5105e8bSPaolo Bonzini 	 * This test runs simple instructions that should roughly take the
1636b5105e8bSPaolo Bonzini 	 * the same time to emulate: PERF_COUNT iterations of "loop" and 3
1637b5105e8bSPaolo Bonzini 	 * setup instructions.  Other performance tests can run PERF_COUNT
1638b5105e8bSPaolo Bonzini 	 * iterations of the same instruction and subtract the cycle count
1639b5105e8bSPaolo Bonzini 	 * of this test.
1640b5105e8bSPaolo Bonzini 	 */
1641b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_loop, "");
1642b5105e8bSPaolo Bonzini 	perf_baseline = cycles_in_big_real_mode(&insn_perf_loop);
1643b5105e8bSPaolo Bonzini 	print_serial_u32(perf_baseline / (PERF_COUNT + 3));
1644b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated jump instruction\n");
1645b5105e8bSPaolo Bonzini }
1646b5105e8bSPaolo Bonzini 
1647b5105e8bSPaolo Bonzini static void test_perf_mov(void)
1648b5105e8bSPaolo Bonzini {
1649b5105e8bSPaolo Bonzini 	u32 cyc;
1650b5105e8bSPaolo Bonzini 
1651b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_move, "mov %esi, %edi");
1652b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_move);
1653b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1654b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated move instruction\n");
1655b5105e8bSPaolo Bonzini }
1656b5105e8bSPaolo Bonzini 
1657b5105e8bSPaolo Bonzini static void test_perf_arith(void)
1658b5105e8bSPaolo Bonzini {
1659b5105e8bSPaolo Bonzini 	u32 cyc;
1660b5105e8bSPaolo Bonzini 
1661b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_arith, "add $4, %edi");
1662b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_arith);
1663b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1664b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated arithmetic instruction\n");
1665b5105e8bSPaolo Bonzini }
1666b5105e8bSPaolo Bonzini 
1667b5105e8bSPaolo Bonzini static void test_perf_memory_load(void)
1668b5105e8bSPaolo Bonzini {
1669b5105e8bSPaolo Bonzini 	u32 cyc, tmp;
1670b5105e8bSPaolo Bonzini 
1671576718d0SBill Wendling 	MK_INSN_PERF(perf_memory_load, "cmpw $0, (%edi)");
1672bd62e289SBill Wendling 
1673bd62e289SBill Wendling 	init_inregs(&(struct regs){ .edi = (u32)&tmp });
1674bd62e289SBill Wendling 
1675b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_load);
1676b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1677b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated memory load instruction\n");
1678b5105e8bSPaolo Bonzini }
1679b5105e8bSPaolo Bonzini 
16809306cb8eSPaolo Bonzini static void test_perf_memory_store(void)
16819306cb8eSPaolo Bonzini {
16829306cb8eSPaolo Bonzini 	u32 cyc, tmp;
16839306cb8eSPaolo Bonzini 
1684576718d0SBill Wendling 	MK_INSN_PERF(perf_memory_store, "movw %ax, (%edi)");
1685bd62e289SBill Wendling 
1686bd62e289SBill Wendling 	init_inregs(&(struct regs){ .edi = (u32)&tmp });
1687bd62e289SBill Wendling 
16889306cb8eSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_store);
16899306cb8eSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
16909306cb8eSPaolo Bonzini 	print_serial(" cycles/emulated memory store instruction\n");
16919306cb8eSPaolo Bonzini }
16929306cb8eSPaolo Bonzini 
1693b5105e8bSPaolo Bonzini static void test_perf_memory_rmw(void)
1694b5105e8bSPaolo Bonzini {
1695b5105e8bSPaolo Bonzini 	u32 cyc, tmp;
1696b5105e8bSPaolo Bonzini 
1697576718d0SBill Wendling 	MK_INSN_PERF(perf_memory_rmw, "addw $1, (%edi)");
1698bd62e289SBill Wendling 
1699bd62e289SBill Wendling 	init_inregs(&(struct regs){ .edi = (u32)&tmp });
1700bd62e289SBill Wendling 
1701b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_rmw);
1702b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1703b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated memory RMW instruction\n");
1704b5105e8bSPaolo Bonzini }
1705b5105e8bSPaolo Bonzini 
17062e3f9f1fSThomas Huth static void test_dr_mod(void)
17070a5701edSNadav Amit {
17080a5701edSNadav Amit 	MK_INSN(drmod, "movl %ebx, %dr0\n\t"
17090a5701edSNadav Amit 		       ".byte 0x0f \n\t .byte 0x21 \n\t .byte 0x0\n\t");
1710bd62e289SBill Wendling 
1711bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0xdead, .ebx = 0xaced });
1712bd62e289SBill Wendling 
17130a5701edSNadav Amit 	exec_in_big_real_mode(&insn_drmod);
17140a5701edSNadav Amit 	report("mov dr with mod bits", R_AX | R_BX, outregs.eax == 0xaced);
17150a5701edSNadav Amit }
17160a5701edSNadav Amit 
17172e3f9f1fSThomas Huth static void test_smsw(void)
171899ee878cSNadav Amit {
171999ee878cSNadav Amit 	MK_INSN(smsw, "movl %cr0, %ebx\n\t"
172099ee878cSNadav Amit 		      "movl %ebx, %ecx\n\t"
172199ee878cSNadav Amit 		      "or $0x40000000, %ebx\n\t"
172299ee878cSNadav Amit 		      "movl %ebx, %cr0\n\t"
172399ee878cSNadav Amit 		      "smswl %eax\n\t"
172499ee878cSNadav Amit 		      "movl %ecx, %cr0\n\t");
1725bd62e289SBill Wendling 
1726bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0x12345678 });
1727bd62e289SBill Wendling 
172899ee878cSNadav Amit 	exec_in_big_real_mode(&insn_smsw);
172999ee878cSNadav Amit 	report("smsw", R_AX | R_BX | R_CX, outregs.eax == outregs.ebx);
173099ee878cSNadav Amit }
173199ee878cSNadav Amit 
17322e3f9f1fSThomas Huth static void test_xadd(void)
17337bee560dSNadav Amit {
17347bee560dSNadav Amit 	MK_INSN(xadd, "xaddl %eax, %eax\n\t");
1735bd62e289SBill Wendling 
1736bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0x12345678 });
1737bd62e289SBill Wendling 
17387bee560dSNadav Amit 	exec_in_big_real_mode(&insn_xadd);
17397bee560dSNadav Amit 	report("xadd", R_AX, outregs.eax == inregs.eax * 2);
17407bee560dSNadav Amit }
17417bee560dSNadav Amit 
174299ee878cSNadav Amit 
17437d36db35SAvi Kivity void realmode_start(void)
17447d36db35SAvi Kivity {
17457d36db35SAvi Kivity 	test_null();
17467d36db35SAvi Kivity 
17477d36db35SAvi Kivity 	test_shld();
17487d36db35SAvi Kivity 	test_push_pop();
17497d36db35SAvi Kivity 	test_pusha_popa();
17507d36db35SAvi Kivity 	test_mov_imm();
17517d36db35SAvi Kivity 	test_cmp_imm();
17527d36db35SAvi Kivity 	test_add_imm();
17537d36db35SAvi Kivity 	test_sub_imm();
17547d36db35SAvi Kivity 	test_xor_imm();
17557d36db35SAvi Kivity 	test_io();
17567d36db35SAvi Kivity 	test_eflags_insn();
17577d36db35SAvi Kivity 	test_jcc_short();
17587d36db35SAvi Kivity 	test_jcc_near();
17597d36db35SAvi Kivity 	/* test_call() uses short jump so call it after testing jcc */
17607d36db35SAvi Kivity 	test_call();
17617d36db35SAvi Kivity 	/* long jmp test uses call near so test it after testing call */
17627d36db35SAvi Kivity 	test_long_jmp();
17637d36db35SAvi Kivity 	test_xchg();
17647d36db35SAvi Kivity 	test_iret();
176596b9ca1eSMohammed Gamal 	test_int();
17668202cf84SRoman Bolshakov 	test_sti_inhibit();
1767fa74f8a6SMohammed Gamal 	test_imul();
176859317bd1SMohammed Gamal 	test_mul();
17690d4c7614SMohammed Gamal 	test_div();
17700d4c7614SMohammed Gamal 	test_idiv();
1771eacef4e2SWei Yongjun 	test_loopcc();
17726e293cf5SWei Yongjun 	test_cbw();
17730cbd5b06SMohammed Gamal 	test_cwd_cdq();
1774b274feedSAvi Kivity 	test_das();
177537f51a4aSWei Yongjun 	test_lds_lss();
1776b1c7c575SWei Yongjun 	test_jcxz();
17778f578e98SAvi Kivity 	test_cpuid();
1778ed93f43bSAvi Kivity 	test_ss_base_for_esp_ebp();
1779c2281fa4SAvi Kivity 	test_sgdt_sidt();
17807ae3645aSAvi Kivity 	test_lahf();
178188b6dac4SPaolo Bonzini 	test_sahf();
1782fd9ea640SAvi Kivity 	test_movzx_movsx();
1783b493b2e8SAvi Kivity 	test_bswap();
17848cd86387SGleb Natapov 	test_aad();
17852a9b5718SPaolo Bonzini 	test_aam();
17862a9b5718SPaolo Bonzini 	test_xlat();
17872a9b5718SPaolo Bonzini 	test_salc();
17880987db7aSGleb Natapov 	test_fninit();
17890a5701edSNadav Amit 	test_dr_mod();
179099ee878cSNadav Amit 	test_smsw();
17911a4c03a0SArthur Chunqi Li 	test_nopl();
17927bee560dSNadav Amit 	test_xadd();
1793b5105e8bSPaolo Bonzini 	test_perf_loop();
1794b5105e8bSPaolo Bonzini 	test_perf_mov();
1795b5105e8bSPaolo Bonzini 	test_perf_arith();
1796b5105e8bSPaolo Bonzini 	test_perf_memory_load();
17979306cb8eSPaolo Bonzini 	test_perf_memory_store();
1798b5105e8bSPaolo Bonzini 	test_perf_memory_rmw();
17997d36db35SAvi Kivity 
1800b393fe28SNadav Amit 	exit(failed);
18017d36db35SAvi Kivity }
18027d36db35SAvi Kivity 
18037d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff };
18047d36db35SAvi Kivity 
1805975ca087SPeter Feiner struct table_descr r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt };
1806a529af7cSNadav Amit struct table_descr r_idt_descr = { 0x3ff, 0 };
18077d36db35SAvi Kivity 
18087d36db35SAvi Kivity asm(
18097d36db35SAvi Kivity 	".section .init \n\t"
18107d36db35SAvi Kivity 
18117d36db35SAvi Kivity 	".code32 \n\t"
18127d36db35SAvi Kivity 
18137d36db35SAvi Kivity 	"mb_magic = 0x1BADB002 \n\t"
18147d36db35SAvi Kivity 	"mb_flags = 0x0 \n\t"
18157d36db35SAvi Kivity 
18167d36db35SAvi Kivity 	"# multiboot header \n\t"
18177d36db35SAvi Kivity 	".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t"
18187d36db35SAvi Kivity 
18197d36db35SAvi Kivity 	".globl start \n\t"
18207d36db35SAvi Kivity 	".data \n\t"
18217d36db35SAvi Kivity 	". = . + 4096 \n\t"
18227d36db35SAvi Kivity 	"stacktop: \n\t"
18237d36db35SAvi Kivity 
18247d36db35SAvi Kivity 	".text \n\t"
18257d36db35SAvi Kivity 	"start: \n\t"
18267d36db35SAvi Kivity 	"lgdt r_gdt_descr \n\t"
1827a529af7cSNadav Amit 	"lidt r_idt_descr \n\t"
18287d36db35SAvi Kivity 	"ljmp $8, $1f; 1: \n\t"
18297d36db35SAvi Kivity 	".code16gcc \n\t"
18307d36db35SAvi Kivity 	"mov $16, %eax \n\t"
18317d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
18327d36db35SAvi Kivity 	"mov %ax, %es \n\t"
18337d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
18347d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
18357d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
18367d36db35SAvi Kivity 	"mov %cr0, %eax \n\t"
18377d36db35SAvi Kivity 	"btc $0, %eax \n\t"
18387d36db35SAvi Kivity 	"mov %eax, %cr0 \n\t"
18397d36db35SAvi Kivity 	"ljmp $0, $realmode_entry \n\t"
18407d36db35SAvi Kivity 
18417d36db35SAvi Kivity 	"realmode_entry: \n\t"
18427d36db35SAvi Kivity 
18437d36db35SAvi Kivity 	"xor %ax, %ax \n\t"
18447d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
18457d36db35SAvi Kivity 	"mov %ax, %es \n\t"
18467d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
18477d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
18487d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
18497d36db35SAvi Kivity 	"mov $stacktop, %esp\n\t"
18507d36db35SAvi Kivity 	"ljmp $0, $realmode_start \n\t"
18517d36db35SAvi Kivity 
18527d36db35SAvi Kivity 	".code16gcc \n\t"
18537d36db35SAvi Kivity 	);
1854