xref: /kvm-unit-tests/x86/realmode.c (revision 231b4c3b57dab2b0733e77a8cffab5064f248dbf)
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);
1187d36db35SAvi Kivity }
1197d36db35SAvi Kivity 
1207d36db35SAvi Kivity struct regs {
1217d36db35SAvi Kivity 	u32 eax, ebx, ecx, edx;
1227d36db35SAvi Kivity 	u32 esi, edi, esp, ebp;
1237d36db35SAvi Kivity 	u32 eip, eflags;
1247d36db35SAvi Kivity };
1257d36db35SAvi Kivity 
126975ca087SPeter Feiner struct table_descr {
127975ca087SPeter Feiner 	u16 limit;
128975ca087SPeter Feiner 	void *base;
129975ca087SPeter Feiner } __attribute__((packed));
130975ca087SPeter Feiner 
1317d36db35SAvi Kivity static u64 gdt[] = {
1327d36db35SAvi Kivity 	0,
1337d36db35SAvi Kivity 	0x00cf9b000000ffffull, // flat 32-bit code segment
1347d36db35SAvi Kivity 	0x00cf93000000ffffull, // flat 32-bit data segment
1357d36db35SAvi Kivity };
1367d36db35SAvi Kivity 
137975ca087SPeter Feiner static struct table_descr gdt_descr = {
1387d36db35SAvi Kivity 	sizeof(gdt) - 1,
1397d36db35SAvi Kivity 	gdt,
1407d36db35SAvi Kivity };
1417d36db35SAvi Kivity 
142d4dc402cSAvi Kivity struct insn_desc {
143d4dc402cSAvi Kivity     u16 ptr;
144d4dc402cSAvi Kivity     u16 len;
145d4dc402cSAvi Kivity };
146d4dc402cSAvi Kivity 
147bd62e289SBill Wendling struct {
148bd62e289SBill Wendling 	u32 stack[128];
149bd62e289SBill Wendling 	char top[];
150bd62e289SBill Wendling } tmp_stack;
151bd62e289SBill Wendling 
15218253fdeSAvi Kivity static struct regs inregs, outregs;
15318253fdeSAvi Kivity 
154bd62e289SBill Wendling static inline void init_inregs(struct regs *regs)
155bd62e289SBill Wendling {
156bd62e289SBill Wendling 	inregs = (struct regs){ 0 };
157bd62e289SBill Wendling 	if (regs)
158bd62e289SBill Wendling 		inregs = *regs;
159bd62e289SBill Wendling 	if (!inregs.esp)
160bd62e289SBill Wendling 		inregs.esp = (unsigned long)&tmp_stack.top;
161bd62e289SBill Wendling }
162bd62e289SBill Wendling 
16318253fdeSAvi Kivity static void exec_in_big_real_mode(struct insn_desc *insn)
1647d36db35SAvi Kivity {
1657d36db35SAvi Kivity 	unsigned long tmp;
1667d36db35SAvi Kivity 	static struct regs save;
1677d36db35SAvi Kivity 	int i;
1687d36db35SAvi Kivity 	extern u8 test_insn[], test_insn_end[];
1697d36db35SAvi Kivity 
170d4dc402cSAvi Kivity 	for (i = 0; i < insn->len; ++i)
171d4dc402cSAvi Kivity 	    test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i];
1727d36db35SAvi Kivity 	for (; i < test_insn_end - test_insn; ++i)
1737d36db35SAvi Kivity 		test_insn[i] = 0x90; // nop
1747d36db35SAvi Kivity 
17518253fdeSAvi Kivity 	save = inregs;
1767d36db35SAvi Kivity 	asm volatile(
1777d36db35SAvi Kivity 		"lgdtl %[gdt_descr] \n\t"
1787d36db35SAvi Kivity 		"mov %%cr0, %[tmp] \n\t"
1797d36db35SAvi Kivity 		"or $1, %[tmp] \n\t"
1807d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
1817d36db35SAvi Kivity 		"mov %[bigseg], %%gs \n\t"
1827d36db35SAvi Kivity 		"and $-2, %[tmp] \n\t"
1837d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
1847d36db35SAvi Kivity 
185eb6687a2SBill Wendling 		/* Save ES, because it is clobbered by some tests. */
186eb6687a2SBill Wendling 		"pushw %%es \n\t"
187eb6687a2SBill Wendling 
18832001692SAvi Kivity 		"pushw %[save]+36; popfw \n\t"
1897d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
1907d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
1917d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
1927d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
1937d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
1947d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
1957d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
1967d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
1977d36db35SAvi Kivity 
1987d36db35SAvi Kivity 		"test_insn: . = . + 32\n\t"
1997d36db35SAvi Kivity 		"test_insn_end: \n\t"
2007d36db35SAvi Kivity 
2017d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
2027d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
2037d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
2047d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
2057d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
2067d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
2077d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
2087d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
2097d36db35SAvi Kivity 
2107d36db35SAvi Kivity 		/* Save EFLAGS in outregs*/
2117d36db35SAvi Kivity 		"pushfl \n\t"
2127d36db35SAvi Kivity 		"popl %[save]+36 \n\t"
2137d36db35SAvi Kivity 
214eb6687a2SBill Wendling 		/* Restore ES for future rep string operations. */
215eb6687a2SBill Wendling 		"popw %%es \n\t"
216eb6687a2SBill Wendling 
2175edbb9aeSPaolo Bonzini 		/* Restore DF for the harness code */
2185edbb9aeSPaolo Bonzini 		"cld\n\t"
2197d36db35SAvi Kivity 		"xor %[tmp], %[tmp] \n\t"
2207d36db35SAvi Kivity 		"mov %[tmp], %%gs \n\t"
2217d36db35SAvi Kivity 		: [tmp]"=&r"(tmp), [save]"+m"(save)
2227d36db35SAvi Kivity 		: [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16)
2237d36db35SAvi Kivity 		: "cc", "memory"
2247d36db35SAvi Kivity 		);
22518253fdeSAvi Kivity 	outregs = save;
2267d36db35SAvi Kivity }
2277d36db35SAvi Kivity 
2287d36db35SAvi Kivity #define R_AX 1
2297d36db35SAvi Kivity #define R_BX 2
2307d36db35SAvi Kivity #define R_CX 4
2317d36db35SAvi Kivity #define R_DX 8
2327d36db35SAvi Kivity #define R_SI 16
2337d36db35SAvi Kivity #define R_DI 32
2347d36db35SAvi Kivity #define R_SP 64
2357d36db35SAvi Kivity #define R_BP 128
2367d36db35SAvi Kivity 
2372e3f9f1fSThomas Huth static int regs_equal(int ignore)
2387d36db35SAvi Kivity {
23918253fdeSAvi Kivity 	const u32 *p1 = &inregs.eax, *p2 = &outregs.eax;  // yuck
2407d36db35SAvi Kivity 	int i;
2417d36db35SAvi Kivity 
2427d36db35SAvi Kivity 	for (i = 0; i < 8; ++i)
2437d36db35SAvi Kivity 		if (!(ignore & (1 << i)) && p1[i] != p2[i])
2447d36db35SAvi Kivity 			return 0;
2457d36db35SAvi Kivity 	return 1;
2467d36db35SAvi Kivity }
2477d36db35SAvi Kivity 
2486055ea1fSAvi Kivity static void report(const char *name, u16 regs_ignore, _Bool ok)
24981050840SAvi Kivity {
2506055ea1fSAvi Kivity     if (!regs_equal(regs_ignore)) {
2516055ea1fSAvi Kivity 	ok = 0;
2526055ea1fSAvi Kivity     }
25381050840SAvi Kivity     print_serial(ok ? "PASS: " : "FAIL: ");
25481050840SAvi Kivity     print_serial(name);
25581050840SAvi Kivity     print_serial("\n");
256b393fe28SNadav Amit     if (!ok)
257b393fe28SNadav Amit 	failed = 1;
25881050840SAvi Kivity }
25981050840SAvi Kivity 
2607d36db35SAvi Kivity #define MK_INSN(name, str)				\
2617d36db35SAvi Kivity     asm (						\
262d4dc402cSAvi Kivity 	 ".pushsection .data.insn  \n\t"		\
263d4dc402cSAvi Kivity 	 "insn_" #name ": \n\t"				\
264d4dc402cSAvi Kivity 	 ".word 1001f, 1002f - 1001f \n\t"		\
265d4dc402cSAvi Kivity 	 ".popsection \n\t"				\
266d4dc402cSAvi Kivity 	 ".pushsection .text.insn, \"ax\" \n\t"		\
267d4dc402cSAvi Kivity 	 "1001: \n\t"					\
268d4dc402cSAvi Kivity 	 "insn_code_" #name ": " str " \n\t"		\
269d4dc402cSAvi Kivity 	 "1002: \n\t"					\
270d4dc402cSAvi Kivity 	 ".popsection"					\
2717d36db35SAvi Kivity     );							\
272d4dc402cSAvi Kivity     extern struct insn_desc insn_##name;
2737d36db35SAvi Kivity 
2742e3f9f1fSThomas Huth static void test_xchg(void)
2757d36db35SAvi Kivity {
2767d36db35SAvi Kivity 	MK_INSN(xchg_test1, "xchg %eax,%eax\n\t");
2777d36db35SAvi Kivity 	MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t");
2787d36db35SAvi Kivity 	MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t");
2797d36db35SAvi Kivity 	MK_INSN(xchg_test4, "xchg %eax,%edx\n\t");
2807d36db35SAvi Kivity 	MK_INSN(xchg_test5, "xchg %eax,%esi\n\t");
2817d36db35SAvi Kivity 	MK_INSN(xchg_test6, "xchg %eax,%edi\n\t");
2827d36db35SAvi Kivity 	MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t");
2837d36db35SAvi Kivity 	MK_INSN(xchg_test8, "xchg %eax,%esp\n\t");
2847d36db35SAvi Kivity 
28518253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7};
2867d36db35SAvi Kivity 
28718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test1);
2886055ea1fSAvi Kivity 	report("xchg 1", 0, 1);
28918253fdeSAvi Kivity 
29018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test2);
2916055ea1fSAvi Kivity 	report("xchg 2", R_AX | R_BX,
2926055ea1fSAvi Kivity 	       outregs.eax == inregs.ebx && outregs.ebx == inregs.eax);
2937d36db35SAvi Kivity 
29418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test3);
2956055ea1fSAvi Kivity 	report("xchg 3", R_AX | R_CX,
2966055ea1fSAvi Kivity 	       outregs.eax == inregs.ecx && outregs.ecx == inregs.eax);
2977d36db35SAvi Kivity 
29818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test4);
2996055ea1fSAvi Kivity 	report("xchg 4", R_AX | R_DX,
3006055ea1fSAvi Kivity 	       outregs.eax == inregs.edx && outregs.edx == inregs.eax);
3017d36db35SAvi Kivity 
30218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test5);
3036055ea1fSAvi Kivity 	report("xchg 5", R_AX | R_SI,
3046055ea1fSAvi Kivity 	       outregs.eax == inregs.esi && outregs.esi == inregs.eax);
3057d36db35SAvi Kivity 
30618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test6);
3076055ea1fSAvi Kivity 	report("xchg 6", R_AX | R_DI,
3086055ea1fSAvi Kivity 	       outregs.eax == inregs.edi && outregs.edi == inregs.eax);
3097d36db35SAvi Kivity 
31018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test7);
3116055ea1fSAvi Kivity 	report("xchg 7", R_AX | R_BP,
3126055ea1fSAvi Kivity 	       outregs.eax == inregs.ebp && outregs.ebp == inregs.eax);
3137d36db35SAvi Kivity 
31418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test8);
3156055ea1fSAvi Kivity 	report("xchg 8", R_AX | R_SP,
3166055ea1fSAvi Kivity 	       outregs.eax == inregs.esp && outregs.esp == inregs.eax);
3177d36db35SAvi Kivity }
3187d36db35SAvi Kivity 
3192e3f9f1fSThomas Huth static void test_shld(void)
3207d36db35SAvi Kivity {
3217d36db35SAvi Kivity 	MK_INSN(shld_test, "shld $8,%edx,%eax\n\t");
3227d36db35SAvi Kivity 
323bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0xbe, .edx = 0xef000000 });
324bd62e289SBill Wendling 
32518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_shld_test);
3266055ea1fSAvi Kivity 	report("shld", ~0, outregs.eax == 0xbeef);
3277d36db35SAvi Kivity }
3287d36db35SAvi Kivity 
3292e3f9f1fSThomas Huth static void test_mov_imm(void)
3307d36db35SAvi Kivity {
3317d36db35SAvi Kivity 	MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax");
3327d36db35SAvi Kivity 	MK_INSN(mov_r16_imm_1, "mov $1234, %ax");
3337d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_1, "mov $0x12, %ah");
3347d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_2, "mov $0x34, %al");
3357d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t");
3367d36db35SAvi Kivity 
337bd62e289SBill Wendling 	init_inregs(NULL);
33818253fdeSAvi Kivity 
33918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r16_imm_1);
3406055ea1fSAvi Kivity 	report("mov 1", R_AX, outregs.eax == 1234);
3417d36db35SAvi Kivity 
3427d36db35SAvi Kivity 	/* test mov $imm, %eax */
34318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r32_imm_1);
3446055ea1fSAvi Kivity 	report("mov 2", R_AX, outregs.eax == 1234567890);
3457d36db35SAvi Kivity 
3467d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
34718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_1);
3486055ea1fSAvi Kivity 	report("mov 3", R_AX, outregs.eax == 0x1200);
3497d36db35SAvi Kivity 
35018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_2);
3516055ea1fSAvi Kivity 	report("mov 4", R_AX, outregs.eax == 0x34);
3527d36db35SAvi Kivity 
35318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_3);
3546055ea1fSAvi Kivity 	report("mov 5", R_AX, outregs.eax == 0x1234);
3557d36db35SAvi Kivity }
3567d36db35SAvi Kivity 
3572e3f9f1fSThomas Huth static void test_sub_imm(void)
3587d36db35SAvi Kivity {
3597d36db35SAvi Kivity 	MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t");
3607d36db35SAvi Kivity 	MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t");
3617d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t");
3627d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t");
3637d36db35SAvi Kivity 
364bd62e289SBill Wendling 	init_inregs(NULL);
36518253fdeSAvi Kivity 
36618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r16_imm_1);
3676055ea1fSAvi Kivity 	report("sub 1", R_AX, outregs.eax == 1224);
3687d36db35SAvi Kivity 
3697d36db35SAvi Kivity 	/* test mov $imm, %eax */
37018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r32_imm_1);
3716055ea1fSAvi Kivity 	report("sub 2", R_AX, outregs.eax == 1234567880);
3727d36db35SAvi Kivity 
3737d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
37418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_1);
3756055ea1fSAvi Kivity 	report("sub 3", R_AX, outregs.eax == 0x0200);
3767d36db35SAvi Kivity 
37718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_2);
3786055ea1fSAvi Kivity 	report("sub 4", R_AX, outregs.eax == 0x24);
3797d36db35SAvi Kivity }
3807d36db35SAvi Kivity 
3812e3f9f1fSThomas Huth static void test_xor_imm(void)
3827d36db35SAvi Kivity {
3837d36db35SAvi Kivity 	MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t");
3847d36db35SAvi Kivity 	MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t");
3857d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t");
3867d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t");
3877d36db35SAvi Kivity 
388bd62e289SBill Wendling 	init_inregs(NULL);
38918253fdeSAvi Kivity 
39018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r16_imm_1);
3916055ea1fSAvi Kivity 	report("xor 1", R_AX, outregs.eax == 0);
3927d36db35SAvi Kivity 
3937d36db35SAvi Kivity 	/* test mov $imm, %eax */
39418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r32_imm_1);
3956055ea1fSAvi Kivity 	report("xor 2", R_AX, outregs.eax == 0);
3967d36db35SAvi Kivity 
3977d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
39818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_1);
3996055ea1fSAvi Kivity 	report("xor 3", R_AX, outregs.eax == 0);
4007d36db35SAvi Kivity 
40118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_2);
4026055ea1fSAvi Kivity 	report("xor 4", R_AX, outregs.eax == 0);
4037d36db35SAvi Kivity }
4047d36db35SAvi Kivity 
4052e3f9f1fSThomas Huth static void test_cmp_imm(void)
4067d36db35SAvi Kivity {
4077d36db35SAvi Kivity 	MK_INSN(cmp_test1, "mov $0x34, %al\n\t"
4087d36db35SAvi Kivity 			   "cmp $0x34, %al\n\t");
4097d36db35SAvi Kivity 	MK_INSN(cmp_test2, "mov $0x34, %al\n\t"
4107d36db35SAvi Kivity 			   "cmp $0x39, %al\n\t");
4117d36db35SAvi Kivity 	MK_INSN(cmp_test3, "mov $0x34, %al\n\t"
4127d36db35SAvi Kivity 			   "cmp $0x24, %al\n\t");
4137d36db35SAvi Kivity 
414bd62e289SBill Wendling 	init_inregs(NULL);
41518253fdeSAvi Kivity 
4167d36db35SAvi Kivity 	/* test cmp imm8 with AL */
4177d36db35SAvi Kivity 	/* ZF: (bit 6) Zero Flag becomes 1 if an operation results
4187d36db35SAvi Kivity 	 * in a 0 writeback, or 0 register
4197d36db35SAvi Kivity 	 */
42018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test1);
4216055ea1fSAvi Kivity 	report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6));
4227d36db35SAvi Kivity 
42318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test2);
4246055ea1fSAvi Kivity 	report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0);
4257d36db35SAvi Kivity 
42618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test3);
4276055ea1fSAvi Kivity 	report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0);
4287d36db35SAvi Kivity }
4297d36db35SAvi Kivity 
4302e3f9f1fSThomas Huth static void test_add_imm(void)
4317d36db35SAvi Kivity {
4327d36db35SAvi Kivity 	MK_INSN(add_test1, "mov $0x43211234, %eax \n\t"
4337d36db35SAvi Kivity 			   "add $0x12344321, %eax \n\t");
4347d36db35SAvi Kivity 	MK_INSN(add_test2, "mov $0x12, %eax \n\t"
4357d36db35SAvi Kivity 			   "add $0x21, %al\n\t");
4367d36db35SAvi Kivity 
437bd62e289SBill Wendling 	init_inregs(NULL);
43818253fdeSAvi Kivity 
43918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test1);
4406055ea1fSAvi Kivity 	report("add 1", ~0, outregs.eax == 0x55555555);
4417d36db35SAvi Kivity 
44218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test2);
4436055ea1fSAvi Kivity 	report("add 2", ~0, outregs.eax == 0x33);
4447d36db35SAvi Kivity }
4457d36db35SAvi Kivity 
4462e3f9f1fSThomas Huth static void test_eflags_insn(void)
4477d36db35SAvi Kivity {
4487d36db35SAvi Kivity 	MK_INSN(clc, "clc");
449b3261e48SMohammed Gamal 	MK_INSN(stc, "stc");
4507d36db35SAvi Kivity 	MK_INSN(cli, "cli");
4517d36db35SAvi Kivity 	MK_INSN(sti, "sti");
4527d36db35SAvi Kivity 	MK_INSN(cld, "cld");
4537d36db35SAvi Kivity 	MK_INSN(std, "std");
4547d36db35SAvi Kivity 
455bd62e289SBill Wendling 	init_inregs(NULL);
45618253fdeSAvi Kivity 
45718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_clc);
4586055ea1fSAvi Kivity 	report("clc", ~0, (outregs.eflags & 1) == 0);
4597d36db35SAvi Kivity 
46018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_stc);
4616055ea1fSAvi Kivity 	report("stc", ~0, (outregs.eflags & 1) == 1);
462b3261e48SMohammed Gamal 
46318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cli);
4646055ea1fSAvi Kivity 	report("cli", ~0, !(outregs.eflags & (1 << 9)));
4657d36db35SAvi Kivity 
46618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sti);
4676055ea1fSAvi Kivity 	report("sti", ~0, outregs.eflags & (1 << 9));
4687d36db35SAvi Kivity 
46918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cld);
4706055ea1fSAvi Kivity 	report("cld", ~0, !(outregs.eflags & (1 << 10)));
4717d36db35SAvi Kivity 
47218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_std);
4736055ea1fSAvi Kivity 	report("std", ~0, (outregs.eflags & (1 << 10)));
4747d36db35SAvi Kivity }
4757d36db35SAvi Kivity 
4762e3f9f1fSThomas Huth static void test_io(void)
4777d36db35SAvi Kivity {
4787d36db35SAvi Kivity 	MK_INSN(io_test1, "mov $0xff, %al \n\t"
4797d36db35SAvi Kivity 		          "out %al, $0xe0 \n\t"
4807d36db35SAvi Kivity 		          "mov $0x00, %al \n\t"
4817d36db35SAvi Kivity 			  "in $0xe0, %al \n\t");
4827d36db35SAvi Kivity 	MK_INSN(io_test2, "mov $0xffff, %ax \n\t"
4837d36db35SAvi Kivity 			  "out %ax, $0xe0 \n\t"
4847d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
4857d36db35SAvi Kivity 			  "in $0xe0, %ax \n\t");
4867d36db35SAvi Kivity 	MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t"
4877d36db35SAvi Kivity 			  "out %eax, $0xe0 \n\t"
4887d36db35SAvi Kivity 			  "mov $0x000000, %eax \n\t"
4897d36db35SAvi Kivity 			  "in $0xe0, %eax \n\t");
4907d36db35SAvi Kivity 	MK_INSN(io_test4, "mov $0xe0, %dx \n\t"
4917d36db35SAvi Kivity 			  "mov $0xff, %al \n\t"
4927d36db35SAvi Kivity 			  "out %al, %dx \n\t"
4937d36db35SAvi Kivity 			  "mov $0x00, %al \n\t"
4947d36db35SAvi Kivity 			  "in %dx, %al \n\t");
4957d36db35SAvi Kivity 	MK_INSN(io_test5, "mov $0xe0, %dx \n\t"
4967d36db35SAvi Kivity 			  "mov $0xffff, %ax \n\t"
4977d36db35SAvi Kivity 			  "out %ax, %dx \n\t"
4987d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
4997d36db35SAvi Kivity 			  "in %dx, %ax \n\t");
5007d36db35SAvi Kivity 	MK_INSN(io_test6, "mov $0xe0, %dx \n\t"
5017d36db35SAvi Kivity 			  "mov $0xffffffff, %eax \n\t"
5027d36db35SAvi Kivity 			  "out %eax, %dx \n\t"
5037d36db35SAvi Kivity 			  "mov $0x00000000, %eax \n\t"
5047d36db35SAvi Kivity 			  "in %dx, %eax \n\t");
5057d36db35SAvi Kivity 
506bd62e289SBill Wendling 	init_inregs(NULL);
50718253fdeSAvi Kivity 
50818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test1);
5096055ea1fSAvi Kivity 	report("pio 1", R_AX, outregs.eax == 0xff);
5107d36db35SAvi Kivity 
51118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test2);
5126055ea1fSAvi Kivity 	report("pio 2", R_AX, outregs.eax == 0xffff);
5137d36db35SAvi Kivity 
51418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test3);
5156055ea1fSAvi Kivity 	report("pio 3", R_AX, outregs.eax == 0xffffffff);
5167d36db35SAvi Kivity 
51718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test4);
5186055ea1fSAvi Kivity 	report("pio 4", R_AX|R_DX, outregs.eax == 0xff);
5197d36db35SAvi Kivity 
52018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test5);
5216055ea1fSAvi Kivity 	report("pio 5", R_AX|R_DX, outregs.eax == 0xffff);
5227d36db35SAvi Kivity 
52318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test6);
5246055ea1fSAvi Kivity 	report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff);
5257d36db35SAvi Kivity }
5267d36db35SAvi Kivity 
527c0b7268dSAvi Kivity asm ("retf: lretw");
5282e3f9f1fSThomas Huth extern void retf(void);
529c0b7268dSAvi Kivity 
5304f66bc86SBruce Rogers asm ("retf_imm: lretw $10");
5312e3f9f1fSThomas Huth extern void retf_imm(void);
5324f66bc86SBruce Rogers 
5332e3f9f1fSThomas Huth static void test_call(void)
5347d36db35SAvi Kivity {
535c0b7268dSAvi Kivity 	u32 addr;
5367d36db35SAvi Kivity 
5377d36db35SAvi Kivity 	MK_INSN(call1, "mov $test_function, %eax \n\t"
5387d36db35SAvi Kivity 		       "call *%eax\n\t");
5397d36db35SAvi Kivity 	MK_INSN(call_near1, "jmp 2f\n\t"
5407d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5417d36db35SAvi Kivity 			    "ret\n\t"
5427d36db35SAvi Kivity 			    "2: call 1b\t");
5437d36db35SAvi Kivity 	MK_INSN(call_near2, "call 1f\n\t"
5447d36db35SAvi Kivity 			    "jmp 2f\n\t"
5457d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5467d36db35SAvi Kivity 			    "ret\n\t"
5477d36db35SAvi Kivity 			    "2:\t");
548c0b7268dSAvi Kivity 	MK_INSN(call_far1,  "lcallw *(%ebx)\n\t");
549556d2680SWei Yongjun 	MK_INSN(call_far2,  "lcallw $0, $retf\n\t");
550c6061817SAvi Kivity 	MK_INSN(ret_imm,    "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b");
5514f66bc86SBruce Rogers 	MK_INSN(retf_imm,   "sub $10, %sp; lcallw $0, $retf_imm");
5527d36db35SAvi Kivity 
553bd62e289SBill Wendling 	init_inregs(NULL);
554bd62e289SBill Wendling 
55518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call1);
5566055ea1fSAvi Kivity 	report("call 1", R_AX, outregs.eax == 0x1234);
5577d36db35SAvi Kivity 
55818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near1);
5596055ea1fSAvi Kivity 	report("call near 1", R_AX, outregs.eax == 0x1234);
5607d36db35SAvi Kivity 
56118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near2);
5626055ea1fSAvi Kivity 	report("call near 2", R_AX, outregs.eax == 0x1234);
563c0b7268dSAvi Kivity 
564c0b7268dSAvi Kivity 	addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f);
565c0b7268dSAvi Kivity 	inregs.ebx = (unsigned)&addr;
56618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_far1);
5676055ea1fSAvi Kivity 	report("call far 1", 0, 1);
568c6061817SAvi Kivity 
569556d2680SWei Yongjun 	exec_in_big_real_mode(&insn_call_far2);
570556d2680SWei Yongjun 	report("call far 2", 0, 1);
571556d2680SWei Yongjun 
57218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_ret_imm);
5736055ea1fSAvi Kivity 	report("ret imm 1", 0, 1);
5744f66bc86SBruce Rogers 
5754f66bc86SBruce Rogers 	exec_in_big_real_mode(&insn_retf_imm);
5764f66bc86SBruce Rogers 	report("retf imm 1", 0, 1);
5777d36db35SAvi Kivity }
5787d36db35SAvi Kivity 
5792e3f9f1fSThomas Huth static void test_jcc_short(void)
5807d36db35SAvi Kivity {
5817d36db35SAvi Kivity 	MK_INSN(jnz_short1, "jnz 1f\n\t"
5827d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
5837d36db35SAvi Kivity 		            "1:\n\t");
5847d36db35SAvi Kivity 	MK_INSN(jnz_short2, "1:\n\t"
5857d36db35SAvi Kivity 			    "cmp $0x1234, %eax\n\t"
5867d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
5877d36db35SAvi Kivity 		            "jnz 1b\n\t");
5887d36db35SAvi Kivity 	MK_INSN(jmp_short1, "jmp 1f\n\t"
5897d36db35SAvi Kivity 		      "mov $0x1234, %eax\n\t"
5907d36db35SAvi Kivity 		      "1:\n\t");
5917d36db35SAvi Kivity 
592bd62e289SBill Wendling 	init_inregs(NULL);
5937d36db35SAvi Kivity 
59418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short1);
5956055ea1fSAvi Kivity 	report("jnz short 1", ~0, 1);
59618253fdeSAvi Kivity 
59718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short2);
5986055ea1fSAvi Kivity 	report("jnz short 2", R_AX, (outregs.eflags & (1 << 6)));
5997d36db35SAvi Kivity 
60018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_short1);
6016055ea1fSAvi Kivity 	report("jmp short 1", ~0, 1);
6027d36db35SAvi Kivity }
6037d36db35SAvi Kivity 
6042e3f9f1fSThomas Huth static void test_jcc_near(void)
6057d36db35SAvi Kivity {
6067d36db35SAvi Kivity 	/* encode near jmp manually. gas will not do it if offsets < 127 byte */
6077d36db35SAvi Kivity 	MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t"
6087d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
6097d36db35SAvi Kivity 	MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t"
6107d36db35SAvi Kivity 			   "mov $0x1234, %eax\n\t"
6117d36db35SAvi Kivity 		           ".byte 0x0f, 0x85, 0xf0, 0xff\n\t");
6127d36db35SAvi Kivity 	MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t"
6137d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
6147d36db35SAvi Kivity 
615bd62e289SBill Wendling 	init_inregs(NULL);
6167d36db35SAvi Kivity 
61718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near1);
6186055ea1fSAvi Kivity 	report("jnz near 1", 0, 1);
61918253fdeSAvi Kivity 
62018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near2);
6216055ea1fSAvi Kivity 	report("jnz near 2", R_AX, outregs.eflags & (1 << 6));
6227d36db35SAvi Kivity 
62318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_near1);
6246055ea1fSAvi Kivity 	report("jmp near 1", 0, 1);
6257d36db35SAvi Kivity }
6267d36db35SAvi Kivity 
6272e3f9f1fSThomas Huth static void test_long_jmp(void)
6287d36db35SAvi Kivity {
6297d36db35SAvi Kivity 	MK_INSN(long_jmp, "call 1f\n\t"
6307d36db35SAvi Kivity 			  "jmp 2f\n\t"
6317d36db35SAvi Kivity 			  "1: jmp $0, $test_function\n\t"
6327d36db35SAvi Kivity 		          "2:\n\t");
633bd62e289SBill Wendling 
634bd62e289SBill Wendling 	init_inregs(NULL);
635bd62e289SBill Wendling 
63618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_long_jmp);
6376055ea1fSAvi Kivity 	report("jmp far 1", R_AX, outregs.eax == 0x1234);
6387d36db35SAvi Kivity }
639fa74f8a6SMohammed Gamal 
6402e3f9f1fSThomas Huth static void test_push_pop(void)
6417d36db35SAvi Kivity {
6427d36db35SAvi Kivity 	MK_INSN(push32, "mov $0x12345678, %eax\n\t"
6437d36db35SAvi Kivity 			"push %eax\n\t"
6447d36db35SAvi Kivity 			"pop %ebx\n\t");
6457d36db35SAvi Kivity 	MK_INSN(push16, "mov $0x1234, %ax\n\t"
6467d36db35SAvi Kivity 			"push %ax\n\t"
6477d36db35SAvi Kivity 			"pop %bx\n\t");
6487d36db35SAvi Kivity 
6497d36db35SAvi Kivity 	MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten
6507d36db35SAvi Kivity 			 "mov $0x123, %ax\n\t"
6517d36db35SAvi Kivity 			 "mov %ax, %es\n\t"
652*231b4c3bSRoman Bolshakov 			 "pushw %es\n\t"
6537d36db35SAvi Kivity 			 "pop %bx \n\t"
6547d36db35SAvi Kivity 			 );
6557d36db35SAvi Kivity 	MK_INSN(pop_es, "push %ax\n\t"
656*231b4c3bSRoman Bolshakov 			"popw %es\n\t"
6577d36db35SAvi Kivity 			"mov %es, %bx\n\t"
6587d36db35SAvi Kivity 			);
659*231b4c3bSRoman Bolshakov 	MK_INSN(push_pop_ss, "pushw %ss\n\t"
6607d36db35SAvi Kivity 			     "pushw %ax\n\t"
6617d36db35SAvi Kivity 			     "popw %ss\n\t"
6627d36db35SAvi Kivity 			     "mov %ss, %bx\n\t"
663*231b4c3bSRoman Bolshakov 			     "popw %ss\n\t"
6647d36db35SAvi Kivity 			);
665*231b4c3bSRoman Bolshakov 	MK_INSN(push_pop_fs, "pushl %fs\n\t"
6667d36db35SAvi Kivity 			     "pushl %eax\n\t"
6677d36db35SAvi Kivity 			     "popl %fs\n\t"
6687d36db35SAvi Kivity 			     "mov %fs, %ebx\n\t"
669*231b4c3bSRoman Bolshakov 			     "popl %fs\n\t"
6707d36db35SAvi Kivity 			);
67109b657b6SAvi Kivity 	MK_INSN(push_pop_high_esp_bits,
67209b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
67309b657b6SAvi Kivity 		"push %ax; \n\t"
67409b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
67509b657b6SAvi Kivity 		"pop %bx");
6767d36db35SAvi Kivity 
677bd62e289SBill Wendling 	init_inregs(NULL);
67818253fdeSAvi Kivity 
67918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push32);
6806055ea1fSAvi Kivity 	report("push/pop 1", R_AX|R_BX,
6816055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x12345678);
6827d36db35SAvi Kivity 
68318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push16);
6846055ea1fSAvi Kivity 	report("push/pop 2", R_AX|R_BX,
6856055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x1234);
6867d36db35SAvi Kivity 
68718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_es);
6886055ea1fSAvi Kivity 	report("push/pop 3", R_AX|R_BX,
6896055ea1fSAvi Kivity 	       outregs.ebx == outregs.eax && outregs.eax == 0x123);
6907d36db35SAvi Kivity 
69118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pop_es);
6926055ea1fSAvi Kivity 	report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax);
6937d36db35SAvi Kivity 
69418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_ss);
6956055ea1fSAvi Kivity 	report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax);
6967d36db35SAvi Kivity 
69718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_fs);
6986055ea1fSAvi Kivity 	report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax);
69909b657b6SAvi Kivity 
70009b657b6SAvi Kivity 	inregs.eax = 0x9977;
70109b657b6SAvi Kivity 	inregs.ebx = 0x7799;
70209b657b6SAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_high_esp_bits);
70309b657b6SAvi Kivity 	report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977);
7047d36db35SAvi Kivity }
7057d36db35SAvi Kivity 
7062e3f9f1fSThomas Huth static void test_null(void)
7077d36db35SAvi Kivity {
708d4dc402cSAvi Kivity 	MK_INSN(null, "");
709d4dc402cSAvi Kivity 
710bd62e289SBill Wendling 	init_inregs(NULL);
71118253fdeSAvi Kivity 
71218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_null);
7136055ea1fSAvi Kivity 	report("null", 0, 1);
7147d36db35SAvi Kivity }
7157d36db35SAvi Kivity 
7162e3f9f1fSThomas Huth static void test_pusha_popa(void)
7177d36db35SAvi Kivity {
7187d36db35SAvi Kivity 	MK_INSN(pusha, "pusha\n\t"
7197d36db35SAvi Kivity 		       "pop %edi\n\t"
7207d36db35SAvi Kivity 		       "pop %esi\n\t"
7217d36db35SAvi Kivity 		       "pop %ebp\n\t"
7227d36db35SAvi Kivity 		       "add $4, %esp\n\t"
7237d36db35SAvi Kivity 		       "pop %ebx\n\t"
7247d36db35SAvi Kivity 		       "pop %edx\n\t"
7257d36db35SAvi Kivity 		       "pop %ecx\n\t"
7267d36db35SAvi Kivity 		       "pop %eax\n\t"
7277d36db35SAvi Kivity 		       );
7287d36db35SAvi Kivity 
7297d36db35SAvi Kivity 	MK_INSN(popa, "push %eax\n\t"
7307d36db35SAvi Kivity 		      "push %ecx\n\t"
7317d36db35SAvi Kivity 		      "push %edx\n\t"
7327d36db35SAvi Kivity 		      "push %ebx\n\t"
7337d36db35SAvi Kivity 		      "push %esp\n\t"
7347d36db35SAvi Kivity 		      "push %ebp\n\t"
7357d36db35SAvi Kivity 		      "push %esi\n\t"
7367d36db35SAvi Kivity 		      "push %edi\n\t"
7377d36db35SAvi Kivity 		      "popa\n\t"
7387d36db35SAvi Kivity 		      );
7397d36db35SAvi Kivity 
740bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6 });
7417d36db35SAvi Kivity 
74218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pusha);
7436055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
74418253fdeSAvi Kivity 
74518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_popa);
7466055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
7477d36db35SAvi Kivity }
7487d36db35SAvi Kivity 
7492e3f9f1fSThomas Huth static void test_iret(void)
7507d36db35SAvi Kivity {
7517d36db35SAvi Kivity 	MK_INSN(iret32, "pushf\n\t"
7527d36db35SAvi Kivity 			"pushl %cs\n\t"
7537d36db35SAvi Kivity 			"call 1f\n\t" /* a near call will push eip onto the stack */
7547d36db35SAvi Kivity 			"jmp 2f\n\t"
755*231b4c3bSRoman Bolshakov 			"1: iretl\n\t"
7567d36db35SAvi Kivity 			"2:\n\t"
7577d36db35SAvi Kivity 		     );
7587d36db35SAvi Kivity 
7597d36db35SAvi Kivity 	MK_INSN(iret16, "pushfw\n\t"
7607d36db35SAvi Kivity 			"pushw %cs\n\t"
7617d36db35SAvi Kivity 			"callw 1f\n\t"
7627d36db35SAvi Kivity 			"jmp 2f\n\t"
7637d36db35SAvi Kivity 			"1: iretw\n\t"
7647d36db35SAvi Kivity 			"2:\n\t");
7657d36db35SAvi Kivity 
7667d36db35SAvi Kivity 	MK_INSN(iret_flags32, "pushfl\n\t"
7677d36db35SAvi Kivity 			      "popl %eax\n\t"
7687d36db35SAvi Kivity 			      "andl $~0x2, %eax\n\t"
769964942e8SNadav Amit 			      "orl $0xffc18028, %eax\n\t"
7707d36db35SAvi Kivity 			      "pushl %eax\n\t"
7717d36db35SAvi Kivity 			      "pushl %cs\n\t"
7727d36db35SAvi Kivity 			      "call 1f\n\t"
7737d36db35SAvi Kivity 			      "jmp 2f\n\t"
774*231b4c3bSRoman Bolshakov 			      "1: iretl\n\t"
7757d36db35SAvi Kivity 			      "2:\n\t");
7767d36db35SAvi Kivity 
7777d36db35SAvi Kivity 	MK_INSN(iret_flags16, "pushfw\n\t"
7787d36db35SAvi Kivity 			      "popw %ax\n\t"
7797d36db35SAvi Kivity 			      "and $~0x2, %ax\n\t"
7807d36db35SAvi Kivity 			      "or $0x8028, %ax\n\t"
7817d36db35SAvi Kivity 			      "pushw %ax\n\t"
7827d36db35SAvi Kivity 			      "pushw %cs\n\t"
7837d36db35SAvi Kivity 			      "callw 1f\n\t"
7847d36db35SAvi Kivity 			      "jmp 2f\n\t"
7857d36db35SAvi Kivity 			      "1: iretw\n\t"
7867d36db35SAvi Kivity 			      "2:\n\t");
7877d36db35SAvi Kivity 
788bd62e289SBill Wendling 	init_inregs(NULL);
7897d36db35SAvi Kivity 
79018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret32);
7916055ea1fSAvi Kivity 	report("iret 1", 0, 1);
7927d36db35SAvi Kivity 
79318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret16);
7946055ea1fSAvi Kivity 	report("iret 2", 0, 1);
7957d36db35SAvi Kivity 
79618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags32);
7976055ea1fSAvi Kivity 	report("iret 3", R_AX, 1);
798964942e8SNadav Amit 	report("rflags.rf", ~0, !(outregs.eflags & (1 << 16)));
79918253fdeSAvi Kivity 
80018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags16);
8016055ea1fSAvi Kivity 	report("iret 4", R_AX, 1);
8027d36db35SAvi Kivity }
8037d36db35SAvi Kivity 
8042e3f9f1fSThomas Huth static void test_int(void)
80596b9ca1eSMohammed Gamal {
806bd62e289SBill Wendling 	init_inregs(NULL);
80796b9ca1eSMohammed Gamal 
80896b9ca1eSMohammed Gamal 	*(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */
80996b9ca1eSMohammed Gamal 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
81096b9ca1eSMohammed Gamal 
81196b9ca1eSMohammed Gamal 	MK_INSN(int11, "int $0x11\n\t");
81296b9ca1eSMohammed Gamal 
81318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_int11);
8146055ea1fSAvi Kivity 	report("int 1", 0, 1);
81596b9ca1eSMohammed Gamal }
81696b9ca1eSMohammed Gamal 
8178202cf84SRoman Bolshakov static void test_sti_inhibit(void)
8188202cf84SRoman Bolshakov {
8198202cf84SRoman Bolshakov 	init_inregs(NULL);
8208202cf84SRoman Bolshakov 
8218202cf84SRoman Bolshakov 	*(u32 *)(0x73 * 4) = 0x1000; /* Store IRQ 11 handler in the IDT */
8228202cf84SRoman Bolshakov 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
8238202cf84SRoman Bolshakov 
8248202cf84SRoman Bolshakov 	MK_INSN(sti_inhibit, "cli\n\t"
8258202cf84SRoman Bolshakov 			     "movw $0x200b, %dx\n\t"
8268202cf84SRoman Bolshakov 			     "movl $1, %eax\n\t"
8278202cf84SRoman Bolshakov 			     "outl %eax, %dx\n\t" /* Set IRQ11 */
8288202cf84SRoman Bolshakov 			     "movl $0, %eax\n\t"
8298202cf84SRoman Bolshakov 			     "outl %eax, %dx\n\t" /* Clear IRQ11 */
8308202cf84SRoman Bolshakov 			     "sti\n\t"
8318202cf84SRoman Bolshakov 			     "hlt\n\t");
8328202cf84SRoman Bolshakov 	exec_in_big_real_mode(&insn_sti_inhibit);
8338202cf84SRoman Bolshakov 
8348202cf84SRoman Bolshakov 	report("sti inhibit", ~0, 1);
8358202cf84SRoman Bolshakov }
8368202cf84SRoman Bolshakov 
8372e3f9f1fSThomas Huth static void test_imul(void)
838fa74f8a6SMohammed Gamal {
839fa74f8a6SMohammed Gamal 	MK_INSN(imul8_1, "mov $2, %al\n\t"
840fa74f8a6SMohammed Gamal 			"mov $-4, %cx\n\t"
841fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
842fa74f8a6SMohammed Gamal 
843fa74f8a6SMohammed Gamal 	MK_INSN(imul16_1, "mov $2, %ax\n\t"
844fa74f8a6SMohammed Gamal 		      "mov $-4, %cx\n\t"
845fa74f8a6SMohammed Gamal 		      "imul %cx\n\t");
846fa74f8a6SMohammed Gamal 
847fa74f8a6SMohammed Gamal 	MK_INSN(imul32_1, "mov $2, %eax\n\t"
848fa74f8a6SMohammed Gamal 		       "mov $-4, %ecx\n\t"
849fa74f8a6SMohammed Gamal 		       "imul %ecx\n\t");
850fa74f8a6SMohammed Gamal 
851fa74f8a6SMohammed Gamal 	MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t"
852fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
853fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
854fa74f8a6SMohammed Gamal 
855fa74f8a6SMohammed Gamal 	MK_INSN(imul16_2, "mov $2, %ax\n\t"
856fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
857fa74f8a6SMohammed Gamal 			"imul %cx\n\t");
858fa74f8a6SMohammed Gamal 
859fa74f8a6SMohammed Gamal 	MK_INSN(imul32_2, "mov $2, %eax\n\t"
860fa74f8a6SMohammed Gamal 			"mov $4, %ecx\n\t"
861fa74f8a6SMohammed Gamal 			"imul %ecx\n\t");
862fa74f8a6SMohammed Gamal 
863bd62e289SBill Wendling 	init_inregs(NULL);
86418253fdeSAvi Kivity 
86518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_1);
8666055ea1fSAvi Kivity 	report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8);
867fa74f8a6SMohammed Gamal 
86818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_1);
8696055ea1fSAvi Kivity 	report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8);
870fa74f8a6SMohammed Gamal 
87118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_1);
8726055ea1fSAvi Kivity 	report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8);
873fa74f8a6SMohammed Gamal 
87418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_2);
8756055ea1fSAvi Kivity 	report("imul 4", R_AX | R_CX | R_DX,
8766055ea1fSAvi Kivity 	       (outregs.eax & 0xffff) == 8
87781050840SAvi Kivity 	       && (outregs.eax & 0xffff0000) == 0x12340000);
878fa74f8a6SMohammed Gamal 
87918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_2);
8806055ea1fSAvi Kivity 	report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8);
881fa74f8a6SMohammed Gamal 
88218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_2);
8836055ea1fSAvi Kivity 	report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8);
884fa74f8a6SMohammed Gamal }
885fa74f8a6SMohammed Gamal 
8862e3f9f1fSThomas Huth static void test_mul(void)
88759317bd1SMohammed Gamal {
88859317bd1SMohammed Gamal 	MK_INSN(mul8, "mov $2, %al\n\t"
88959317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
89059317bd1SMohammed Gamal 			"imul %cl\n\t");
89159317bd1SMohammed Gamal 
89259317bd1SMohammed Gamal 	MK_INSN(mul16, "mov $2, %ax\n\t"
89359317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
89459317bd1SMohammed Gamal 			"imul %cx\n\t");
89559317bd1SMohammed Gamal 
89659317bd1SMohammed Gamal 	MK_INSN(mul32, "mov $2, %eax\n\t"
89759317bd1SMohammed Gamal 			"mov $4, %ecx\n\t"
89859317bd1SMohammed Gamal 			"imul %ecx\n\t");
89959317bd1SMohammed Gamal 
900bd62e289SBill Wendling 	init_inregs(NULL);
90118253fdeSAvi Kivity 
90218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul8);
9036055ea1fSAvi Kivity 	report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8);
90459317bd1SMohammed Gamal 
90518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul16);
9066055ea1fSAvi Kivity 	report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8);
90759317bd1SMohammed Gamal 
90818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul32);
9096055ea1fSAvi Kivity 	report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8);
91059317bd1SMohammed Gamal }
91159317bd1SMohammed Gamal 
9122e3f9f1fSThomas Huth static void test_div(void)
9130d4c7614SMohammed Gamal {
9140d4c7614SMohammed Gamal 	MK_INSN(div8, "mov $257, %ax\n\t"
9150d4c7614SMohammed Gamal 			"mov $2, %cl\n\t"
9160d4c7614SMohammed Gamal 			"div %cl\n\t");
9170d4c7614SMohammed Gamal 
9180d4c7614SMohammed Gamal 	MK_INSN(div16, "mov $512, %ax\n\t"
9190d4c7614SMohammed Gamal 			"mov $5, %cx\n\t"
9200d4c7614SMohammed Gamal 			"div %cx\n\t");
9210d4c7614SMohammed Gamal 
9220d4c7614SMohammed Gamal 	MK_INSN(div32, "mov $512, %eax\n\t"
9230d4c7614SMohammed Gamal 			"mov $5, %ecx\n\t"
9240d4c7614SMohammed Gamal 			"div %ecx\n\t");
9250d4c7614SMohammed Gamal 
926bd62e289SBill Wendling 	init_inregs(NULL);
92718253fdeSAvi Kivity 
92818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div8);
9296055ea1fSAvi Kivity 	report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384);
9300d4c7614SMohammed Gamal 
93118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div16);
9326055ea1fSAvi Kivity 	report("div 2", R_AX | R_CX | R_DX,
9336055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
9340d4c7614SMohammed Gamal 
93518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div32);
9366055ea1fSAvi Kivity 	report("div 3", R_AX | R_CX | R_DX,
9376055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
9380d4c7614SMohammed Gamal }
9390d4c7614SMohammed Gamal 
9402e3f9f1fSThomas Huth static void test_idiv(void)
9410d4c7614SMohammed Gamal {
9420d4c7614SMohammed Gamal 	MK_INSN(idiv8, "mov $256, %ax\n\t"
9430d4c7614SMohammed Gamal 			"mov $-2, %cl\n\t"
9440d4c7614SMohammed Gamal 			"idiv %cl\n\t");
9450d4c7614SMohammed Gamal 
9460d4c7614SMohammed Gamal 	MK_INSN(idiv16, "mov $512, %ax\n\t"
9470d4c7614SMohammed Gamal 			"mov $-2, %cx\n\t"
9480d4c7614SMohammed Gamal 			"idiv %cx\n\t");
9490d4c7614SMohammed Gamal 
9500d4c7614SMohammed Gamal 	MK_INSN(idiv32, "mov $512, %eax\n\t"
9510d4c7614SMohammed Gamal 			"mov $-2, %ecx\n\t"
9520d4c7614SMohammed Gamal 			"idiv %ecx\n\t");
9530d4c7614SMohammed Gamal 
954bd62e289SBill Wendling 	init_inregs(NULL);
95518253fdeSAvi Kivity 
95618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv8);
9576055ea1fSAvi Kivity 	report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128);
9580d4c7614SMohammed Gamal 
95918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv16);
9606055ea1fSAvi Kivity 	report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256);
9610d4c7614SMohammed Gamal 
96218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv32);
9636055ea1fSAvi Kivity 	report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256);
9640d4c7614SMohammed Gamal }
9650d4c7614SMohammed Gamal 
9662e3f9f1fSThomas Huth static void test_cbw(void)
9676e293cf5SWei Yongjun {
9686e293cf5SWei Yongjun 	MK_INSN(cbw, "mov $0xFE, %eax \n\t"
9696e293cf5SWei Yongjun 		     "cbw\n\t");
9706e293cf5SWei Yongjun 	MK_INSN(cwde, "mov $0xFFFE, %eax \n\t"
9716e293cf5SWei Yongjun 		      "cwde\n\t");
9726e293cf5SWei Yongjun 
973bd62e289SBill Wendling 	init_inregs(NULL);
97418253fdeSAvi Kivity 
97518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cbw);
9766055ea1fSAvi Kivity 	report("cbq 1", ~0, outregs.eax == 0xFFFE);
9776e293cf5SWei Yongjun 
97818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwde);
9796055ea1fSAvi Kivity 	report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE);
9806e293cf5SWei Yongjun }
9816e293cf5SWei Yongjun 
9822e3f9f1fSThomas Huth static void test_loopcc(void)
983eacef4e2SWei Yongjun {
984eacef4e2SWei Yongjun 	MK_INSN(loop, "mov $10, %ecx\n\t"
985eacef4e2SWei Yongjun 		      "1: inc %eax\n\t"
986eacef4e2SWei Yongjun 		      "loop 1b\n\t");
987eacef4e2SWei Yongjun 
988eacef4e2SWei Yongjun 	MK_INSN(loope, "mov $10, %ecx\n\t"
989eacef4e2SWei Yongjun 		       "mov $1, %eax\n\t"
990eacef4e2SWei Yongjun 		       "1: dec %eax\n\t"
991eacef4e2SWei Yongjun 		       "loope 1b\n\t");
992eacef4e2SWei Yongjun 
993eacef4e2SWei Yongjun 	MK_INSN(loopne, "mov $10, %ecx\n\t"
994eacef4e2SWei Yongjun 		        "mov $5, %eax\n\t"
995eacef4e2SWei Yongjun 		        "1: dec %eax\n\t"
996eacef4e2SWei Yongjun 			"loopne 1b\n\t");
997eacef4e2SWei Yongjun 
998bd62e289SBill Wendling 	init_inregs(NULL);
999eacef4e2SWei Yongjun 
100018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loop);
10016055ea1fSAvi Kivity 	report("LOOPcc short 1", R_AX, outregs.eax == 10);
100218253fdeSAvi Kivity 
100318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loope);
10046055ea1fSAvi Kivity 	report("LOOPcc short 2", R_AX | R_CX,
10056055ea1fSAvi Kivity 	       outregs.eax == -1 && outregs.ecx == 8);
1006eacef4e2SWei Yongjun 
100718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loopne);
10086055ea1fSAvi Kivity 	report("LOOPcc short 3", R_AX | R_CX,
10096055ea1fSAvi Kivity 	       outregs.eax == 0 && outregs.ecx == 5);
1010eacef4e2SWei Yongjun }
1011eacef4e2SWei Yongjun 
1012b274feedSAvi Kivity static void test_das(void)
1013b274feedSAvi Kivity {
1014b274feedSAvi Kivity     short i;
101581050840SAvi Kivity     u16 nr_fail = 0;
1016b274feedSAvi Kivity     static unsigned test_cases[1024] = {
1017b274feedSAvi Kivity         0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00,
1018b274feedSAvi Kivity         0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01,
1019b274feedSAvi Kivity         0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02,
1020b274feedSAvi Kivity         0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03,
1021b274feedSAvi Kivity         0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04,
1022b274feedSAvi Kivity         0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05,
1023b274feedSAvi Kivity         0x06000606, 0x8701a606, 0x56100006, 0x9711a006,
1024b274feedSAvi Kivity         0x02000707, 0x8301a707, 0x12100107, 0x9311a107,
1025b274feedSAvi Kivity         0x02000808, 0x8301a808, 0x12100208, 0x9311a208,
1026b274feedSAvi Kivity         0x06000909, 0x8701a909, 0x16100309, 0x9711a309,
1027b274feedSAvi Kivity         0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a,
1028b274feedSAvi Kivity         0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b,
1029b274feedSAvi Kivity         0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c,
1030b274feedSAvi Kivity         0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d,
1031b274feedSAvi Kivity         0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e,
1032b274feedSAvi Kivity         0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f,
1033b274feedSAvi Kivity         0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10,
1034b274feedSAvi Kivity         0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11,
1035b274feedSAvi Kivity         0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12,
1036b274feedSAvi Kivity         0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13,
1037b274feedSAvi Kivity         0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14,
1038b274feedSAvi Kivity         0x02001515, 0x8301b515, 0x16100f15, 0x9711af15,
1039b274feedSAvi Kivity         0x02001616, 0x8301b616, 0x12101016, 0x9311b016,
1040b274feedSAvi Kivity         0x06001717, 0x8701b717, 0x16101117, 0x9711b117,
1041b274feedSAvi Kivity         0x06001818, 0x8701b818, 0x16101218, 0x9711b218,
1042b274feedSAvi Kivity         0x02001919, 0x8301b919, 0x12101319, 0x9311b319,
1043b274feedSAvi Kivity         0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a,
1044b274feedSAvi Kivity         0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b,
1045b274feedSAvi Kivity         0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c,
1046b274feedSAvi Kivity         0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d,
1047b274feedSAvi Kivity         0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e,
1048b274feedSAvi Kivity         0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f,
1049b274feedSAvi Kivity         0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20,
1050b274feedSAvi Kivity         0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21,
1051b274feedSAvi Kivity         0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22,
1052b274feedSAvi Kivity         0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23,
1053b274feedSAvi Kivity         0x06002424, 0x8301c424, 0x16101e24, 0x9711be24,
1054b274feedSAvi Kivity         0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25,
1055b274feedSAvi Kivity         0x02002626, 0x8701c626, 0x12102026, 0x9711c026,
1056b274feedSAvi Kivity         0x06002727, 0x8301c727, 0x16102127, 0x9311c127,
1057b274feedSAvi Kivity         0x06002828, 0x8301c828, 0x16102228, 0x9311c228,
1058b274feedSAvi Kivity         0x02002929, 0x8701c929, 0x12102329, 0x9711c329,
1059b274feedSAvi Kivity         0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a,
1060b274feedSAvi Kivity         0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b,
1061b274feedSAvi Kivity         0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c,
1062b274feedSAvi Kivity         0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d,
1063b274feedSAvi Kivity         0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e,
1064b274feedSAvi Kivity         0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f,
1065b274feedSAvi Kivity         0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30,
1066b274feedSAvi Kivity         0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31,
1067b274feedSAvi Kivity         0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32,
1068b274feedSAvi Kivity         0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33,
1069b274feedSAvi Kivity         0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34,
1070b274feedSAvi Kivity         0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35,
1071b274feedSAvi Kivity         0x06003636, 0x8301d636, 0x16103036, 0x9311d036,
1072b274feedSAvi Kivity         0x02003737, 0x8701d737, 0x12103137, 0x9711d137,
1073b274feedSAvi Kivity         0x02003838, 0x8701d838, 0x12103238, 0x9711d238,
1074b274feedSAvi Kivity         0x06003939, 0x8301d939, 0x16103339, 0x9311d339,
1075b274feedSAvi Kivity         0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a,
1076b274feedSAvi Kivity         0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b,
1077b274feedSAvi Kivity         0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c,
1078b274feedSAvi Kivity         0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d,
1079b274feedSAvi Kivity         0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e,
1080b274feedSAvi Kivity         0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f,
1081b274feedSAvi Kivity         0x02004040, 0x8301e040, 0x16103a40, 0x9311da40,
1082b274feedSAvi Kivity         0x06004141, 0x8701e141, 0x12103b41, 0x9711db41,
1083b274feedSAvi Kivity         0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42,
1084b274feedSAvi Kivity         0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43,
1085b274feedSAvi Kivity         0x06004444, 0x8701e444, 0x12103e44, 0x9711de44,
1086b274feedSAvi Kivity         0x02004545, 0x8301e545, 0x16103f45, 0x9311df45,
1087b274feedSAvi Kivity         0x02004646, 0x8301e646, 0x12104046, 0x9311e046,
1088b274feedSAvi Kivity         0x06004747, 0x8701e747, 0x16104147, 0x9711e147,
1089b274feedSAvi Kivity         0x06004848, 0x8701e848, 0x16104248, 0x9711e248,
1090b274feedSAvi Kivity         0x02004949, 0x8301e949, 0x12104349, 0x9311e349,
1091b274feedSAvi Kivity         0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a,
1092b274feedSAvi Kivity         0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b,
1093b274feedSAvi Kivity         0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c,
1094b274feedSAvi Kivity         0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d,
1095b274feedSAvi Kivity         0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e,
1096b274feedSAvi Kivity         0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f,
1097b274feedSAvi Kivity         0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50,
1098b274feedSAvi Kivity         0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51,
1099b274feedSAvi Kivity         0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52,
1100b274feedSAvi Kivity         0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53,
1101b274feedSAvi Kivity         0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54,
1102b274feedSAvi Kivity         0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55,
1103b274feedSAvi Kivity         0x06005656, 0x8701f656, 0x16105056, 0x9711f056,
1104b274feedSAvi Kivity         0x02005757, 0x8301f757, 0x12105157, 0x9311f157,
1105b274feedSAvi Kivity         0x02005858, 0x8301f858, 0x12105258, 0x9311f258,
1106b274feedSAvi Kivity         0x06005959, 0x8701f959, 0x16105359, 0x9711f359,
1107b274feedSAvi Kivity         0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a,
1108b274feedSAvi Kivity         0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b,
1109b274feedSAvi Kivity         0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c,
1110b274feedSAvi Kivity         0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d,
1111b274feedSAvi Kivity         0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e,
1112b274feedSAvi Kivity         0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f,
1113b274feedSAvi Kivity         0x06006060, 0x47010060, 0x16105a60, 0x9711fa60,
1114b274feedSAvi Kivity         0x02006161, 0x03010161, 0x12105b61, 0x9311fb61,
1115b274feedSAvi Kivity         0x02006262, 0x03010262, 0x16105c62, 0x9711fc62,
1116b274feedSAvi Kivity         0x06006363, 0x07010363, 0x12105d63, 0x9311fd63,
1117b274feedSAvi Kivity         0x02006464, 0x03010464, 0x12105e64, 0x9311fe64,
1118b274feedSAvi Kivity         0x06006565, 0x07010565, 0x16105f65, 0x9711ff65,
1119b274feedSAvi Kivity         0x06006666, 0x07010666, 0x16106066, 0x57110066,
1120b274feedSAvi Kivity         0x02006767, 0x03010767, 0x12106167, 0x13110167,
1121b274feedSAvi Kivity         0x02006868, 0x03010868, 0x12106268, 0x13110268,
1122b274feedSAvi Kivity         0x06006969, 0x07010969, 0x16106369, 0x17110369,
1123b274feedSAvi Kivity         0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a,
1124b274feedSAvi Kivity         0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b,
1125b274feedSAvi Kivity         0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c,
1126b274feedSAvi Kivity         0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d,
1127b274feedSAvi Kivity         0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e,
1128b274feedSAvi Kivity         0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f,
1129b274feedSAvi Kivity         0x02007070, 0x03011070, 0x16106a70, 0x17110a70,
1130b274feedSAvi Kivity         0x06007171, 0x07011171, 0x12106b71, 0x13110b71,
1131b274feedSAvi Kivity         0x06007272, 0x07011272, 0x16106c72, 0x17110c72,
1132b274feedSAvi Kivity         0x02007373, 0x03011373, 0x12106d73, 0x13110d73,
1133b274feedSAvi Kivity         0x06007474, 0x07011474, 0x12106e74, 0x13110e74,
1134b274feedSAvi Kivity         0x02007575, 0x03011575, 0x16106f75, 0x17110f75,
1135b274feedSAvi Kivity         0x02007676, 0x03011676, 0x12107076, 0x13111076,
1136b274feedSAvi Kivity         0x06007777, 0x07011777, 0x16107177, 0x17111177,
1137b274feedSAvi Kivity         0x06007878, 0x07011878, 0x16107278, 0x17111278,
1138b274feedSAvi Kivity         0x02007979, 0x03011979, 0x12107379, 0x13111379,
1139b274feedSAvi Kivity         0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a,
1140b274feedSAvi Kivity         0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b,
1141b274feedSAvi Kivity         0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c,
1142b274feedSAvi Kivity         0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d,
1143b274feedSAvi Kivity         0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e,
1144b274feedSAvi Kivity         0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f,
1145b274feedSAvi Kivity         0x82008080, 0x03012080, 0x12107a80, 0x13111a80,
1146b274feedSAvi Kivity         0x86008181, 0x07012181, 0x16107b81, 0x17111b81,
1147b274feedSAvi Kivity         0x86008282, 0x07012282, 0x12107c82, 0x13111c82,
1148b274feedSAvi Kivity         0x82008383, 0x03012383, 0x16107d83, 0x17111d83,
1149b274feedSAvi Kivity         0x86008484, 0x07012484, 0x16107e84, 0x17111e84,
1150b274feedSAvi Kivity         0x82008585, 0x03012585, 0x12107f85, 0x13111f85,
1151b274feedSAvi Kivity         0x82008686, 0x03012686, 0x92108086, 0x13112086,
1152b274feedSAvi Kivity         0x86008787, 0x07012787, 0x96108187, 0x17112187,
1153b274feedSAvi Kivity         0x86008888, 0x07012888, 0x96108288, 0x17112288,
1154b274feedSAvi Kivity         0x82008989, 0x03012989, 0x92108389, 0x13112389,
1155b274feedSAvi Kivity         0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a,
1156b274feedSAvi Kivity         0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b,
1157b274feedSAvi Kivity         0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c,
1158b274feedSAvi Kivity         0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d,
1159b274feedSAvi Kivity         0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e,
1160b274feedSAvi Kivity         0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f,
1161b274feedSAvi Kivity         0x86009090, 0x07013090, 0x92108a90, 0x13112a90,
1162b274feedSAvi Kivity         0x82009191, 0x03013191, 0x96108b91, 0x17112b91,
1163b274feedSAvi Kivity         0x82009292, 0x03013292, 0x92108c92, 0x13112c92,
1164b274feedSAvi Kivity         0x86009393, 0x07013393, 0x96108d93, 0x17112d93,
1165b274feedSAvi Kivity         0x82009494, 0x03013494, 0x96108e94, 0x17112e94,
1166b274feedSAvi Kivity         0x86009595, 0x07013595, 0x92108f95, 0x13112f95,
1167b274feedSAvi Kivity         0x86009696, 0x07013696, 0x96109096, 0x17113096,
1168b274feedSAvi Kivity         0x82009797, 0x03013797, 0x92109197, 0x13113197,
1169b274feedSAvi Kivity         0x82009898, 0x03013898, 0x92109298, 0x13113298,
1170b274feedSAvi Kivity         0x86009999, 0x07013999, 0x96109399, 0x17113399,
1171b274feedSAvi Kivity         0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a,
1172b274feedSAvi Kivity         0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b,
1173b274feedSAvi Kivity         0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c,
1174b274feedSAvi Kivity         0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d,
1175b274feedSAvi Kivity         0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e,
1176b274feedSAvi Kivity         0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f,
1177b274feedSAvi Kivity         0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0,
1178b274feedSAvi Kivity         0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1,
1179b274feedSAvi Kivity         0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2,
1180b274feedSAvi Kivity         0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3,
1181b274feedSAvi Kivity         0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4,
1182b274feedSAvi Kivity         0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5,
1183b274feedSAvi Kivity         0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6,
1184b274feedSAvi Kivity         0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7,
1185b274feedSAvi Kivity         0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8,
1186b274feedSAvi Kivity         0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9,
1187b274feedSAvi Kivity         0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa,
1188b274feedSAvi Kivity         0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab,
1189b274feedSAvi Kivity         0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac,
1190b274feedSAvi Kivity         0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad,
1191b274feedSAvi Kivity         0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae,
1192b274feedSAvi Kivity         0x130049af, 0x130149af, 0x131049af, 0x131149af,
1193b274feedSAvi Kivity         0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0,
1194b274feedSAvi Kivity         0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1,
1195b274feedSAvi Kivity         0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2,
1196b274feedSAvi Kivity         0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3,
1197b274feedSAvi Kivity         0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4,
1198b274feedSAvi Kivity         0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5,
1199b274feedSAvi Kivity         0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6,
1200b274feedSAvi Kivity         0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7,
1201b274feedSAvi Kivity         0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8,
1202b274feedSAvi Kivity         0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9,
1203b274feedSAvi Kivity         0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba,
1204b274feedSAvi Kivity         0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb,
1205b274feedSAvi Kivity         0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc,
1206b274feedSAvi Kivity         0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd,
1207b274feedSAvi Kivity         0x130058be, 0x130158be, 0x131058be, 0x131158be,
1208b274feedSAvi Kivity         0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf,
1209b274feedSAvi Kivity         0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0,
1210b274feedSAvi Kivity         0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1,
1211b274feedSAvi Kivity         0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2,
1212b274feedSAvi Kivity         0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3,
1213b274feedSAvi Kivity         0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4,
1214b274feedSAvi Kivity         0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5,
1215b274feedSAvi Kivity         0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6,
1216b274feedSAvi Kivity         0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7,
1217b274feedSAvi Kivity         0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8,
1218b274feedSAvi Kivity         0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9,
1219b274feedSAvi Kivity         0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca,
1220b274feedSAvi Kivity         0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb,
1221b274feedSAvi Kivity         0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc,
1222b274feedSAvi Kivity         0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd,
1223b274feedSAvi Kivity         0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce,
1224b274feedSAvi Kivity         0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf,
1225b274feedSAvi Kivity         0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0,
1226b274feedSAvi Kivity         0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1,
1227b274feedSAvi Kivity         0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2,
1228b274feedSAvi Kivity         0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3,
1229b274feedSAvi Kivity         0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4,
1230b274feedSAvi Kivity         0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5,
1231b274feedSAvi Kivity         0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6,
1232b274feedSAvi Kivity         0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7,
1233b274feedSAvi Kivity         0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8,
1234b274feedSAvi Kivity         0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9,
1235b274feedSAvi Kivity         0x170074da, 0x170174da, 0x171074da, 0x171174da,
1236b274feedSAvi Kivity         0x130075db, 0x130175db, 0x131075db, 0x131175db,
1237b274feedSAvi Kivity         0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc,
1238b274feedSAvi Kivity         0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd,
1239b274feedSAvi Kivity         0x170078de, 0x170178de, 0x171078de, 0x171178de,
1240b274feedSAvi Kivity         0x130079df, 0x130179df, 0x131079df, 0x131179df,
1241b274feedSAvi Kivity         0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0,
1242b274feedSAvi Kivity         0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1,
1243b274feedSAvi Kivity         0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2,
1244b274feedSAvi Kivity         0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3,
1245b274feedSAvi Kivity         0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4,
1246b274feedSAvi Kivity         0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5,
1247b274feedSAvi Kivity         0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6,
1248b274feedSAvi Kivity         0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7,
1249b274feedSAvi Kivity         0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8,
1250b274feedSAvi Kivity         0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9,
1251b274feedSAvi Kivity         0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea,
1252b274feedSAvi Kivity         0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb,
1253b274feedSAvi Kivity         0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec,
1254b274feedSAvi Kivity         0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed,
1255b274feedSAvi Kivity         0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee,
1256b274feedSAvi Kivity         0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef,
1257b274feedSAvi Kivity         0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0,
1258b274feedSAvi Kivity         0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1,
1259b274feedSAvi Kivity         0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2,
1260b274feedSAvi Kivity         0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3,
1261b274feedSAvi Kivity         0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4,
1262b274feedSAvi Kivity         0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5,
1263b274feedSAvi Kivity         0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6,
1264b274feedSAvi Kivity         0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7,
1265b274feedSAvi Kivity         0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8,
1266b274feedSAvi Kivity         0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9,
1267b274feedSAvi Kivity         0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa,
1268b274feedSAvi Kivity         0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb,
1269b274feedSAvi Kivity         0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc,
1270b274feedSAvi Kivity         0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd,
1271b274feedSAvi Kivity         0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe,
1272b274feedSAvi Kivity         0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff,
1273b274feedSAvi Kivity     };
1274b274feedSAvi Kivity 
1275b274feedSAvi Kivity     MK_INSN(das, "das");
1276b274feedSAvi Kivity 
1277bd62e289SBill Wendling     init_inregs(NULL);
127818253fdeSAvi Kivity 
1279b274feedSAvi Kivity     for (i = 0; i < 1024; ++i) {
1280b274feedSAvi Kivity         unsigned tmp = test_cases[i];
1281b274feedSAvi Kivity         inregs.eax = tmp & 0xff;
1282b274feedSAvi Kivity         inregs.eflags = (tmp >> 16) & 0xff;
128318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_das);
128418253fdeSAvi Kivity 	if (!regs_equal(R_AX)
1285b274feedSAvi Kivity             || outregs.eax != ((tmp >> 8) & 0xff)
1286b274feedSAvi Kivity             || (outregs.eflags & 0xff) != (tmp >> 24)) {
128781050840SAvi Kivity 	    ++nr_fail;
128881050840SAvi Kivity 	    break;
1289b274feedSAvi Kivity         }
1290b274feedSAvi Kivity     }
12916055ea1fSAvi Kivity     report("DAS", ~0, nr_fail == 0);
1292b274feedSAvi Kivity }
1293b274feedSAvi Kivity 
12942e3f9f1fSThomas Huth static void test_cwd_cdq(void)
12950cbd5b06SMohammed Gamal {
12960cbd5b06SMohammed Gamal 	/* Sign-bit set */
12970cbd5b06SMohammed Gamal 	MK_INSN(cwd_1, "mov $0x8000, %ax\n\t"
12980cbd5b06SMohammed Gamal 		       "cwd\n\t");
12990cbd5b06SMohammed Gamal 
13000cbd5b06SMohammed Gamal 	/* Sign-bit not set */
13010cbd5b06SMohammed Gamal 	MK_INSN(cwd_2, "mov $0x1000, %ax\n\t"
13020cbd5b06SMohammed Gamal 		       "cwd\n\t");
13030cbd5b06SMohammed Gamal 
13040cbd5b06SMohammed Gamal 	/* Sign-bit set */
13050cbd5b06SMohammed Gamal 	MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t"
13060cbd5b06SMohammed Gamal 		       "cdq\n\t");
13070cbd5b06SMohammed Gamal 
13080cbd5b06SMohammed Gamal 	/* Sign-bit not set */
13090cbd5b06SMohammed Gamal 	MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t"
13100cbd5b06SMohammed Gamal 		       "cdq\n\t");
13110cbd5b06SMohammed Gamal 
1312bd62e289SBill Wendling 	init_inregs(NULL);
131318253fdeSAvi Kivity 
131418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_1);
13156055ea1fSAvi Kivity 	report("cwd 1", R_AX | R_DX,
13166055ea1fSAvi Kivity 	       outregs.eax == 0x8000 && outregs.edx == 0xffff);
13170cbd5b06SMohammed Gamal 
131818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_2);
13196055ea1fSAvi Kivity 	report("cwd 2", R_AX | R_DX,
13206055ea1fSAvi Kivity 	       outregs.eax == 0x1000 && outregs.edx == 0);
13210cbd5b06SMohammed Gamal 
132218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_1);
13236055ea1fSAvi Kivity 	report("cdq 1", R_AX | R_DX,
13246055ea1fSAvi Kivity 	       outregs.eax == 0x80000000 && outregs.edx == 0xffffffff);
13250cbd5b06SMohammed Gamal 
132618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_2);
13276055ea1fSAvi Kivity 	report("cdq 2", R_AX | R_DX,
13286055ea1fSAvi Kivity 	       outregs.eax == 0x10000000 && outregs.edx == 0);
13290cbd5b06SMohammed Gamal }
13300cbd5b06SMohammed Gamal 
133137f51a4aSWei Yongjun static struct {
133237f51a4aSWei Yongjun         void *address;
133337f51a4aSWei Yongjun         unsigned short sel;
133437f51a4aSWei Yongjun } __attribute__((packed)) desc = {
133537f51a4aSWei Yongjun 	(void *)0x1234,
133637f51a4aSWei Yongjun 	0x10,
133737f51a4aSWei Yongjun };
133837f51a4aSWei Yongjun 
13392e3f9f1fSThomas Huth static void test_lds_lss(void)
134037f51a4aSWei Yongjun {
1341bd62e289SBill Wendling 	init_inregs(&(struct regs){ .ebx = (unsigned long)&desc });
134237f51a4aSWei Yongjun 
1343*231b4c3bSRoman Bolshakov 	MK_INSN(lds, "pushl %ds\n\t"
134437f51a4aSWei Yongjun 		     "lds (%ebx), %eax\n\t"
134537f51a4aSWei Yongjun 		     "mov %ds, %ebx\n\t"
1346*231b4c3bSRoman Bolshakov 		     "popl %ds\n\t");
134737f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lds);
134837f51a4aSWei Yongjun 	report("lds", R_AX | R_BX,
134937f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
135037f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
135137f51a4aSWei Yongjun 
1352eb6687a2SBill Wendling 	MK_INSN(les, "les (%ebx), %eax\n\t"
1353eb6687a2SBill Wendling 		     "mov %es, %ebx\n\t");
135437f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_les);
135537f51a4aSWei Yongjun 	report("les", R_AX | R_BX,
135637f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
135737f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
135837f51a4aSWei Yongjun 
1359*231b4c3bSRoman Bolshakov 	MK_INSN(lfs, "pushl %fs\n\t"
136037f51a4aSWei Yongjun 		     "lfs (%ebx), %eax\n\t"
136137f51a4aSWei Yongjun 		     "mov %fs, %ebx\n\t"
1362*231b4c3bSRoman Bolshakov 		     "popl %fs\n\t");
136337f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lfs);
136437f51a4aSWei Yongjun 	report("lfs", R_AX | R_BX,
136537f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
136637f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
136737f51a4aSWei Yongjun 
1368*231b4c3bSRoman Bolshakov 	MK_INSN(lgs, "pushl %gs\n\t"
136937f51a4aSWei Yongjun 		     "lgs (%ebx), %eax\n\t"
137037f51a4aSWei Yongjun 		     "mov %gs, %ebx\n\t"
1371*231b4c3bSRoman Bolshakov 		     "popl %gs\n\t");
137237f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lgs);
137337f51a4aSWei Yongjun 	report("lgs", R_AX | R_BX,
137437f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
137537f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
137637f51a4aSWei Yongjun 
1377*231b4c3bSRoman Bolshakov 	MK_INSN(lss, "pushl %ss\n\t"
137837f51a4aSWei Yongjun 		     "lss (%ebx), %eax\n\t"
137937f51a4aSWei Yongjun 		     "mov %ss, %ebx\n\t"
1380*231b4c3bSRoman Bolshakov 		     "popl %ss\n\t");
138137f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lss);
138237f51a4aSWei Yongjun 	report("lss", R_AX | R_BX,
138337f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
138437f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
138537f51a4aSWei Yongjun }
138637f51a4aSWei Yongjun 
13872e3f9f1fSThomas Huth static void test_jcxz(void)
1388b1c7c575SWei Yongjun {
1389b1c7c575SWei Yongjun 	MK_INSN(jcxz1, "jcxz 1f\n\t"
1390b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1391b1c7c575SWei Yongjun 		       "1:\n\t");
1392b1c7c575SWei Yongjun 	MK_INSN(jcxz2, "mov $0x100, %ecx\n\t"
1393b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1394b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1395b1c7c575SWei Yongjun 		       "mov $0, %ecx\n\t"
1396b1c7c575SWei Yongjun 		       "1:\n\t");
1397b1c7c575SWei Yongjun 	MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t"
1398b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1399b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1400b1c7c575SWei Yongjun 		       "1:\n\t");
1401b1c7c575SWei Yongjun 	MK_INSN(jecxz1, "jecxz 1f\n\t"
1402b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1403b1c7c575SWei Yongjun 			"1:\n\t");
1404b1c7c575SWei Yongjun 	MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t"
1405b1c7c575SWei Yongjun 			"jecxz 1f\n\t"
1406b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1407b1c7c575SWei Yongjun 			"mov $0, %ecx\n\t"
1408b1c7c575SWei Yongjun 			"1:\n\t");
1409b1c7c575SWei Yongjun 
1410bd62e289SBill Wendling 	init_inregs(NULL);
1411b1c7c575SWei Yongjun 
1412b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz1);
1413b1c7c575SWei Yongjun 	report("jcxz short 1", 0, 1);
1414b1c7c575SWei Yongjun 
1415b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz2);
1416b1c7c575SWei Yongjun 	report("jcxz short 2", R_AX, outregs.eax == 0x1234);
1417b1c7c575SWei Yongjun 
1418b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz3);
1419b1c7c575SWei Yongjun 	report("jcxz short 3", R_CX, outregs.ecx == 0x10000);
1420b1c7c575SWei Yongjun 
1421b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz1);
1422b1c7c575SWei Yongjun 	report("jecxz short 1", 0, 1);
1423b1c7c575SWei Yongjun 
1424b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz2);
1425b1c7c575SWei Yongjun 	report("jecxz short 2", R_AX, outregs.eax == 0x1234);
1426b1c7c575SWei Yongjun }
1427b1c7c575SWei Yongjun 
14288f578e98SAvi Kivity static void test_cpuid(void)
14298f578e98SAvi Kivity {
14308f578e98SAvi Kivity     MK_INSN(cpuid, "cpuid");
14318f578e98SAvi Kivity     unsigned function = 0x1234;
14328f578e98SAvi Kivity     unsigned eax, ebx, ecx, edx;
14338f578e98SAvi Kivity 
1434bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = function });
1435bd62e289SBill Wendling 
1436bd62e289SBill Wendling     eax = inregs.eax;
1437bd62e289SBill Wendling     ecx = inregs.ecx;
1438674d2dbeSPaolo Bonzini     asm("cpuid" : "+a"(eax), "=b"(ebx), "+c"(ecx), "=d"(edx));
14398f578e98SAvi Kivity     exec_in_big_real_mode(&insn_cpuid);
14408f578e98SAvi Kivity     report("cpuid", R_AX|R_BX|R_CX|R_DX,
14418f578e98SAvi Kivity 	   outregs.eax == eax && outregs.ebx == ebx
14428f578e98SAvi Kivity 	   && outregs.ecx == ecx && outregs.edx == edx);
14438f578e98SAvi Kivity }
14448f578e98SAvi Kivity 
1445ed93f43bSAvi Kivity static void test_ss_base_for_esp_ebp(void)
1446ed93f43bSAvi Kivity {
1447ed93f43bSAvi Kivity     MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss");
1448ed93f43bSAvi Kivity     MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss");
1449ed93f43bSAvi Kivity     static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 };
1450ed93f43bSAvi Kivity 
1451bd62e289SBill Wendling     init_inregs(&(struct regs){ .ebx = 1, .ebp = (unsigned)array });
1452bd62e289SBill Wendling 
1453ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel1);
1454ed93f43bSAvi Kivity     report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321);
1455bd62e289SBill Wendling 
1456ed93f43bSAvi Kivity     inregs.ebx = 1;
1457ed93f43bSAvi Kivity     inregs.ebp = (unsigned)array;
1458ed93f43bSAvi Kivity     inregs.edi = 0;
1459ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel2);
1460ed93f43bSAvi Kivity     report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321);
1461ed93f43bSAvi Kivity }
1462ed93f43bSAvi Kivity 
1463975ca087SPeter Feiner extern unsigned long long r_gdt[];
1464975ca087SPeter Feiner 
1465c2281fa4SAvi Kivity static void test_sgdt_sidt(void)
1466c2281fa4SAvi Kivity {
1467c2281fa4SAvi Kivity     MK_INSN(sgdt, "sgdtw (%eax)");
1468c2281fa4SAvi Kivity     MK_INSN(sidt, "sidtw (%eax)");
1469975ca087SPeter Feiner     struct table_descr x, y;
1470c2281fa4SAvi Kivity 
1471bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = (unsigned)&y });
1472bd62e289SBill Wendling 
1473c2281fa4SAvi Kivity     asm volatile("sgdtw %0" : "=m"(x));
1474c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sgdt);
1475975ca087SPeter Feiner     report("sgdt", 0, x.limit == y.limit && x.base == y.base);
1476c2281fa4SAvi Kivity 
1477c2281fa4SAvi Kivity     inregs.eax = (unsigned)&y;
1478c2281fa4SAvi Kivity     asm volatile("sidtw %0" : "=m"(x));
1479c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sidt);
1480975ca087SPeter Feiner     report("sidt", 0, x.limit == y.limit && x.base == y.base);
1481c2281fa4SAvi Kivity }
1482c2281fa4SAvi Kivity 
148388b6dac4SPaolo Bonzini static void test_sahf(void)
148488b6dac4SPaolo Bonzini {
148588b6dac4SPaolo Bonzini     MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw");
148688b6dac4SPaolo Bonzini 
1487bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0xfd00 });
1488bd62e289SBill Wendling 
148988b6dac4SPaolo Bonzini     exec_in_big_real_mode(&insn_sahf);
149088b6dac4SPaolo Bonzini     report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7));
149188b6dac4SPaolo Bonzini }
149288b6dac4SPaolo Bonzini 
14937ae3645aSAvi Kivity static void test_lahf(void)
14947ae3645aSAvi Kivity {
14957ae3645aSAvi Kivity     MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf");
14967ae3645aSAvi Kivity 
1497bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0xc7 });
1498bd62e289SBill Wendling 
14997ae3645aSAvi Kivity     exec_in_big_real_mode(&insn_lahf);
15007ae3645aSAvi Kivity     report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax);
15017ae3645aSAvi Kivity }
15027ae3645aSAvi Kivity 
1503fd9ea640SAvi Kivity static void test_movzx_movsx(void)
1504fd9ea640SAvi Kivity {
1505fd9ea640SAvi Kivity     MK_INSN(movsx, "movsx %al, %ebx");
1506fd9ea640SAvi Kivity     MK_INSN(movzx, "movzx %al, %ebx");
15073013e079SGleb Natapov     MK_INSN(movzsah, "movsx %ah, %ebx");
15083013e079SGleb Natapov     MK_INSN(movzxah, "movzx %ah, %ebx");
1509fd9ea640SAvi Kivity 
1510bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x1234569c });
1511bd62e289SBill Wendling 
1512fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movsx);
1513fd9ea640SAvi Kivity     report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax);
1514fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movzx);
1515fd9ea640SAvi Kivity     report("movzx", R_BX, outregs.ebx == (unsigned char)inregs.eax);
15163013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzsah);
15173013e079SGleb Natapov     report("movsx ah", R_BX, outregs.ebx == (signed char)(inregs.eax>>8));
15183013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzxah);
15193013e079SGleb Natapov     report("movzx ah", R_BX, outregs.ebx == (unsigned char)(inregs.eax >> 8));
1520fd9ea640SAvi Kivity }
1521fd9ea640SAvi Kivity 
1522b493b2e8SAvi Kivity static void test_bswap(void)
1523b493b2e8SAvi Kivity {
1524b493b2e8SAvi Kivity     MK_INSN(bswap, "bswap %ecx");
1525b493b2e8SAvi Kivity 
1526bd62e289SBill Wendling     init_inregs(&(struct regs){ .ecx = 0x12345678 });
1527bd62e289SBill Wendling 
1528b493b2e8SAvi Kivity     exec_in_big_real_mode(&insn_bswap);
1529b493b2e8SAvi Kivity     report("bswap", R_CX, outregs.ecx == 0x78563412);
1530b493b2e8SAvi Kivity }
1531b493b2e8SAvi Kivity 
15328cd86387SGleb Natapov static void test_aad(void)
15338cd86387SGleb Natapov {
15348cd86387SGleb Natapov     MK_INSN(aad, "aad");
15358cd86387SGleb Natapov 
1536bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x12345678 });
1537bd62e289SBill Wendling 
15388cd86387SGleb Natapov     exec_in_big_real_mode(&insn_aad);
15398cd86387SGleb Natapov     report("aad", R_AX, outregs.eax == 0x123400d4);
15408cd86387SGleb Natapov }
15418cd86387SGleb Natapov 
15422a9b5718SPaolo Bonzini static void test_aam(void)
15432a9b5718SPaolo Bonzini {
15442a9b5718SPaolo Bonzini     MK_INSN(aam, "aam");
15452a9b5718SPaolo Bonzini 
1546bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x76543210 });
1547bd62e289SBill Wendling 
15482a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_aam);
15492a9b5718SPaolo Bonzini     report("aam", R_AX, outregs.eax == 0x76540106);
15502a9b5718SPaolo Bonzini }
15512a9b5718SPaolo Bonzini 
15522a9b5718SPaolo Bonzini static void test_xlat(void)
15532a9b5718SPaolo Bonzini {
15542a9b5718SPaolo Bonzini     MK_INSN(xlat, "xlat");
15552a9b5718SPaolo Bonzini     u8 table[256];
15562a9b5718SPaolo Bonzini     int i;
15572a9b5718SPaolo Bonzini 
15582a9b5718SPaolo Bonzini     for (i = 0; i < 256; i++) {
15592a9b5718SPaolo Bonzini         table[i] = i + 1;
15602a9b5718SPaolo Bonzini     }
15612a9b5718SPaolo Bonzini 
1562bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x89abcdef, .ebx = (u32)table });
1563bd62e289SBill Wendling 
15642a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_xlat);
15652a9b5718SPaolo Bonzini     report("xlat", R_AX, outregs.eax == 0x89abcdf0);
15662a9b5718SPaolo Bonzini }
15672a9b5718SPaolo Bonzini 
15682a9b5718SPaolo Bonzini static void test_salc(void)
15692a9b5718SPaolo Bonzini {
15702a9b5718SPaolo Bonzini     MK_INSN(clc_salc, "clc; .byte 0xd6");
15712a9b5718SPaolo Bonzini     MK_INSN(stc_salc, "stc; .byte 0xd6");
15722a9b5718SPaolo Bonzini 
1573bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x12345678 });
1574bd62e289SBill Wendling 
15752a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_clc_salc);
15762a9b5718SPaolo Bonzini     report("salc (1)", R_AX, outregs.eax == 0x12345600);
15772a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_stc_salc);
15782a9b5718SPaolo Bonzini     report("salc (2)", R_AX, outregs.eax == 0x123456ff);
15792a9b5718SPaolo Bonzini }
15802a9b5718SPaolo Bonzini 
15810987db7aSGleb Natapov static void test_fninit(void)
15820987db7aSGleb Natapov {
15830987db7aSGleb Natapov 	u16 fcw = -1, fsw = -1;
15840987db7aSGleb Natapov 	MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)");
15850987db7aSGleb Natapov 
1586bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = (u32)&fsw, .ebx = (u32)&fcw });
15870987db7aSGleb Natapov 
15880987db7aSGleb Natapov 	exec_in_big_real_mode(&insn_fninit);
15890987db7aSGleb Natapov 	report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f);
15900987db7aSGleb Natapov }
15910987db7aSGleb Natapov 
15921a4c03a0SArthur Chunqi Li static void test_nopl(void)
15931a4c03a0SArthur Chunqi Li {
15941a4c03a0SArthur Chunqi Li 	MK_INSN(nopl1, ".byte 0x90\n\r"); // 1 byte nop
15951a4c03a0SArthur Chunqi Li 	MK_INSN(nopl2, ".byte 0x66, 0x90\n\r"); // 2 bytes nop
15961a4c03a0SArthur Chunqi Li 	MK_INSN(nopl3, ".byte 0x0f, 0x1f, 0x00\n\r"); // 3 bytes nop
15971a4c03a0SArthur Chunqi Li 	MK_INSN(nopl4, ".byte 0x0f, 0x1f, 0x40, 0x00\n\r"); // 4 bytes nop
15981a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl1);
15991a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl2);
16001a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl3);
16011a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl4);
16021a4c03a0SArthur Chunqi Li 	report("nopl", 0, 1);
16031a4c03a0SArthur Chunqi Li }
16041a4c03a0SArthur Chunqi Li 
1605b5105e8bSPaolo Bonzini static u32 perf_baseline;
1606b5105e8bSPaolo Bonzini 
16077505ea23SPaolo Bonzini #define PERF_COUNT 1000000
1608b5105e8bSPaolo Bonzini 
1609b5105e8bSPaolo Bonzini #define MK_INSN_PERF(name, insn)                                \
1610b5105e8bSPaolo Bonzini 	MK_INSN(name, "rdtsc; mov %eax, %ebx; mov %edx, %esi\n" \
1611b5105e8bSPaolo Bonzini 		      "1:" insn "\n"                            \
16127505ea23SPaolo Bonzini 		      ".byte 0x67; loop 1b\n"                   \
1613b5105e8bSPaolo Bonzini 		      "rdtsc");
1614b5105e8bSPaolo Bonzini 
1615b5105e8bSPaolo Bonzini static u32 cycles_in_big_real_mode(struct insn_desc *insn)
1616b5105e8bSPaolo Bonzini {
1617b5105e8bSPaolo Bonzini 	u64 start, end;
1618b5105e8bSPaolo Bonzini 
1619bd62e289SBill Wendling 	init_inregs(&(struct regs){ .ecx = PERF_COUNT });
1620bd62e289SBill Wendling 
1621b5105e8bSPaolo Bonzini 	exec_in_big_real_mode(insn);
1622b5105e8bSPaolo Bonzini 	start = ((u64)outregs.esi << 32) | outregs.ebx;
1623b5105e8bSPaolo Bonzini 	end = ((u64)outregs.edx << 32) | outregs.eax;
1624b5105e8bSPaolo Bonzini 
1625b5105e8bSPaolo Bonzini 	return end - start;
1626b5105e8bSPaolo Bonzini }
1627b5105e8bSPaolo Bonzini 
1628b5105e8bSPaolo Bonzini static void test_perf_loop(void)
1629b5105e8bSPaolo Bonzini {
1630b5105e8bSPaolo Bonzini 	/*
1631b5105e8bSPaolo Bonzini 	 * This test runs simple instructions that should roughly take the
1632b5105e8bSPaolo Bonzini 	 * the same time to emulate: PERF_COUNT iterations of "loop" and 3
1633b5105e8bSPaolo Bonzini 	 * setup instructions.  Other performance tests can run PERF_COUNT
1634b5105e8bSPaolo Bonzini 	 * iterations of the same instruction and subtract the cycle count
1635b5105e8bSPaolo Bonzini 	 * of this test.
1636b5105e8bSPaolo Bonzini 	 */
1637b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_loop, "");
1638b5105e8bSPaolo Bonzini 	perf_baseline = cycles_in_big_real_mode(&insn_perf_loop);
1639b5105e8bSPaolo Bonzini 	print_serial_u32(perf_baseline / (PERF_COUNT + 3));
1640b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated jump instruction\n");
1641b5105e8bSPaolo Bonzini }
1642b5105e8bSPaolo Bonzini 
1643b5105e8bSPaolo Bonzini static void test_perf_mov(void)
1644b5105e8bSPaolo Bonzini {
1645b5105e8bSPaolo Bonzini 	u32 cyc;
1646b5105e8bSPaolo Bonzini 
1647b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_move, "mov %esi, %edi");
1648b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_move);
1649b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1650b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated move instruction\n");
1651b5105e8bSPaolo Bonzini }
1652b5105e8bSPaolo Bonzini 
1653b5105e8bSPaolo Bonzini static void test_perf_arith(void)
1654b5105e8bSPaolo Bonzini {
1655b5105e8bSPaolo Bonzini 	u32 cyc;
1656b5105e8bSPaolo Bonzini 
1657b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_arith, "add $4, %edi");
1658b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_arith);
1659b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1660b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated arithmetic instruction\n");
1661b5105e8bSPaolo Bonzini }
1662b5105e8bSPaolo Bonzini 
1663b5105e8bSPaolo Bonzini static void test_perf_memory_load(void)
1664b5105e8bSPaolo Bonzini {
1665b5105e8bSPaolo Bonzini 	u32 cyc, tmp;
1666b5105e8bSPaolo Bonzini 
1667576718d0SBill Wendling 	MK_INSN_PERF(perf_memory_load, "cmpw $0, (%edi)");
1668bd62e289SBill Wendling 
1669bd62e289SBill Wendling 	init_inregs(&(struct regs){ .edi = (u32)&tmp });
1670bd62e289SBill Wendling 
1671b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_load);
1672b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1673b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated memory load instruction\n");
1674b5105e8bSPaolo Bonzini }
1675b5105e8bSPaolo Bonzini 
16769306cb8eSPaolo Bonzini static void test_perf_memory_store(void)
16779306cb8eSPaolo Bonzini {
16789306cb8eSPaolo Bonzini 	u32 cyc, tmp;
16799306cb8eSPaolo Bonzini 
1680576718d0SBill Wendling 	MK_INSN_PERF(perf_memory_store, "movw %ax, (%edi)");
1681bd62e289SBill Wendling 
1682bd62e289SBill Wendling 	init_inregs(&(struct regs){ .edi = (u32)&tmp });
1683bd62e289SBill Wendling 
16849306cb8eSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_store);
16859306cb8eSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
16869306cb8eSPaolo Bonzini 	print_serial(" cycles/emulated memory store instruction\n");
16879306cb8eSPaolo Bonzini }
16889306cb8eSPaolo Bonzini 
1689b5105e8bSPaolo Bonzini static void test_perf_memory_rmw(void)
1690b5105e8bSPaolo Bonzini {
1691b5105e8bSPaolo Bonzini 	u32 cyc, tmp;
1692b5105e8bSPaolo Bonzini 
1693576718d0SBill Wendling 	MK_INSN_PERF(perf_memory_rmw, "addw $1, (%edi)");
1694bd62e289SBill Wendling 
1695bd62e289SBill Wendling 	init_inregs(&(struct regs){ .edi = (u32)&tmp });
1696bd62e289SBill Wendling 
1697b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_rmw);
1698b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1699b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated memory RMW instruction\n");
1700b5105e8bSPaolo Bonzini }
1701b5105e8bSPaolo Bonzini 
17022e3f9f1fSThomas Huth static void test_dr_mod(void)
17030a5701edSNadav Amit {
17040a5701edSNadav Amit 	MK_INSN(drmod, "movl %ebx, %dr0\n\t"
17050a5701edSNadav Amit 		       ".byte 0x0f \n\t .byte 0x21 \n\t .byte 0x0\n\t");
1706bd62e289SBill Wendling 
1707bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0xdead, .ebx = 0xaced });
1708bd62e289SBill Wendling 
17090a5701edSNadav Amit 	exec_in_big_real_mode(&insn_drmod);
17100a5701edSNadav Amit 	report("mov dr with mod bits", R_AX | R_BX, outregs.eax == 0xaced);
17110a5701edSNadav Amit }
17120a5701edSNadav Amit 
17132e3f9f1fSThomas Huth static void test_smsw(void)
171499ee878cSNadav Amit {
171599ee878cSNadav Amit 	MK_INSN(smsw, "movl %cr0, %ebx\n\t"
171699ee878cSNadav Amit 		      "movl %ebx, %ecx\n\t"
171799ee878cSNadav Amit 		      "or $0x40000000, %ebx\n\t"
171899ee878cSNadav Amit 		      "movl %ebx, %cr0\n\t"
171999ee878cSNadav Amit 		      "smswl %eax\n\t"
172099ee878cSNadav Amit 		      "movl %ecx, %cr0\n\t");
1721bd62e289SBill Wendling 
1722bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0x12345678 });
1723bd62e289SBill Wendling 
172499ee878cSNadav Amit 	exec_in_big_real_mode(&insn_smsw);
172599ee878cSNadav Amit 	report("smsw", R_AX | R_BX | R_CX, outregs.eax == outregs.ebx);
172699ee878cSNadav Amit }
172799ee878cSNadav Amit 
17282e3f9f1fSThomas Huth static void test_xadd(void)
17297bee560dSNadav Amit {
17307bee560dSNadav Amit 	MK_INSN(xadd, "xaddl %eax, %eax\n\t");
1731bd62e289SBill Wendling 
1732bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0x12345678 });
1733bd62e289SBill Wendling 
17347bee560dSNadav Amit 	exec_in_big_real_mode(&insn_xadd);
17357bee560dSNadav Amit 	report("xadd", R_AX, outregs.eax == inregs.eax * 2);
17367bee560dSNadav Amit }
17377bee560dSNadav Amit 
173899ee878cSNadav Amit 
17397d36db35SAvi Kivity void realmode_start(void)
17407d36db35SAvi Kivity {
17417d36db35SAvi Kivity 	test_null();
17427d36db35SAvi Kivity 
17437d36db35SAvi Kivity 	test_shld();
17447d36db35SAvi Kivity 	test_push_pop();
17457d36db35SAvi Kivity 	test_pusha_popa();
17467d36db35SAvi Kivity 	test_mov_imm();
17477d36db35SAvi Kivity 	test_cmp_imm();
17487d36db35SAvi Kivity 	test_add_imm();
17497d36db35SAvi Kivity 	test_sub_imm();
17507d36db35SAvi Kivity 	test_xor_imm();
17517d36db35SAvi Kivity 	test_io();
17527d36db35SAvi Kivity 	test_eflags_insn();
17537d36db35SAvi Kivity 	test_jcc_short();
17547d36db35SAvi Kivity 	test_jcc_near();
17557d36db35SAvi Kivity 	/* test_call() uses short jump so call it after testing jcc */
17567d36db35SAvi Kivity 	test_call();
17577d36db35SAvi Kivity 	/* long jmp test uses call near so test it after testing call */
17587d36db35SAvi Kivity 	test_long_jmp();
17597d36db35SAvi Kivity 	test_xchg();
17607d36db35SAvi Kivity 	test_iret();
176196b9ca1eSMohammed Gamal 	test_int();
17628202cf84SRoman Bolshakov 	test_sti_inhibit();
1763fa74f8a6SMohammed Gamal 	test_imul();
176459317bd1SMohammed Gamal 	test_mul();
17650d4c7614SMohammed Gamal 	test_div();
17660d4c7614SMohammed Gamal 	test_idiv();
1767eacef4e2SWei Yongjun 	test_loopcc();
17686e293cf5SWei Yongjun 	test_cbw();
17690cbd5b06SMohammed Gamal 	test_cwd_cdq();
1770b274feedSAvi Kivity 	test_das();
177137f51a4aSWei Yongjun 	test_lds_lss();
1772b1c7c575SWei Yongjun 	test_jcxz();
17738f578e98SAvi Kivity 	test_cpuid();
1774ed93f43bSAvi Kivity 	test_ss_base_for_esp_ebp();
1775c2281fa4SAvi Kivity 	test_sgdt_sidt();
17767ae3645aSAvi Kivity 	test_lahf();
177788b6dac4SPaolo Bonzini 	test_sahf();
1778fd9ea640SAvi Kivity 	test_movzx_movsx();
1779b493b2e8SAvi Kivity 	test_bswap();
17808cd86387SGleb Natapov 	test_aad();
17812a9b5718SPaolo Bonzini 	test_aam();
17822a9b5718SPaolo Bonzini 	test_xlat();
17832a9b5718SPaolo Bonzini 	test_salc();
17840987db7aSGleb Natapov 	test_fninit();
17850a5701edSNadav Amit 	test_dr_mod();
178699ee878cSNadav Amit 	test_smsw();
17871a4c03a0SArthur Chunqi Li 	test_nopl();
17887bee560dSNadav Amit 	test_xadd();
1789b5105e8bSPaolo Bonzini 	test_perf_loop();
1790b5105e8bSPaolo Bonzini 	test_perf_mov();
1791b5105e8bSPaolo Bonzini 	test_perf_arith();
1792b5105e8bSPaolo Bonzini 	test_perf_memory_load();
17939306cb8eSPaolo Bonzini 	test_perf_memory_store();
1794b5105e8bSPaolo Bonzini 	test_perf_memory_rmw();
17957d36db35SAvi Kivity 
1796b393fe28SNadav Amit 	exit(failed);
17977d36db35SAvi Kivity }
17987d36db35SAvi Kivity 
17997d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff };
18007d36db35SAvi Kivity 
1801975ca087SPeter Feiner struct table_descr r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt };
18027d36db35SAvi Kivity 
18037d36db35SAvi Kivity asm(
18047d36db35SAvi Kivity 	".section .init \n\t"
18057d36db35SAvi Kivity 
18067d36db35SAvi Kivity 	".code32 \n\t"
18077d36db35SAvi Kivity 
18087d36db35SAvi Kivity 	"mb_magic = 0x1BADB002 \n\t"
18097d36db35SAvi Kivity 	"mb_flags = 0x0 \n\t"
18107d36db35SAvi Kivity 
18117d36db35SAvi Kivity 	"# multiboot header \n\t"
18127d36db35SAvi Kivity 	".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t"
18137d36db35SAvi Kivity 
18147d36db35SAvi Kivity 	".globl start \n\t"
18157d36db35SAvi Kivity 	".data \n\t"
18167d36db35SAvi Kivity 	". = . + 4096 \n\t"
18177d36db35SAvi Kivity 	"stacktop: \n\t"
18187d36db35SAvi Kivity 
18197d36db35SAvi Kivity 	".text \n\t"
18207d36db35SAvi Kivity 	"start: \n\t"
18217d36db35SAvi Kivity 	"lgdt r_gdt_descr \n\t"
18227d36db35SAvi Kivity 	"ljmp $8, $1f; 1: \n\t"
18237d36db35SAvi Kivity 	".code16gcc \n\t"
18247d36db35SAvi Kivity 	"mov $16, %eax \n\t"
18257d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
18267d36db35SAvi Kivity 	"mov %ax, %es \n\t"
18277d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
18287d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
18297d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
18307d36db35SAvi Kivity 	"mov %cr0, %eax \n\t"
18317d36db35SAvi Kivity 	"btc $0, %eax \n\t"
18327d36db35SAvi Kivity 	"mov %eax, %cr0 \n\t"
18337d36db35SAvi Kivity 	"ljmp $0, $realmode_entry \n\t"
18347d36db35SAvi Kivity 
18357d36db35SAvi Kivity 	"realmode_entry: \n\t"
18367d36db35SAvi Kivity 
18377d36db35SAvi Kivity 	"xor %ax, %ax \n\t"
18387d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
18397d36db35SAvi Kivity 	"mov %ax, %es \n\t"
18407d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
18417d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
18427d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
18437d36db35SAvi Kivity 	"mov $stacktop, %esp\n\t"
18447d36db35SAvi Kivity 	"ljmp $0, $realmode_start \n\t"
18457d36db35SAvi Kivity 
18467d36db35SAvi Kivity 	".code16gcc \n\t"
18477d36db35SAvi Kivity 	);
1848