xref: /kvm-unit-tests/x86/realmode.c (revision c83858a4e0b3b6d9554c866cb5163a27fa5964bf)
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);
80*c83858a4SNadav Amit 
81*c83858a4SNadav Amit 	/* IER: disable interrupts */
82*c83858a4SNadav Amit 	outb(0x00, serial_iobase + 0x01);
83*c83858a4SNadav Amit 	/* LCR: 8 bits, no parity, one stop bit */
84*c83858a4SNadav Amit 	outb(0x03, serial_iobase + 0x03);
85*c83858a4SNadav Amit 	/* FCR: disable FIFO queues */
86*c83858a4SNadav Amit 	outb(0x00, serial_iobase + 0x02);
87*c83858a4SNadav Amit 	/* MCR: RTS, DTR on */
88*c83858a4SNadav Amit 	outb(0x03, serial_iobase + 0x04);
89f366255fSPaolo Bonzini }
90f366255fSPaolo Bonzini #endif
91f366255fSPaolo Bonzini 
927d36db35SAvi Kivity static void print_serial(const char *buf)
937d36db35SAvi Kivity {
947d36db35SAvi Kivity 	unsigned long len = strlen(buf);
95f366255fSPaolo Bonzini #ifdef USE_SERIAL
96f366255fSPaolo Bonzini 	unsigned long i;
97f366255fSPaolo Bonzini 	if (!serial_inited) {
98f366255fSPaolo Bonzini 	    serial_init();
99f366255fSPaolo Bonzini 	    serial_inited = 1;
100f366255fSPaolo Bonzini 	}
1017d36db35SAvi Kivity 
102f366255fSPaolo Bonzini 	for (i = 0; i < len; i++) {
103f366255fSPaolo Bonzini 	    serial_outb(buf[i]);
104f366255fSPaolo Bonzini 	}
105f366255fSPaolo Bonzini #else
1065edbb9aeSPaolo Bonzini 	asm volatile ("addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1));
107f366255fSPaolo Bonzini #endif
1087d36db35SAvi Kivity }
1097d36db35SAvi Kivity 
110b5105e8bSPaolo Bonzini static void print_serial_u32(u32 value)
111b5105e8bSPaolo Bonzini {
112b5105e8bSPaolo Bonzini 	char n[12], *p;
113b5105e8bSPaolo Bonzini 	p = &n[11];
114b5105e8bSPaolo Bonzini 	*p = 0;
115b5105e8bSPaolo Bonzini 	do {
116b5105e8bSPaolo Bonzini 		*--p = '0' + (value % 10);
117b5105e8bSPaolo Bonzini 		value /= 10;
118b5105e8bSPaolo Bonzini 	} while (value > 0);
119b5105e8bSPaolo Bonzini 	print_serial(p);
120b5105e8bSPaolo Bonzini }
121b5105e8bSPaolo Bonzini 
122b393fe28SNadav Amit static int failed;
123b393fe28SNadav Amit 
1247d36db35SAvi Kivity static void exit(int code)
1257d36db35SAvi Kivity {
126f366255fSPaolo Bonzini 	outb(code, 0xf4);
1273b9b2d55SNadav Amit 
1283b9b2d55SNadav Amit 	while (1) {
1293b9b2d55SNadav Amit 		asm volatile("hlt" ::: "memory");
1303b9b2d55SNadav Amit 	}
1317d36db35SAvi Kivity }
1327d36db35SAvi Kivity 
1337d36db35SAvi Kivity struct regs {
1347d36db35SAvi Kivity 	u32 eax, ebx, ecx, edx;
1357d36db35SAvi Kivity 	u32 esi, edi, esp, ebp;
1367d36db35SAvi Kivity 	u32 eip, eflags;
1377d36db35SAvi Kivity };
1387d36db35SAvi Kivity 
139975ca087SPeter Feiner struct table_descr {
140975ca087SPeter Feiner 	u16 limit;
141975ca087SPeter Feiner 	void *base;
142975ca087SPeter Feiner } __attribute__((packed));
143975ca087SPeter Feiner 
1447d36db35SAvi Kivity static u64 gdt[] = {
1457d36db35SAvi Kivity 	0,
1467d36db35SAvi Kivity 	0x00cf9b000000ffffull, // flat 32-bit code segment
1477d36db35SAvi Kivity 	0x00cf93000000ffffull, // flat 32-bit data segment
1487d36db35SAvi Kivity };
1497d36db35SAvi Kivity 
150975ca087SPeter Feiner static struct table_descr gdt_descr = {
1517d36db35SAvi Kivity 	sizeof(gdt) - 1,
1527d36db35SAvi Kivity 	gdt,
1537d36db35SAvi Kivity };
1547d36db35SAvi Kivity 
155d4dc402cSAvi Kivity struct insn_desc {
156d4dc402cSAvi Kivity     u16 ptr;
157d4dc402cSAvi Kivity     u16 len;
158d4dc402cSAvi Kivity };
159d4dc402cSAvi Kivity 
160bd62e289SBill Wendling struct {
161bd62e289SBill Wendling 	u32 stack[128];
162bd62e289SBill Wendling 	char top[];
163bd62e289SBill Wendling } tmp_stack;
164bd62e289SBill Wendling 
16518253fdeSAvi Kivity static struct regs inregs, outregs;
16618253fdeSAvi Kivity 
167bd62e289SBill Wendling static inline void init_inregs(struct regs *regs)
168bd62e289SBill Wendling {
169bd62e289SBill Wendling 	inregs = (struct regs){ 0 };
170bd62e289SBill Wendling 	if (regs)
171bd62e289SBill Wendling 		inregs = *regs;
172bd62e289SBill Wendling 	if (!inregs.esp)
173bd62e289SBill Wendling 		inregs.esp = (unsigned long)&tmp_stack.top;
174bd62e289SBill Wendling }
175bd62e289SBill Wendling 
17618253fdeSAvi Kivity static void exec_in_big_real_mode(struct insn_desc *insn)
1777d36db35SAvi Kivity {
1787d36db35SAvi Kivity 	unsigned long tmp;
1797d36db35SAvi Kivity 	static struct regs save;
1807d36db35SAvi Kivity 	int i;
1817d36db35SAvi Kivity 	extern u8 test_insn[], test_insn_end[];
1827d36db35SAvi Kivity 
183d4dc402cSAvi Kivity 	for (i = 0; i < insn->len; ++i)
184d4dc402cSAvi Kivity 	    test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i];
1857d36db35SAvi Kivity 	for (; i < test_insn_end - test_insn; ++i)
1867d36db35SAvi Kivity 		test_insn[i] = 0x90; // nop
1877d36db35SAvi Kivity 
18818253fdeSAvi Kivity 	save = inregs;
1897d36db35SAvi Kivity 	asm volatile(
1907d36db35SAvi Kivity 		"lgdtl %[gdt_descr] \n\t"
1917d36db35SAvi Kivity 		"mov %%cr0, %[tmp] \n\t"
1927d36db35SAvi Kivity 		"or $1, %[tmp] \n\t"
1937d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
1947d36db35SAvi Kivity 		"mov %[bigseg], %%gs \n\t"
1957d36db35SAvi Kivity 		"and $-2, %[tmp] \n\t"
1967d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
1977d36db35SAvi Kivity 
198eb6687a2SBill Wendling 		/* Save ES, because it is clobbered by some tests. */
199eb6687a2SBill Wendling 		"pushw %%es \n\t"
200eb6687a2SBill Wendling 
20132001692SAvi Kivity 		"pushw %[save]+36; popfw \n\t"
2027d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
2037d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
2047d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
2057d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
2067d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
2077d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
2087d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
2097d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
2107d36db35SAvi Kivity 
2117d36db35SAvi Kivity 		"test_insn: . = . + 32\n\t"
2127d36db35SAvi Kivity 		"test_insn_end: \n\t"
2137d36db35SAvi Kivity 
2147d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
2157d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
2167d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
2177d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
2187d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
2197d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
2207d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
2217d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
2227d36db35SAvi Kivity 
2237d36db35SAvi Kivity 		/* Save EFLAGS in outregs*/
2247d36db35SAvi Kivity 		"pushfl \n\t"
2257d36db35SAvi Kivity 		"popl %[save]+36 \n\t"
2267d36db35SAvi Kivity 
227eb6687a2SBill Wendling 		/* Restore ES for future rep string operations. */
228eb6687a2SBill Wendling 		"popw %%es \n\t"
229eb6687a2SBill Wendling 
2305edbb9aeSPaolo Bonzini 		/* Restore DF for the harness code */
2315edbb9aeSPaolo Bonzini 		"cld\n\t"
2327d36db35SAvi Kivity 		"xor %[tmp], %[tmp] \n\t"
2337d36db35SAvi Kivity 		"mov %[tmp], %%gs \n\t"
2347d36db35SAvi Kivity 		: [tmp]"=&r"(tmp), [save]"+m"(save)
2357d36db35SAvi Kivity 		: [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16)
2367d36db35SAvi Kivity 		: "cc", "memory"
2377d36db35SAvi Kivity 		);
23818253fdeSAvi Kivity 	outregs = save;
2397d36db35SAvi Kivity }
2407d36db35SAvi Kivity 
2417d36db35SAvi Kivity #define R_AX 1
2427d36db35SAvi Kivity #define R_BX 2
2437d36db35SAvi Kivity #define R_CX 4
2447d36db35SAvi Kivity #define R_DX 8
2457d36db35SAvi Kivity #define R_SI 16
2467d36db35SAvi Kivity #define R_DI 32
2477d36db35SAvi Kivity #define R_SP 64
2487d36db35SAvi Kivity #define R_BP 128
2497d36db35SAvi Kivity 
2502e3f9f1fSThomas Huth static int regs_equal(int ignore)
2517d36db35SAvi Kivity {
25218253fdeSAvi Kivity 	const u32 *p1 = &inregs.eax, *p2 = &outregs.eax;  // yuck
2537d36db35SAvi Kivity 	int i;
2547d36db35SAvi Kivity 
2557d36db35SAvi Kivity 	for (i = 0; i < 8; ++i)
2567d36db35SAvi Kivity 		if (!(ignore & (1 << i)) && p1[i] != p2[i])
2577d36db35SAvi Kivity 			return 0;
2587d36db35SAvi Kivity 	return 1;
2597d36db35SAvi Kivity }
2607d36db35SAvi Kivity 
2616055ea1fSAvi Kivity static void report(const char *name, u16 regs_ignore, _Bool ok)
26281050840SAvi Kivity {
2636055ea1fSAvi Kivity     if (!regs_equal(regs_ignore)) {
2646055ea1fSAvi Kivity 	ok = 0;
2656055ea1fSAvi Kivity     }
26681050840SAvi Kivity     print_serial(ok ? "PASS: " : "FAIL: ");
26781050840SAvi Kivity     print_serial(name);
26881050840SAvi Kivity     print_serial("\n");
269b393fe28SNadav Amit     if (!ok)
270b393fe28SNadav Amit 	failed = 1;
27181050840SAvi Kivity }
27281050840SAvi Kivity 
2737d36db35SAvi Kivity #define MK_INSN(name, str)				\
2747d36db35SAvi Kivity     asm (						\
275d4dc402cSAvi Kivity 	 ".pushsection .data.insn  \n\t"		\
276d4dc402cSAvi Kivity 	 "insn_" #name ": \n\t"				\
277d4dc402cSAvi Kivity 	 ".word 1001f, 1002f - 1001f \n\t"		\
278d4dc402cSAvi Kivity 	 ".popsection \n\t"				\
279d4dc402cSAvi Kivity 	 ".pushsection .text.insn, \"ax\" \n\t"		\
280d4dc402cSAvi Kivity 	 "1001: \n\t"					\
281d4dc402cSAvi Kivity 	 "insn_code_" #name ": " str " \n\t"		\
282d4dc402cSAvi Kivity 	 "1002: \n\t"					\
283d4dc402cSAvi Kivity 	 ".popsection"					\
2847d36db35SAvi Kivity     );							\
285d4dc402cSAvi Kivity     extern struct insn_desc insn_##name;
2867d36db35SAvi Kivity 
2872e3f9f1fSThomas Huth static void test_xchg(void)
2887d36db35SAvi Kivity {
2897d36db35SAvi Kivity 	MK_INSN(xchg_test1, "xchg %eax,%eax\n\t");
2907d36db35SAvi Kivity 	MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t");
2917d36db35SAvi Kivity 	MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t");
2927d36db35SAvi Kivity 	MK_INSN(xchg_test4, "xchg %eax,%edx\n\t");
2937d36db35SAvi Kivity 	MK_INSN(xchg_test5, "xchg %eax,%esi\n\t");
2947d36db35SAvi Kivity 	MK_INSN(xchg_test6, "xchg %eax,%edi\n\t");
2957d36db35SAvi Kivity 	MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t");
2967d36db35SAvi Kivity 	MK_INSN(xchg_test8, "xchg %eax,%esp\n\t");
2977d36db35SAvi Kivity 
29818253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7};
2997d36db35SAvi Kivity 
30018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test1);
3016055ea1fSAvi Kivity 	report("xchg 1", 0, 1);
30218253fdeSAvi Kivity 
30318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test2);
3046055ea1fSAvi Kivity 	report("xchg 2", R_AX | R_BX,
3056055ea1fSAvi Kivity 	       outregs.eax == inregs.ebx && outregs.ebx == inregs.eax);
3067d36db35SAvi Kivity 
30718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test3);
3086055ea1fSAvi Kivity 	report("xchg 3", R_AX | R_CX,
3096055ea1fSAvi Kivity 	       outregs.eax == inregs.ecx && outregs.ecx == inregs.eax);
3107d36db35SAvi Kivity 
31118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test4);
3126055ea1fSAvi Kivity 	report("xchg 4", R_AX | R_DX,
3136055ea1fSAvi Kivity 	       outregs.eax == inregs.edx && outregs.edx == inregs.eax);
3147d36db35SAvi Kivity 
31518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test5);
3166055ea1fSAvi Kivity 	report("xchg 5", R_AX | R_SI,
3176055ea1fSAvi Kivity 	       outregs.eax == inregs.esi && outregs.esi == inregs.eax);
3187d36db35SAvi Kivity 
31918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test6);
3206055ea1fSAvi Kivity 	report("xchg 6", R_AX | R_DI,
3216055ea1fSAvi Kivity 	       outregs.eax == inregs.edi && outregs.edi == inregs.eax);
3227d36db35SAvi Kivity 
32318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test7);
3246055ea1fSAvi Kivity 	report("xchg 7", R_AX | R_BP,
3256055ea1fSAvi Kivity 	       outregs.eax == inregs.ebp && outregs.ebp == inregs.eax);
3267d36db35SAvi Kivity 
32718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test8);
3286055ea1fSAvi Kivity 	report("xchg 8", R_AX | R_SP,
3296055ea1fSAvi Kivity 	       outregs.eax == inregs.esp && outregs.esp == inregs.eax);
3307d36db35SAvi Kivity }
3317d36db35SAvi Kivity 
3322e3f9f1fSThomas Huth static void test_shld(void)
3337d36db35SAvi Kivity {
3347d36db35SAvi Kivity 	MK_INSN(shld_test, "shld $8,%edx,%eax\n\t");
3357d36db35SAvi Kivity 
336bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0xbe, .edx = 0xef000000 });
337bd62e289SBill Wendling 
33818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_shld_test);
3396055ea1fSAvi Kivity 	report("shld", ~0, outregs.eax == 0xbeef);
3407d36db35SAvi Kivity }
3417d36db35SAvi Kivity 
3422e3f9f1fSThomas Huth static void test_mov_imm(void)
3437d36db35SAvi Kivity {
3447d36db35SAvi Kivity 	MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax");
3457d36db35SAvi Kivity 	MK_INSN(mov_r16_imm_1, "mov $1234, %ax");
3467d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_1, "mov $0x12, %ah");
3477d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_2, "mov $0x34, %al");
3487d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t");
3497d36db35SAvi Kivity 
350bd62e289SBill Wendling 	init_inregs(NULL);
35118253fdeSAvi Kivity 
35218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r16_imm_1);
3536055ea1fSAvi Kivity 	report("mov 1", R_AX, outregs.eax == 1234);
3547d36db35SAvi Kivity 
3557d36db35SAvi Kivity 	/* test mov $imm, %eax */
35618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r32_imm_1);
3576055ea1fSAvi Kivity 	report("mov 2", R_AX, outregs.eax == 1234567890);
3587d36db35SAvi Kivity 
3597d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
36018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_1);
3616055ea1fSAvi Kivity 	report("mov 3", R_AX, outregs.eax == 0x1200);
3627d36db35SAvi Kivity 
36318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_2);
3646055ea1fSAvi Kivity 	report("mov 4", R_AX, outregs.eax == 0x34);
3657d36db35SAvi Kivity 
36618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_3);
3676055ea1fSAvi Kivity 	report("mov 5", R_AX, outregs.eax == 0x1234);
3687d36db35SAvi Kivity }
3697d36db35SAvi Kivity 
3702e3f9f1fSThomas Huth static void test_sub_imm(void)
3717d36db35SAvi Kivity {
3727d36db35SAvi Kivity 	MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t");
3737d36db35SAvi Kivity 	MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t");
3747d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t");
3757d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t");
3767d36db35SAvi Kivity 
377bd62e289SBill Wendling 	init_inregs(NULL);
37818253fdeSAvi Kivity 
37918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r16_imm_1);
3806055ea1fSAvi Kivity 	report("sub 1", R_AX, outregs.eax == 1224);
3817d36db35SAvi Kivity 
3827d36db35SAvi Kivity 	/* test mov $imm, %eax */
38318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r32_imm_1);
3846055ea1fSAvi Kivity 	report("sub 2", R_AX, outregs.eax == 1234567880);
3857d36db35SAvi Kivity 
3867d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
38718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_1);
3886055ea1fSAvi Kivity 	report("sub 3", R_AX, outregs.eax == 0x0200);
3897d36db35SAvi Kivity 
39018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_2);
3916055ea1fSAvi Kivity 	report("sub 4", R_AX, outregs.eax == 0x24);
3927d36db35SAvi Kivity }
3937d36db35SAvi Kivity 
3942e3f9f1fSThomas Huth static void test_xor_imm(void)
3957d36db35SAvi Kivity {
3967d36db35SAvi Kivity 	MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t");
3977d36db35SAvi Kivity 	MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t");
3987d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t");
3997d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t");
4007d36db35SAvi Kivity 
401bd62e289SBill Wendling 	init_inregs(NULL);
40218253fdeSAvi Kivity 
40318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r16_imm_1);
4046055ea1fSAvi Kivity 	report("xor 1", R_AX, outregs.eax == 0);
4057d36db35SAvi Kivity 
4067d36db35SAvi Kivity 	/* test mov $imm, %eax */
40718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r32_imm_1);
4086055ea1fSAvi Kivity 	report("xor 2", R_AX, outregs.eax == 0);
4097d36db35SAvi Kivity 
4107d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
41118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_1);
4126055ea1fSAvi Kivity 	report("xor 3", R_AX, outregs.eax == 0);
4137d36db35SAvi Kivity 
41418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_2);
4156055ea1fSAvi Kivity 	report("xor 4", R_AX, outregs.eax == 0);
4167d36db35SAvi Kivity }
4177d36db35SAvi Kivity 
4182e3f9f1fSThomas Huth static void test_cmp_imm(void)
4197d36db35SAvi Kivity {
4207d36db35SAvi Kivity 	MK_INSN(cmp_test1, "mov $0x34, %al\n\t"
4217d36db35SAvi Kivity 			   "cmp $0x34, %al\n\t");
4227d36db35SAvi Kivity 	MK_INSN(cmp_test2, "mov $0x34, %al\n\t"
4237d36db35SAvi Kivity 			   "cmp $0x39, %al\n\t");
4247d36db35SAvi Kivity 	MK_INSN(cmp_test3, "mov $0x34, %al\n\t"
4257d36db35SAvi Kivity 			   "cmp $0x24, %al\n\t");
4267d36db35SAvi Kivity 
427bd62e289SBill Wendling 	init_inregs(NULL);
42818253fdeSAvi Kivity 
4297d36db35SAvi Kivity 	/* test cmp imm8 with AL */
4307d36db35SAvi Kivity 	/* ZF: (bit 6) Zero Flag becomes 1 if an operation results
4317d36db35SAvi Kivity 	 * in a 0 writeback, or 0 register
4327d36db35SAvi Kivity 	 */
43318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test1);
4346055ea1fSAvi Kivity 	report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6));
4357d36db35SAvi Kivity 
43618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test2);
4376055ea1fSAvi Kivity 	report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0);
4387d36db35SAvi Kivity 
43918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test3);
4406055ea1fSAvi Kivity 	report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0);
4417d36db35SAvi Kivity }
4427d36db35SAvi Kivity 
4432e3f9f1fSThomas Huth static void test_add_imm(void)
4447d36db35SAvi Kivity {
4457d36db35SAvi Kivity 	MK_INSN(add_test1, "mov $0x43211234, %eax \n\t"
4467d36db35SAvi Kivity 			   "add $0x12344321, %eax \n\t");
4477d36db35SAvi Kivity 	MK_INSN(add_test2, "mov $0x12, %eax \n\t"
4487d36db35SAvi Kivity 			   "add $0x21, %al\n\t");
4497d36db35SAvi Kivity 
450bd62e289SBill Wendling 	init_inregs(NULL);
45118253fdeSAvi Kivity 
45218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test1);
4536055ea1fSAvi Kivity 	report("add 1", ~0, outregs.eax == 0x55555555);
4547d36db35SAvi Kivity 
45518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test2);
4566055ea1fSAvi Kivity 	report("add 2", ~0, outregs.eax == 0x33);
4577d36db35SAvi Kivity }
4587d36db35SAvi Kivity 
4592e3f9f1fSThomas Huth static void test_eflags_insn(void)
4607d36db35SAvi Kivity {
4617d36db35SAvi Kivity 	MK_INSN(clc, "clc");
462b3261e48SMohammed Gamal 	MK_INSN(stc, "stc");
4637d36db35SAvi Kivity 	MK_INSN(cli, "cli");
4647d36db35SAvi Kivity 	MK_INSN(sti, "sti");
4657d36db35SAvi Kivity 	MK_INSN(cld, "cld");
4667d36db35SAvi Kivity 	MK_INSN(std, "std");
4677d36db35SAvi Kivity 
468bd62e289SBill Wendling 	init_inregs(NULL);
46918253fdeSAvi Kivity 
47018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_clc);
4716055ea1fSAvi Kivity 	report("clc", ~0, (outregs.eflags & 1) == 0);
4727d36db35SAvi Kivity 
47318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_stc);
4746055ea1fSAvi Kivity 	report("stc", ~0, (outregs.eflags & 1) == 1);
475b3261e48SMohammed Gamal 
47618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cli);
4776055ea1fSAvi Kivity 	report("cli", ~0, !(outregs.eflags & (1 << 9)));
4787d36db35SAvi Kivity 
47918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sti);
4806055ea1fSAvi Kivity 	report("sti", ~0, outregs.eflags & (1 << 9));
4817d36db35SAvi Kivity 
48218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cld);
4836055ea1fSAvi Kivity 	report("cld", ~0, !(outregs.eflags & (1 << 10)));
4847d36db35SAvi Kivity 
48518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_std);
4866055ea1fSAvi Kivity 	report("std", ~0, (outregs.eflags & (1 << 10)));
4877d36db35SAvi Kivity }
4887d36db35SAvi Kivity 
4892e3f9f1fSThomas Huth static void test_io(void)
4907d36db35SAvi Kivity {
4917d36db35SAvi Kivity 	MK_INSN(io_test1, "mov $0xff, %al \n\t"
4927d36db35SAvi Kivity 		          "out %al, $0xe0 \n\t"
4937d36db35SAvi Kivity 		          "mov $0x00, %al \n\t"
4947d36db35SAvi Kivity 			  "in $0xe0, %al \n\t");
4957d36db35SAvi Kivity 	MK_INSN(io_test2, "mov $0xffff, %ax \n\t"
4967d36db35SAvi Kivity 			  "out %ax, $0xe0 \n\t"
4977d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
4987d36db35SAvi Kivity 			  "in $0xe0, %ax \n\t");
4997d36db35SAvi Kivity 	MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t"
5007d36db35SAvi Kivity 			  "out %eax, $0xe0 \n\t"
5017d36db35SAvi Kivity 			  "mov $0x000000, %eax \n\t"
5027d36db35SAvi Kivity 			  "in $0xe0, %eax \n\t");
5037d36db35SAvi Kivity 	MK_INSN(io_test4, "mov $0xe0, %dx \n\t"
5047d36db35SAvi Kivity 			  "mov $0xff, %al \n\t"
5057d36db35SAvi Kivity 			  "out %al, %dx \n\t"
5067d36db35SAvi Kivity 			  "mov $0x00, %al \n\t"
5077d36db35SAvi Kivity 			  "in %dx, %al \n\t");
5087d36db35SAvi Kivity 	MK_INSN(io_test5, "mov $0xe0, %dx \n\t"
5097d36db35SAvi Kivity 			  "mov $0xffff, %ax \n\t"
5107d36db35SAvi Kivity 			  "out %ax, %dx \n\t"
5117d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
5127d36db35SAvi Kivity 			  "in %dx, %ax \n\t");
5137d36db35SAvi Kivity 	MK_INSN(io_test6, "mov $0xe0, %dx \n\t"
5147d36db35SAvi Kivity 			  "mov $0xffffffff, %eax \n\t"
5157d36db35SAvi Kivity 			  "out %eax, %dx \n\t"
5167d36db35SAvi Kivity 			  "mov $0x00000000, %eax \n\t"
5177d36db35SAvi Kivity 			  "in %dx, %eax \n\t");
5187d36db35SAvi Kivity 
519bd62e289SBill Wendling 	init_inregs(NULL);
52018253fdeSAvi Kivity 
52118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test1);
5226055ea1fSAvi Kivity 	report("pio 1", R_AX, outregs.eax == 0xff);
5237d36db35SAvi Kivity 
52418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test2);
5256055ea1fSAvi Kivity 	report("pio 2", R_AX, outregs.eax == 0xffff);
5267d36db35SAvi Kivity 
52718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test3);
5286055ea1fSAvi Kivity 	report("pio 3", R_AX, outregs.eax == 0xffffffff);
5297d36db35SAvi Kivity 
53018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test4);
5316055ea1fSAvi Kivity 	report("pio 4", R_AX|R_DX, outregs.eax == 0xff);
5327d36db35SAvi Kivity 
53318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test5);
5346055ea1fSAvi Kivity 	report("pio 5", R_AX|R_DX, outregs.eax == 0xffff);
5357d36db35SAvi Kivity 
53618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test6);
5376055ea1fSAvi Kivity 	report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff);
5387d36db35SAvi Kivity }
5397d36db35SAvi Kivity 
540c0b7268dSAvi Kivity asm ("retf: lretw");
5412e3f9f1fSThomas Huth extern void retf(void);
542c0b7268dSAvi Kivity 
5434f66bc86SBruce Rogers asm ("retf_imm: lretw $10");
5442e3f9f1fSThomas Huth extern void retf_imm(void);
5454f66bc86SBruce Rogers 
5462e3f9f1fSThomas Huth static void test_call(void)
5477d36db35SAvi Kivity {
548c0b7268dSAvi Kivity 	u32 addr;
5497d36db35SAvi Kivity 
5507d36db35SAvi Kivity 	MK_INSN(call1, "mov $test_function, %eax \n\t"
5517d36db35SAvi Kivity 		       "call *%eax\n\t");
5527d36db35SAvi Kivity 	MK_INSN(call_near1, "jmp 2f\n\t"
5537d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5547d36db35SAvi Kivity 			    "ret\n\t"
5557d36db35SAvi Kivity 			    "2: call 1b\t");
5567d36db35SAvi Kivity 	MK_INSN(call_near2, "call 1f\n\t"
5577d36db35SAvi Kivity 			    "jmp 2f\n\t"
5587d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5597d36db35SAvi Kivity 			    "ret\n\t"
5607d36db35SAvi Kivity 			    "2:\t");
561c0b7268dSAvi Kivity 	MK_INSN(call_far1,  "lcallw *(%ebx)\n\t");
562556d2680SWei Yongjun 	MK_INSN(call_far2,  "lcallw $0, $retf\n\t");
563c6061817SAvi Kivity 	MK_INSN(ret_imm,    "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b");
5644f66bc86SBruce Rogers 	MK_INSN(retf_imm,   "sub $10, %sp; lcallw $0, $retf_imm");
5657d36db35SAvi Kivity 
566bd62e289SBill Wendling 	init_inregs(NULL);
567bd62e289SBill Wendling 
56818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call1);
5696055ea1fSAvi Kivity 	report("call 1", R_AX, outregs.eax == 0x1234);
5707d36db35SAvi Kivity 
57118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near1);
5726055ea1fSAvi Kivity 	report("call near 1", R_AX, outregs.eax == 0x1234);
5737d36db35SAvi Kivity 
57418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near2);
5756055ea1fSAvi Kivity 	report("call near 2", R_AX, outregs.eax == 0x1234);
576c0b7268dSAvi Kivity 
577c0b7268dSAvi Kivity 	addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f);
578c0b7268dSAvi Kivity 	inregs.ebx = (unsigned)&addr;
57918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_far1);
5806055ea1fSAvi Kivity 	report("call far 1", 0, 1);
581c6061817SAvi Kivity 
582556d2680SWei Yongjun 	exec_in_big_real_mode(&insn_call_far2);
583556d2680SWei Yongjun 	report("call far 2", 0, 1);
584556d2680SWei Yongjun 
58518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_ret_imm);
5866055ea1fSAvi Kivity 	report("ret imm 1", 0, 1);
5874f66bc86SBruce Rogers 
5884f66bc86SBruce Rogers 	exec_in_big_real_mode(&insn_retf_imm);
5894f66bc86SBruce Rogers 	report("retf imm 1", 0, 1);
5907d36db35SAvi Kivity }
5917d36db35SAvi Kivity 
5922e3f9f1fSThomas Huth static void test_jcc_short(void)
5937d36db35SAvi Kivity {
5947d36db35SAvi Kivity 	MK_INSN(jnz_short1, "jnz 1f\n\t"
5957d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
5967d36db35SAvi Kivity 		            "1:\n\t");
5977d36db35SAvi Kivity 	MK_INSN(jnz_short2, "1:\n\t"
5987d36db35SAvi Kivity 			    "cmp $0x1234, %eax\n\t"
5997d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
6007d36db35SAvi Kivity 		            "jnz 1b\n\t");
6017d36db35SAvi Kivity 	MK_INSN(jmp_short1, "jmp 1f\n\t"
6027d36db35SAvi Kivity 		      "mov $0x1234, %eax\n\t"
6037d36db35SAvi Kivity 		      "1:\n\t");
6047d36db35SAvi Kivity 
605bd62e289SBill Wendling 	init_inregs(NULL);
6067d36db35SAvi Kivity 
60718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short1);
6086055ea1fSAvi Kivity 	report("jnz short 1", ~0, 1);
60918253fdeSAvi Kivity 
61018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short2);
6116055ea1fSAvi Kivity 	report("jnz short 2", R_AX, (outregs.eflags & (1 << 6)));
6127d36db35SAvi Kivity 
61318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_short1);
6146055ea1fSAvi Kivity 	report("jmp short 1", ~0, 1);
6157d36db35SAvi Kivity }
6167d36db35SAvi Kivity 
6172e3f9f1fSThomas Huth static void test_jcc_near(void)
6187d36db35SAvi Kivity {
6197d36db35SAvi Kivity 	/* encode near jmp manually. gas will not do it if offsets < 127 byte */
6207d36db35SAvi Kivity 	MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t"
6217d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
6227d36db35SAvi Kivity 	MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t"
6237d36db35SAvi Kivity 			   "mov $0x1234, %eax\n\t"
6247d36db35SAvi Kivity 		           ".byte 0x0f, 0x85, 0xf0, 0xff\n\t");
6257d36db35SAvi Kivity 	MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t"
6267d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
6277d36db35SAvi Kivity 
628bd62e289SBill Wendling 	init_inregs(NULL);
6297d36db35SAvi Kivity 
63018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near1);
6316055ea1fSAvi Kivity 	report("jnz near 1", 0, 1);
63218253fdeSAvi Kivity 
63318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near2);
6346055ea1fSAvi Kivity 	report("jnz near 2", R_AX, outregs.eflags & (1 << 6));
6357d36db35SAvi Kivity 
63618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_near1);
6376055ea1fSAvi Kivity 	report("jmp near 1", 0, 1);
6387d36db35SAvi Kivity }
6397d36db35SAvi Kivity 
6402e3f9f1fSThomas Huth static void test_long_jmp(void)
6417d36db35SAvi Kivity {
6427d36db35SAvi Kivity 	MK_INSN(long_jmp, "call 1f\n\t"
6437d36db35SAvi Kivity 			  "jmp 2f\n\t"
6447d36db35SAvi Kivity 			  "1: jmp $0, $test_function\n\t"
6457d36db35SAvi Kivity 		          "2:\n\t");
646bd62e289SBill Wendling 
647bd62e289SBill Wendling 	init_inregs(NULL);
648bd62e289SBill Wendling 
64918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_long_jmp);
6506055ea1fSAvi Kivity 	report("jmp far 1", R_AX, outregs.eax == 0x1234);
6517d36db35SAvi Kivity }
652fa74f8a6SMohammed Gamal 
6532e3f9f1fSThomas Huth static void test_push_pop(void)
6547d36db35SAvi Kivity {
6557d36db35SAvi Kivity 	MK_INSN(push32, "mov $0x12345678, %eax\n\t"
6567d36db35SAvi Kivity 			"push %eax\n\t"
6577d36db35SAvi Kivity 			"pop %ebx\n\t");
6587d36db35SAvi Kivity 	MK_INSN(push16, "mov $0x1234, %ax\n\t"
6597d36db35SAvi Kivity 			"push %ax\n\t"
6607d36db35SAvi Kivity 			"pop %bx\n\t");
6617d36db35SAvi Kivity 
6627d36db35SAvi Kivity 	MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten
6637d36db35SAvi Kivity 			 "mov $0x123, %ax\n\t"
6647d36db35SAvi Kivity 			 "mov %ax, %es\n\t"
665231b4c3bSRoman Bolshakov 			 "pushw %es\n\t"
6667d36db35SAvi Kivity 			 "pop %bx \n\t"
6677d36db35SAvi Kivity 			 );
6687d36db35SAvi Kivity 	MK_INSN(pop_es, "push %ax\n\t"
669231b4c3bSRoman Bolshakov 			"popw %es\n\t"
6707d36db35SAvi Kivity 			"mov %es, %bx\n\t"
6717d36db35SAvi Kivity 			);
672231b4c3bSRoman Bolshakov 	MK_INSN(push_pop_ss, "pushw %ss\n\t"
6737d36db35SAvi Kivity 			     "pushw %ax\n\t"
6747d36db35SAvi Kivity 			     "popw %ss\n\t"
6757d36db35SAvi Kivity 			     "mov %ss, %bx\n\t"
676231b4c3bSRoman Bolshakov 			     "popw %ss\n\t"
6777d36db35SAvi Kivity 			);
678231b4c3bSRoman Bolshakov 	MK_INSN(push_pop_fs, "pushl %fs\n\t"
6797d36db35SAvi Kivity 			     "pushl %eax\n\t"
6807d36db35SAvi Kivity 			     "popl %fs\n\t"
6817d36db35SAvi Kivity 			     "mov %fs, %ebx\n\t"
682231b4c3bSRoman Bolshakov 			     "popl %fs\n\t"
6837d36db35SAvi Kivity 			);
68409b657b6SAvi Kivity 	MK_INSN(push_pop_high_esp_bits,
68509b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
68609b657b6SAvi Kivity 		"push %ax; \n\t"
68709b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
68809b657b6SAvi Kivity 		"pop %bx");
6897d36db35SAvi Kivity 
690bd62e289SBill Wendling 	init_inregs(NULL);
69118253fdeSAvi Kivity 
69218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push32);
6936055ea1fSAvi Kivity 	report("push/pop 1", R_AX|R_BX,
6946055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x12345678);
6957d36db35SAvi Kivity 
69618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push16);
6976055ea1fSAvi Kivity 	report("push/pop 2", R_AX|R_BX,
6986055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x1234);
6997d36db35SAvi Kivity 
70018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_es);
7016055ea1fSAvi Kivity 	report("push/pop 3", R_AX|R_BX,
7026055ea1fSAvi Kivity 	       outregs.ebx == outregs.eax && outregs.eax == 0x123);
7037d36db35SAvi Kivity 
70418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pop_es);
7056055ea1fSAvi Kivity 	report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax);
7067d36db35SAvi Kivity 
70718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_ss);
7086055ea1fSAvi Kivity 	report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax);
7097d36db35SAvi Kivity 
71018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_fs);
7116055ea1fSAvi Kivity 	report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax);
71209b657b6SAvi Kivity 
71309b657b6SAvi Kivity 	inregs.eax = 0x9977;
71409b657b6SAvi Kivity 	inregs.ebx = 0x7799;
71509b657b6SAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_high_esp_bits);
71609b657b6SAvi Kivity 	report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977);
7177d36db35SAvi Kivity }
7187d36db35SAvi Kivity 
7192e3f9f1fSThomas Huth static void test_null(void)
7207d36db35SAvi Kivity {
721d4dc402cSAvi Kivity 	MK_INSN(null, "");
722d4dc402cSAvi Kivity 
723bd62e289SBill Wendling 	init_inregs(NULL);
72418253fdeSAvi Kivity 
72518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_null);
7266055ea1fSAvi Kivity 	report("null", 0, 1);
7277d36db35SAvi Kivity }
7287d36db35SAvi Kivity 
7292e3f9f1fSThomas Huth static void test_pusha_popa(void)
7307d36db35SAvi Kivity {
7317d36db35SAvi Kivity 	MK_INSN(pusha, "pusha\n\t"
7327d36db35SAvi Kivity 		       "pop %edi\n\t"
7337d36db35SAvi Kivity 		       "pop %esi\n\t"
7347d36db35SAvi Kivity 		       "pop %ebp\n\t"
7357d36db35SAvi Kivity 		       "add $4, %esp\n\t"
7367d36db35SAvi Kivity 		       "pop %ebx\n\t"
7377d36db35SAvi Kivity 		       "pop %edx\n\t"
7387d36db35SAvi Kivity 		       "pop %ecx\n\t"
7397d36db35SAvi Kivity 		       "pop %eax\n\t"
7407d36db35SAvi Kivity 		       );
7417d36db35SAvi Kivity 
7427d36db35SAvi Kivity 	MK_INSN(popa, "push %eax\n\t"
7437d36db35SAvi Kivity 		      "push %ecx\n\t"
7447d36db35SAvi Kivity 		      "push %edx\n\t"
7457d36db35SAvi Kivity 		      "push %ebx\n\t"
7467d36db35SAvi Kivity 		      "push %esp\n\t"
7477d36db35SAvi Kivity 		      "push %ebp\n\t"
7487d36db35SAvi Kivity 		      "push %esi\n\t"
7497d36db35SAvi Kivity 		      "push %edi\n\t"
7507d36db35SAvi Kivity 		      "popa\n\t"
7517d36db35SAvi Kivity 		      );
7527d36db35SAvi Kivity 
753bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6 });
7547d36db35SAvi Kivity 
75518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pusha);
7566055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
75718253fdeSAvi Kivity 
75818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_popa);
7596055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
7607d36db35SAvi Kivity }
7617d36db35SAvi Kivity 
7622e3f9f1fSThomas Huth static void test_iret(void)
7637d36db35SAvi Kivity {
7647d36db35SAvi Kivity 	MK_INSN(iret32, "pushf\n\t"
7657d36db35SAvi Kivity 			"pushl %cs\n\t"
7667d36db35SAvi Kivity 			"call 1f\n\t" /* a near call will push eip onto the stack */
7677d36db35SAvi Kivity 			"jmp 2f\n\t"
768231b4c3bSRoman Bolshakov 			"1: iretl\n\t"
7697d36db35SAvi Kivity 			"2:\n\t"
7707d36db35SAvi Kivity 		     );
7717d36db35SAvi Kivity 
7727d36db35SAvi Kivity 	MK_INSN(iret16, "pushfw\n\t"
7737d36db35SAvi Kivity 			"pushw %cs\n\t"
7747d36db35SAvi Kivity 			"callw 1f\n\t"
7757d36db35SAvi Kivity 			"jmp 2f\n\t"
7767d36db35SAvi Kivity 			"1: iretw\n\t"
7777d36db35SAvi Kivity 			"2:\n\t");
7787d36db35SAvi Kivity 
7797d36db35SAvi Kivity 	MK_INSN(iret_flags32, "pushfl\n\t"
7807d36db35SAvi Kivity 			      "popl %eax\n\t"
7817d36db35SAvi Kivity 			      "andl $~0x2, %eax\n\t"
782964942e8SNadav Amit 			      "orl $0xffc18028, %eax\n\t"
7837d36db35SAvi Kivity 			      "pushl %eax\n\t"
7847d36db35SAvi Kivity 			      "pushl %cs\n\t"
7857d36db35SAvi Kivity 			      "call 1f\n\t"
7867d36db35SAvi Kivity 			      "jmp 2f\n\t"
787231b4c3bSRoman Bolshakov 			      "1: iretl\n\t"
7887d36db35SAvi Kivity 			      "2:\n\t");
7897d36db35SAvi Kivity 
7907d36db35SAvi Kivity 	MK_INSN(iret_flags16, "pushfw\n\t"
7917d36db35SAvi Kivity 			      "popw %ax\n\t"
7927d36db35SAvi Kivity 			      "and $~0x2, %ax\n\t"
7937d36db35SAvi Kivity 			      "or $0x8028, %ax\n\t"
7947d36db35SAvi Kivity 			      "pushw %ax\n\t"
7957d36db35SAvi Kivity 			      "pushw %cs\n\t"
7967d36db35SAvi Kivity 			      "callw 1f\n\t"
7977d36db35SAvi Kivity 			      "jmp 2f\n\t"
7987d36db35SAvi Kivity 			      "1: iretw\n\t"
7997d36db35SAvi Kivity 			      "2:\n\t");
8007d36db35SAvi Kivity 
801bd62e289SBill Wendling 	init_inregs(NULL);
8027d36db35SAvi Kivity 
80318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret32);
8046055ea1fSAvi Kivity 	report("iret 1", 0, 1);
8057d36db35SAvi Kivity 
80618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret16);
8076055ea1fSAvi Kivity 	report("iret 2", 0, 1);
8087d36db35SAvi Kivity 
80918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags32);
8106055ea1fSAvi Kivity 	report("iret 3", R_AX, 1);
811964942e8SNadav Amit 	report("rflags.rf", ~0, !(outregs.eflags & (1 << 16)));
81218253fdeSAvi Kivity 
81318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags16);
8146055ea1fSAvi Kivity 	report("iret 4", R_AX, 1);
8157d36db35SAvi Kivity }
8167d36db35SAvi Kivity 
8172e3f9f1fSThomas Huth static void test_int(void)
81896b9ca1eSMohammed Gamal {
819bd62e289SBill Wendling 	init_inregs(NULL);
82096b9ca1eSMohammed Gamal 
82196b9ca1eSMohammed Gamal 	*(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */
82296b9ca1eSMohammed Gamal 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
82396b9ca1eSMohammed Gamal 
82496b9ca1eSMohammed Gamal 	MK_INSN(int11, "int $0x11\n\t");
82596b9ca1eSMohammed Gamal 
82618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_int11);
8276055ea1fSAvi Kivity 	report("int 1", 0, 1);
82896b9ca1eSMohammed Gamal }
82996b9ca1eSMohammed Gamal 
8308202cf84SRoman Bolshakov static void test_sti_inhibit(void)
8318202cf84SRoman Bolshakov {
8328202cf84SRoman Bolshakov 	init_inregs(NULL);
8338202cf84SRoman Bolshakov 
8348202cf84SRoman Bolshakov 	*(u32 *)(0x73 * 4) = 0x1000; /* Store IRQ 11 handler in the IDT */
8358202cf84SRoman Bolshakov 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
8368202cf84SRoman Bolshakov 
8378202cf84SRoman Bolshakov 	MK_INSN(sti_inhibit, "cli\n\t"
8388202cf84SRoman Bolshakov 			     "movw $0x200b, %dx\n\t"
8398202cf84SRoman Bolshakov 			     "movl $1, %eax\n\t"
8408202cf84SRoman Bolshakov 			     "outl %eax, %dx\n\t" /* Set IRQ11 */
8418202cf84SRoman Bolshakov 			     "movl $0, %eax\n\t"
8428202cf84SRoman Bolshakov 			     "outl %eax, %dx\n\t" /* Clear IRQ11 */
8438202cf84SRoman Bolshakov 			     "sti\n\t"
8448202cf84SRoman Bolshakov 			     "hlt\n\t");
8458202cf84SRoman Bolshakov 	exec_in_big_real_mode(&insn_sti_inhibit);
8468202cf84SRoman Bolshakov 
8478202cf84SRoman Bolshakov 	report("sti inhibit", ~0, 1);
8488202cf84SRoman Bolshakov }
8498202cf84SRoman Bolshakov 
8502e3f9f1fSThomas Huth static void test_imul(void)
851fa74f8a6SMohammed Gamal {
852fa74f8a6SMohammed Gamal 	MK_INSN(imul8_1, "mov $2, %al\n\t"
853fa74f8a6SMohammed Gamal 			"mov $-4, %cx\n\t"
854fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
855fa74f8a6SMohammed Gamal 
856fa74f8a6SMohammed Gamal 	MK_INSN(imul16_1, "mov $2, %ax\n\t"
857fa74f8a6SMohammed Gamal 		      "mov $-4, %cx\n\t"
858fa74f8a6SMohammed Gamal 		      "imul %cx\n\t");
859fa74f8a6SMohammed Gamal 
860fa74f8a6SMohammed Gamal 	MK_INSN(imul32_1, "mov $2, %eax\n\t"
861fa74f8a6SMohammed Gamal 		       "mov $-4, %ecx\n\t"
862fa74f8a6SMohammed Gamal 		       "imul %ecx\n\t");
863fa74f8a6SMohammed Gamal 
864fa74f8a6SMohammed Gamal 	MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t"
865fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
866fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
867fa74f8a6SMohammed Gamal 
868fa74f8a6SMohammed Gamal 	MK_INSN(imul16_2, "mov $2, %ax\n\t"
869fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
870fa74f8a6SMohammed Gamal 			"imul %cx\n\t");
871fa74f8a6SMohammed Gamal 
872fa74f8a6SMohammed Gamal 	MK_INSN(imul32_2, "mov $2, %eax\n\t"
873fa74f8a6SMohammed Gamal 			"mov $4, %ecx\n\t"
874fa74f8a6SMohammed Gamal 			"imul %ecx\n\t");
875fa74f8a6SMohammed Gamal 
876bd62e289SBill Wendling 	init_inregs(NULL);
87718253fdeSAvi Kivity 
87818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_1);
8796055ea1fSAvi Kivity 	report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8);
880fa74f8a6SMohammed Gamal 
88118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_1);
8826055ea1fSAvi Kivity 	report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8);
883fa74f8a6SMohammed Gamal 
88418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_1);
8856055ea1fSAvi Kivity 	report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8);
886fa74f8a6SMohammed Gamal 
88718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_2);
8886055ea1fSAvi Kivity 	report("imul 4", R_AX | R_CX | R_DX,
8896055ea1fSAvi Kivity 	       (outregs.eax & 0xffff) == 8
89081050840SAvi Kivity 	       && (outregs.eax & 0xffff0000) == 0x12340000);
891fa74f8a6SMohammed Gamal 
89218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_2);
8936055ea1fSAvi Kivity 	report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8);
894fa74f8a6SMohammed Gamal 
89518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_2);
8966055ea1fSAvi Kivity 	report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8);
897fa74f8a6SMohammed Gamal }
898fa74f8a6SMohammed Gamal 
8992e3f9f1fSThomas Huth static void test_mul(void)
90059317bd1SMohammed Gamal {
90159317bd1SMohammed Gamal 	MK_INSN(mul8, "mov $2, %al\n\t"
90259317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
90359317bd1SMohammed Gamal 			"imul %cl\n\t");
90459317bd1SMohammed Gamal 
90559317bd1SMohammed Gamal 	MK_INSN(mul16, "mov $2, %ax\n\t"
90659317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
90759317bd1SMohammed Gamal 			"imul %cx\n\t");
90859317bd1SMohammed Gamal 
90959317bd1SMohammed Gamal 	MK_INSN(mul32, "mov $2, %eax\n\t"
91059317bd1SMohammed Gamal 			"mov $4, %ecx\n\t"
91159317bd1SMohammed Gamal 			"imul %ecx\n\t");
91259317bd1SMohammed Gamal 
913bd62e289SBill Wendling 	init_inregs(NULL);
91418253fdeSAvi Kivity 
91518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul8);
9166055ea1fSAvi Kivity 	report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8);
91759317bd1SMohammed Gamal 
91818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul16);
9196055ea1fSAvi Kivity 	report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8);
92059317bd1SMohammed Gamal 
92118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul32);
9226055ea1fSAvi Kivity 	report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8);
92359317bd1SMohammed Gamal }
92459317bd1SMohammed Gamal 
9252e3f9f1fSThomas Huth static void test_div(void)
9260d4c7614SMohammed Gamal {
9270d4c7614SMohammed Gamal 	MK_INSN(div8, "mov $257, %ax\n\t"
9280d4c7614SMohammed Gamal 			"mov $2, %cl\n\t"
9290d4c7614SMohammed Gamal 			"div %cl\n\t");
9300d4c7614SMohammed Gamal 
9310d4c7614SMohammed Gamal 	MK_INSN(div16, "mov $512, %ax\n\t"
9320d4c7614SMohammed Gamal 			"mov $5, %cx\n\t"
9330d4c7614SMohammed Gamal 			"div %cx\n\t");
9340d4c7614SMohammed Gamal 
9350d4c7614SMohammed Gamal 	MK_INSN(div32, "mov $512, %eax\n\t"
9360d4c7614SMohammed Gamal 			"mov $5, %ecx\n\t"
9370d4c7614SMohammed Gamal 			"div %ecx\n\t");
9380d4c7614SMohammed Gamal 
939bd62e289SBill Wendling 	init_inregs(NULL);
94018253fdeSAvi Kivity 
94118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div8);
9426055ea1fSAvi Kivity 	report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384);
9430d4c7614SMohammed Gamal 
94418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div16);
9456055ea1fSAvi Kivity 	report("div 2", R_AX | R_CX | R_DX,
9466055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
9470d4c7614SMohammed Gamal 
94818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div32);
9496055ea1fSAvi Kivity 	report("div 3", R_AX | R_CX | R_DX,
9506055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
9510d4c7614SMohammed Gamal }
9520d4c7614SMohammed Gamal 
9532e3f9f1fSThomas Huth static void test_idiv(void)
9540d4c7614SMohammed Gamal {
9550d4c7614SMohammed Gamal 	MK_INSN(idiv8, "mov $256, %ax\n\t"
9560d4c7614SMohammed Gamal 			"mov $-2, %cl\n\t"
9570d4c7614SMohammed Gamal 			"idiv %cl\n\t");
9580d4c7614SMohammed Gamal 
9590d4c7614SMohammed Gamal 	MK_INSN(idiv16, "mov $512, %ax\n\t"
9600d4c7614SMohammed Gamal 			"mov $-2, %cx\n\t"
9610d4c7614SMohammed Gamal 			"idiv %cx\n\t");
9620d4c7614SMohammed Gamal 
9630d4c7614SMohammed Gamal 	MK_INSN(idiv32, "mov $512, %eax\n\t"
9640d4c7614SMohammed Gamal 			"mov $-2, %ecx\n\t"
9650d4c7614SMohammed Gamal 			"idiv %ecx\n\t");
9660d4c7614SMohammed Gamal 
967bd62e289SBill Wendling 	init_inregs(NULL);
96818253fdeSAvi Kivity 
96918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv8);
9706055ea1fSAvi Kivity 	report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128);
9710d4c7614SMohammed Gamal 
97218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv16);
9736055ea1fSAvi Kivity 	report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256);
9740d4c7614SMohammed Gamal 
97518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv32);
9766055ea1fSAvi Kivity 	report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256);
9770d4c7614SMohammed Gamal }
9780d4c7614SMohammed Gamal 
9792e3f9f1fSThomas Huth static void test_cbw(void)
9806e293cf5SWei Yongjun {
9816e293cf5SWei Yongjun 	MK_INSN(cbw, "mov $0xFE, %eax \n\t"
9826e293cf5SWei Yongjun 		     "cbw\n\t");
9836e293cf5SWei Yongjun 	MK_INSN(cwde, "mov $0xFFFE, %eax \n\t"
9846e293cf5SWei Yongjun 		      "cwde\n\t");
9856e293cf5SWei Yongjun 
986bd62e289SBill Wendling 	init_inregs(NULL);
98718253fdeSAvi Kivity 
98818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cbw);
9896055ea1fSAvi Kivity 	report("cbq 1", ~0, outregs.eax == 0xFFFE);
9906e293cf5SWei Yongjun 
99118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwde);
9926055ea1fSAvi Kivity 	report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE);
9936e293cf5SWei Yongjun }
9946e293cf5SWei Yongjun 
9952e3f9f1fSThomas Huth static void test_loopcc(void)
996eacef4e2SWei Yongjun {
997eacef4e2SWei Yongjun 	MK_INSN(loop, "mov $10, %ecx\n\t"
998eacef4e2SWei Yongjun 		      "1: inc %eax\n\t"
999eacef4e2SWei Yongjun 		      "loop 1b\n\t");
1000eacef4e2SWei Yongjun 
1001eacef4e2SWei Yongjun 	MK_INSN(loope, "mov $10, %ecx\n\t"
1002eacef4e2SWei Yongjun 		       "mov $1, %eax\n\t"
1003eacef4e2SWei Yongjun 		       "1: dec %eax\n\t"
1004eacef4e2SWei Yongjun 		       "loope 1b\n\t");
1005eacef4e2SWei Yongjun 
1006eacef4e2SWei Yongjun 	MK_INSN(loopne, "mov $10, %ecx\n\t"
1007eacef4e2SWei Yongjun 		        "mov $5, %eax\n\t"
1008eacef4e2SWei Yongjun 		        "1: dec %eax\n\t"
1009eacef4e2SWei Yongjun 			"loopne 1b\n\t");
1010eacef4e2SWei Yongjun 
1011bd62e289SBill Wendling 	init_inregs(NULL);
1012eacef4e2SWei Yongjun 
101318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loop);
10146055ea1fSAvi Kivity 	report("LOOPcc short 1", R_AX, outregs.eax == 10);
101518253fdeSAvi Kivity 
101618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loope);
10176055ea1fSAvi Kivity 	report("LOOPcc short 2", R_AX | R_CX,
10186055ea1fSAvi Kivity 	       outregs.eax == -1 && outregs.ecx == 8);
1019eacef4e2SWei Yongjun 
102018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loopne);
10216055ea1fSAvi Kivity 	report("LOOPcc short 3", R_AX | R_CX,
10226055ea1fSAvi Kivity 	       outregs.eax == 0 && outregs.ecx == 5);
1023eacef4e2SWei Yongjun }
1024eacef4e2SWei Yongjun 
1025b274feedSAvi Kivity static void test_das(void)
1026b274feedSAvi Kivity {
1027b274feedSAvi Kivity     short i;
102881050840SAvi Kivity     u16 nr_fail = 0;
1029b274feedSAvi Kivity     static unsigned test_cases[1024] = {
1030b274feedSAvi Kivity         0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00,
1031b274feedSAvi Kivity         0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01,
1032b274feedSAvi Kivity         0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02,
1033b274feedSAvi Kivity         0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03,
1034b274feedSAvi Kivity         0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04,
1035b274feedSAvi Kivity         0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05,
1036b274feedSAvi Kivity         0x06000606, 0x8701a606, 0x56100006, 0x9711a006,
1037b274feedSAvi Kivity         0x02000707, 0x8301a707, 0x12100107, 0x9311a107,
1038b274feedSAvi Kivity         0x02000808, 0x8301a808, 0x12100208, 0x9311a208,
1039b274feedSAvi Kivity         0x06000909, 0x8701a909, 0x16100309, 0x9711a309,
1040b274feedSAvi Kivity         0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a,
1041b274feedSAvi Kivity         0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b,
1042b274feedSAvi Kivity         0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c,
1043b274feedSAvi Kivity         0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d,
1044b274feedSAvi Kivity         0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e,
1045b274feedSAvi Kivity         0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f,
1046b274feedSAvi Kivity         0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10,
1047b274feedSAvi Kivity         0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11,
1048b274feedSAvi Kivity         0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12,
1049b274feedSAvi Kivity         0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13,
1050b274feedSAvi Kivity         0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14,
1051b274feedSAvi Kivity         0x02001515, 0x8301b515, 0x16100f15, 0x9711af15,
1052b274feedSAvi Kivity         0x02001616, 0x8301b616, 0x12101016, 0x9311b016,
1053b274feedSAvi Kivity         0x06001717, 0x8701b717, 0x16101117, 0x9711b117,
1054b274feedSAvi Kivity         0x06001818, 0x8701b818, 0x16101218, 0x9711b218,
1055b274feedSAvi Kivity         0x02001919, 0x8301b919, 0x12101319, 0x9311b319,
1056b274feedSAvi Kivity         0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a,
1057b274feedSAvi Kivity         0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b,
1058b274feedSAvi Kivity         0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c,
1059b274feedSAvi Kivity         0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d,
1060b274feedSAvi Kivity         0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e,
1061b274feedSAvi Kivity         0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f,
1062b274feedSAvi Kivity         0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20,
1063b274feedSAvi Kivity         0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21,
1064b274feedSAvi Kivity         0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22,
1065b274feedSAvi Kivity         0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23,
1066b274feedSAvi Kivity         0x06002424, 0x8301c424, 0x16101e24, 0x9711be24,
1067b274feedSAvi Kivity         0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25,
1068b274feedSAvi Kivity         0x02002626, 0x8701c626, 0x12102026, 0x9711c026,
1069b274feedSAvi Kivity         0x06002727, 0x8301c727, 0x16102127, 0x9311c127,
1070b274feedSAvi Kivity         0x06002828, 0x8301c828, 0x16102228, 0x9311c228,
1071b274feedSAvi Kivity         0x02002929, 0x8701c929, 0x12102329, 0x9711c329,
1072b274feedSAvi Kivity         0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a,
1073b274feedSAvi Kivity         0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b,
1074b274feedSAvi Kivity         0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c,
1075b274feedSAvi Kivity         0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d,
1076b274feedSAvi Kivity         0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e,
1077b274feedSAvi Kivity         0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f,
1078b274feedSAvi Kivity         0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30,
1079b274feedSAvi Kivity         0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31,
1080b274feedSAvi Kivity         0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32,
1081b274feedSAvi Kivity         0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33,
1082b274feedSAvi Kivity         0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34,
1083b274feedSAvi Kivity         0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35,
1084b274feedSAvi Kivity         0x06003636, 0x8301d636, 0x16103036, 0x9311d036,
1085b274feedSAvi Kivity         0x02003737, 0x8701d737, 0x12103137, 0x9711d137,
1086b274feedSAvi Kivity         0x02003838, 0x8701d838, 0x12103238, 0x9711d238,
1087b274feedSAvi Kivity         0x06003939, 0x8301d939, 0x16103339, 0x9311d339,
1088b274feedSAvi Kivity         0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a,
1089b274feedSAvi Kivity         0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b,
1090b274feedSAvi Kivity         0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c,
1091b274feedSAvi Kivity         0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d,
1092b274feedSAvi Kivity         0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e,
1093b274feedSAvi Kivity         0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f,
1094b274feedSAvi Kivity         0x02004040, 0x8301e040, 0x16103a40, 0x9311da40,
1095b274feedSAvi Kivity         0x06004141, 0x8701e141, 0x12103b41, 0x9711db41,
1096b274feedSAvi Kivity         0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42,
1097b274feedSAvi Kivity         0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43,
1098b274feedSAvi Kivity         0x06004444, 0x8701e444, 0x12103e44, 0x9711de44,
1099b274feedSAvi Kivity         0x02004545, 0x8301e545, 0x16103f45, 0x9311df45,
1100b274feedSAvi Kivity         0x02004646, 0x8301e646, 0x12104046, 0x9311e046,
1101b274feedSAvi Kivity         0x06004747, 0x8701e747, 0x16104147, 0x9711e147,
1102b274feedSAvi Kivity         0x06004848, 0x8701e848, 0x16104248, 0x9711e248,
1103b274feedSAvi Kivity         0x02004949, 0x8301e949, 0x12104349, 0x9311e349,
1104b274feedSAvi Kivity         0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a,
1105b274feedSAvi Kivity         0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b,
1106b274feedSAvi Kivity         0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c,
1107b274feedSAvi Kivity         0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d,
1108b274feedSAvi Kivity         0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e,
1109b274feedSAvi Kivity         0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f,
1110b274feedSAvi Kivity         0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50,
1111b274feedSAvi Kivity         0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51,
1112b274feedSAvi Kivity         0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52,
1113b274feedSAvi Kivity         0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53,
1114b274feedSAvi Kivity         0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54,
1115b274feedSAvi Kivity         0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55,
1116b274feedSAvi Kivity         0x06005656, 0x8701f656, 0x16105056, 0x9711f056,
1117b274feedSAvi Kivity         0x02005757, 0x8301f757, 0x12105157, 0x9311f157,
1118b274feedSAvi Kivity         0x02005858, 0x8301f858, 0x12105258, 0x9311f258,
1119b274feedSAvi Kivity         0x06005959, 0x8701f959, 0x16105359, 0x9711f359,
1120b274feedSAvi Kivity         0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a,
1121b274feedSAvi Kivity         0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b,
1122b274feedSAvi Kivity         0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c,
1123b274feedSAvi Kivity         0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d,
1124b274feedSAvi Kivity         0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e,
1125b274feedSAvi Kivity         0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f,
1126b274feedSAvi Kivity         0x06006060, 0x47010060, 0x16105a60, 0x9711fa60,
1127b274feedSAvi Kivity         0x02006161, 0x03010161, 0x12105b61, 0x9311fb61,
1128b274feedSAvi Kivity         0x02006262, 0x03010262, 0x16105c62, 0x9711fc62,
1129b274feedSAvi Kivity         0x06006363, 0x07010363, 0x12105d63, 0x9311fd63,
1130b274feedSAvi Kivity         0x02006464, 0x03010464, 0x12105e64, 0x9311fe64,
1131b274feedSAvi Kivity         0x06006565, 0x07010565, 0x16105f65, 0x9711ff65,
1132b274feedSAvi Kivity         0x06006666, 0x07010666, 0x16106066, 0x57110066,
1133b274feedSAvi Kivity         0x02006767, 0x03010767, 0x12106167, 0x13110167,
1134b274feedSAvi Kivity         0x02006868, 0x03010868, 0x12106268, 0x13110268,
1135b274feedSAvi Kivity         0x06006969, 0x07010969, 0x16106369, 0x17110369,
1136b274feedSAvi Kivity         0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a,
1137b274feedSAvi Kivity         0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b,
1138b274feedSAvi Kivity         0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c,
1139b274feedSAvi Kivity         0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d,
1140b274feedSAvi Kivity         0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e,
1141b274feedSAvi Kivity         0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f,
1142b274feedSAvi Kivity         0x02007070, 0x03011070, 0x16106a70, 0x17110a70,
1143b274feedSAvi Kivity         0x06007171, 0x07011171, 0x12106b71, 0x13110b71,
1144b274feedSAvi Kivity         0x06007272, 0x07011272, 0x16106c72, 0x17110c72,
1145b274feedSAvi Kivity         0x02007373, 0x03011373, 0x12106d73, 0x13110d73,
1146b274feedSAvi Kivity         0x06007474, 0x07011474, 0x12106e74, 0x13110e74,
1147b274feedSAvi Kivity         0x02007575, 0x03011575, 0x16106f75, 0x17110f75,
1148b274feedSAvi Kivity         0x02007676, 0x03011676, 0x12107076, 0x13111076,
1149b274feedSAvi Kivity         0x06007777, 0x07011777, 0x16107177, 0x17111177,
1150b274feedSAvi Kivity         0x06007878, 0x07011878, 0x16107278, 0x17111278,
1151b274feedSAvi Kivity         0x02007979, 0x03011979, 0x12107379, 0x13111379,
1152b274feedSAvi Kivity         0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a,
1153b274feedSAvi Kivity         0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b,
1154b274feedSAvi Kivity         0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c,
1155b274feedSAvi Kivity         0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d,
1156b274feedSAvi Kivity         0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e,
1157b274feedSAvi Kivity         0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f,
1158b274feedSAvi Kivity         0x82008080, 0x03012080, 0x12107a80, 0x13111a80,
1159b274feedSAvi Kivity         0x86008181, 0x07012181, 0x16107b81, 0x17111b81,
1160b274feedSAvi Kivity         0x86008282, 0x07012282, 0x12107c82, 0x13111c82,
1161b274feedSAvi Kivity         0x82008383, 0x03012383, 0x16107d83, 0x17111d83,
1162b274feedSAvi Kivity         0x86008484, 0x07012484, 0x16107e84, 0x17111e84,
1163b274feedSAvi Kivity         0x82008585, 0x03012585, 0x12107f85, 0x13111f85,
1164b274feedSAvi Kivity         0x82008686, 0x03012686, 0x92108086, 0x13112086,
1165b274feedSAvi Kivity         0x86008787, 0x07012787, 0x96108187, 0x17112187,
1166b274feedSAvi Kivity         0x86008888, 0x07012888, 0x96108288, 0x17112288,
1167b274feedSAvi Kivity         0x82008989, 0x03012989, 0x92108389, 0x13112389,
1168b274feedSAvi Kivity         0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a,
1169b274feedSAvi Kivity         0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b,
1170b274feedSAvi Kivity         0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c,
1171b274feedSAvi Kivity         0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d,
1172b274feedSAvi Kivity         0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e,
1173b274feedSAvi Kivity         0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f,
1174b274feedSAvi Kivity         0x86009090, 0x07013090, 0x92108a90, 0x13112a90,
1175b274feedSAvi Kivity         0x82009191, 0x03013191, 0x96108b91, 0x17112b91,
1176b274feedSAvi Kivity         0x82009292, 0x03013292, 0x92108c92, 0x13112c92,
1177b274feedSAvi Kivity         0x86009393, 0x07013393, 0x96108d93, 0x17112d93,
1178b274feedSAvi Kivity         0x82009494, 0x03013494, 0x96108e94, 0x17112e94,
1179b274feedSAvi Kivity         0x86009595, 0x07013595, 0x92108f95, 0x13112f95,
1180b274feedSAvi Kivity         0x86009696, 0x07013696, 0x96109096, 0x17113096,
1181b274feedSAvi Kivity         0x82009797, 0x03013797, 0x92109197, 0x13113197,
1182b274feedSAvi Kivity         0x82009898, 0x03013898, 0x92109298, 0x13113298,
1183b274feedSAvi Kivity         0x86009999, 0x07013999, 0x96109399, 0x17113399,
1184b274feedSAvi Kivity         0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a,
1185b274feedSAvi Kivity         0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b,
1186b274feedSAvi Kivity         0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c,
1187b274feedSAvi Kivity         0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d,
1188b274feedSAvi Kivity         0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e,
1189b274feedSAvi Kivity         0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f,
1190b274feedSAvi Kivity         0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0,
1191b274feedSAvi Kivity         0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1,
1192b274feedSAvi Kivity         0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2,
1193b274feedSAvi Kivity         0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3,
1194b274feedSAvi Kivity         0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4,
1195b274feedSAvi Kivity         0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5,
1196b274feedSAvi Kivity         0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6,
1197b274feedSAvi Kivity         0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7,
1198b274feedSAvi Kivity         0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8,
1199b274feedSAvi Kivity         0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9,
1200b274feedSAvi Kivity         0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa,
1201b274feedSAvi Kivity         0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab,
1202b274feedSAvi Kivity         0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac,
1203b274feedSAvi Kivity         0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad,
1204b274feedSAvi Kivity         0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae,
1205b274feedSAvi Kivity         0x130049af, 0x130149af, 0x131049af, 0x131149af,
1206b274feedSAvi Kivity         0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0,
1207b274feedSAvi Kivity         0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1,
1208b274feedSAvi Kivity         0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2,
1209b274feedSAvi Kivity         0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3,
1210b274feedSAvi Kivity         0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4,
1211b274feedSAvi Kivity         0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5,
1212b274feedSAvi Kivity         0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6,
1213b274feedSAvi Kivity         0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7,
1214b274feedSAvi Kivity         0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8,
1215b274feedSAvi Kivity         0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9,
1216b274feedSAvi Kivity         0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba,
1217b274feedSAvi Kivity         0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb,
1218b274feedSAvi Kivity         0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc,
1219b274feedSAvi Kivity         0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd,
1220b274feedSAvi Kivity         0x130058be, 0x130158be, 0x131058be, 0x131158be,
1221b274feedSAvi Kivity         0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf,
1222b274feedSAvi Kivity         0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0,
1223b274feedSAvi Kivity         0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1,
1224b274feedSAvi Kivity         0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2,
1225b274feedSAvi Kivity         0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3,
1226b274feedSAvi Kivity         0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4,
1227b274feedSAvi Kivity         0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5,
1228b274feedSAvi Kivity         0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6,
1229b274feedSAvi Kivity         0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7,
1230b274feedSAvi Kivity         0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8,
1231b274feedSAvi Kivity         0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9,
1232b274feedSAvi Kivity         0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca,
1233b274feedSAvi Kivity         0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb,
1234b274feedSAvi Kivity         0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc,
1235b274feedSAvi Kivity         0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd,
1236b274feedSAvi Kivity         0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce,
1237b274feedSAvi Kivity         0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf,
1238b274feedSAvi Kivity         0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0,
1239b274feedSAvi Kivity         0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1,
1240b274feedSAvi Kivity         0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2,
1241b274feedSAvi Kivity         0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3,
1242b274feedSAvi Kivity         0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4,
1243b274feedSAvi Kivity         0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5,
1244b274feedSAvi Kivity         0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6,
1245b274feedSAvi Kivity         0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7,
1246b274feedSAvi Kivity         0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8,
1247b274feedSAvi Kivity         0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9,
1248b274feedSAvi Kivity         0x170074da, 0x170174da, 0x171074da, 0x171174da,
1249b274feedSAvi Kivity         0x130075db, 0x130175db, 0x131075db, 0x131175db,
1250b274feedSAvi Kivity         0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc,
1251b274feedSAvi Kivity         0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd,
1252b274feedSAvi Kivity         0x170078de, 0x170178de, 0x171078de, 0x171178de,
1253b274feedSAvi Kivity         0x130079df, 0x130179df, 0x131079df, 0x131179df,
1254b274feedSAvi Kivity         0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0,
1255b274feedSAvi Kivity         0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1,
1256b274feedSAvi Kivity         0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2,
1257b274feedSAvi Kivity         0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3,
1258b274feedSAvi Kivity         0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4,
1259b274feedSAvi Kivity         0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5,
1260b274feedSAvi Kivity         0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6,
1261b274feedSAvi Kivity         0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7,
1262b274feedSAvi Kivity         0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8,
1263b274feedSAvi Kivity         0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9,
1264b274feedSAvi Kivity         0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea,
1265b274feedSAvi Kivity         0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb,
1266b274feedSAvi Kivity         0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec,
1267b274feedSAvi Kivity         0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed,
1268b274feedSAvi Kivity         0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee,
1269b274feedSAvi Kivity         0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef,
1270b274feedSAvi Kivity         0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0,
1271b274feedSAvi Kivity         0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1,
1272b274feedSAvi Kivity         0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2,
1273b274feedSAvi Kivity         0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3,
1274b274feedSAvi Kivity         0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4,
1275b274feedSAvi Kivity         0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5,
1276b274feedSAvi Kivity         0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6,
1277b274feedSAvi Kivity         0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7,
1278b274feedSAvi Kivity         0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8,
1279b274feedSAvi Kivity         0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9,
1280b274feedSAvi Kivity         0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa,
1281b274feedSAvi Kivity         0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb,
1282b274feedSAvi Kivity         0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc,
1283b274feedSAvi Kivity         0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd,
1284b274feedSAvi Kivity         0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe,
1285b274feedSAvi Kivity         0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff,
1286b274feedSAvi Kivity     };
1287b274feedSAvi Kivity 
1288b274feedSAvi Kivity     MK_INSN(das, "das");
1289b274feedSAvi Kivity 
1290bd62e289SBill Wendling     init_inregs(NULL);
129118253fdeSAvi Kivity 
1292b274feedSAvi Kivity     for (i = 0; i < 1024; ++i) {
1293b274feedSAvi Kivity         unsigned tmp = test_cases[i];
1294b274feedSAvi Kivity         inregs.eax = tmp & 0xff;
1295b274feedSAvi Kivity         inregs.eflags = (tmp >> 16) & 0xff;
129618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_das);
129718253fdeSAvi Kivity 	if (!regs_equal(R_AX)
1298b274feedSAvi Kivity             || outregs.eax != ((tmp >> 8) & 0xff)
1299b274feedSAvi Kivity             || (outregs.eflags & 0xff) != (tmp >> 24)) {
130081050840SAvi Kivity 	    ++nr_fail;
130181050840SAvi Kivity 	    break;
1302b274feedSAvi Kivity         }
1303b274feedSAvi Kivity     }
13046055ea1fSAvi Kivity     report("DAS", ~0, nr_fail == 0);
1305b274feedSAvi Kivity }
1306b274feedSAvi Kivity 
13072e3f9f1fSThomas Huth static void test_cwd_cdq(void)
13080cbd5b06SMohammed Gamal {
13090cbd5b06SMohammed Gamal 	/* Sign-bit set */
13100cbd5b06SMohammed Gamal 	MK_INSN(cwd_1, "mov $0x8000, %ax\n\t"
13110cbd5b06SMohammed Gamal 		       "cwd\n\t");
13120cbd5b06SMohammed Gamal 
13130cbd5b06SMohammed Gamal 	/* Sign-bit not set */
13140cbd5b06SMohammed Gamal 	MK_INSN(cwd_2, "mov $0x1000, %ax\n\t"
13150cbd5b06SMohammed Gamal 		       "cwd\n\t");
13160cbd5b06SMohammed Gamal 
13170cbd5b06SMohammed Gamal 	/* Sign-bit set */
13180cbd5b06SMohammed Gamal 	MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t"
13190cbd5b06SMohammed Gamal 		       "cdq\n\t");
13200cbd5b06SMohammed Gamal 
13210cbd5b06SMohammed Gamal 	/* Sign-bit not set */
13220cbd5b06SMohammed Gamal 	MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t"
13230cbd5b06SMohammed Gamal 		       "cdq\n\t");
13240cbd5b06SMohammed Gamal 
1325bd62e289SBill Wendling 	init_inregs(NULL);
132618253fdeSAvi Kivity 
132718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_1);
13286055ea1fSAvi Kivity 	report("cwd 1", R_AX | R_DX,
13296055ea1fSAvi Kivity 	       outregs.eax == 0x8000 && outregs.edx == 0xffff);
13300cbd5b06SMohammed Gamal 
133118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_2);
13326055ea1fSAvi Kivity 	report("cwd 2", R_AX | R_DX,
13336055ea1fSAvi Kivity 	       outregs.eax == 0x1000 && outregs.edx == 0);
13340cbd5b06SMohammed Gamal 
133518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_1);
13366055ea1fSAvi Kivity 	report("cdq 1", R_AX | R_DX,
13376055ea1fSAvi Kivity 	       outregs.eax == 0x80000000 && outregs.edx == 0xffffffff);
13380cbd5b06SMohammed Gamal 
133918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_2);
13406055ea1fSAvi Kivity 	report("cdq 2", R_AX | R_DX,
13416055ea1fSAvi Kivity 	       outregs.eax == 0x10000000 && outregs.edx == 0);
13420cbd5b06SMohammed Gamal }
13430cbd5b06SMohammed Gamal 
134437f51a4aSWei Yongjun static struct {
134537f51a4aSWei Yongjun         void *address;
134637f51a4aSWei Yongjun         unsigned short sel;
134737f51a4aSWei Yongjun } __attribute__((packed)) desc = {
134837f51a4aSWei Yongjun 	(void *)0x1234,
134937f51a4aSWei Yongjun 	0x10,
135037f51a4aSWei Yongjun };
135137f51a4aSWei Yongjun 
13522e3f9f1fSThomas Huth static void test_lds_lss(void)
135337f51a4aSWei Yongjun {
1354bd62e289SBill Wendling 	init_inregs(&(struct regs){ .ebx = (unsigned long)&desc });
135537f51a4aSWei Yongjun 
1356231b4c3bSRoman Bolshakov 	MK_INSN(lds, "pushl %ds\n\t"
135737f51a4aSWei Yongjun 		     "lds (%ebx), %eax\n\t"
135837f51a4aSWei Yongjun 		     "mov %ds, %ebx\n\t"
1359231b4c3bSRoman Bolshakov 		     "popl %ds\n\t");
136037f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lds);
136137f51a4aSWei Yongjun 	report("lds", R_AX | R_BX,
136237f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
136337f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
136437f51a4aSWei Yongjun 
1365eb6687a2SBill Wendling 	MK_INSN(les, "les (%ebx), %eax\n\t"
1366eb6687a2SBill Wendling 		     "mov %es, %ebx\n\t");
136737f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_les);
136837f51a4aSWei Yongjun 	report("les", R_AX | R_BX,
136937f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
137037f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
137137f51a4aSWei Yongjun 
1372231b4c3bSRoman Bolshakov 	MK_INSN(lfs, "pushl %fs\n\t"
137337f51a4aSWei Yongjun 		     "lfs (%ebx), %eax\n\t"
137437f51a4aSWei Yongjun 		     "mov %fs, %ebx\n\t"
1375231b4c3bSRoman Bolshakov 		     "popl %fs\n\t");
137637f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lfs);
137737f51a4aSWei Yongjun 	report("lfs", R_AX | R_BX,
137837f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
137937f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
138037f51a4aSWei Yongjun 
1381231b4c3bSRoman Bolshakov 	MK_INSN(lgs, "pushl %gs\n\t"
138237f51a4aSWei Yongjun 		     "lgs (%ebx), %eax\n\t"
138337f51a4aSWei Yongjun 		     "mov %gs, %ebx\n\t"
1384231b4c3bSRoman Bolshakov 		     "popl %gs\n\t");
138537f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lgs);
138637f51a4aSWei Yongjun 	report("lgs", R_AX | R_BX,
138737f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
138837f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
138937f51a4aSWei Yongjun 
1390d7903be6SNadav Amit 	MK_INSN(lss, "mov %ss, %dx\n\t"
139137f51a4aSWei Yongjun 		     "lss (%ebx), %eax\n\t"
139237f51a4aSWei Yongjun 		     "mov %ss, %ebx\n\t"
1393d7903be6SNadav Amit 		     "mov %dx, %ss\n\t");
139437f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lss);
139537f51a4aSWei Yongjun 	report("lss", R_AX | R_BX,
139637f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
139737f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
139837f51a4aSWei Yongjun }
139937f51a4aSWei Yongjun 
14002e3f9f1fSThomas Huth static void test_jcxz(void)
1401b1c7c575SWei Yongjun {
1402b1c7c575SWei Yongjun 	MK_INSN(jcxz1, "jcxz 1f\n\t"
1403b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1404b1c7c575SWei Yongjun 		       "1:\n\t");
1405b1c7c575SWei Yongjun 	MK_INSN(jcxz2, "mov $0x100, %ecx\n\t"
1406b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1407b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1408b1c7c575SWei Yongjun 		       "mov $0, %ecx\n\t"
1409b1c7c575SWei Yongjun 		       "1:\n\t");
1410b1c7c575SWei Yongjun 	MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t"
1411b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1412b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1413b1c7c575SWei Yongjun 		       "1:\n\t");
1414b1c7c575SWei Yongjun 	MK_INSN(jecxz1, "jecxz 1f\n\t"
1415b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1416b1c7c575SWei Yongjun 			"1:\n\t");
1417b1c7c575SWei Yongjun 	MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t"
1418b1c7c575SWei Yongjun 			"jecxz 1f\n\t"
1419b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1420b1c7c575SWei Yongjun 			"mov $0, %ecx\n\t"
1421b1c7c575SWei Yongjun 			"1:\n\t");
1422b1c7c575SWei Yongjun 
1423bd62e289SBill Wendling 	init_inregs(NULL);
1424b1c7c575SWei Yongjun 
1425b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz1);
1426b1c7c575SWei Yongjun 	report("jcxz short 1", 0, 1);
1427b1c7c575SWei Yongjun 
1428b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz2);
1429b1c7c575SWei Yongjun 	report("jcxz short 2", R_AX, outregs.eax == 0x1234);
1430b1c7c575SWei Yongjun 
1431b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz3);
1432b1c7c575SWei Yongjun 	report("jcxz short 3", R_CX, outregs.ecx == 0x10000);
1433b1c7c575SWei Yongjun 
1434b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz1);
1435b1c7c575SWei Yongjun 	report("jecxz short 1", 0, 1);
1436b1c7c575SWei Yongjun 
1437b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz2);
1438b1c7c575SWei Yongjun 	report("jecxz short 2", R_AX, outregs.eax == 0x1234);
1439b1c7c575SWei Yongjun }
1440b1c7c575SWei Yongjun 
14418f578e98SAvi Kivity static void test_cpuid(void)
14428f578e98SAvi Kivity {
14438f578e98SAvi Kivity     MK_INSN(cpuid, "cpuid");
14448f578e98SAvi Kivity     unsigned function = 0x1234;
14458f578e98SAvi Kivity     unsigned eax, ebx, ecx, edx;
14468f578e98SAvi Kivity 
1447bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = function });
1448bd62e289SBill Wendling 
1449bd62e289SBill Wendling     eax = inregs.eax;
1450bd62e289SBill Wendling     ecx = inregs.ecx;
1451674d2dbeSPaolo Bonzini     asm("cpuid" : "+a"(eax), "=b"(ebx), "+c"(ecx), "=d"(edx));
14528f578e98SAvi Kivity     exec_in_big_real_mode(&insn_cpuid);
14538f578e98SAvi Kivity     report("cpuid", R_AX|R_BX|R_CX|R_DX,
14548f578e98SAvi Kivity 	   outregs.eax == eax && outregs.ebx == ebx
14558f578e98SAvi Kivity 	   && outregs.ecx == ecx && outregs.edx == edx);
14568f578e98SAvi Kivity }
14578f578e98SAvi Kivity 
1458ed93f43bSAvi Kivity static void test_ss_base_for_esp_ebp(void)
1459ed93f43bSAvi Kivity {
1460ed93f43bSAvi Kivity     MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss");
1461ed93f43bSAvi Kivity     MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss");
1462ed93f43bSAvi Kivity     static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 };
1463ed93f43bSAvi Kivity 
1464bd62e289SBill Wendling     init_inregs(&(struct regs){ .ebx = 1, .ebp = (unsigned)array });
1465bd62e289SBill Wendling 
1466ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel1);
1467ed93f43bSAvi Kivity     report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321);
1468bd62e289SBill Wendling 
1469ed93f43bSAvi Kivity     inregs.ebx = 1;
1470ed93f43bSAvi Kivity     inregs.ebp = (unsigned)array;
1471ed93f43bSAvi Kivity     inregs.edi = 0;
1472ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel2);
1473ed93f43bSAvi Kivity     report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321);
1474ed93f43bSAvi Kivity }
1475ed93f43bSAvi Kivity 
1476975ca087SPeter Feiner extern unsigned long long r_gdt[];
1477975ca087SPeter Feiner 
1478c2281fa4SAvi Kivity static void test_sgdt_sidt(void)
1479c2281fa4SAvi Kivity {
1480c2281fa4SAvi Kivity     MK_INSN(sgdt, "sgdtw (%eax)");
1481c2281fa4SAvi Kivity     MK_INSN(sidt, "sidtw (%eax)");
1482975ca087SPeter Feiner     struct table_descr x, y;
1483c2281fa4SAvi Kivity 
1484bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = (unsigned)&y });
1485bd62e289SBill Wendling 
1486c2281fa4SAvi Kivity     asm volatile("sgdtw %0" : "=m"(x));
1487c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sgdt);
1488975ca087SPeter Feiner     report("sgdt", 0, x.limit == y.limit && x.base == y.base);
1489c2281fa4SAvi Kivity 
1490c2281fa4SAvi Kivity     inregs.eax = (unsigned)&y;
1491c2281fa4SAvi Kivity     asm volatile("sidtw %0" : "=m"(x));
1492c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sidt);
1493975ca087SPeter Feiner     report("sidt", 0, x.limit == y.limit && x.base == y.base);
1494c2281fa4SAvi Kivity }
1495c2281fa4SAvi Kivity 
149688b6dac4SPaolo Bonzini static void test_sahf(void)
149788b6dac4SPaolo Bonzini {
149888b6dac4SPaolo Bonzini     MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw");
149988b6dac4SPaolo Bonzini 
1500bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0xfd00 });
1501bd62e289SBill Wendling 
150288b6dac4SPaolo Bonzini     exec_in_big_real_mode(&insn_sahf);
150388b6dac4SPaolo Bonzini     report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7));
150488b6dac4SPaolo Bonzini }
150588b6dac4SPaolo Bonzini 
15067ae3645aSAvi Kivity static void test_lahf(void)
15077ae3645aSAvi Kivity {
15087ae3645aSAvi Kivity     MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf");
15097ae3645aSAvi Kivity 
1510bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0xc7 });
1511bd62e289SBill Wendling 
15127ae3645aSAvi Kivity     exec_in_big_real_mode(&insn_lahf);
15137ae3645aSAvi Kivity     report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax);
15147ae3645aSAvi Kivity }
15157ae3645aSAvi Kivity 
1516fd9ea640SAvi Kivity static void test_movzx_movsx(void)
1517fd9ea640SAvi Kivity {
1518fd9ea640SAvi Kivity     MK_INSN(movsx, "movsx %al, %ebx");
1519fd9ea640SAvi Kivity     MK_INSN(movzx, "movzx %al, %ebx");
15203013e079SGleb Natapov     MK_INSN(movzsah, "movsx %ah, %ebx");
15213013e079SGleb Natapov     MK_INSN(movzxah, "movzx %ah, %ebx");
1522fd9ea640SAvi Kivity 
1523bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x1234569c });
1524bd62e289SBill Wendling 
1525fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movsx);
1526fd9ea640SAvi Kivity     report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax);
1527fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movzx);
1528fd9ea640SAvi Kivity     report("movzx", R_BX, outregs.ebx == (unsigned char)inregs.eax);
15293013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzsah);
15303013e079SGleb Natapov     report("movsx ah", R_BX, outregs.ebx == (signed char)(inregs.eax>>8));
15313013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzxah);
15323013e079SGleb Natapov     report("movzx ah", R_BX, outregs.ebx == (unsigned char)(inregs.eax >> 8));
1533fd9ea640SAvi Kivity }
1534fd9ea640SAvi Kivity 
1535b493b2e8SAvi Kivity static void test_bswap(void)
1536b493b2e8SAvi Kivity {
1537b493b2e8SAvi Kivity     MK_INSN(bswap, "bswap %ecx");
1538b493b2e8SAvi Kivity 
1539bd62e289SBill Wendling     init_inregs(&(struct regs){ .ecx = 0x12345678 });
1540bd62e289SBill Wendling 
1541b493b2e8SAvi Kivity     exec_in_big_real_mode(&insn_bswap);
1542b493b2e8SAvi Kivity     report("bswap", R_CX, outregs.ecx == 0x78563412);
1543b493b2e8SAvi Kivity }
1544b493b2e8SAvi Kivity 
15458cd86387SGleb Natapov static void test_aad(void)
15468cd86387SGleb Natapov {
15478cd86387SGleb Natapov     MK_INSN(aad, "aad");
15488cd86387SGleb Natapov 
1549bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x12345678 });
1550bd62e289SBill Wendling 
15518cd86387SGleb Natapov     exec_in_big_real_mode(&insn_aad);
15528cd86387SGleb Natapov     report("aad", R_AX, outregs.eax == 0x123400d4);
15538cd86387SGleb Natapov }
15548cd86387SGleb Natapov 
15552a9b5718SPaolo Bonzini static void test_aam(void)
15562a9b5718SPaolo Bonzini {
15572a9b5718SPaolo Bonzini     MK_INSN(aam, "aam");
15582a9b5718SPaolo Bonzini 
1559bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x76543210 });
1560bd62e289SBill Wendling 
15612a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_aam);
15622a9b5718SPaolo Bonzini     report("aam", R_AX, outregs.eax == 0x76540106);
15632a9b5718SPaolo Bonzini }
15642a9b5718SPaolo Bonzini 
15652a9b5718SPaolo Bonzini static void test_xlat(void)
15662a9b5718SPaolo Bonzini {
15672a9b5718SPaolo Bonzini     MK_INSN(xlat, "xlat");
15682a9b5718SPaolo Bonzini     u8 table[256];
15692a9b5718SPaolo Bonzini     int i;
15702a9b5718SPaolo Bonzini 
15712a9b5718SPaolo Bonzini     for (i = 0; i < 256; i++) {
15722a9b5718SPaolo Bonzini         table[i] = i + 1;
15732a9b5718SPaolo Bonzini     }
15742a9b5718SPaolo Bonzini 
1575bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x89abcdef, .ebx = (u32)table });
1576bd62e289SBill Wendling 
15772a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_xlat);
15782a9b5718SPaolo Bonzini     report("xlat", R_AX, outregs.eax == 0x89abcdf0);
15792a9b5718SPaolo Bonzini }
15802a9b5718SPaolo Bonzini 
15812a9b5718SPaolo Bonzini static void test_salc(void)
15822a9b5718SPaolo Bonzini {
15832a9b5718SPaolo Bonzini     MK_INSN(clc_salc, "clc; .byte 0xd6");
15842a9b5718SPaolo Bonzini     MK_INSN(stc_salc, "stc; .byte 0xd6");
15852a9b5718SPaolo Bonzini 
1586bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x12345678 });
1587bd62e289SBill Wendling 
15882a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_clc_salc);
15892a9b5718SPaolo Bonzini     report("salc (1)", R_AX, outregs.eax == 0x12345600);
15902a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_stc_salc);
15912a9b5718SPaolo Bonzini     report("salc (2)", R_AX, outregs.eax == 0x123456ff);
15922a9b5718SPaolo Bonzini }
15932a9b5718SPaolo Bonzini 
15940987db7aSGleb Natapov static void test_fninit(void)
15950987db7aSGleb Natapov {
15960987db7aSGleb Natapov 	u16 fcw = -1, fsw = -1;
15970987db7aSGleb Natapov 	MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)");
15980987db7aSGleb Natapov 
1599bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = (u32)&fsw, .ebx = (u32)&fcw });
16000987db7aSGleb Natapov 
16010987db7aSGleb Natapov 	exec_in_big_real_mode(&insn_fninit);
16020987db7aSGleb Natapov 	report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f);
16030987db7aSGleb Natapov }
16040987db7aSGleb Natapov 
16051a4c03a0SArthur Chunqi Li static void test_nopl(void)
16061a4c03a0SArthur Chunqi Li {
16071a4c03a0SArthur Chunqi Li 	MK_INSN(nopl1, ".byte 0x90\n\r"); // 1 byte nop
16081a4c03a0SArthur Chunqi Li 	MK_INSN(nopl2, ".byte 0x66, 0x90\n\r"); // 2 bytes nop
16091a4c03a0SArthur Chunqi Li 	MK_INSN(nopl3, ".byte 0x0f, 0x1f, 0x00\n\r"); // 3 bytes nop
16101a4c03a0SArthur Chunqi Li 	MK_INSN(nopl4, ".byte 0x0f, 0x1f, 0x40, 0x00\n\r"); // 4 bytes nop
16111a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl1);
16121a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl2);
16131a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl3);
16141a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl4);
16151a4c03a0SArthur Chunqi Li 	report("nopl", 0, 1);
16161a4c03a0SArthur Chunqi Li }
16171a4c03a0SArthur Chunqi Li 
1618b5105e8bSPaolo Bonzini static u32 perf_baseline;
1619b5105e8bSPaolo Bonzini 
16207505ea23SPaolo Bonzini #define PERF_COUNT 1000000
1621b5105e8bSPaolo Bonzini 
1622b5105e8bSPaolo Bonzini #define MK_INSN_PERF(name, insn)                                \
1623b5105e8bSPaolo Bonzini 	MK_INSN(name, "rdtsc; mov %eax, %ebx; mov %edx, %esi\n" \
1624b5105e8bSPaolo Bonzini 		      "1:" insn "\n"                            \
16257505ea23SPaolo Bonzini 		      ".byte 0x67; loop 1b\n"                   \
1626b5105e8bSPaolo Bonzini 		      "rdtsc");
1627b5105e8bSPaolo Bonzini 
1628b5105e8bSPaolo Bonzini static u32 cycles_in_big_real_mode(struct insn_desc *insn)
1629b5105e8bSPaolo Bonzini {
1630b5105e8bSPaolo Bonzini 	u64 start, end;
1631b5105e8bSPaolo Bonzini 
1632bd62e289SBill Wendling 	init_inregs(&(struct regs){ .ecx = PERF_COUNT });
1633bd62e289SBill Wendling 
1634b5105e8bSPaolo Bonzini 	exec_in_big_real_mode(insn);
1635b5105e8bSPaolo Bonzini 	start = ((u64)outregs.esi << 32) | outregs.ebx;
1636b5105e8bSPaolo Bonzini 	end = ((u64)outregs.edx << 32) | outregs.eax;
1637b5105e8bSPaolo Bonzini 
1638b5105e8bSPaolo Bonzini 	return end - start;
1639b5105e8bSPaolo Bonzini }
1640b5105e8bSPaolo Bonzini 
1641b5105e8bSPaolo Bonzini static void test_perf_loop(void)
1642b5105e8bSPaolo Bonzini {
1643b5105e8bSPaolo Bonzini 	/*
1644b5105e8bSPaolo Bonzini 	 * This test runs simple instructions that should roughly take the
1645b5105e8bSPaolo Bonzini 	 * the same time to emulate: PERF_COUNT iterations of "loop" and 3
1646b5105e8bSPaolo Bonzini 	 * setup instructions.  Other performance tests can run PERF_COUNT
1647b5105e8bSPaolo Bonzini 	 * iterations of the same instruction and subtract the cycle count
1648b5105e8bSPaolo Bonzini 	 * of this test.
1649b5105e8bSPaolo Bonzini 	 */
1650b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_loop, "");
1651b5105e8bSPaolo Bonzini 	perf_baseline = cycles_in_big_real_mode(&insn_perf_loop);
1652b5105e8bSPaolo Bonzini 	print_serial_u32(perf_baseline / (PERF_COUNT + 3));
1653b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated jump instruction\n");
1654b5105e8bSPaolo Bonzini }
1655b5105e8bSPaolo Bonzini 
1656b5105e8bSPaolo Bonzini static void test_perf_mov(void)
1657b5105e8bSPaolo Bonzini {
1658b5105e8bSPaolo Bonzini 	u32 cyc;
1659b5105e8bSPaolo Bonzini 
1660b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_move, "mov %esi, %edi");
1661b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_move);
1662b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1663b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated move instruction\n");
1664b5105e8bSPaolo Bonzini }
1665b5105e8bSPaolo Bonzini 
1666b5105e8bSPaolo Bonzini static void test_perf_arith(void)
1667b5105e8bSPaolo Bonzini {
1668b5105e8bSPaolo Bonzini 	u32 cyc;
1669b5105e8bSPaolo Bonzini 
1670b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_arith, "add $4, %edi");
1671b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_arith);
1672b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1673b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated arithmetic instruction\n");
1674b5105e8bSPaolo Bonzini }
1675b5105e8bSPaolo Bonzini 
1676b5105e8bSPaolo Bonzini static void test_perf_memory_load(void)
1677b5105e8bSPaolo Bonzini {
1678b5105e8bSPaolo Bonzini 	u32 cyc, tmp;
1679b5105e8bSPaolo Bonzini 
1680576718d0SBill Wendling 	MK_INSN_PERF(perf_memory_load, "cmpw $0, (%edi)");
1681bd62e289SBill Wendling 
1682bd62e289SBill Wendling 	init_inregs(&(struct regs){ .edi = (u32)&tmp });
1683bd62e289SBill Wendling 
1684b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_load);
1685b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1686b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated memory load instruction\n");
1687b5105e8bSPaolo Bonzini }
1688b5105e8bSPaolo Bonzini 
16899306cb8eSPaolo Bonzini static void test_perf_memory_store(void)
16909306cb8eSPaolo Bonzini {
16919306cb8eSPaolo Bonzini 	u32 cyc, tmp;
16929306cb8eSPaolo Bonzini 
1693576718d0SBill Wendling 	MK_INSN_PERF(perf_memory_store, "movw %ax, (%edi)");
1694bd62e289SBill Wendling 
1695bd62e289SBill Wendling 	init_inregs(&(struct regs){ .edi = (u32)&tmp });
1696bd62e289SBill Wendling 
16979306cb8eSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_store);
16989306cb8eSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
16999306cb8eSPaolo Bonzini 	print_serial(" cycles/emulated memory store instruction\n");
17009306cb8eSPaolo Bonzini }
17019306cb8eSPaolo Bonzini 
1702b5105e8bSPaolo Bonzini static void test_perf_memory_rmw(void)
1703b5105e8bSPaolo Bonzini {
1704b5105e8bSPaolo Bonzini 	u32 cyc, tmp;
1705b5105e8bSPaolo Bonzini 
1706576718d0SBill Wendling 	MK_INSN_PERF(perf_memory_rmw, "addw $1, (%edi)");
1707bd62e289SBill Wendling 
1708bd62e289SBill Wendling 	init_inregs(&(struct regs){ .edi = (u32)&tmp });
1709bd62e289SBill Wendling 
1710b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_rmw);
1711b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1712b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated memory RMW instruction\n");
1713b5105e8bSPaolo Bonzini }
1714b5105e8bSPaolo Bonzini 
17152e3f9f1fSThomas Huth static void test_dr_mod(void)
17160a5701edSNadav Amit {
17170a5701edSNadav Amit 	MK_INSN(drmod, "movl %ebx, %dr0\n\t"
17180a5701edSNadav Amit 		       ".byte 0x0f \n\t .byte 0x21 \n\t .byte 0x0\n\t");
1719bd62e289SBill Wendling 
1720bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0xdead, .ebx = 0xaced });
1721bd62e289SBill Wendling 
17220a5701edSNadav Amit 	exec_in_big_real_mode(&insn_drmod);
17230a5701edSNadav Amit 	report("mov dr with mod bits", R_AX | R_BX, outregs.eax == 0xaced);
17240a5701edSNadav Amit }
17250a5701edSNadav Amit 
17262e3f9f1fSThomas Huth static void test_smsw(void)
172799ee878cSNadav Amit {
172899ee878cSNadav Amit 	MK_INSN(smsw, "movl %cr0, %ebx\n\t"
172999ee878cSNadav Amit 		      "movl %ebx, %ecx\n\t"
173099ee878cSNadav Amit 		      "or $0x40000000, %ebx\n\t"
173199ee878cSNadav Amit 		      "movl %ebx, %cr0\n\t"
173299ee878cSNadav Amit 		      "smswl %eax\n\t"
173399ee878cSNadav Amit 		      "movl %ecx, %cr0\n\t");
1734bd62e289SBill Wendling 
1735bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0x12345678 });
1736bd62e289SBill Wendling 
173799ee878cSNadav Amit 	exec_in_big_real_mode(&insn_smsw);
173899ee878cSNadav Amit 	report("smsw", R_AX | R_BX | R_CX, outregs.eax == outregs.ebx);
173999ee878cSNadav Amit }
174099ee878cSNadav Amit 
17412e3f9f1fSThomas Huth static void test_xadd(void)
17427bee560dSNadav Amit {
17437bee560dSNadav Amit 	MK_INSN(xadd, "xaddl %eax, %eax\n\t");
1744bd62e289SBill Wendling 
1745bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0x12345678 });
1746bd62e289SBill Wendling 
17477bee560dSNadav Amit 	exec_in_big_real_mode(&insn_xadd);
17487bee560dSNadav Amit 	report("xadd", R_AX, outregs.eax == inregs.eax * 2);
17497bee560dSNadav Amit }
17507bee560dSNadav Amit 
175199ee878cSNadav Amit 
17527d36db35SAvi Kivity void realmode_start(void)
17537d36db35SAvi Kivity {
17547d36db35SAvi Kivity 	test_null();
17557d36db35SAvi Kivity 
17567d36db35SAvi Kivity 	test_shld();
17577d36db35SAvi Kivity 	test_push_pop();
17587d36db35SAvi Kivity 	test_pusha_popa();
17597d36db35SAvi Kivity 	test_mov_imm();
17607d36db35SAvi Kivity 	test_cmp_imm();
17617d36db35SAvi Kivity 	test_add_imm();
17627d36db35SAvi Kivity 	test_sub_imm();
17637d36db35SAvi Kivity 	test_xor_imm();
17647d36db35SAvi Kivity 	test_io();
17657d36db35SAvi Kivity 	test_eflags_insn();
17667d36db35SAvi Kivity 	test_jcc_short();
17677d36db35SAvi Kivity 	test_jcc_near();
17687d36db35SAvi Kivity 	/* test_call() uses short jump so call it after testing jcc */
17697d36db35SAvi Kivity 	test_call();
17707d36db35SAvi Kivity 	/* long jmp test uses call near so test it after testing call */
17717d36db35SAvi Kivity 	test_long_jmp();
17727d36db35SAvi Kivity 	test_xchg();
17737d36db35SAvi Kivity 	test_iret();
177496b9ca1eSMohammed Gamal 	test_int();
17758202cf84SRoman Bolshakov 	test_sti_inhibit();
1776fa74f8a6SMohammed Gamal 	test_imul();
177759317bd1SMohammed Gamal 	test_mul();
17780d4c7614SMohammed Gamal 	test_div();
17790d4c7614SMohammed Gamal 	test_idiv();
1780eacef4e2SWei Yongjun 	test_loopcc();
17816e293cf5SWei Yongjun 	test_cbw();
17820cbd5b06SMohammed Gamal 	test_cwd_cdq();
1783b274feedSAvi Kivity 	test_das();
178437f51a4aSWei Yongjun 	test_lds_lss();
1785b1c7c575SWei Yongjun 	test_jcxz();
17868f578e98SAvi Kivity 	test_cpuid();
1787ed93f43bSAvi Kivity 	test_ss_base_for_esp_ebp();
1788c2281fa4SAvi Kivity 	test_sgdt_sidt();
17897ae3645aSAvi Kivity 	test_lahf();
179088b6dac4SPaolo Bonzini 	test_sahf();
1791fd9ea640SAvi Kivity 	test_movzx_movsx();
1792b493b2e8SAvi Kivity 	test_bswap();
17938cd86387SGleb Natapov 	test_aad();
17942a9b5718SPaolo Bonzini 	test_aam();
17952a9b5718SPaolo Bonzini 	test_xlat();
17962a9b5718SPaolo Bonzini 	test_salc();
17970987db7aSGleb Natapov 	test_fninit();
17980a5701edSNadav Amit 	test_dr_mod();
179999ee878cSNadav Amit 	test_smsw();
18001a4c03a0SArthur Chunqi Li 	test_nopl();
18017bee560dSNadav Amit 	test_xadd();
1802b5105e8bSPaolo Bonzini 	test_perf_loop();
1803b5105e8bSPaolo Bonzini 	test_perf_mov();
1804b5105e8bSPaolo Bonzini 	test_perf_arith();
1805b5105e8bSPaolo Bonzini 	test_perf_memory_load();
18069306cb8eSPaolo Bonzini 	test_perf_memory_store();
1807b5105e8bSPaolo Bonzini 	test_perf_memory_rmw();
18087d36db35SAvi Kivity 
1809b393fe28SNadav Amit 	exit(failed);
18107d36db35SAvi Kivity }
18117d36db35SAvi Kivity 
18127d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff };
18137d36db35SAvi Kivity 
1814975ca087SPeter Feiner struct table_descr r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt };
1815a529af7cSNadav Amit struct table_descr r_idt_descr = { 0x3ff, 0 };
18167d36db35SAvi Kivity 
18177d36db35SAvi Kivity asm(
18187d36db35SAvi Kivity 	".section .init \n\t"
18197d36db35SAvi Kivity 
18207d36db35SAvi Kivity 	".code32 \n\t"
18217d36db35SAvi Kivity 
18227d36db35SAvi Kivity 	"mb_magic = 0x1BADB002 \n\t"
18237d36db35SAvi Kivity 	"mb_flags = 0x0 \n\t"
18247d36db35SAvi Kivity 
18257d36db35SAvi Kivity 	"# multiboot header \n\t"
18267d36db35SAvi Kivity 	".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t"
18277d36db35SAvi Kivity 
18287d36db35SAvi Kivity 	".globl start \n\t"
18297d36db35SAvi Kivity 	".data \n\t"
18307d36db35SAvi Kivity 	". = . + 4096 \n\t"
18317d36db35SAvi Kivity 	"stacktop: \n\t"
18327d36db35SAvi Kivity 
18337d36db35SAvi Kivity 	".text \n\t"
18347d36db35SAvi Kivity 	"start: \n\t"
18357d36db35SAvi Kivity 	"lgdt r_gdt_descr \n\t"
1836a529af7cSNadav Amit 	"lidt r_idt_descr \n\t"
18377d36db35SAvi Kivity 	"ljmp $8, $1f; 1: \n\t"
18387d36db35SAvi Kivity 	".code16gcc \n\t"
18397d36db35SAvi Kivity 	"mov $16, %eax \n\t"
18407d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
18417d36db35SAvi Kivity 	"mov %ax, %es \n\t"
18427d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
18437d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
18447d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
18457d36db35SAvi Kivity 	"mov %cr0, %eax \n\t"
18467d36db35SAvi Kivity 	"btc $0, %eax \n\t"
18477d36db35SAvi Kivity 	"mov %eax, %cr0 \n\t"
18487d36db35SAvi Kivity 	"ljmp $0, $realmode_entry \n\t"
18497d36db35SAvi Kivity 
18507d36db35SAvi Kivity 	"realmode_entry: \n\t"
18517d36db35SAvi Kivity 
18527d36db35SAvi Kivity 	"xor %ax, %ax \n\t"
18537d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
18547d36db35SAvi Kivity 	"mov %ax, %es \n\t"
18557d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
18567d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
18577d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
18587d36db35SAvi Kivity 	"mov $stacktop, %esp\n\t"
18597d36db35SAvi Kivity 	"ljmp $0, $realmode_start \n\t"
18607d36db35SAvi Kivity 
18617d36db35SAvi Kivity 	".code16gcc \n\t"
18627d36db35SAvi Kivity 	);
1863