xref: /kvm-unit-tests/x86/realmode.c (revision 5fcf556167e62d32cffb57640dcfe711fdd147cd)
1*5fcf5561SBill Wendling #include <linux/compiler.h>
2*5fcf5561SBill Wendling 
3f366255fSPaolo Bonzini #ifndef USE_SERIAL
4f366255fSPaolo Bonzini #define USE_SERIAL
5f366255fSPaolo Bonzini #endif
6f366255fSPaolo Bonzini 
747086996SBill Wendling #define ARRAY_SIZE(_a) (sizeof(_a)/sizeof((_a)[0]))
847086996SBill Wendling 
97d36db35SAvi Kivity asm(".code16gcc");
107d36db35SAvi Kivity 
117d36db35SAvi Kivity typedef unsigned char u8;
127d36db35SAvi Kivity typedef unsigned short u16;
137d36db35SAvi Kivity typedef unsigned u32;
147d36db35SAvi Kivity typedef unsigned long long u64;
157d36db35SAvi Kivity 
16bd62e289SBill Wendling #ifndef NULL
17bd62e289SBill Wendling #define NULL ((void*)0)
18bd62e289SBill Wendling #endif
19bd62e289SBill Wendling 
202e3f9f1fSThomas Huth void realmode_start(void);
217d36db35SAvi Kivity void test_function(void);
227d36db35SAvi Kivity 
237d36db35SAvi Kivity asm(
247d36db35SAvi Kivity 	"test_function: \n\t"
257d36db35SAvi Kivity 	"mov $0x1234, %eax \n\t"
267d36db35SAvi Kivity 	"ret"
277d36db35SAvi Kivity    );
287d36db35SAvi Kivity 
strlen(const char * str)297d36db35SAvi Kivity static int strlen(const char *str)
307d36db35SAvi Kivity {
317d36db35SAvi Kivity 	int n;
327d36db35SAvi Kivity 
337d36db35SAvi Kivity 	for (n = 0; *str; ++str)
347d36db35SAvi Kivity 		++n;
357d36db35SAvi Kivity 	return n;
367d36db35SAvi Kivity }
377d36db35SAvi Kivity 
outb(u8 data,u16 port)38f366255fSPaolo Bonzini static void outb(u8 data, u16 port)
39f366255fSPaolo Bonzini {
40f366255fSPaolo Bonzini 	asm volatile("out %0, %1" : : "a"(data), "d"(port));
41f366255fSPaolo Bonzini }
42f366255fSPaolo Bonzini 
43f366255fSPaolo Bonzini #ifdef USE_SERIAL
44f366255fSPaolo Bonzini static int serial_iobase = 0x3f8;
45f366255fSPaolo Bonzini static int serial_inited = 0;
46f366255fSPaolo Bonzini 
inb(u16 port)47f366255fSPaolo Bonzini static u8 inb(u16 port)
48f366255fSPaolo Bonzini {
49f366255fSPaolo Bonzini 	u8 data;
50f366255fSPaolo Bonzini 	asm volatile("in %1, %0" : "=a"(data) : "d"(port));
51f366255fSPaolo Bonzini 	return data;
52f366255fSPaolo Bonzini }
53f366255fSPaolo Bonzini 
serial_outb(char ch)54f366255fSPaolo Bonzini static void serial_outb(char ch)
55f366255fSPaolo Bonzini {
56f366255fSPaolo Bonzini 	u8 lsr;
57f366255fSPaolo Bonzini 
58f366255fSPaolo Bonzini 	do {
59f366255fSPaolo Bonzini 		lsr = inb(serial_iobase + 0x05);
60f366255fSPaolo Bonzini 	} while (!(lsr & 0x20));
61f366255fSPaolo Bonzini 
62f366255fSPaolo Bonzini 	outb(ch, serial_iobase + 0x00);
63f366255fSPaolo Bonzini }
64f366255fSPaolo Bonzini 
serial_init(void)65f366255fSPaolo Bonzini static void serial_init(void)
66f366255fSPaolo Bonzini {
67f366255fSPaolo Bonzini 	u8 lcr;
68f366255fSPaolo Bonzini 
69f366255fSPaolo Bonzini 	/* set DLAB */
70f366255fSPaolo Bonzini 	lcr = inb(serial_iobase + 0x03);
71f366255fSPaolo Bonzini 	lcr |= 0x80;
72f366255fSPaolo Bonzini 	outb(lcr, serial_iobase + 0x03);
73f366255fSPaolo Bonzini 
74f366255fSPaolo Bonzini 	/* set baud rate to 115200 */
75f366255fSPaolo Bonzini 	outb(0x01, serial_iobase + 0x00);
76f366255fSPaolo Bonzini 	outb(0x00, serial_iobase + 0x01);
77f366255fSPaolo Bonzini 
78f366255fSPaolo Bonzini 	/* clear DLAB */
79f366255fSPaolo Bonzini 	lcr = inb(serial_iobase + 0x03);
80f366255fSPaolo Bonzini 	lcr &= ~0x80;
81f366255fSPaolo Bonzini 	outb(lcr, serial_iobase + 0x03);
82c83858a4SNadav Amit 
83c83858a4SNadav Amit 	/* IER: disable interrupts */
84c83858a4SNadav Amit 	outb(0x00, serial_iobase + 0x01);
85c83858a4SNadav Amit 	/* LCR: 8 bits, no parity, one stop bit */
86c83858a4SNadav Amit 	outb(0x03, serial_iobase + 0x03);
87c83858a4SNadav Amit 	/* FCR: disable FIFO queues */
88c83858a4SNadav Amit 	outb(0x00, serial_iobase + 0x02);
89c83858a4SNadav Amit 	/* MCR: RTS, DTR on */
90c83858a4SNadav Amit 	outb(0x03, serial_iobase + 0x04);
91f366255fSPaolo Bonzini }
92f366255fSPaolo Bonzini #endif
93f366255fSPaolo Bonzini 
print_serial(const char * buf)947d36db35SAvi Kivity static void print_serial(const char *buf)
957d36db35SAvi Kivity {
967d36db35SAvi Kivity 	unsigned long len = strlen(buf);
97f366255fSPaolo Bonzini #ifdef USE_SERIAL
98f366255fSPaolo Bonzini 	unsigned long i;
99f366255fSPaolo Bonzini 	if (!serial_inited) {
100f366255fSPaolo Bonzini 	    serial_init();
101f366255fSPaolo Bonzini 	    serial_inited = 1;
102f366255fSPaolo Bonzini 	}
1037d36db35SAvi Kivity 
104f366255fSPaolo Bonzini 	for (i = 0; i < len; i++) {
105f366255fSPaolo Bonzini 	    serial_outb(buf[i]);
106f366255fSPaolo Bonzini 	}
107f366255fSPaolo Bonzini #else
1085edbb9aeSPaolo Bonzini 	asm volatile ("addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1));
109f366255fSPaolo Bonzini #endif
1107d36db35SAvi Kivity }
1117d36db35SAvi Kivity 
print_serial_u32(u32 value)112b5105e8bSPaolo Bonzini static void print_serial_u32(u32 value)
113b5105e8bSPaolo Bonzini {
114b5105e8bSPaolo Bonzini 	char n[12], *p;
115b5105e8bSPaolo Bonzini 	p = &n[11];
116b5105e8bSPaolo Bonzini 	*p = 0;
117b5105e8bSPaolo Bonzini 	do {
118b5105e8bSPaolo Bonzini 		*--p = '0' + (value % 10);
119b5105e8bSPaolo Bonzini 		value /= 10;
120b5105e8bSPaolo Bonzini 	} while (value > 0);
121b5105e8bSPaolo Bonzini 	print_serial(p);
122b5105e8bSPaolo Bonzini }
123b5105e8bSPaolo Bonzini 
124b393fe28SNadav Amit static int failed;
125b393fe28SNadav Amit 
exit(int code)1267d36db35SAvi Kivity static void exit(int code)
1277d36db35SAvi Kivity {
128f366255fSPaolo Bonzini 	outb(code, 0xf4);
1293b9b2d55SNadav Amit 
13057479453SNadav Amit 	if (code == 0)
13157479453SNadav Amit 		print_serial("--- DONE: 0 ---\n");
13257479453SNadav Amit 	else
13357479453SNadav Amit 		print_serial("--- DONE: 1 ---\n");
13457479453SNadav Amit 
1353b9b2d55SNadav Amit 	while (1) {
1363b9b2d55SNadav Amit 		asm volatile("hlt" ::: "memory");
1373b9b2d55SNadav Amit 	}
1387d36db35SAvi Kivity }
1397d36db35SAvi Kivity 
1407d36db35SAvi Kivity struct regs {
1417d36db35SAvi Kivity 	u32 eax, ebx, ecx, edx;
1427d36db35SAvi Kivity 	u32 esi, edi, esp, ebp;
1437d36db35SAvi Kivity 	u32 eip, eflags;
1447d36db35SAvi Kivity };
1457d36db35SAvi Kivity 
146975ca087SPeter Feiner struct table_descr {
147975ca087SPeter Feiner 	u16 limit;
148975ca087SPeter Feiner 	void *base;
149975ca087SPeter Feiner } __attribute__((packed));
150975ca087SPeter Feiner 
1517d36db35SAvi Kivity static u64 gdt[] = {
1527d36db35SAvi Kivity 	0,
1537d36db35SAvi Kivity 	0x00cf9b000000ffffull, // flat 32-bit code segment
1547d36db35SAvi Kivity 	0x00cf93000000ffffull, // flat 32-bit data segment
1557d36db35SAvi Kivity };
1567d36db35SAvi Kivity 
157975ca087SPeter Feiner static struct table_descr gdt_descr = {
1587d36db35SAvi Kivity 	sizeof(gdt) - 1,
1597d36db35SAvi Kivity 	gdt,
1607d36db35SAvi Kivity };
1617d36db35SAvi Kivity 
162d4dc402cSAvi Kivity struct insn_desc {
163d4dc402cSAvi Kivity     u16 ptr;
164d4dc402cSAvi Kivity     u16 len;
165d4dc402cSAvi Kivity };
166d4dc402cSAvi Kivity 
167bd62e289SBill Wendling struct {
168bd62e289SBill Wendling 	u32 stack[128];
169bd62e289SBill Wendling 	char top[];
170bd62e289SBill Wendling } tmp_stack;
171bd62e289SBill Wendling 
17218253fdeSAvi Kivity static struct regs inregs, outregs;
17318253fdeSAvi Kivity 
init_inregs(struct regs * regs)174bd62e289SBill Wendling static inline void init_inregs(struct regs *regs)
175bd62e289SBill Wendling {
176bd62e289SBill Wendling 	inregs = (struct regs){ 0 };
177bd62e289SBill Wendling 	if (regs)
178bd62e289SBill Wendling 		inregs = *regs;
179bd62e289SBill Wendling 	if (!inregs.esp)
180bd62e289SBill Wendling 		inregs.esp = (unsigned long)&tmp_stack.top;
181bd62e289SBill Wendling }
182bd62e289SBill Wendling 
exec_in_big_real_mode(struct insn_desc * insn)183*5fcf5561SBill Wendling static noinline void exec_in_big_real_mode(struct insn_desc *insn)
1847d36db35SAvi Kivity {
1857d36db35SAvi Kivity 	unsigned long tmp;
1867d36db35SAvi Kivity 	static struct regs save;
1877d36db35SAvi Kivity 	int i;
1887d36db35SAvi Kivity 	extern u8 test_insn[], test_insn_end[];
1897d36db35SAvi Kivity 
190d4dc402cSAvi Kivity 	for (i = 0; i < insn->len; ++i)
191d4dc402cSAvi Kivity 	    test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i];
1927d36db35SAvi Kivity 	for (; i < test_insn_end - test_insn; ++i)
1937d36db35SAvi Kivity 		test_insn[i] = 0x90; // nop
1947d36db35SAvi Kivity 
19518253fdeSAvi Kivity 	save = inregs;
1967d36db35SAvi Kivity 	asm volatile(
1977d36db35SAvi Kivity 		"lgdtl %[gdt_descr] \n\t"
1987d36db35SAvi Kivity 		"mov %%cr0, %[tmp] \n\t"
1997d36db35SAvi Kivity 		"or $1, %[tmp] \n\t"
2007d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
2017d36db35SAvi Kivity 		"mov %[bigseg], %%gs \n\t"
2027d36db35SAvi Kivity 		"and $-2, %[tmp] \n\t"
2037d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
2047d36db35SAvi Kivity 
205eb6687a2SBill Wendling 		/* Save ES, because it is clobbered by some tests. */
206eb6687a2SBill Wendling 		"pushw %%es \n\t"
207eb6687a2SBill Wendling 
20832001692SAvi Kivity 		"pushw %[save]+36; popfw \n\t"
2097d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
2107d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
2117d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
2127d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
2137d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
2147d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
2157d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
2167d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
2177d36db35SAvi Kivity 
2187d36db35SAvi Kivity 		"test_insn: . = . + 32\n\t"
2197d36db35SAvi Kivity 		"test_insn_end: \n\t"
2207d36db35SAvi Kivity 
2217d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
2227d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
2237d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
2247d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
2257d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
2267d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
2277d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
2287d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
2297d36db35SAvi Kivity 
2307d36db35SAvi Kivity 		/* Save EFLAGS in outregs*/
2317d36db35SAvi Kivity 		"pushfl \n\t"
2327d36db35SAvi Kivity 		"popl %[save]+36 \n\t"
2337d36db35SAvi Kivity 
234eb6687a2SBill Wendling 		/* Restore ES for future rep string operations. */
235eb6687a2SBill Wendling 		"popw %%es \n\t"
236eb6687a2SBill Wendling 
2375edbb9aeSPaolo Bonzini 		/* Restore DF for the harness code */
2385edbb9aeSPaolo Bonzini 		"cld\n\t"
2397d36db35SAvi Kivity 		"xor %[tmp], %[tmp] \n\t"
2407d36db35SAvi Kivity 		"mov %[tmp], %%gs \n\t"
2417d36db35SAvi Kivity 		: [tmp]"=&r"(tmp), [save]"+m"(save)
2427d36db35SAvi Kivity 		: [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16)
2437d36db35SAvi Kivity 		: "cc", "memory"
2447d36db35SAvi Kivity 		);
24518253fdeSAvi Kivity 	outregs = save;
2467d36db35SAvi Kivity }
2477d36db35SAvi Kivity 
2487d36db35SAvi Kivity #define R_AX 1
2497d36db35SAvi Kivity #define R_BX 2
2507d36db35SAvi Kivity #define R_CX 4
2517d36db35SAvi Kivity #define R_DX 8
2527d36db35SAvi Kivity #define R_SI 16
2537d36db35SAvi Kivity #define R_DI 32
2547d36db35SAvi Kivity #define R_SP 64
2557d36db35SAvi Kivity #define R_BP 128
2567d36db35SAvi Kivity 
regs_equal(int ignore)2572e3f9f1fSThomas Huth static int regs_equal(int ignore)
2587d36db35SAvi Kivity {
25918253fdeSAvi Kivity 	const u32 *p1 = &inregs.eax, *p2 = &outregs.eax;  // yuck
2607d36db35SAvi Kivity 	int i;
2617d36db35SAvi Kivity 
2627d36db35SAvi Kivity 	for (i = 0; i < 8; ++i)
2637d36db35SAvi Kivity 		if (!(ignore & (1 << i)) && p1[i] != p2[i])
2647d36db35SAvi Kivity 			return 0;
2657d36db35SAvi Kivity 	return 1;
2667d36db35SAvi Kivity }
2677d36db35SAvi Kivity 
report(const char * name,u16 regs_ignore,_Bool ok)2686055ea1fSAvi Kivity static void report(const char *name, u16 regs_ignore, _Bool ok)
26981050840SAvi Kivity {
2706055ea1fSAvi Kivity     if (!regs_equal(regs_ignore)) {
2716055ea1fSAvi Kivity 	ok = 0;
2726055ea1fSAvi Kivity     }
27381050840SAvi Kivity     print_serial(ok ? "PASS: " : "FAIL: ");
27481050840SAvi Kivity     print_serial(name);
27581050840SAvi Kivity     print_serial("\n");
276b393fe28SNadav Amit     if (!ok)
277b393fe28SNadav Amit 	failed = 1;
27881050840SAvi Kivity }
27981050840SAvi Kivity 
2807d36db35SAvi Kivity #define MK_INSN(name, str)				\
2817d36db35SAvi Kivity     asm (						\
282d4dc402cSAvi Kivity 	 ".pushsection .data.insn  \n\t"		\
283d4dc402cSAvi Kivity 	 "insn_" #name ": \n\t"				\
284d4dc402cSAvi Kivity 	 ".word 1001f, 1002f - 1001f \n\t"		\
285d4dc402cSAvi Kivity 	 ".popsection \n\t"				\
286d4dc402cSAvi Kivity 	 ".pushsection .text.insn, \"ax\" \n\t"		\
287d4dc402cSAvi Kivity 	 "1001: \n\t"					\
288d4dc402cSAvi Kivity 	 "insn_code_" #name ": " str " \n\t"		\
289d4dc402cSAvi Kivity 	 "1002: \n\t"					\
290d4dc402cSAvi Kivity 	 ".popsection"					\
2917d36db35SAvi Kivity     );							\
292d4dc402cSAvi Kivity     extern struct insn_desc insn_##name;
2937d36db35SAvi Kivity 
test_xchg(void)2942e3f9f1fSThomas Huth static void test_xchg(void)
2957d36db35SAvi Kivity {
2967d36db35SAvi Kivity 	MK_INSN(xchg_test1, "xchg %eax,%eax\n\t");
2977d36db35SAvi Kivity 	MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t");
2987d36db35SAvi Kivity 	MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t");
2997d36db35SAvi Kivity 	MK_INSN(xchg_test4, "xchg %eax,%edx\n\t");
3007d36db35SAvi Kivity 	MK_INSN(xchg_test5, "xchg %eax,%esi\n\t");
3017d36db35SAvi Kivity 	MK_INSN(xchg_test6, "xchg %eax,%edi\n\t");
3027d36db35SAvi Kivity 	MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t");
3037d36db35SAvi Kivity 	MK_INSN(xchg_test8, "xchg %eax,%esp\n\t");
3047d36db35SAvi Kivity 
30518253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7};
3067d36db35SAvi Kivity 
30718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test1);
3086055ea1fSAvi Kivity 	report("xchg 1", 0, 1);
30918253fdeSAvi Kivity 
31018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test2);
3116055ea1fSAvi Kivity 	report("xchg 2", R_AX | R_BX,
3126055ea1fSAvi Kivity 	       outregs.eax == inregs.ebx && outregs.ebx == inregs.eax);
3137d36db35SAvi Kivity 
31418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test3);
3156055ea1fSAvi Kivity 	report("xchg 3", R_AX | R_CX,
3166055ea1fSAvi Kivity 	       outregs.eax == inregs.ecx && outregs.ecx == inregs.eax);
3177d36db35SAvi Kivity 
31818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test4);
3196055ea1fSAvi Kivity 	report("xchg 4", R_AX | R_DX,
3206055ea1fSAvi Kivity 	       outregs.eax == inregs.edx && outregs.edx == inregs.eax);
3217d36db35SAvi Kivity 
32218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test5);
3236055ea1fSAvi Kivity 	report("xchg 5", R_AX | R_SI,
3246055ea1fSAvi Kivity 	       outregs.eax == inregs.esi && outregs.esi == inregs.eax);
3257d36db35SAvi Kivity 
32618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test6);
3276055ea1fSAvi Kivity 	report("xchg 6", R_AX | R_DI,
3286055ea1fSAvi Kivity 	       outregs.eax == inregs.edi && outregs.edi == inregs.eax);
3297d36db35SAvi Kivity 
33018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test7);
3316055ea1fSAvi Kivity 	report("xchg 7", R_AX | R_BP,
3326055ea1fSAvi Kivity 	       outregs.eax == inregs.ebp && outregs.ebp == inregs.eax);
3337d36db35SAvi Kivity 
33418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test8);
3356055ea1fSAvi Kivity 	report("xchg 8", R_AX | R_SP,
3366055ea1fSAvi Kivity 	       outregs.eax == inregs.esp && outregs.esp == inregs.eax);
3377d36db35SAvi Kivity }
3387d36db35SAvi Kivity 
test_shld(void)3392e3f9f1fSThomas Huth static void test_shld(void)
3407d36db35SAvi Kivity {
3417d36db35SAvi Kivity 	MK_INSN(shld_test, "shld $8,%edx,%eax\n\t");
3427d36db35SAvi Kivity 
343bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0xbe, .edx = 0xef000000 });
344bd62e289SBill Wendling 
34518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_shld_test);
3466055ea1fSAvi Kivity 	report("shld", ~0, outregs.eax == 0xbeef);
3477d36db35SAvi Kivity }
3487d36db35SAvi Kivity 
test_mov_imm(void)3492e3f9f1fSThomas Huth static void test_mov_imm(void)
3507d36db35SAvi Kivity {
3517d36db35SAvi Kivity 	MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax");
3527d36db35SAvi Kivity 	MK_INSN(mov_r16_imm_1, "mov $1234, %ax");
3537d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_1, "mov $0x12, %ah");
3547d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_2, "mov $0x34, %al");
3557d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t");
3567d36db35SAvi Kivity 
357bd62e289SBill Wendling 	init_inregs(NULL);
35818253fdeSAvi Kivity 
35918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r16_imm_1);
3606055ea1fSAvi Kivity 	report("mov 1", R_AX, outregs.eax == 1234);
3617d36db35SAvi Kivity 
3627d36db35SAvi Kivity 	/* test mov $imm, %eax */
36318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r32_imm_1);
3646055ea1fSAvi Kivity 	report("mov 2", R_AX, outregs.eax == 1234567890);
3657d36db35SAvi Kivity 
3667d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
36718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_1);
3686055ea1fSAvi Kivity 	report("mov 3", R_AX, outregs.eax == 0x1200);
3697d36db35SAvi Kivity 
37018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_2);
3716055ea1fSAvi Kivity 	report("mov 4", R_AX, outregs.eax == 0x34);
3727d36db35SAvi Kivity 
37318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_3);
3746055ea1fSAvi Kivity 	report("mov 5", R_AX, outregs.eax == 0x1234);
3757d36db35SAvi Kivity }
3767d36db35SAvi Kivity 
test_sub_imm(void)3772e3f9f1fSThomas Huth static void test_sub_imm(void)
3787d36db35SAvi Kivity {
3797d36db35SAvi Kivity 	MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t");
3807d36db35SAvi Kivity 	MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t");
3817d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t");
3827d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t");
3837d36db35SAvi Kivity 
384bd62e289SBill Wendling 	init_inregs(NULL);
38518253fdeSAvi Kivity 
38618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r16_imm_1);
3876055ea1fSAvi Kivity 	report("sub 1", R_AX, outregs.eax == 1224);
3887d36db35SAvi Kivity 
3897d36db35SAvi Kivity 	/* test mov $imm, %eax */
39018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r32_imm_1);
3916055ea1fSAvi Kivity 	report("sub 2", R_AX, outregs.eax == 1234567880);
3927d36db35SAvi Kivity 
3937d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
39418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_1);
3956055ea1fSAvi Kivity 	report("sub 3", R_AX, outregs.eax == 0x0200);
3967d36db35SAvi Kivity 
39718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_2);
3986055ea1fSAvi Kivity 	report("sub 4", R_AX, outregs.eax == 0x24);
3997d36db35SAvi Kivity }
4007d36db35SAvi Kivity 
test_xor_imm(void)4012e3f9f1fSThomas Huth static void test_xor_imm(void)
4027d36db35SAvi Kivity {
4037d36db35SAvi Kivity 	MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t");
4047d36db35SAvi Kivity 	MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t");
4057d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t");
4067d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t");
4077d36db35SAvi Kivity 
408bd62e289SBill Wendling 	init_inregs(NULL);
40918253fdeSAvi Kivity 
41018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r16_imm_1);
4116055ea1fSAvi Kivity 	report("xor 1", R_AX, outregs.eax == 0);
4127d36db35SAvi Kivity 
4137d36db35SAvi Kivity 	/* test mov $imm, %eax */
41418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r32_imm_1);
4156055ea1fSAvi Kivity 	report("xor 2", R_AX, outregs.eax == 0);
4167d36db35SAvi Kivity 
4177d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
41818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_1);
4196055ea1fSAvi Kivity 	report("xor 3", R_AX, outregs.eax == 0);
4207d36db35SAvi Kivity 
42118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_2);
4226055ea1fSAvi Kivity 	report("xor 4", R_AX, outregs.eax == 0);
4237d36db35SAvi Kivity }
4247d36db35SAvi Kivity 
test_cmp_imm(void)4252e3f9f1fSThomas Huth static void test_cmp_imm(void)
4267d36db35SAvi Kivity {
4277d36db35SAvi Kivity 	MK_INSN(cmp_test1, "mov $0x34, %al\n\t"
4287d36db35SAvi Kivity 			   "cmp $0x34, %al\n\t");
4297d36db35SAvi Kivity 	MK_INSN(cmp_test2, "mov $0x34, %al\n\t"
4307d36db35SAvi Kivity 			   "cmp $0x39, %al\n\t");
4317d36db35SAvi Kivity 	MK_INSN(cmp_test3, "mov $0x34, %al\n\t"
4327d36db35SAvi Kivity 			   "cmp $0x24, %al\n\t");
4337d36db35SAvi Kivity 
434bd62e289SBill Wendling 	init_inregs(NULL);
43518253fdeSAvi Kivity 
4367d36db35SAvi Kivity 	/* test cmp imm8 with AL */
4377d36db35SAvi Kivity 	/* ZF: (bit 6) Zero Flag becomes 1 if an operation results
4387d36db35SAvi Kivity 	 * in a 0 writeback, or 0 register
4397d36db35SAvi Kivity 	 */
44018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test1);
4416055ea1fSAvi Kivity 	report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6));
4427d36db35SAvi Kivity 
44318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test2);
4446055ea1fSAvi Kivity 	report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0);
4457d36db35SAvi Kivity 
44618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test3);
4476055ea1fSAvi Kivity 	report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0);
4487d36db35SAvi Kivity }
4497d36db35SAvi Kivity 
test_add_imm(void)4502e3f9f1fSThomas Huth static void test_add_imm(void)
4517d36db35SAvi Kivity {
4527d36db35SAvi Kivity 	MK_INSN(add_test1, "mov $0x43211234, %eax \n\t"
4537d36db35SAvi Kivity 			   "add $0x12344321, %eax \n\t");
4547d36db35SAvi Kivity 	MK_INSN(add_test2, "mov $0x12, %eax \n\t"
4557d36db35SAvi Kivity 			   "add $0x21, %al\n\t");
4567d36db35SAvi Kivity 
457bd62e289SBill Wendling 	init_inregs(NULL);
45818253fdeSAvi Kivity 
45918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test1);
4606055ea1fSAvi Kivity 	report("add 1", ~0, outregs.eax == 0x55555555);
4617d36db35SAvi Kivity 
46218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test2);
4636055ea1fSAvi Kivity 	report("add 2", ~0, outregs.eax == 0x33);
4647d36db35SAvi Kivity }
4657d36db35SAvi Kivity 
test_eflags_insn(void)4662e3f9f1fSThomas Huth static void test_eflags_insn(void)
4677d36db35SAvi Kivity {
4687d36db35SAvi Kivity 	MK_INSN(clc, "clc");
469b3261e48SMohammed Gamal 	MK_INSN(stc, "stc");
4707d36db35SAvi Kivity 	MK_INSN(cli, "cli");
4717d36db35SAvi Kivity 	MK_INSN(sti, "sti");
4727d36db35SAvi Kivity 	MK_INSN(cld, "cld");
4737d36db35SAvi Kivity 	MK_INSN(std, "std");
4747d36db35SAvi Kivity 
475bd62e289SBill Wendling 	init_inregs(NULL);
47618253fdeSAvi Kivity 
47718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_clc);
4786055ea1fSAvi Kivity 	report("clc", ~0, (outregs.eflags & 1) == 0);
4797d36db35SAvi Kivity 
48018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_stc);
4816055ea1fSAvi Kivity 	report("stc", ~0, (outregs.eflags & 1) == 1);
482b3261e48SMohammed Gamal 
48318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cli);
4846055ea1fSAvi Kivity 	report("cli", ~0, !(outregs.eflags & (1 << 9)));
4857d36db35SAvi Kivity 
48618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sti);
4876055ea1fSAvi Kivity 	report("sti", ~0, outregs.eflags & (1 << 9));
4887d36db35SAvi Kivity 
48918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cld);
4906055ea1fSAvi Kivity 	report("cld", ~0, !(outregs.eflags & (1 << 10)));
4917d36db35SAvi Kivity 
49218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_std);
4936055ea1fSAvi Kivity 	report("std", ~0, (outregs.eflags & (1 << 10)));
4947d36db35SAvi Kivity }
4957d36db35SAvi Kivity 
test_io(void)4962e3f9f1fSThomas Huth static void test_io(void)
4977d36db35SAvi Kivity {
4987d36db35SAvi Kivity 	MK_INSN(io_test1, "mov $0xff, %al \n\t"
4997d36db35SAvi Kivity 		          "out %al, $0xe0 \n\t"
5007d36db35SAvi Kivity 		          "mov $0x00, %al \n\t"
5017d36db35SAvi Kivity 			  "in $0xe0, %al \n\t");
5027d36db35SAvi Kivity 	MK_INSN(io_test2, "mov $0xffff, %ax \n\t"
5037d36db35SAvi Kivity 			  "out %ax, $0xe0 \n\t"
5047d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
5057d36db35SAvi Kivity 			  "in $0xe0, %ax \n\t");
5067d36db35SAvi Kivity 	MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t"
5077d36db35SAvi Kivity 			  "out %eax, $0xe0 \n\t"
5087d36db35SAvi Kivity 			  "mov $0x000000, %eax \n\t"
5097d36db35SAvi Kivity 			  "in $0xe0, %eax \n\t");
5107d36db35SAvi Kivity 	MK_INSN(io_test4, "mov $0xe0, %dx \n\t"
5117d36db35SAvi Kivity 			  "mov $0xff, %al \n\t"
5127d36db35SAvi Kivity 			  "out %al, %dx \n\t"
5137d36db35SAvi Kivity 			  "mov $0x00, %al \n\t"
5147d36db35SAvi Kivity 			  "in %dx, %al \n\t");
5157d36db35SAvi Kivity 	MK_INSN(io_test5, "mov $0xe0, %dx \n\t"
5167d36db35SAvi Kivity 			  "mov $0xffff, %ax \n\t"
5177d36db35SAvi Kivity 			  "out %ax, %dx \n\t"
5187d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
5197d36db35SAvi Kivity 			  "in %dx, %ax \n\t");
5207d36db35SAvi Kivity 	MK_INSN(io_test6, "mov $0xe0, %dx \n\t"
5217d36db35SAvi Kivity 			  "mov $0xffffffff, %eax \n\t"
5227d36db35SAvi Kivity 			  "out %eax, %dx \n\t"
5237d36db35SAvi Kivity 			  "mov $0x00000000, %eax \n\t"
5247d36db35SAvi Kivity 			  "in %dx, %eax \n\t");
5257d36db35SAvi Kivity 
526bd62e289SBill Wendling 	init_inregs(NULL);
52718253fdeSAvi Kivity 
52818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test1);
5296055ea1fSAvi Kivity 	report("pio 1", R_AX, outregs.eax == 0xff);
5307d36db35SAvi Kivity 
53118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test2);
5326055ea1fSAvi Kivity 	report("pio 2", R_AX, outregs.eax == 0xffff);
5337d36db35SAvi Kivity 
53418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test3);
5356055ea1fSAvi Kivity 	report("pio 3", R_AX, outregs.eax == 0xffffffff);
5367d36db35SAvi Kivity 
53718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test4);
5386055ea1fSAvi Kivity 	report("pio 4", R_AX|R_DX, outregs.eax == 0xff);
5397d36db35SAvi Kivity 
54018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test5);
5416055ea1fSAvi Kivity 	report("pio 5", R_AX|R_DX, outregs.eax == 0xffff);
5427d36db35SAvi Kivity 
54318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test6);
5446055ea1fSAvi Kivity 	report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff);
5457d36db35SAvi Kivity }
5467d36db35SAvi Kivity 
547c0b7268dSAvi Kivity asm ("retf: lretw");
5482e3f9f1fSThomas Huth extern void retf(void);
549c0b7268dSAvi Kivity 
5504f66bc86SBruce Rogers asm ("retf_imm: lretw $10");
5512e3f9f1fSThomas Huth extern void retf_imm(void);
5524f66bc86SBruce Rogers 
test_call(void)5532e3f9f1fSThomas Huth static void test_call(void)
5547d36db35SAvi Kivity {
555c0b7268dSAvi Kivity 	u32 addr;
5567d36db35SAvi Kivity 
5577d36db35SAvi Kivity 	MK_INSN(call1, "mov $test_function, %eax \n\t"
5587d36db35SAvi Kivity 		       "call *%eax\n\t");
5597d36db35SAvi Kivity 	MK_INSN(call_near1, "jmp 2f\n\t"
5607d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5617d36db35SAvi Kivity 			    "ret\n\t"
5627d36db35SAvi Kivity 			    "2: call 1b\t");
5637d36db35SAvi Kivity 	MK_INSN(call_near2, "call 1f\n\t"
5647d36db35SAvi Kivity 			    "jmp 2f\n\t"
5657d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5667d36db35SAvi Kivity 			    "ret\n\t"
5677d36db35SAvi Kivity 			    "2:\t");
568c0b7268dSAvi Kivity 	MK_INSN(call_far1,  "lcallw *(%ebx)\n\t");
569556d2680SWei Yongjun 	MK_INSN(call_far2,  "lcallw $0, $retf\n\t");
570c6061817SAvi Kivity 	MK_INSN(ret_imm,    "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b");
5714f66bc86SBruce Rogers 	MK_INSN(retf_imm,   "sub $10, %sp; lcallw $0, $retf_imm");
5727d36db35SAvi Kivity 
573bd62e289SBill Wendling 	init_inregs(NULL);
574bd62e289SBill Wendling 
57518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call1);
5766055ea1fSAvi Kivity 	report("call 1", R_AX, outregs.eax == 0x1234);
5777d36db35SAvi Kivity 
57818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near1);
5796055ea1fSAvi Kivity 	report("call near 1", R_AX, outregs.eax == 0x1234);
5807d36db35SAvi Kivity 
58118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near2);
5826055ea1fSAvi Kivity 	report("call near 2", R_AX, outregs.eax == 0x1234);
583c0b7268dSAvi Kivity 
584c0b7268dSAvi Kivity 	addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f);
585c0b7268dSAvi Kivity 	inregs.ebx = (unsigned)&addr;
58618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_far1);
5876055ea1fSAvi Kivity 	report("call far 1", 0, 1);
588c6061817SAvi Kivity 
589556d2680SWei Yongjun 	exec_in_big_real_mode(&insn_call_far2);
590556d2680SWei Yongjun 	report("call far 2", 0, 1);
591556d2680SWei Yongjun 
59218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_ret_imm);
5936055ea1fSAvi Kivity 	report("ret imm 1", 0, 1);
5944f66bc86SBruce Rogers 
5954f66bc86SBruce Rogers 	exec_in_big_real_mode(&insn_retf_imm);
5964f66bc86SBruce Rogers 	report("retf imm 1", 0, 1);
5977d36db35SAvi Kivity }
5987d36db35SAvi Kivity 
test_jcc_short(void)5992e3f9f1fSThomas Huth static void test_jcc_short(void)
6007d36db35SAvi Kivity {
6017d36db35SAvi Kivity 	MK_INSN(jnz_short1, "jnz 1f\n\t"
6027d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
6037d36db35SAvi Kivity 		            "1:\n\t");
6047d36db35SAvi Kivity 	MK_INSN(jnz_short2, "1:\n\t"
6057d36db35SAvi Kivity 			    "cmp $0x1234, %eax\n\t"
6067d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
6077d36db35SAvi Kivity 		            "jnz 1b\n\t");
6087d36db35SAvi Kivity 	MK_INSN(jmp_short1, "jmp 1f\n\t"
6097d36db35SAvi Kivity 		      "mov $0x1234, %eax\n\t"
6107d36db35SAvi Kivity 		      "1:\n\t");
6117d36db35SAvi Kivity 
612bd62e289SBill Wendling 	init_inregs(NULL);
6137d36db35SAvi Kivity 
61418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short1);
6156055ea1fSAvi Kivity 	report("jnz short 1", ~0, 1);
61618253fdeSAvi Kivity 
61718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short2);
6186055ea1fSAvi Kivity 	report("jnz short 2", R_AX, (outregs.eflags & (1 << 6)));
6197d36db35SAvi Kivity 
62018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_short1);
6216055ea1fSAvi Kivity 	report("jmp short 1", ~0, 1);
6227d36db35SAvi Kivity }
6237d36db35SAvi Kivity 
test_jcc_near(void)6242e3f9f1fSThomas Huth static void test_jcc_near(void)
6257d36db35SAvi Kivity {
6267d36db35SAvi Kivity 	/* encode near jmp manually. gas will not do it if offsets < 127 byte */
6277d36db35SAvi Kivity 	MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t"
6287d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
6297d36db35SAvi Kivity 	MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t"
6307d36db35SAvi Kivity 			   "mov $0x1234, %eax\n\t"
6317d36db35SAvi Kivity 		           ".byte 0x0f, 0x85, 0xf0, 0xff\n\t");
6327d36db35SAvi Kivity 	MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t"
6337d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
6347d36db35SAvi Kivity 
635bd62e289SBill Wendling 	init_inregs(NULL);
6367d36db35SAvi Kivity 
63718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near1);
6386055ea1fSAvi Kivity 	report("jnz near 1", 0, 1);
63918253fdeSAvi Kivity 
64018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near2);
6416055ea1fSAvi Kivity 	report("jnz near 2", R_AX, outregs.eflags & (1 << 6));
6427d36db35SAvi Kivity 
64318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_near1);
6446055ea1fSAvi Kivity 	report("jmp near 1", 0, 1);
6457d36db35SAvi Kivity }
6467d36db35SAvi Kivity 
test_long_jmp(void)6472e3f9f1fSThomas Huth static void test_long_jmp(void)
6487d36db35SAvi Kivity {
6492616ad93SRoman Bolshakov 	MK_INSN(long_jmp, "calll 1f\n\t"
6507d36db35SAvi Kivity 			  "jmp 2f\n\t"
6517d36db35SAvi Kivity 			  "1: jmp $0, $test_function\n\t"
6527d36db35SAvi Kivity 		          "2:\n\t");
653bd62e289SBill Wendling 
654bd62e289SBill Wendling 	init_inregs(NULL);
655bd62e289SBill Wendling 
65618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_long_jmp);
6576055ea1fSAvi Kivity 	report("jmp far 1", R_AX, outregs.eax == 0x1234);
6587d36db35SAvi Kivity }
659fa74f8a6SMohammed Gamal 
test_push_pop(void)6602e3f9f1fSThomas Huth static void test_push_pop(void)
6617d36db35SAvi Kivity {
6627d36db35SAvi Kivity 	MK_INSN(push32, "mov $0x12345678, %eax\n\t"
6637d36db35SAvi Kivity 			"push %eax\n\t"
6647d36db35SAvi Kivity 			"pop %ebx\n\t");
6657d36db35SAvi Kivity 	MK_INSN(push16, "mov $0x1234, %ax\n\t"
6667d36db35SAvi Kivity 			"push %ax\n\t"
6677d36db35SAvi Kivity 			"pop %bx\n\t");
6687d36db35SAvi Kivity 
6697d36db35SAvi Kivity 	MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten
6707d36db35SAvi Kivity 			 "mov $0x123, %ax\n\t"
6717d36db35SAvi Kivity 			 "mov %ax, %es\n\t"
672231b4c3bSRoman Bolshakov 			 "pushw %es\n\t"
6737d36db35SAvi Kivity 			 "pop %bx \n\t"
6747d36db35SAvi Kivity 			 );
6757d36db35SAvi Kivity 	MK_INSN(pop_es, "push %ax\n\t"
676231b4c3bSRoman Bolshakov 			"popw %es\n\t"
6777d36db35SAvi Kivity 			"mov %es, %bx\n\t"
6787d36db35SAvi Kivity 			);
679231b4c3bSRoman Bolshakov 	MK_INSN(push_pop_ss, "pushw %ss\n\t"
6807d36db35SAvi Kivity 			     "pushw %ax\n\t"
6817d36db35SAvi Kivity 			     "popw %ss\n\t"
6827d36db35SAvi Kivity 			     "mov %ss, %bx\n\t"
683231b4c3bSRoman Bolshakov 			     "popw %ss\n\t"
6847d36db35SAvi Kivity 			);
685231b4c3bSRoman Bolshakov 	MK_INSN(push_pop_fs, "pushl %fs\n\t"
6867d36db35SAvi Kivity 			     "pushl %eax\n\t"
6877d36db35SAvi Kivity 			     "popl %fs\n\t"
6887d36db35SAvi Kivity 			     "mov %fs, %ebx\n\t"
689231b4c3bSRoman Bolshakov 			     "popl %fs\n\t"
6907d36db35SAvi Kivity 			);
69109b657b6SAvi Kivity 	MK_INSN(push_pop_high_esp_bits,
69209b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
69309b657b6SAvi Kivity 		"push %ax; \n\t"
69409b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
69509b657b6SAvi Kivity 		"pop %bx");
6967d36db35SAvi Kivity 
697bd62e289SBill Wendling 	init_inregs(NULL);
69818253fdeSAvi Kivity 
69918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push32);
7006055ea1fSAvi Kivity 	report("push/pop 1", R_AX|R_BX,
7016055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x12345678);
7027d36db35SAvi Kivity 
70318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push16);
7046055ea1fSAvi Kivity 	report("push/pop 2", R_AX|R_BX,
7056055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x1234);
7067d36db35SAvi Kivity 
70718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_es);
7086055ea1fSAvi Kivity 	report("push/pop 3", R_AX|R_BX,
7096055ea1fSAvi Kivity 	       outregs.ebx == outregs.eax && outregs.eax == 0x123);
7107d36db35SAvi Kivity 
71118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pop_es);
7126055ea1fSAvi Kivity 	report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax);
7137d36db35SAvi Kivity 
71418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_ss);
7156055ea1fSAvi Kivity 	report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax);
7167d36db35SAvi Kivity 
71718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_fs);
7186055ea1fSAvi Kivity 	report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax);
71909b657b6SAvi Kivity 
72009b657b6SAvi Kivity 	inregs.eax = 0x9977;
72109b657b6SAvi Kivity 	inregs.ebx = 0x7799;
72209b657b6SAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_high_esp_bits);
72309b657b6SAvi Kivity 	report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977);
7247d36db35SAvi Kivity }
7257d36db35SAvi Kivity 
test_null(void)7262e3f9f1fSThomas Huth static void test_null(void)
7277d36db35SAvi Kivity {
728d4dc402cSAvi Kivity 	MK_INSN(null, "");
729d4dc402cSAvi Kivity 
730bd62e289SBill Wendling 	init_inregs(NULL);
73118253fdeSAvi Kivity 
73218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_null);
7336055ea1fSAvi Kivity 	report("null", 0, 1);
7347d36db35SAvi Kivity }
7357d36db35SAvi Kivity 
test_pusha_popa(void)7362e3f9f1fSThomas Huth static void test_pusha_popa(void)
7377d36db35SAvi Kivity {
7382616ad93SRoman Bolshakov 	MK_INSN(pusha, "pushal\n\t"
7392616ad93SRoman Bolshakov 		       "popl %edi\n\t"
7402616ad93SRoman Bolshakov 		       "popl %esi\n\t"
7412616ad93SRoman Bolshakov 		       "popl %ebp\n\t"
7422616ad93SRoman Bolshakov 		       "addl $4, %esp\n\t"
7432616ad93SRoman Bolshakov 		       "popl %ebx\n\t"
7442616ad93SRoman Bolshakov 		       "popl %edx\n\t"
7452616ad93SRoman Bolshakov 		       "popl %ecx\n\t"
7462616ad93SRoman Bolshakov 		       "popl %eax\n\t"
7477d36db35SAvi Kivity 		       );
7487d36db35SAvi Kivity 
7492616ad93SRoman Bolshakov 	MK_INSN(popa, "pushl %eax\n\t"
7502616ad93SRoman Bolshakov 		      "pushl %ecx\n\t"
7512616ad93SRoman Bolshakov 		      "pushl %edx\n\t"
7522616ad93SRoman Bolshakov 		      "pushl %ebx\n\t"
7532616ad93SRoman Bolshakov 		      "pushl %esp\n\t"
7542616ad93SRoman Bolshakov 		      "pushl %ebp\n\t"
7552616ad93SRoman Bolshakov 		      "pushl %esi\n\t"
7562616ad93SRoman Bolshakov 		      "pushl %edi\n\t"
7572616ad93SRoman Bolshakov 		      "popal\n\t"
7587d36db35SAvi Kivity 		      );
7597d36db35SAvi Kivity 
760bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6 });
7617d36db35SAvi Kivity 
76218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pusha);
7636055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
76418253fdeSAvi Kivity 
76518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_popa);
7666055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
7677d36db35SAvi Kivity }
7687d36db35SAvi Kivity 
test_iret(void)7692e3f9f1fSThomas Huth static void test_iret(void)
7707d36db35SAvi Kivity {
7712616ad93SRoman Bolshakov 	MK_INSN(iret32, "pushfl\n\t"
7727d36db35SAvi Kivity 			"pushl %cs\n\t"
7732616ad93SRoman Bolshakov 			"calll 1f\n\t" /* a near call will push eip onto the stack */
7747d36db35SAvi Kivity 			"jmp 2f\n\t"
775231b4c3bSRoman Bolshakov 			"1: iretl\n\t"
7767d36db35SAvi Kivity 			"2:\n\t"
7777d36db35SAvi Kivity 		     );
7787d36db35SAvi Kivity 
7797d36db35SAvi Kivity 	MK_INSN(iret16, "pushfw\n\t"
7807d36db35SAvi Kivity 			"pushw %cs\n\t"
7817d36db35SAvi Kivity 			"callw 1f\n\t"
7827d36db35SAvi Kivity 			"jmp 2f\n\t"
7837d36db35SAvi Kivity 			"1: iretw\n\t"
7847d36db35SAvi Kivity 			"2:\n\t");
7857d36db35SAvi Kivity 
7867d36db35SAvi Kivity 	MK_INSN(iret_flags32, "pushfl\n\t"
7877d36db35SAvi Kivity 			      "popl %eax\n\t"
7887d36db35SAvi Kivity 			      "andl $~0x2, %eax\n\t"
789964942e8SNadav Amit 			      "orl $0xffc18028, %eax\n\t"
7907d36db35SAvi Kivity 			      "pushl %eax\n\t"
7917d36db35SAvi Kivity 			      "pushl %cs\n\t"
7922616ad93SRoman Bolshakov 			      "calll 1f\n\t"
7937d36db35SAvi Kivity 			      "jmp 2f\n\t"
794231b4c3bSRoman Bolshakov 			      "1: iretl\n\t"
7957d36db35SAvi Kivity 			      "2:\n\t");
7967d36db35SAvi Kivity 
7977d36db35SAvi Kivity 	MK_INSN(iret_flags16, "pushfw\n\t"
7987d36db35SAvi Kivity 			      "popw %ax\n\t"
7997d36db35SAvi Kivity 			      "and $~0x2, %ax\n\t"
8007d36db35SAvi Kivity 			      "or $0x8028, %ax\n\t"
8017d36db35SAvi Kivity 			      "pushw %ax\n\t"
8027d36db35SAvi Kivity 			      "pushw %cs\n\t"
8037d36db35SAvi Kivity 			      "callw 1f\n\t"
8047d36db35SAvi Kivity 			      "jmp 2f\n\t"
8057d36db35SAvi Kivity 			      "1: iretw\n\t"
8067d36db35SAvi Kivity 			      "2:\n\t");
8077d36db35SAvi Kivity 
808bd62e289SBill Wendling 	init_inregs(NULL);
8097d36db35SAvi Kivity 
81018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret32);
8116055ea1fSAvi Kivity 	report("iret 1", 0, 1);
8127d36db35SAvi Kivity 
81318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret16);
8146055ea1fSAvi Kivity 	report("iret 2", 0, 1);
8157d36db35SAvi Kivity 
81618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags32);
8176055ea1fSAvi Kivity 	report("iret 3", R_AX, 1);
818964942e8SNadav Amit 	report("rflags.rf", ~0, !(outregs.eflags & (1 << 16)));
81918253fdeSAvi Kivity 
82018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags16);
8216055ea1fSAvi Kivity 	report("iret 4", R_AX, 1);
8227d36db35SAvi Kivity }
8237d36db35SAvi Kivity 
test_int(void)8242e3f9f1fSThomas Huth static void test_int(void)
82596b9ca1eSMohammed Gamal {
826bd62e289SBill Wendling 	init_inregs(NULL);
82796b9ca1eSMohammed Gamal 
82896b9ca1eSMohammed Gamal 	*(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */
82996b9ca1eSMohammed Gamal 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
83096b9ca1eSMohammed Gamal 
83196b9ca1eSMohammed Gamal 	MK_INSN(int11, "int $0x11\n\t");
83296b9ca1eSMohammed Gamal 
83318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_int11);
8346055ea1fSAvi Kivity 	report("int 1", 0, 1);
83596b9ca1eSMohammed Gamal }
83696b9ca1eSMohammed Gamal 
test_sti_inhibit(void)8378202cf84SRoman Bolshakov static void test_sti_inhibit(void)
8388202cf84SRoman Bolshakov {
8398202cf84SRoman Bolshakov 	init_inregs(NULL);
8408202cf84SRoman Bolshakov 
8418202cf84SRoman Bolshakov 	*(u32 *)(0x73 * 4) = 0x1000; /* Store IRQ 11 handler in the IDT */
8428202cf84SRoman Bolshakov 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
8438202cf84SRoman Bolshakov 
8448202cf84SRoman Bolshakov 	MK_INSN(sti_inhibit, "cli\n\t"
8458202cf84SRoman Bolshakov 			     "movw $0x200b, %dx\n\t"
8468202cf84SRoman Bolshakov 			     "movl $1, %eax\n\t"
8478202cf84SRoman Bolshakov 			     "outl %eax, %dx\n\t" /* Set IRQ11 */
8488202cf84SRoman Bolshakov 			     "movl $0, %eax\n\t"
8498202cf84SRoman Bolshakov 			     "outl %eax, %dx\n\t" /* Clear IRQ11 */
8508202cf84SRoman Bolshakov 			     "sti\n\t"
8518202cf84SRoman Bolshakov 			     "hlt\n\t");
8528202cf84SRoman Bolshakov 	exec_in_big_real_mode(&insn_sti_inhibit);
8538202cf84SRoman Bolshakov 
8548202cf84SRoman Bolshakov 	report("sti inhibit", ~0, 1);
8558202cf84SRoman Bolshakov }
8568202cf84SRoman Bolshakov 
test_imul(void)8572e3f9f1fSThomas Huth static void test_imul(void)
858fa74f8a6SMohammed Gamal {
859fa74f8a6SMohammed Gamal 	MK_INSN(imul8_1, "mov $2, %al\n\t"
860fa74f8a6SMohammed Gamal 			"mov $-4, %cx\n\t"
861fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
862fa74f8a6SMohammed Gamal 
863fa74f8a6SMohammed Gamal 	MK_INSN(imul16_1, "mov $2, %ax\n\t"
864fa74f8a6SMohammed Gamal 		      "mov $-4, %cx\n\t"
865fa74f8a6SMohammed Gamal 		      "imul %cx\n\t");
866fa74f8a6SMohammed Gamal 
867fa74f8a6SMohammed Gamal 	MK_INSN(imul32_1, "mov $2, %eax\n\t"
868fa74f8a6SMohammed Gamal 		       "mov $-4, %ecx\n\t"
869fa74f8a6SMohammed Gamal 		       "imul %ecx\n\t");
870fa74f8a6SMohammed Gamal 
871fa74f8a6SMohammed Gamal 	MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t"
872fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
873fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
874fa74f8a6SMohammed Gamal 
875fa74f8a6SMohammed Gamal 	MK_INSN(imul16_2, "mov $2, %ax\n\t"
876fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
877fa74f8a6SMohammed Gamal 			"imul %cx\n\t");
878fa74f8a6SMohammed Gamal 
879fa74f8a6SMohammed Gamal 	MK_INSN(imul32_2, "mov $2, %eax\n\t"
880fa74f8a6SMohammed Gamal 			"mov $4, %ecx\n\t"
881fa74f8a6SMohammed Gamal 			"imul %ecx\n\t");
882fa74f8a6SMohammed Gamal 
883bd62e289SBill Wendling 	init_inregs(NULL);
88418253fdeSAvi Kivity 
88518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_1);
8866055ea1fSAvi Kivity 	report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8);
887fa74f8a6SMohammed Gamal 
88818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_1);
8896055ea1fSAvi Kivity 	report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8);
890fa74f8a6SMohammed Gamal 
89118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_1);
8926055ea1fSAvi Kivity 	report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8);
893fa74f8a6SMohammed Gamal 
89418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_2);
8956055ea1fSAvi Kivity 	report("imul 4", R_AX | R_CX | R_DX,
8966055ea1fSAvi Kivity 	       (outregs.eax & 0xffff) == 8
89781050840SAvi Kivity 	       && (outregs.eax & 0xffff0000) == 0x12340000);
898fa74f8a6SMohammed Gamal 
89918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_2);
9006055ea1fSAvi Kivity 	report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8);
901fa74f8a6SMohammed Gamal 
90218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_2);
9036055ea1fSAvi Kivity 	report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8);
904fa74f8a6SMohammed Gamal }
905fa74f8a6SMohammed Gamal 
test_mul(void)9062e3f9f1fSThomas Huth static void test_mul(void)
90759317bd1SMohammed Gamal {
90859317bd1SMohammed Gamal 	MK_INSN(mul8, "mov $2, %al\n\t"
90959317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
91059317bd1SMohammed Gamal 			"imul %cl\n\t");
91159317bd1SMohammed Gamal 
91259317bd1SMohammed Gamal 	MK_INSN(mul16, "mov $2, %ax\n\t"
91359317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
91459317bd1SMohammed Gamal 			"imul %cx\n\t");
91559317bd1SMohammed Gamal 
91659317bd1SMohammed Gamal 	MK_INSN(mul32, "mov $2, %eax\n\t"
91759317bd1SMohammed Gamal 			"mov $4, %ecx\n\t"
91859317bd1SMohammed Gamal 			"imul %ecx\n\t");
91959317bd1SMohammed Gamal 
920bd62e289SBill Wendling 	init_inregs(NULL);
92118253fdeSAvi Kivity 
92218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul8);
9236055ea1fSAvi Kivity 	report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8);
92459317bd1SMohammed Gamal 
92518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul16);
9266055ea1fSAvi Kivity 	report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8);
92759317bd1SMohammed Gamal 
92818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul32);
9296055ea1fSAvi Kivity 	report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8);
93059317bd1SMohammed Gamal }
93159317bd1SMohammed Gamal 
test_div(void)9322e3f9f1fSThomas Huth static void test_div(void)
9330d4c7614SMohammed Gamal {
9340d4c7614SMohammed Gamal 	MK_INSN(div8, "mov $257, %ax\n\t"
9350d4c7614SMohammed Gamal 			"mov $2, %cl\n\t"
9360d4c7614SMohammed Gamal 			"div %cl\n\t");
9370d4c7614SMohammed Gamal 
9380d4c7614SMohammed Gamal 	MK_INSN(div16, "mov $512, %ax\n\t"
9390d4c7614SMohammed Gamal 			"mov $5, %cx\n\t"
9400d4c7614SMohammed Gamal 			"div %cx\n\t");
9410d4c7614SMohammed Gamal 
9420d4c7614SMohammed Gamal 	MK_INSN(div32, "mov $512, %eax\n\t"
9430d4c7614SMohammed Gamal 			"mov $5, %ecx\n\t"
9440d4c7614SMohammed Gamal 			"div %ecx\n\t");
9450d4c7614SMohammed Gamal 
946bd62e289SBill Wendling 	init_inregs(NULL);
94718253fdeSAvi Kivity 
94818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div8);
9496055ea1fSAvi Kivity 	report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384);
9500d4c7614SMohammed Gamal 
95118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div16);
9526055ea1fSAvi Kivity 	report("div 2", R_AX | R_CX | R_DX,
9536055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
9540d4c7614SMohammed Gamal 
95518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div32);
9566055ea1fSAvi Kivity 	report("div 3", R_AX | R_CX | R_DX,
9576055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
9580d4c7614SMohammed Gamal }
9590d4c7614SMohammed Gamal 
test_idiv(void)9602e3f9f1fSThomas Huth static void test_idiv(void)
9610d4c7614SMohammed Gamal {
9620d4c7614SMohammed Gamal 	MK_INSN(idiv8, "mov $256, %ax\n\t"
9630d4c7614SMohammed Gamal 			"mov $-2, %cl\n\t"
9640d4c7614SMohammed Gamal 			"idiv %cl\n\t");
9650d4c7614SMohammed Gamal 
9660d4c7614SMohammed Gamal 	MK_INSN(idiv16, "mov $512, %ax\n\t"
9670d4c7614SMohammed Gamal 			"mov $-2, %cx\n\t"
9680d4c7614SMohammed Gamal 			"idiv %cx\n\t");
9690d4c7614SMohammed Gamal 
9700d4c7614SMohammed Gamal 	MK_INSN(idiv32, "mov $512, %eax\n\t"
9710d4c7614SMohammed Gamal 			"mov $-2, %ecx\n\t"
9720d4c7614SMohammed Gamal 			"idiv %ecx\n\t");
9730d4c7614SMohammed Gamal 
974bd62e289SBill Wendling 	init_inregs(NULL);
97518253fdeSAvi Kivity 
97618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv8);
9776055ea1fSAvi Kivity 	report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128);
9780d4c7614SMohammed Gamal 
97918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv16);
9806055ea1fSAvi Kivity 	report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256);
9810d4c7614SMohammed Gamal 
98218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv32);
9836055ea1fSAvi Kivity 	report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256);
9840d4c7614SMohammed Gamal }
9850d4c7614SMohammed Gamal 
test_cbw(void)9862e3f9f1fSThomas Huth static void test_cbw(void)
9876e293cf5SWei Yongjun {
9886e293cf5SWei Yongjun 	MK_INSN(cbw, "mov $0xFE, %eax \n\t"
9896e293cf5SWei Yongjun 		     "cbw\n\t");
9906e293cf5SWei Yongjun 	MK_INSN(cwde, "mov $0xFFFE, %eax \n\t"
9916e293cf5SWei Yongjun 		      "cwde\n\t");
9926e293cf5SWei Yongjun 
993bd62e289SBill Wendling 	init_inregs(NULL);
99418253fdeSAvi Kivity 
99518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cbw);
9966055ea1fSAvi Kivity 	report("cbq 1", ~0, outregs.eax == 0xFFFE);
9976e293cf5SWei Yongjun 
99818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwde);
9996055ea1fSAvi Kivity 	report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE);
10006e293cf5SWei Yongjun }
10016e293cf5SWei Yongjun 
test_loopcc(void)10022e3f9f1fSThomas Huth static void test_loopcc(void)
1003eacef4e2SWei Yongjun {
1004eacef4e2SWei Yongjun 	MK_INSN(loop, "mov $10, %ecx\n\t"
1005eacef4e2SWei Yongjun 		      "1: inc %eax\n\t"
1006eacef4e2SWei Yongjun 		      "loop 1b\n\t");
1007eacef4e2SWei Yongjun 
1008eacef4e2SWei Yongjun 	MK_INSN(loope, "mov $10, %ecx\n\t"
1009eacef4e2SWei Yongjun 		       "mov $1, %eax\n\t"
1010eacef4e2SWei Yongjun 		       "1: dec %eax\n\t"
1011eacef4e2SWei Yongjun 		       "loope 1b\n\t");
1012eacef4e2SWei Yongjun 
1013eacef4e2SWei Yongjun 	MK_INSN(loopne, "mov $10, %ecx\n\t"
1014eacef4e2SWei Yongjun 		        "mov $5, %eax\n\t"
1015eacef4e2SWei Yongjun 		        "1: dec %eax\n\t"
1016eacef4e2SWei Yongjun 			"loopne 1b\n\t");
1017eacef4e2SWei Yongjun 
1018bd62e289SBill Wendling 	init_inregs(NULL);
1019eacef4e2SWei Yongjun 
102018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loop);
10216055ea1fSAvi Kivity 	report("LOOPcc short 1", R_AX, outregs.eax == 10);
102218253fdeSAvi Kivity 
102318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loope);
10246055ea1fSAvi Kivity 	report("LOOPcc short 2", R_AX | R_CX,
10256055ea1fSAvi Kivity 	       outregs.eax == -1 && outregs.ecx == 8);
1026eacef4e2SWei Yongjun 
102718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loopne);
10286055ea1fSAvi Kivity 	report("LOOPcc short 3", R_AX | R_CX,
10296055ea1fSAvi Kivity 	       outregs.eax == 0 && outregs.ecx == 5);
1030eacef4e2SWei Yongjun }
1031eacef4e2SWei Yongjun 
test_das(void)1032b274feedSAvi Kivity static void test_das(void)
1033b274feedSAvi Kivity {
1034b274feedSAvi Kivity     short i;
103581050840SAvi Kivity     u16 nr_fail = 0;
1036b274feedSAvi Kivity     static unsigned test_cases[1024] = {
1037b274feedSAvi Kivity         0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00,
1038b274feedSAvi Kivity         0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01,
1039b274feedSAvi Kivity         0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02,
1040b274feedSAvi Kivity         0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03,
1041b274feedSAvi Kivity         0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04,
1042b274feedSAvi Kivity         0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05,
1043b274feedSAvi Kivity         0x06000606, 0x8701a606, 0x56100006, 0x9711a006,
1044b274feedSAvi Kivity         0x02000707, 0x8301a707, 0x12100107, 0x9311a107,
1045b274feedSAvi Kivity         0x02000808, 0x8301a808, 0x12100208, 0x9311a208,
1046b274feedSAvi Kivity         0x06000909, 0x8701a909, 0x16100309, 0x9711a309,
1047b274feedSAvi Kivity         0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a,
1048b274feedSAvi Kivity         0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b,
1049b274feedSAvi Kivity         0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c,
1050b274feedSAvi Kivity         0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d,
1051b274feedSAvi Kivity         0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e,
1052b274feedSAvi Kivity         0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f,
1053b274feedSAvi Kivity         0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10,
1054b274feedSAvi Kivity         0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11,
1055b274feedSAvi Kivity         0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12,
1056b274feedSAvi Kivity         0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13,
1057b274feedSAvi Kivity         0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14,
1058b274feedSAvi Kivity         0x02001515, 0x8301b515, 0x16100f15, 0x9711af15,
1059b274feedSAvi Kivity         0x02001616, 0x8301b616, 0x12101016, 0x9311b016,
1060b274feedSAvi Kivity         0x06001717, 0x8701b717, 0x16101117, 0x9711b117,
1061b274feedSAvi Kivity         0x06001818, 0x8701b818, 0x16101218, 0x9711b218,
1062b274feedSAvi Kivity         0x02001919, 0x8301b919, 0x12101319, 0x9311b319,
1063b274feedSAvi Kivity         0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a,
1064b274feedSAvi Kivity         0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b,
1065b274feedSAvi Kivity         0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c,
1066b274feedSAvi Kivity         0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d,
1067b274feedSAvi Kivity         0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e,
1068b274feedSAvi Kivity         0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f,
1069b274feedSAvi Kivity         0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20,
1070b274feedSAvi Kivity         0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21,
1071b274feedSAvi Kivity         0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22,
1072b274feedSAvi Kivity         0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23,
1073b274feedSAvi Kivity         0x06002424, 0x8301c424, 0x16101e24, 0x9711be24,
1074b274feedSAvi Kivity         0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25,
1075b274feedSAvi Kivity         0x02002626, 0x8701c626, 0x12102026, 0x9711c026,
1076b274feedSAvi Kivity         0x06002727, 0x8301c727, 0x16102127, 0x9311c127,
1077b274feedSAvi Kivity         0x06002828, 0x8301c828, 0x16102228, 0x9311c228,
1078b274feedSAvi Kivity         0x02002929, 0x8701c929, 0x12102329, 0x9711c329,
1079b274feedSAvi Kivity         0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a,
1080b274feedSAvi Kivity         0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b,
1081b274feedSAvi Kivity         0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c,
1082b274feedSAvi Kivity         0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d,
1083b274feedSAvi Kivity         0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e,
1084b274feedSAvi Kivity         0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f,
1085b274feedSAvi Kivity         0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30,
1086b274feedSAvi Kivity         0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31,
1087b274feedSAvi Kivity         0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32,
1088b274feedSAvi Kivity         0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33,
1089b274feedSAvi Kivity         0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34,
1090b274feedSAvi Kivity         0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35,
1091b274feedSAvi Kivity         0x06003636, 0x8301d636, 0x16103036, 0x9311d036,
1092b274feedSAvi Kivity         0x02003737, 0x8701d737, 0x12103137, 0x9711d137,
1093b274feedSAvi Kivity         0x02003838, 0x8701d838, 0x12103238, 0x9711d238,
1094b274feedSAvi Kivity         0x06003939, 0x8301d939, 0x16103339, 0x9311d339,
1095b274feedSAvi Kivity         0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a,
1096b274feedSAvi Kivity         0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b,
1097b274feedSAvi Kivity         0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c,
1098b274feedSAvi Kivity         0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d,
1099b274feedSAvi Kivity         0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e,
1100b274feedSAvi Kivity         0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f,
1101b274feedSAvi Kivity         0x02004040, 0x8301e040, 0x16103a40, 0x9311da40,
1102b274feedSAvi Kivity         0x06004141, 0x8701e141, 0x12103b41, 0x9711db41,
1103b274feedSAvi Kivity         0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42,
1104b274feedSAvi Kivity         0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43,
1105b274feedSAvi Kivity         0x06004444, 0x8701e444, 0x12103e44, 0x9711de44,
1106b274feedSAvi Kivity         0x02004545, 0x8301e545, 0x16103f45, 0x9311df45,
1107b274feedSAvi Kivity         0x02004646, 0x8301e646, 0x12104046, 0x9311e046,
1108b274feedSAvi Kivity         0x06004747, 0x8701e747, 0x16104147, 0x9711e147,
1109b274feedSAvi Kivity         0x06004848, 0x8701e848, 0x16104248, 0x9711e248,
1110b274feedSAvi Kivity         0x02004949, 0x8301e949, 0x12104349, 0x9311e349,
1111b274feedSAvi Kivity         0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a,
1112b274feedSAvi Kivity         0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b,
1113b274feedSAvi Kivity         0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c,
1114b274feedSAvi Kivity         0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d,
1115b274feedSAvi Kivity         0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e,
1116b274feedSAvi Kivity         0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f,
1117b274feedSAvi Kivity         0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50,
1118b274feedSAvi Kivity         0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51,
1119b274feedSAvi Kivity         0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52,
1120b274feedSAvi Kivity         0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53,
1121b274feedSAvi Kivity         0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54,
1122b274feedSAvi Kivity         0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55,
1123b274feedSAvi Kivity         0x06005656, 0x8701f656, 0x16105056, 0x9711f056,
1124b274feedSAvi Kivity         0x02005757, 0x8301f757, 0x12105157, 0x9311f157,
1125b274feedSAvi Kivity         0x02005858, 0x8301f858, 0x12105258, 0x9311f258,
1126b274feedSAvi Kivity         0x06005959, 0x8701f959, 0x16105359, 0x9711f359,
1127b274feedSAvi Kivity         0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a,
1128b274feedSAvi Kivity         0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b,
1129b274feedSAvi Kivity         0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c,
1130b274feedSAvi Kivity         0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d,
1131b274feedSAvi Kivity         0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e,
1132b274feedSAvi Kivity         0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f,
1133b274feedSAvi Kivity         0x06006060, 0x47010060, 0x16105a60, 0x9711fa60,
1134b274feedSAvi Kivity         0x02006161, 0x03010161, 0x12105b61, 0x9311fb61,
1135b274feedSAvi Kivity         0x02006262, 0x03010262, 0x16105c62, 0x9711fc62,
1136b274feedSAvi Kivity         0x06006363, 0x07010363, 0x12105d63, 0x9311fd63,
1137b274feedSAvi Kivity         0x02006464, 0x03010464, 0x12105e64, 0x9311fe64,
1138b274feedSAvi Kivity         0x06006565, 0x07010565, 0x16105f65, 0x9711ff65,
1139b274feedSAvi Kivity         0x06006666, 0x07010666, 0x16106066, 0x57110066,
1140b274feedSAvi Kivity         0x02006767, 0x03010767, 0x12106167, 0x13110167,
1141b274feedSAvi Kivity         0x02006868, 0x03010868, 0x12106268, 0x13110268,
1142b274feedSAvi Kivity         0x06006969, 0x07010969, 0x16106369, 0x17110369,
1143b274feedSAvi Kivity         0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a,
1144b274feedSAvi Kivity         0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b,
1145b274feedSAvi Kivity         0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c,
1146b274feedSAvi Kivity         0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d,
1147b274feedSAvi Kivity         0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e,
1148b274feedSAvi Kivity         0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f,
1149b274feedSAvi Kivity         0x02007070, 0x03011070, 0x16106a70, 0x17110a70,
1150b274feedSAvi Kivity         0x06007171, 0x07011171, 0x12106b71, 0x13110b71,
1151b274feedSAvi Kivity         0x06007272, 0x07011272, 0x16106c72, 0x17110c72,
1152b274feedSAvi Kivity         0x02007373, 0x03011373, 0x12106d73, 0x13110d73,
1153b274feedSAvi Kivity         0x06007474, 0x07011474, 0x12106e74, 0x13110e74,
1154b274feedSAvi Kivity         0x02007575, 0x03011575, 0x16106f75, 0x17110f75,
1155b274feedSAvi Kivity         0x02007676, 0x03011676, 0x12107076, 0x13111076,
1156b274feedSAvi Kivity         0x06007777, 0x07011777, 0x16107177, 0x17111177,
1157b274feedSAvi Kivity         0x06007878, 0x07011878, 0x16107278, 0x17111278,
1158b274feedSAvi Kivity         0x02007979, 0x03011979, 0x12107379, 0x13111379,
1159b274feedSAvi Kivity         0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a,
1160b274feedSAvi Kivity         0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b,
1161b274feedSAvi Kivity         0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c,
1162b274feedSAvi Kivity         0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d,
1163b274feedSAvi Kivity         0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e,
1164b274feedSAvi Kivity         0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f,
1165b274feedSAvi Kivity         0x82008080, 0x03012080, 0x12107a80, 0x13111a80,
1166b274feedSAvi Kivity         0x86008181, 0x07012181, 0x16107b81, 0x17111b81,
1167b274feedSAvi Kivity         0x86008282, 0x07012282, 0x12107c82, 0x13111c82,
1168b274feedSAvi Kivity         0x82008383, 0x03012383, 0x16107d83, 0x17111d83,
1169b274feedSAvi Kivity         0x86008484, 0x07012484, 0x16107e84, 0x17111e84,
1170b274feedSAvi Kivity         0x82008585, 0x03012585, 0x12107f85, 0x13111f85,
1171b274feedSAvi Kivity         0x82008686, 0x03012686, 0x92108086, 0x13112086,
1172b274feedSAvi Kivity         0x86008787, 0x07012787, 0x96108187, 0x17112187,
1173b274feedSAvi Kivity         0x86008888, 0x07012888, 0x96108288, 0x17112288,
1174b274feedSAvi Kivity         0x82008989, 0x03012989, 0x92108389, 0x13112389,
1175b274feedSAvi Kivity         0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a,
1176b274feedSAvi Kivity         0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b,
1177b274feedSAvi Kivity         0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c,
1178b274feedSAvi Kivity         0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d,
1179b274feedSAvi Kivity         0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e,
1180b274feedSAvi Kivity         0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f,
1181b274feedSAvi Kivity         0x86009090, 0x07013090, 0x92108a90, 0x13112a90,
1182b274feedSAvi Kivity         0x82009191, 0x03013191, 0x96108b91, 0x17112b91,
1183b274feedSAvi Kivity         0x82009292, 0x03013292, 0x92108c92, 0x13112c92,
1184b274feedSAvi Kivity         0x86009393, 0x07013393, 0x96108d93, 0x17112d93,
1185b274feedSAvi Kivity         0x82009494, 0x03013494, 0x96108e94, 0x17112e94,
1186b274feedSAvi Kivity         0x86009595, 0x07013595, 0x92108f95, 0x13112f95,
1187b274feedSAvi Kivity         0x86009696, 0x07013696, 0x96109096, 0x17113096,
1188b274feedSAvi Kivity         0x82009797, 0x03013797, 0x92109197, 0x13113197,
1189b274feedSAvi Kivity         0x82009898, 0x03013898, 0x92109298, 0x13113298,
1190b274feedSAvi Kivity         0x86009999, 0x07013999, 0x96109399, 0x17113399,
1191b274feedSAvi Kivity         0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a,
1192b274feedSAvi Kivity         0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b,
1193b274feedSAvi Kivity         0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c,
1194b274feedSAvi Kivity         0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d,
1195b274feedSAvi Kivity         0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e,
1196b274feedSAvi Kivity         0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f,
1197b274feedSAvi Kivity         0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0,
1198b274feedSAvi Kivity         0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1,
1199b274feedSAvi Kivity         0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2,
1200b274feedSAvi Kivity         0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3,
1201b274feedSAvi Kivity         0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4,
1202b274feedSAvi Kivity         0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5,
1203b274feedSAvi Kivity         0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6,
1204b274feedSAvi Kivity         0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7,
1205b274feedSAvi Kivity         0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8,
1206b274feedSAvi Kivity         0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9,
1207b274feedSAvi Kivity         0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa,
1208b274feedSAvi Kivity         0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab,
1209b274feedSAvi Kivity         0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac,
1210b274feedSAvi Kivity         0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad,
1211b274feedSAvi Kivity         0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae,
1212b274feedSAvi Kivity         0x130049af, 0x130149af, 0x131049af, 0x131149af,
1213b274feedSAvi Kivity         0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0,
1214b274feedSAvi Kivity         0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1,
1215b274feedSAvi Kivity         0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2,
1216b274feedSAvi Kivity         0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3,
1217b274feedSAvi Kivity         0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4,
1218b274feedSAvi Kivity         0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5,
1219b274feedSAvi Kivity         0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6,
1220b274feedSAvi Kivity         0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7,
1221b274feedSAvi Kivity         0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8,
1222b274feedSAvi Kivity         0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9,
1223b274feedSAvi Kivity         0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba,
1224b274feedSAvi Kivity         0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb,
1225b274feedSAvi Kivity         0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc,
1226b274feedSAvi Kivity         0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd,
1227b274feedSAvi Kivity         0x130058be, 0x130158be, 0x131058be, 0x131158be,
1228b274feedSAvi Kivity         0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf,
1229b274feedSAvi Kivity         0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0,
1230b274feedSAvi Kivity         0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1,
1231b274feedSAvi Kivity         0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2,
1232b274feedSAvi Kivity         0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3,
1233b274feedSAvi Kivity         0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4,
1234b274feedSAvi Kivity         0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5,
1235b274feedSAvi Kivity         0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6,
1236b274feedSAvi Kivity         0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7,
1237b274feedSAvi Kivity         0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8,
1238b274feedSAvi Kivity         0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9,
1239b274feedSAvi Kivity         0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca,
1240b274feedSAvi Kivity         0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb,
1241b274feedSAvi Kivity         0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc,
1242b274feedSAvi Kivity         0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd,
1243b274feedSAvi Kivity         0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce,
1244b274feedSAvi Kivity         0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf,
1245b274feedSAvi Kivity         0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0,
1246b274feedSAvi Kivity         0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1,
1247b274feedSAvi Kivity         0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2,
1248b274feedSAvi Kivity         0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3,
1249b274feedSAvi Kivity         0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4,
1250b274feedSAvi Kivity         0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5,
1251b274feedSAvi Kivity         0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6,
1252b274feedSAvi Kivity         0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7,
1253b274feedSAvi Kivity         0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8,
1254b274feedSAvi Kivity         0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9,
1255b274feedSAvi Kivity         0x170074da, 0x170174da, 0x171074da, 0x171174da,
1256b274feedSAvi Kivity         0x130075db, 0x130175db, 0x131075db, 0x131175db,
1257b274feedSAvi Kivity         0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc,
1258b274feedSAvi Kivity         0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd,
1259b274feedSAvi Kivity         0x170078de, 0x170178de, 0x171078de, 0x171178de,
1260b274feedSAvi Kivity         0x130079df, 0x130179df, 0x131079df, 0x131179df,
1261b274feedSAvi Kivity         0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0,
1262b274feedSAvi Kivity         0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1,
1263b274feedSAvi Kivity         0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2,
1264b274feedSAvi Kivity         0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3,
1265b274feedSAvi Kivity         0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4,
1266b274feedSAvi Kivity         0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5,
1267b274feedSAvi Kivity         0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6,
1268b274feedSAvi Kivity         0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7,
1269b274feedSAvi Kivity         0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8,
1270b274feedSAvi Kivity         0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9,
1271b274feedSAvi Kivity         0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea,
1272b274feedSAvi Kivity         0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb,
1273b274feedSAvi Kivity         0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec,
1274b274feedSAvi Kivity         0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed,
1275b274feedSAvi Kivity         0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee,
1276b274feedSAvi Kivity         0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef,
1277b274feedSAvi Kivity         0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0,
1278b274feedSAvi Kivity         0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1,
1279b274feedSAvi Kivity         0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2,
1280b274feedSAvi Kivity         0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3,
1281b274feedSAvi Kivity         0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4,
1282b274feedSAvi Kivity         0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5,
1283b274feedSAvi Kivity         0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6,
1284b274feedSAvi Kivity         0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7,
1285b274feedSAvi Kivity         0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8,
1286b274feedSAvi Kivity         0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9,
1287b274feedSAvi Kivity         0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa,
1288b274feedSAvi Kivity         0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb,
1289b274feedSAvi Kivity         0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc,
1290b274feedSAvi Kivity         0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd,
1291b274feedSAvi Kivity         0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe,
1292b274feedSAvi Kivity         0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff,
1293b274feedSAvi Kivity     };
1294b274feedSAvi Kivity 
1295b274feedSAvi Kivity     MK_INSN(das, "das");
1296b274feedSAvi Kivity 
1297bd62e289SBill Wendling     init_inregs(NULL);
129818253fdeSAvi Kivity 
1299b274feedSAvi Kivity     for (i = 0; i < 1024; ++i) {
1300b274feedSAvi Kivity         unsigned tmp = test_cases[i];
1301b274feedSAvi Kivity         inregs.eax = tmp & 0xff;
1302b274feedSAvi Kivity         inregs.eflags = (tmp >> 16) & 0xff;
130318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_das);
130418253fdeSAvi Kivity 	if (!regs_equal(R_AX)
1305b274feedSAvi Kivity             || outregs.eax != ((tmp >> 8) & 0xff)
1306b274feedSAvi Kivity             || (outregs.eflags & 0xff) != (tmp >> 24)) {
130781050840SAvi Kivity 	    ++nr_fail;
130881050840SAvi Kivity 	    break;
1309b274feedSAvi Kivity         }
1310b274feedSAvi Kivity     }
13116055ea1fSAvi Kivity     report("DAS", ~0, nr_fail == 0);
1312b274feedSAvi Kivity }
1313b274feedSAvi Kivity 
test_cwd_cdq(void)13142e3f9f1fSThomas Huth static void test_cwd_cdq(void)
13150cbd5b06SMohammed Gamal {
13160cbd5b06SMohammed Gamal 	/* Sign-bit set */
13170cbd5b06SMohammed Gamal 	MK_INSN(cwd_1, "mov $0x8000, %ax\n\t"
13180cbd5b06SMohammed Gamal 		       "cwd\n\t");
13190cbd5b06SMohammed Gamal 
13200cbd5b06SMohammed Gamal 	/* Sign-bit not set */
13210cbd5b06SMohammed Gamal 	MK_INSN(cwd_2, "mov $0x1000, %ax\n\t"
13220cbd5b06SMohammed Gamal 		       "cwd\n\t");
13230cbd5b06SMohammed Gamal 
13240cbd5b06SMohammed Gamal 	/* Sign-bit set */
13250cbd5b06SMohammed Gamal 	MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t"
13260cbd5b06SMohammed Gamal 		       "cdq\n\t");
13270cbd5b06SMohammed Gamal 
13280cbd5b06SMohammed Gamal 	/* Sign-bit not set */
13290cbd5b06SMohammed Gamal 	MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t"
13300cbd5b06SMohammed Gamal 		       "cdq\n\t");
13310cbd5b06SMohammed Gamal 
1332bd62e289SBill Wendling 	init_inregs(NULL);
133318253fdeSAvi Kivity 
133418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_1);
13356055ea1fSAvi Kivity 	report("cwd 1", R_AX | R_DX,
13366055ea1fSAvi Kivity 	       outregs.eax == 0x8000 && outregs.edx == 0xffff);
13370cbd5b06SMohammed Gamal 
133818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_2);
13396055ea1fSAvi Kivity 	report("cwd 2", R_AX | R_DX,
13406055ea1fSAvi Kivity 	       outregs.eax == 0x1000 && outregs.edx == 0);
13410cbd5b06SMohammed Gamal 
134218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_1);
13436055ea1fSAvi Kivity 	report("cdq 1", R_AX | R_DX,
13446055ea1fSAvi Kivity 	       outregs.eax == 0x80000000 && outregs.edx == 0xffffffff);
13450cbd5b06SMohammed Gamal 
134618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_2);
13476055ea1fSAvi Kivity 	report("cdq 2", R_AX | R_DX,
13486055ea1fSAvi Kivity 	       outregs.eax == 0x10000000 && outregs.edx == 0);
13490cbd5b06SMohammed Gamal }
13500cbd5b06SMohammed Gamal 
135137f51a4aSWei Yongjun static struct {
135237f51a4aSWei Yongjun         void *address;
135337f51a4aSWei Yongjun         unsigned short sel;
135437f51a4aSWei Yongjun } __attribute__((packed)) desc = {
135537f51a4aSWei Yongjun 	(void *)0x1234,
135637f51a4aSWei Yongjun 	0x10,
135737f51a4aSWei Yongjun };
135837f51a4aSWei Yongjun 
test_lds_lss(void)13592e3f9f1fSThomas Huth static void test_lds_lss(void)
136037f51a4aSWei Yongjun {
1361bd62e289SBill Wendling 	init_inregs(&(struct regs){ .ebx = (unsigned long)&desc });
136237f51a4aSWei Yongjun 
1363231b4c3bSRoman Bolshakov 	MK_INSN(lds, "pushl %ds\n\t"
136437f51a4aSWei Yongjun 		     "lds (%ebx), %eax\n\t"
136537f51a4aSWei Yongjun 		     "mov %ds, %ebx\n\t"
1366231b4c3bSRoman Bolshakov 		     "popl %ds\n\t");
136737f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lds);
136837f51a4aSWei Yongjun 	report("lds", R_AX | R_BX,
136937f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
137037f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
137137f51a4aSWei Yongjun 
1372eb6687a2SBill Wendling 	MK_INSN(les, "les (%ebx), %eax\n\t"
1373eb6687a2SBill Wendling 		     "mov %es, %ebx\n\t");
137437f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_les);
137537f51a4aSWei Yongjun 	report("les", R_AX | R_BX,
137637f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
137737f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
137837f51a4aSWei Yongjun 
1379231b4c3bSRoman Bolshakov 	MK_INSN(lfs, "pushl %fs\n\t"
138037f51a4aSWei Yongjun 		     "lfs (%ebx), %eax\n\t"
138137f51a4aSWei Yongjun 		     "mov %fs, %ebx\n\t"
1382231b4c3bSRoman Bolshakov 		     "popl %fs\n\t");
138337f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lfs);
138437f51a4aSWei Yongjun 	report("lfs", R_AX | R_BX,
138537f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
138637f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
138737f51a4aSWei Yongjun 
1388231b4c3bSRoman Bolshakov 	MK_INSN(lgs, "pushl %gs\n\t"
138937f51a4aSWei Yongjun 		     "lgs (%ebx), %eax\n\t"
139037f51a4aSWei Yongjun 		     "mov %gs, %ebx\n\t"
1391231b4c3bSRoman Bolshakov 		     "popl %gs\n\t");
139237f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lgs);
139337f51a4aSWei Yongjun 	report("lgs", R_AX | R_BX,
139437f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
139537f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
139637f51a4aSWei Yongjun 
1397d7903be6SNadav Amit 	MK_INSN(lss, "mov %ss, %dx\n\t"
139837f51a4aSWei Yongjun 		     "lss (%ebx), %eax\n\t"
139937f51a4aSWei Yongjun 		     "mov %ss, %ebx\n\t"
1400d7903be6SNadav Amit 		     "mov %dx, %ss\n\t");
140137f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lss);
140237f51a4aSWei Yongjun 	report("lss", R_AX | R_BX,
140337f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
140437f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
140537f51a4aSWei Yongjun }
140637f51a4aSWei Yongjun 
test_jcxz(void)14072e3f9f1fSThomas Huth static void test_jcxz(void)
1408b1c7c575SWei Yongjun {
1409b1c7c575SWei Yongjun 	MK_INSN(jcxz1, "jcxz 1f\n\t"
1410b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1411b1c7c575SWei Yongjun 		       "1:\n\t");
1412b1c7c575SWei Yongjun 	MK_INSN(jcxz2, "mov $0x100, %ecx\n\t"
1413b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1414b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1415b1c7c575SWei Yongjun 		       "mov $0, %ecx\n\t"
1416b1c7c575SWei Yongjun 		       "1:\n\t");
1417b1c7c575SWei Yongjun 	MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t"
1418b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1419b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1420b1c7c575SWei Yongjun 		       "1:\n\t");
1421b1c7c575SWei Yongjun 	MK_INSN(jecxz1, "jecxz 1f\n\t"
1422b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1423b1c7c575SWei Yongjun 			"1:\n\t");
1424b1c7c575SWei Yongjun 	MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t"
1425b1c7c575SWei Yongjun 			"jecxz 1f\n\t"
1426b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1427b1c7c575SWei Yongjun 			"mov $0, %ecx\n\t"
1428b1c7c575SWei Yongjun 			"1:\n\t");
1429b1c7c575SWei Yongjun 
1430bd62e289SBill Wendling 	init_inregs(NULL);
1431b1c7c575SWei Yongjun 
1432b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz1);
1433b1c7c575SWei Yongjun 	report("jcxz short 1", 0, 1);
1434b1c7c575SWei Yongjun 
1435b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz2);
1436b1c7c575SWei Yongjun 	report("jcxz short 2", R_AX, outregs.eax == 0x1234);
1437b1c7c575SWei Yongjun 
1438b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz3);
1439b1c7c575SWei Yongjun 	report("jcxz short 3", R_CX, outregs.ecx == 0x10000);
1440b1c7c575SWei Yongjun 
1441b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz1);
1442b1c7c575SWei Yongjun 	report("jecxz short 1", 0, 1);
1443b1c7c575SWei Yongjun 
1444b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz2);
1445b1c7c575SWei Yongjun 	report("jecxz short 2", R_AX, outregs.eax == 0x1234);
1446b1c7c575SWei Yongjun }
1447b1c7c575SWei Yongjun 
test_cpuid(void)14488f578e98SAvi Kivity static void test_cpuid(void)
14498f578e98SAvi Kivity {
14508f578e98SAvi Kivity     MK_INSN(cpuid, "cpuid");
14518f578e98SAvi Kivity     unsigned function = 0x1234;
14528f578e98SAvi Kivity     unsigned eax, ebx, ecx, edx;
14538f578e98SAvi Kivity 
1454bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = function });
1455bd62e289SBill Wendling 
1456bd62e289SBill Wendling     eax = inregs.eax;
1457bd62e289SBill Wendling     ecx = inregs.ecx;
1458674d2dbeSPaolo Bonzini     asm("cpuid" : "+a"(eax), "=b"(ebx), "+c"(ecx), "=d"(edx));
14598f578e98SAvi Kivity     exec_in_big_real_mode(&insn_cpuid);
14608f578e98SAvi Kivity     report("cpuid", R_AX|R_BX|R_CX|R_DX,
14618f578e98SAvi Kivity 	   outregs.eax == eax && outregs.ebx == ebx
14628f578e98SAvi Kivity 	   && outregs.ecx == ecx && outregs.edx == edx);
14638f578e98SAvi Kivity }
14648f578e98SAvi Kivity 
test_ss_base_for_esp_ebp(void)1465ed93f43bSAvi Kivity static void test_ss_base_for_esp_ebp(void)
1466ed93f43bSAvi Kivity {
1467ed93f43bSAvi Kivity     MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss");
1468ed93f43bSAvi Kivity     MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss");
1469ed93f43bSAvi Kivity     static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 };
1470ed93f43bSAvi Kivity 
1471bd62e289SBill Wendling     init_inregs(&(struct regs){ .ebx = 1, .ebp = (unsigned)array });
1472bd62e289SBill Wendling 
1473ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel1);
1474ed93f43bSAvi Kivity     report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321);
1475bd62e289SBill Wendling 
1476ed93f43bSAvi Kivity     inregs.ebx = 1;
1477ed93f43bSAvi Kivity     inregs.ebp = (unsigned)array;
1478ed93f43bSAvi Kivity     inregs.edi = 0;
1479ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel2);
1480ed93f43bSAvi Kivity     report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321);
1481ed93f43bSAvi Kivity }
1482ed93f43bSAvi Kivity 
1483975ca087SPeter Feiner extern unsigned long long r_gdt[];
1484975ca087SPeter Feiner 
test_sgdt_sidt(void)1485c2281fa4SAvi Kivity static void test_sgdt_sidt(void)
1486c2281fa4SAvi Kivity {
1487c2281fa4SAvi Kivity     MK_INSN(sgdt, "sgdtw (%eax)");
1488c2281fa4SAvi Kivity     MK_INSN(sidt, "sidtw (%eax)");
1489975ca087SPeter Feiner     struct table_descr x, y;
1490c2281fa4SAvi Kivity 
1491bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = (unsigned)&y });
1492bd62e289SBill Wendling 
1493c2281fa4SAvi Kivity     asm volatile("sgdtw %0" : "=m"(x));
1494c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sgdt);
1495975ca087SPeter Feiner     report("sgdt", 0, x.limit == y.limit && x.base == y.base);
1496c2281fa4SAvi Kivity 
1497c2281fa4SAvi Kivity     inregs.eax = (unsigned)&y;
1498c2281fa4SAvi Kivity     asm volatile("sidtw %0" : "=m"(x));
1499c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sidt);
1500975ca087SPeter Feiner     report("sidt", 0, x.limit == y.limit && x.base == y.base);
1501c2281fa4SAvi Kivity }
1502c2281fa4SAvi Kivity 
test_sahf(void)150388b6dac4SPaolo Bonzini static void test_sahf(void)
150488b6dac4SPaolo Bonzini {
150588b6dac4SPaolo Bonzini     MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw");
150688b6dac4SPaolo Bonzini 
1507bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0xfd00 });
1508bd62e289SBill Wendling 
150988b6dac4SPaolo Bonzini     exec_in_big_real_mode(&insn_sahf);
151088b6dac4SPaolo Bonzini     report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7));
151188b6dac4SPaolo Bonzini }
151288b6dac4SPaolo Bonzini 
test_lahf(void)15137ae3645aSAvi Kivity static void test_lahf(void)
15147ae3645aSAvi Kivity {
15157ae3645aSAvi Kivity     MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf");
15167ae3645aSAvi Kivity 
1517bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0xc7 });
1518bd62e289SBill Wendling 
15197ae3645aSAvi Kivity     exec_in_big_real_mode(&insn_lahf);
15207ae3645aSAvi Kivity     report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax);
15217ae3645aSAvi Kivity }
15227ae3645aSAvi Kivity 
test_movzx_movsx(void)1523fd9ea640SAvi Kivity static void test_movzx_movsx(void)
1524fd9ea640SAvi Kivity {
1525fd9ea640SAvi Kivity     MK_INSN(movsx, "movsx %al, %ebx");
1526fd9ea640SAvi Kivity     MK_INSN(movzx, "movzx %al, %ebx");
15273013e079SGleb Natapov     MK_INSN(movzsah, "movsx %ah, %ebx");
15283013e079SGleb Natapov     MK_INSN(movzxah, "movzx %ah, %ebx");
1529fd9ea640SAvi Kivity 
1530bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x1234569c });
1531bd62e289SBill Wendling 
1532fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movsx);
1533fd9ea640SAvi Kivity     report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax);
1534fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movzx);
1535fd9ea640SAvi Kivity     report("movzx", R_BX, outregs.ebx == (unsigned char)inregs.eax);
15363013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzsah);
15373013e079SGleb Natapov     report("movsx ah", R_BX, outregs.ebx == (signed char)(inregs.eax>>8));
15383013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzxah);
15393013e079SGleb Natapov     report("movzx ah", R_BX, outregs.ebx == (unsigned char)(inregs.eax >> 8));
1540fd9ea640SAvi Kivity }
1541fd9ea640SAvi Kivity 
test_bswap(void)1542b493b2e8SAvi Kivity static void test_bswap(void)
1543b493b2e8SAvi Kivity {
1544b493b2e8SAvi Kivity     MK_INSN(bswap, "bswap %ecx");
1545b493b2e8SAvi Kivity 
1546bd62e289SBill Wendling     init_inregs(&(struct regs){ .ecx = 0x12345678 });
1547bd62e289SBill Wendling 
1548b493b2e8SAvi Kivity     exec_in_big_real_mode(&insn_bswap);
1549b493b2e8SAvi Kivity     report("bswap", R_CX, outregs.ecx == 0x78563412);
1550b493b2e8SAvi Kivity }
1551b493b2e8SAvi Kivity 
test_aad(void)15528cd86387SGleb Natapov static void test_aad(void)
15538cd86387SGleb Natapov {
15548cd86387SGleb Natapov     MK_INSN(aad, "aad");
15558cd86387SGleb Natapov 
1556bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x12345678 });
1557bd62e289SBill Wendling 
15588cd86387SGleb Natapov     exec_in_big_real_mode(&insn_aad);
15598cd86387SGleb Natapov     report("aad", R_AX, outregs.eax == 0x123400d4);
15608cd86387SGleb Natapov }
15618cd86387SGleb Natapov 
test_aam(void)15622a9b5718SPaolo Bonzini static void test_aam(void)
15632a9b5718SPaolo Bonzini {
15642a9b5718SPaolo Bonzini     MK_INSN(aam, "aam");
15652a9b5718SPaolo Bonzini 
1566bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x76543210 });
1567bd62e289SBill Wendling 
15682a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_aam);
15692a9b5718SPaolo Bonzini     report("aam", R_AX, outregs.eax == 0x76540106);
15702a9b5718SPaolo Bonzini }
15712a9b5718SPaolo Bonzini 
test_xlat(void)15722a9b5718SPaolo Bonzini static void test_xlat(void)
15732a9b5718SPaolo Bonzini {
15742a9b5718SPaolo Bonzini     MK_INSN(xlat, "xlat");
15752a9b5718SPaolo Bonzini     u8 table[256];
15762a9b5718SPaolo Bonzini     int i;
15772a9b5718SPaolo Bonzini 
15782a9b5718SPaolo Bonzini     for (i = 0; i < 256; i++) {
15792a9b5718SPaolo Bonzini         table[i] = i + 1;
15802a9b5718SPaolo Bonzini     }
15812a9b5718SPaolo Bonzini 
1582bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x89abcdef, .ebx = (u32)table });
1583bd62e289SBill Wendling 
15842a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_xlat);
15852a9b5718SPaolo Bonzini     report("xlat", R_AX, outregs.eax == 0x89abcdf0);
15862a9b5718SPaolo Bonzini }
15872a9b5718SPaolo Bonzini 
test_salc(void)15882a9b5718SPaolo Bonzini static void test_salc(void)
15892a9b5718SPaolo Bonzini {
15902a9b5718SPaolo Bonzini     MK_INSN(clc_salc, "clc; .byte 0xd6");
15912a9b5718SPaolo Bonzini     MK_INSN(stc_salc, "stc; .byte 0xd6");
15922a9b5718SPaolo Bonzini 
1593bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x12345678 });
1594bd62e289SBill Wendling 
15952a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_clc_salc);
15962a9b5718SPaolo Bonzini     report("salc (1)", R_AX, outregs.eax == 0x12345600);
15972a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_stc_salc);
15982a9b5718SPaolo Bonzini     report("salc (2)", R_AX, outregs.eax == 0x123456ff);
15992a9b5718SPaolo Bonzini }
16002a9b5718SPaolo Bonzini 
test_fninit(void)16010987db7aSGleb Natapov static void test_fninit(void)
16020987db7aSGleb Natapov {
16030987db7aSGleb Natapov 	u16 fcw = -1, fsw = -1;
16040987db7aSGleb Natapov 	MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)");
16050987db7aSGleb Natapov 
1606bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = (u32)&fsw, .ebx = (u32)&fcw });
16070987db7aSGleb Natapov 
16080987db7aSGleb Natapov 	exec_in_big_real_mode(&insn_fninit);
16090987db7aSGleb Natapov 	report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f);
16100987db7aSGleb Natapov }
16110987db7aSGleb Natapov 
test_nopl(void)16121a4c03a0SArthur Chunqi Li static void test_nopl(void)
16131a4c03a0SArthur Chunqi Li {
16141a4c03a0SArthur Chunqi Li 	MK_INSN(nopl1, ".byte 0x90\n\r"); // 1 byte nop
16151a4c03a0SArthur Chunqi Li 	MK_INSN(nopl2, ".byte 0x66, 0x90\n\r"); // 2 bytes nop
16161a4c03a0SArthur Chunqi Li 	MK_INSN(nopl3, ".byte 0x0f, 0x1f, 0x00\n\r"); // 3 bytes nop
16171a4c03a0SArthur Chunqi Li 	MK_INSN(nopl4, ".byte 0x0f, 0x1f, 0x40, 0x00\n\r"); // 4 bytes nop
16181a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl1);
16191a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl2);
16201a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl3);
16211a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl4);
16221a4c03a0SArthur Chunqi Li 	report("nopl", 0, 1);
16231a4c03a0SArthur Chunqi Li }
16241a4c03a0SArthur Chunqi Li 
1625b5105e8bSPaolo Bonzini static u32 perf_baseline;
1626b5105e8bSPaolo Bonzini 
16277505ea23SPaolo Bonzini #define PERF_COUNT 1000000
1628b5105e8bSPaolo Bonzini 
1629b5105e8bSPaolo Bonzini #define MK_INSN_PERF(name, insn)                                \
1630b5105e8bSPaolo Bonzini 	MK_INSN(name, "rdtsc; mov %eax, %ebx; mov %edx, %esi\n" \
1631b5105e8bSPaolo Bonzini 		      "1:" insn "\n"                            \
16327505ea23SPaolo Bonzini 		      ".byte 0x67; loop 1b\n"                   \
1633b5105e8bSPaolo Bonzini 		      "rdtsc");
1634b5105e8bSPaolo Bonzini 
cycles_in_big_real_mode(struct insn_desc * insn)1635b5105e8bSPaolo Bonzini static u32 cycles_in_big_real_mode(struct insn_desc *insn)
1636b5105e8bSPaolo Bonzini {
1637b5105e8bSPaolo Bonzini 	u64 start, end;
1638b5105e8bSPaolo Bonzini 
1639bd62e289SBill Wendling 	init_inregs(&(struct regs){ .ecx = PERF_COUNT });
1640bd62e289SBill Wendling 
1641b5105e8bSPaolo Bonzini 	exec_in_big_real_mode(insn);
1642b5105e8bSPaolo Bonzini 	start = ((u64)outregs.esi << 32) | outregs.ebx;
1643b5105e8bSPaolo Bonzini 	end = ((u64)outregs.edx << 32) | outregs.eax;
1644b5105e8bSPaolo Bonzini 
1645b5105e8bSPaolo Bonzini 	return end - start;
1646b5105e8bSPaolo Bonzini }
1647b5105e8bSPaolo Bonzini 
test_perf_loop(void)1648b5105e8bSPaolo Bonzini static void test_perf_loop(void)
1649b5105e8bSPaolo Bonzini {
1650b5105e8bSPaolo Bonzini 	/*
1651b5105e8bSPaolo Bonzini 	 * This test runs simple instructions that should roughly take the
1652b5105e8bSPaolo Bonzini 	 * the same time to emulate: PERF_COUNT iterations of "loop" and 3
1653b5105e8bSPaolo Bonzini 	 * setup instructions.  Other performance tests can run PERF_COUNT
1654b5105e8bSPaolo Bonzini 	 * iterations of the same instruction and subtract the cycle count
1655b5105e8bSPaolo Bonzini 	 * of this test.
1656b5105e8bSPaolo Bonzini 	 */
1657b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_loop, "");
1658b5105e8bSPaolo Bonzini 	perf_baseline = cycles_in_big_real_mode(&insn_perf_loop);
1659b5105e8bSPaolo Bonzini 	print_serial_u32(perf_baseline / (PERF_COUNT + 3));
1660b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated jump instruction\n");
1661b5105e8bSPaolo Bonzini }
1662b5105e8bSPaolo Bonzini 
test_perf_mov(void)1663b5105e8bSPaolo Bonzini static void test_perf_mov(void)
1664b5105e8bSPaolo Bonzini {
1665b5105e8bSPaolo Bonzini 	u32 cyc;
1666b5105e8bSPaolo Bonzini 
1667b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_move, "mov %esi, %edi");
1668b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_move);
1669b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1670b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated move instruction\n");
1671b5105e8bSPaolo Bonzini }
1672b5105e8bSPaolo Bonzini 
test_perf_arith(void)1673b5105e8bSPaolo Bonzini static void test_perf_arith(void)
1674b5105e8bSPaolo Bonzini {
1675b5105e8bSPaolo Bonzini 	u32 cyc;
1676b5105e8bSPaolo Bonzini 
1677b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_arith, "add $4, %edi");
1678b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_arith);
1679b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1680b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated arithmetic instruction\n");
1681b5105e8bSPaolo Bonzini }
1682b5105e8bSPaolo Bonzini 
test_perf_memory_load(void)1683b5105e8bSPaolo Bonzini static void test_perf_memory_load(void)
1684b5105e8bSPaolo Bonzini {
1685b5105e8bSPaolo Bonzini 	u32 cyc, tmp;
1686b5105e8bSPaolo Bonzini 
1687576718d0SBill Wendling 	MK_INSN_PERF(perf_memory_load, "cmpw $0, (%edi)");
1688bd62e289SBill Wendling 
1689bd62e289SBill Wendling 	init_inregs(&(struct regs){ .edi = (u32)&tmp });
1690bd62e289SBill Wendling 
1691b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_load);
1692b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1693b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated memory load instruction\n");
1694b5105e8bSPaolo Bonzini }
1695b5105e8bSPaolo Bonzini 
test_perf_memory_store(void)16969306cb8eSPaolo Bonzini static void test_perf_memory_store(void)
16979306cb8eSPaolo Bonzini {
16989306cb8eSPaolo Bonzini 	u32 cyc, tmp;
16999306cb8eSPaolo Bonzini 
1700576718d0SBill Wendling 	MK_INSN_PERF(perf_memory_store, "movw %ax, (%edi)");
1701bd62e289SBill Wendling 
1702bd62e289SBill Wendling 	init_inregs(&(struct regs){ .edi = (u32)&tmp });
1703bd62e289SBill Wendling 
17049306cb8eSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_store);
17059306cb8eSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
17069306cb8eSPaolo Bonzini 	print_serial(" cycles/emulated memory store instruction\n");
17079306cb8eSPaolo Bonzini }
17089306cb8eSPaolo Bonzini 
test_perf_memory_rmw(void)1709b5105e8bSPaolo Bonzini static void test_perf_memory_rmw(void)
1710b5105e8bSPaolo Bonzini {
1711b5105e8bSPaolo Bonzini 	u32 cyc, tmp;
1712b5105e8bSPaolo Bonzini 
1713576718d0SBill Wendling 	MK_INSN_PERF(perf_memory_rmw, "addw $1, (%edi)");
1714bd62e289SBill Wendling 
1715bd62e289SBill Wendling 	init_inregs(&(struct regs){ .edi = (u32)&tmp });
1716bd62e289SBill Wendling 
1717b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_rmw);
1718b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1719b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated memory RMW instruction\n");
1720b5105e8bSPaolo Bonzini }
1721b5105e8bSPaolo Bonzini 
test_dr_mod(void)17222e3f9f1fSThomas Huth static void test_dr_mod(void)
17230a5701edSNadav Amit {
17240a5701edSNadav Amit 	MK_INSN(drmod, "movl %ebx, %dr0\n\t"
17250a5701edSNadav Amit 		       ".byte 0x0f \n\t .byte 0x21 \n\t .byte 0x0\n\t");
1726bd62e289SBill Wendling 
1727bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0xdead, .ebx = 0xaced });
1728bd62e289SBill Wendling 
17290a5701edSNadav Amit 	exec_in_big_real_mode(&insn_drmod);
17300a5701edSNadav Amit 	report("mov dr with mod bits", R_AX | R_BX, outregs.eax == 0xaced);
17310a5701edSNadav Amit }
17320a5701edSNadav Amit 
test_smsw(void)17332e3f9f1fSThomas Huth static void test_smsw(void)
173499ee878cSNadav Amit {
173599ee878cSNadav Amit 	MK_INSN(smsw, "movl %cr0, %ebx\n\t"
173699ee878cSNadav Amit 		      "movl %ebx, %ecx\n\t"
173799ee878cSNadav Amit 		      "or $0x40000000, %ebx\n\t"
173899ee878cSNadav Amit 		      "movl %ebx, %cr0\n\t"
173999ee878cSNadav Amit 		      "smswl %eax\n\t"
174099ee878cSNadav Amit 		      "movl %ecx, %cr0\n\t");
1741bd62e289SBill Wendling 
1742bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0x12345678 });
1743bd62e289SBill Wendling 
174499ee878cSNadav Amit 	exec_in_big_real_mode(&insn_smsw);
174599ee878cSNadav Amit 	report("smsw", R_AX | R_BX | R_CX, outregs.eax == outregs.ebx);
174699ee878cSNadav Amit }
174799ee878cSNadav Amit 
test_xadd(void)17482e3f9f1fSThomas Huth static void test_xadd(void)
17497bee560dSNadav Amit {
17507bee560dSNadav Amit 	MK_INSN(xadd, "xaddl %eax, %eax\n\t");
1751bd62e289SBill Wendling 
1752bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0x12345678 });
1753bd62e289SBill Wendling 
17547bee560dSNadav Amit 	exec_in_big_real_mode(&insn_xadd);
17557bee560dSNadav Amit 	report("xadd", R_AX, outregs.eax == inregs.eax * 2);
17567bee560dSNadav Amit }
17577bee560dSNadav Amit 
175899ee878cSNadav Amit 
realmode_start(void)17597d36db35SAvi Kivity void realmode_start(void)
17607d36db35SAvi Kivity {
17617d36db35SAvi Kivity 	test_null();
17627d36db35SAvi Kivity 
17637d36db35SAvi Kivity 	test_shld();
17647d36db35SAvi Kivity 	test_push_pop();
17657d36db35SAvi Kivity 	test_pusha_popa();
17667d36db35SAvi Kivity 	test_mov_imm();
17677d36db35SAvi Kivity 	test_cmp_imm();
17687d36db35SAvi Kivity 	test_add_imm();
17697d36db35SAvi Kivity 	test_sub_imm();
17707d36db35SAvi Kivity 	test_xor_imm();
17717d36db35SAvi Kivity 	test_io();
17727d36db35SAvi Kivity 	test_eflags_insn();
17737d36db35SAvi Kivity 	test_jcc_short();
17747d36db35SAvi Kivity 	test_jcc_near();
17757d36db35SAvi Kivity 	/* test_call() uses short jump so call it after testing jcc */
17767d36db35SAvi Kivity 	test_call();
17777d36db35SAvi Kivity 	/* long jmp test uses call near so test it after testing call */
17787d36db35SAvi Kivity 	test_long_jmp();
17797d36db35SAvi Kivity 	test_xchg();
17807d36db35SAvi Kivity 	test_iret();
178196b9ca1eSMohammed Gamal 	test_int();
17828202cf84SRoman Bolshakov 	test_sti_inhibit();
1783fa74f8a6SMohammed Gamal 	test_imul();
178459317bd1SMohammed Gamal 	test_mul();
17850d4c7614SMohammed Gamal 	test_div();
17860d4c7614SMohammed Gamal 	test_idiv();
1787eacef4e2SWei Yongjun 	test_loopcc();
17886e293cf5SWei Yongjun 	test_cbw();
17890cbd5b06SMohammed Gamal 	test_cwd_cdq();
1790b274feedSAvi Kivity 	test_das();
179137f51a4aSWei Yongjun 	test_lds_lss();
1792b1c7c575SWei Yongjun 	test_jcxz();
17938f578e98SAvi Kivity 	test_cpuid();
1794ed93f43bSAvi Kivity 	test_ss_base_for_esp_ebp();
1795c2281fa4SAvi Kivity 	test_sgdt_sidt();
17967ae3645aSAvi Kivity 	test_lahf();
179788b6dac4SPaolo Bonzini 	test_sahf();
1798fd9ea640SAvi Kivity 	test_movzx_movsx();
1799b493b2e8SAvi Kivity 	test_bswap();
18008cd86387SGleb Natapov 	test_aad();
18012a9b5718SPaolo Bonzini 	test_aam();
18022a9b5718SPaolo Bonzini 	test_xlat();
18032a9b5718SPaolo Bonzini 	test_salc();
18040987db7aSGleb Natapov 	test_fninit();
18050a5701edSNadav Amit 	test_dr_mod();
180699ee878cSNadav Amit 	test_smsw();
18071a4c03a0SArthur Chunqi Li 	test_nopl();
18087bee560dSNadav Amit 	test_xadd();
1809b5105e8bSPaolo Bonzini 	test_perf_loop();
1810b5105e8bSPaolo Bonzini 	test_perf_mov();
1811b5105e8bSPaolo Bonzini 	test_perf_arith();
1812b5105e8bSPaolo Bonzini 	test_perf_memory_load();
18139306cb8eSPaolo Bonzini 	test_perf_memory_store();
1814b5105e8bSPaolo Bonzini 	test_perf_memory_rmw();
18157d36db35SAvi Kivity 
1816b393fe28SNadav Amit 	exit(failed);
18177d36db35SAvi Kivity }
18187d36db35SAvi Kivity 
18197d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff };
18207d36db35SAvi Kivity 
1821975ca087SPeter Feiner struct table_descr r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt };
1822a529af7cSNadav Amit struct table_descr r_idt_descr = { 0x3ff, 0 };
18237d36db35SAvi Kivity 
18247d36db35SAvi Kivity asm(
18257d36db35SAvi Kivity 	".section .init \n\t"
18267d36db35SAvi Kivity 
18277d36db35SAvi Kivity 	".code32 \n\t"
18287d36db35SAvi Kivity 
18297d36db35SAvi Kivity 	"mb_magic = 0x1BADB002 \n\t"
18307d36db35SAvi Kivity 	"mb_flags = 0x0 \n\t"
18317d36db35SAvi Kivity 
18327d36db35SAvi Kivity 	"# multiboot header \n\t"
18337d36db35SAvi Kivity 	".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t"
18347d36db35SAvi Kivity 
18357d36db35SAvi Kivity 	".globl start \n\t"
18367d36db35SAvi Kivity 	".data \n\t"
18377d36db35SAvi Kivity 	". = . + 4096 \n\t"
18387d36db35SAvi Kivity 	"stacktop: \n\t"
18397d36db35SAvi Kivity 
18407d36db35SAvi Kivity 	".text \n\t"
18417d36db35SAvi Kivity 	"start: \n\t"
18427d36db35SAvi Kivity 	"lgdt r_gdt_descr \n\t"
1843a529af7cSNadav Amit 	"lidt r_idt_descr \n\t"
18447d36db35SAvi Kivity 	"ljmp $8, $1f; 1: \n\t"
18457d36db35SAvi Kivity 	".code16gcc \n\t"
18467d36db35SAvi Kivity 	"mov $16, %eax \n\t"
18477d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
18487d36db35SAvi Kivity 	"mov %ax, %es \n\t"
18497d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
18507d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
18517d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
18527d36db35SAvi Kivity 	"mov %cr0, %eax \n\t"
18537d36db35SAvi Kivity 	"btc $0, %eax \n\t"
18547d36db35SAvi Kivity 	"mov %eax, %cr0 \n\t"
18557d36db35SAvi Kivity 	"ljmp $0, $realmode_entry \n\t"
18567d36db35SAvi Kivity 
18577d36db35SAvi Kivity 	"realmode_entry: \n\t"
18587d36db35SAvi Kivity 
18597d36db35SAvi Kivity 	"xor %ax, %ax \n\t"
18607d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
18617d36db35SAvi Kivity 	"mov %ax, %es \n\t"
18627d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
18637d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
18647d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
18657d36db35SAvi Kivity 	"mov $stacktop, %esp\n\t"
18667d36db35SAvi Kivity 	"ljmp $0, $realmode_start \n\t"
18677d36db35SAvi Kivity 
18687d36db35SAvi Kivity 	".code16gcc \n\t"
18697d36db35SAvi Kivity 	);
1870