xref: /kvm-unit-tests/x86/realmode.c (revision bd62e289e0daa2c129a5ed501a7e7af20fa3649d)
1f366255fSPaolo Bonzini #ifndef USE_SERIAL
2f366255fSPaolo Bonzini #define USE_SERIAL
3f366255fSPaolo Bonzini #endif
4f366255fSPaolo Bonzini 
547086996SBill Wendling #define ARRAY_SIZE(_a) (sizeof(_a)/sizeof((_a)[0]))
647086996SBill Wendling 
77d36db35SAvi Kivity asm(".code16gcc");
87d36db35SAvi Kivity 
97d36db35SAvi Kivity typedef unsigned char u8;
107d36db35SAvi Kivity typedef unsigned short u16;
117d36db35SAvi Kivity typedef unsigned u32;
127d36db35SAvi Kivity typedef unsigned long long u64;
137d36db35SAvi Kivity 
14*bd62e289SBill Wendling #ifndef NULL
15*bd62e289SBill Wendling #define NULL ((void*)0)
16*bd62e289SBill Wendling #endif
17*bd62e289SBill Wendling 
182e3f9f1fSThomas Huth void realmode_start(void);
197d36db35SAvi Kivity void test_function(void);
207d36db35SAvi Kivity 
217d36db35SAvi Kivity asm(
227d36db35SAvi Kivity 	"test_function: \n\t"
237d36db35SAvi Kivity 	"mov $0x1234, %eax \n\t"
247d36db35SAvi Kivity 	"ret"
257d36db35SAvi Kivity    );
267d36db35SAvi Kivity 
277d36db35SAvi Kivity static int strlen(const char *str)
287d36db35SAvi Kivity {
297d36db35SAvi Kivity 	int n;
307d36db35SAvi Kivity 
317d36db35SAvi Kivity 	for (n = 0; *str; ++str)
327d36db35SAvi Kivity 		++n;
337d36db35SAvi Kivity 	return n;
347d36db35SAvi Kivity }
357d36db35SAvi Kivity 
36f366255fSPaolo Bonzini static void outb(u8 data, u16 port)
37f366255fSPaolo Bonzini {
38f366255fSPaolo Bonzini 	asm volatile("out %0, %1" : : "a"(data), "d"(port));
39f366255fSPaolo Bonzini }
40f366255fSPaolo Bonzini 
41f366255fSPaolo Bonzini #ifdef USE_SERIAL
42f366255fSPaolo Bonzini static int serial_iobase = 0x3f8;
43f366255fSPaolo Bonzini static int serial_inited = 0;
44f366255fSPaolo Bonzini 
45f366255fSPaolo Bonzini static u8 inb(u16 port)
46f366255fSPaolo Bonzini {
47f366255fSPaolo Bonzini 	u8 data;
48f366255fSPaolo Bonzini 	asm volatile("in %1, %0" : "=a"(data) : "d"(port));
49f366255fSPaolo Bonzini 	return data;
50f366255fSPaolo Bonzini }
51f366255fSPaolo Bonzini 
52f366255fSPaolo Bonzini static void serial_outb(char ch)
53f366255fSPaolo Bonzini {
54f366255fSPaolo Bonzini 	u8 lsr;
55f366255fSPaolo Bonzini 
56f366255fSPaolo Bonzini 	do {
57f366255fSPaolo Bonzini 		lsr = inb(serial_iobase + 0x05);
58f366255fSPaolo Bonzini 	} while (!(lsr & 0x20));
59f366255fSPaolo Bonzini 
60f366255fSPaolo Bonzini 	outb(ch, serial_iobase + 0x00);
61f366255fSPaolo Bonzini }
62f366255fSPaolo Bonzini 
63f366255fSPaolo Bonzini static void serial_init(void)
64f366255fSPaolo Bonzini {
65f366255fSPaolo Bonzini 	u8 lcr;
66f366255fSPaolo Bonzini 
67f366255fSPaolo Bonzini 	/* set DLAB */
68f366255fSPaolo Bonzini 	lcr = inb(serial_iobase + 0x03);
69f366255fSPaolo Bonzini 	lcr |= 0x80;
70f366255fSPaolo Bonzini 	outb(lcr, serial_iobase + 0x03);
71f366255fSPaolo Bonzini 
72f366255fSPaolo Bonzini 	/* set baud rate to 115200 */
73f366255fSPaolo Bonzini 	outb(0x01, serial_iobase + 0x00);
74f366255fSPaolo Bonzini 	outb(0x00, serial_iobase + 0x01);
75f366255fSPaolo Bonzini 
76f366255fSPaolo Bonzini 	/* clear DLAB */
77f366255fSPaolo Bonzini 	lcr = inb(serial_iobase + 0x03);
78f366255fSPaolo Bonzini 	lcr &= ~0x80;
79f366255fSPaolo Bonzini 	outb(lcr, serial_iobase + 0x03);
80f366255fSPaolo Bonzini }
81f366255fSPaolo Bonzini #endif
82f366255fSPaolo Bonzini 
837d36db35SAvi Kivity static void print_serial(const char *buf)
847d36db35SAvi Kivity {
857d36db35SAvi Kivity 	unsigned long len = strlen(buf);
86f366255fSPaolo Bonzini #ifdef USE_SERIAL
87f366255fSPaolo Bonzini 	unsigned long i;
88f366255fSPaolo Bonzini 	if (!serial_inited) {
89f366255fSPaolo Bonzini 	    serial_init();
90f366255fSPaolo Bonzini 	    serial_inited = 1;
91f366255fSPaolo Bonzini 	}
927d36db35SAvi Kivity 
93f366255fSPaolo Bonzini 	for (i = 0; i < len; i++) {
94f366255fSPaolo Bonzini 	    serial_outb(buf[i]);
95f366255fSPaolo Bonzini 	}
96f366255fSPaolo Bonzini #else
975edbb9aeSPaolo Bonzini 	asm volatile ("addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1));
98f366255fSPaolo Bonzini #endif
997d36db35SAvi Kivity }
1007d36db35SAvi Kivity 
101b5105e8bSPaolo Bonzini static void print_serial_u32(u32 value)
102b5105e8bSPaolo Bonzini {
103b5105e8bSPaolo Bonzini 	char n[12], *p;
104b5105e8bSPaolo Bonzini 	p = &n[11];
105b5105e8bSPaolo Bonzini 	*p = 0;
106b5105e8bSPaolo Bonzini 	do {
107b5105e8bSPaolo Bonzini 		*--p = '0' + (value % 10);
108b5105e8bSPaolo Bonzini 		value /= 10;
109b5105e8bSPaolo Bonzini 	} while (value > 0);
110b5105e8bSPaolo Bonzini 	print_serial(p);
111b5105e8bSPaolo Bonzini }
112b5105e8bSPaolo Bonzini 
113b393fe28SNadav Amit static int failed;
114b393fe28SNadav Amit 
1157d36db35SAvi Kivity static void exit(int code)
1167d36db35SAvi Kivity {
117f366255fSPaolo Bonzini 	outb(code, 0xf4);
1187d36db35SAvi Kivity }
1197d36db35SAvi Kivity 
1207d36db35SAvi Kivity struct regs {
1217d36db35SAvi Kivity 	u32 eax, ebx, ecx, edx;
1227d36db35SAvi Kivity 	u32 esi, edi, esp, ebp;
1237d36db35SAvi Kivity 	u32 eip, eflags;
1247d36db35SAvi Kivity };
1257d36db35SAvi Kivity 
126975ca087SPeter Feiner struct table_descr {
127975ca087SPeter Feiner 	u16 limit;
128975ca087SPeter Feiner 	void *base;
129975ca087SPeter Feiner } __attribute__((packed));
130975ca087SPeter Feiner 
1317d36db35SAvi Kivity static u64 gdt[] = {
1327d36db35SAvi Kivity 	0,
1337d36db35SAvi Kivity 	0x00cf9b000000ffffull, // flat 32-bit code segment
1347d36db35SAvi Kivity 	0x00cf93000000ffffull, // flat 32-bit data segment
1357d36db35SAvi Kivity };
1367d36db35SAvi Kivity 
137975ca087SPeter Feiner static struct table_descr gdt_descr = {
1387d36db35SAvi Kivity 	sizeof(gdt) - 1,
1397d36db35SAvi Kivity 	gdt,
1407d36db35SAvi Kivity };
1417d36db35SAvi Kivity 
142d4dc402cSAvi Kivity struct insn_desc {
143d4dc402cSAvi Kivity     u16 ptr;
144d4dc402cSAvi Kivity     u16 len;
145d4dc402cSAvi Kivity };
146d4dc402cSAvi Kivity 
147*bd62e289SBill Wendling struct {
148*bd62e289SBill Wendling 	u32 stack[128];
149*bd62e289SBill Wendling 	char top[];
150*bd62e289SBill Wendling } tmp_stack;
151*bd62e289SBill Wendling 
15218253fdeSAvi Kivity static struct regs inregs, outregs;
15318253fdeSAvi Kivity 
154*bd62e289SBill Wendling static inline void init_inregs(struct regs *regs)
155*bd62e289SBill Wendling {
156*bd62e289SBill Wendling 	inregs = (struct regs){ 0 };
157*bd62e289SBill Wendling 	if (regs)
158*bd62e289SBill Wendling 		inregs = *regs;
159*bd62e289SBill Wendling 	if (!inregs.esp)
160*bd62e289SBill Wendling 		inregs.esp = (unsigned long)&tmp_stack.top;
161*bd62e289SBill Wendling }
162*bd62e289SBill Wendling 
16318253fdeSAvi Kivity static void exec_in_big_real_mode(struct insn_desc *insn)
1647d36db35SAvi Kivity {
1657d36db35SAvi Kivity 	unsigned long tmp;
1667d36db35SAvi Kivity 	static struct regs save;
1677d36db35SAvi Kivity 	int i;
1687d36db35SAvi Kivity 	extern u8 test_insn[], test_insn_end[];
1697d36db35SAvi Kivity 
170d4dc402cSAvi Kivity 	for (i = 0; i < insn->len; ++i)
171d4dc402cSAvi Kivity 	    test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i];
1727d36db35SAvi Kivity 	for (; i < test_insn_end - test_insn; ++i)
1737d36db35SAvi Kivity 		test_insn[i] = 0x90; // nop
1747d36db35SAvi Kivity 
17518253fdeSAvi Kivity 	save = inregs;
1767d36db35SAvi Kivity 	asm volatile(
1777d36db35SAvi Kivity 		"lgdtl %[gdt_descr] \n\t"
1787d36db35SAvi Kivity 		"mov %%cr0, %[tmp] \n\t"
1797d36db35SAvi Kivity 		"or $1, %[tmp] \n\t"
1807d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
1817d36db35SAvi Kivity 		"mov %[bigseg], %%gs \n\t"
1827d36db35SAvi Kivity 		"and $-2, %[tmp] \n\t"
1837d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
1847d36db35SAvi Kivity 
185eb6687a2SBill Wendling 		/* Save ES, because it is clobbered by some tests. */
186eb6687a2SBill Wendling 		"pushw %%es \n\t"
187eb6687a2SBill Wendling 
18832001692SAvi Kivity 		"pushw %[save]+36; popfw \n\t"
1897d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
1907d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
1917d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
1927d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
1937d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
1947d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
1957d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
1967d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
1977d36db35SAvi Kivity 
1987d36db35SAvi Kivity 		"test_insn: . = . + 32\n\t"
1997d36db35SAvi Kivity 		"test_insn_end: \n\t"
2007d36db35SAvi Kivity 
2017d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
2027d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
2037d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
2047d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
2057d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
2067d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
2077d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
2087d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
2097d36db35SAvi Kivity 
2107d36db35SAvi Kivity 		/* Save EFLAGS in outregs*/
2117d36db35SAvi Kivity 		"pushfl \n\t"
2127d36db35SAvi Kivity 		"popl %[save]+36 \n\t"
2137d36db35SAvi Kivity 
214eb6687a2SBill Wendling 		/* Restore ES for future rep string operations. */
215eb6687a2SBill Wendling 		"popw %%es \n\t"
216eb6687a2SBill Wendling 
2175edbb9aeSPaolo Bonzini 		/* Restore DF for the harness code */
2185edbb9aeSPaolo Bonzini 		"cld\n\t"
2197d36db35SAvi Kivity 		"xor %[tmp], %[tmp] \n\t"
2207d36db35SAvi Kivity 		"mov %[tmp], %%gs \n\t"
2217d36db35SAvi Kivity 		: [tmp]"=&r"(tmp), [save]"+m"(save)
2227d36db35SAvi Kivity 		: [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16)
2237d36db35SAvi Kivity 		: "cc", "memory"
2247d36db35SAvi Kivity 		);
22518253fdeSAvi Kivity 	outregs = save;
2267d36db35SAvi Kivity }
2277d36db35SAvi Kivity 
2287d36db35SAvi Kivity #define R_AX 1
2297d36db35SAvi Kivity #define R_BX 2
2307d36db35SAvi Kivity #define R_CX 4
2317d36db35SAvi Kivity #define R_DX 8
2327d36db35SAvi Kivity #define R_SI 16
2337d36db35SAvi Kivity #define R_DI 32
2347d36db35SAvi Kivity #define R_SP 64
2357d36db35SAvi Kivity #define R_BP 128
2367d36db35SAvi Kivity 
2372e3f9f1fSThomas Huth static int regs_equal(int ignore)
2387d36db35SAvi Kivity {
23918253fdeSAvi Kivity 	const u32 *p1 = &inregs.eax, *p2 = &outregs.eax;  // yuck
2407d36db35SAvi Kivity 	int i;
2417d36db35SAvi Kivity 
2427d36db35SAvi Kivity 	for (i = 0; i < 8; ++i)
2437d36db35SAvi Kivity 		if (!(ignore & (1 << i)) && p1[i] != p2[i])
2447d36db35SAvi Kivity 			return 0;
2457d36db35SAvi Kivity 	return 1;
2467d36db35SAvi Kivity }
2477d36db35SAvi Kivity 
2486055ea1fSAvi Kivity static void report(const char *name, u16 regs_ignore, _Bool ok)
24981050840SAvi Kivity {
2506055ea1fSAvi Kivity     if (!regs_equal(regs_ignore)) {
2516055ea1fSAvi Kivity 	ok = 0;
2526055ea1fSAvi Kivity     }
25381050840SAvi Kivity     print_serial(ok ? "PASS: " : "FAIL: ");
25481050840SAvi Kivity     print_serial(name);
25581050840SAvi Kivity     print_serial("\n");
256b393fe28SNadav Amit     if (!ok)
257b393fe28SNadav Amit 	failed = 1;
25881050840SAvi Kivity }
25981050840SAvi Kivity 
2607d36db35SAvi Kivity #define MK_INSN(name, str)				\
2617d36db35SAvi Kivity     asm (						\
262d4dc402cSAvi Kivity 	 ".pushsection .data.insn  \n\t"		\
263d4dc402cSAvi Kivity 	 "insn_" #name ": \n\t"				\
264d4dc402cSAvi Kivity 	 ".word 1001f, 1002f - 1001f \n\t"		\
265d4dc402cSAvi Kivity 	 ".popsection \n\t"				\
266d4dc402cSAvi Kivity 	 ".pushsection .text.insn, \"ax\" \n\t"		\
267d4dc402cSAvi Kivity 	 "1001: \n\t"					\
268d4dc402cSAvi Kivity 	 "insn_code_" #name ": " str " \n\t"		\
269d4dc402cSAvi Kivity 	 "1002: \n\t"					\
270d4dc402cSAvi Kivity 	 ".popsection"					\
2717d36db35SAvi Kivity     );							\
272d4dc402cSAvi Kivity     extern struct insn_desc insn_##name;
2737d36db35SAvi Kivity 
2742e3f9f1fSThomas Huth static void test_xchg(void)
2757d36db35SAvi Kivity {
2767d36db35SAvi Kivity 	MK_INSN(xchg_test1, "xchg %eax,%eax\n\t");
2777d36db35SAvi Kivity 	MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t");
2787d36db35SAvi Kivity 	MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t");
2797d36db35SAvi Kivity 	MK_INSN(xchg_test4, "xchg %eax,%edx\n\t");
2807d36db35SAvi Kivity 	MK_INSN(xchg_test5, "xchg %eax,%esi\n\t");
2817d36db35SAvi Kivity 	MK_INSN(xchg_test6, "xchg %eax,%edi\n\t");
2827d36db35SAvi Kivity 	MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t");
2837d36db35SAvi Kivity 	MK_INSN(xchg_test8, "xchg %eax,%esp\n\t");
2847d36db35SAvi Kivity 
28518253fdeSAvi Kivity 	inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7};
2867d36db35SAvi Kivity 
28718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test1);
2886055ea1fSAvi Kivity 	report("xchg 1", 0, 1);
28918253fdeSAvi Kivity 
29018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test2);
2916055ea1fSAvi Kivity 	report("xchg 2", R_AX | R_BX,
2926055ea1fSAvi Kivity 	       outregs.eax == inregs.ebx && outregs.ebx == inregs.eax);
2937d36db35SAvi Kivity 
29418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test3);
2956055ea1fSAvi Kivity 	report("xchg 3", R_AX | R_CX,
2966055ea1fSAvi Kivity 	       outregs.eax == inregs.ecx && outregs.ecx == inregs.eax);
2977d36db35SAvi Kivity 
29818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test4);
2996055ea1fSAvi Kivity 	report("xchg 4", R_AX | R_DX,
3006055ea1fSAvi Kivity 	       outregs.eax == inregs.edx && outregs.edx == inregs.eax);
3017d36db35SAvi Kivity 
30218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test5);
3036055ea1fSAvi Kivity 	report("xchg 5", R_AX | R_SI,
3046055ea1fSAvi Kivity 	       outregs.eax == inregs.esi && outregs.esi == inregs.eax);
3057d36db35SAvi Kivity 
30618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test6);
3076055ea1fSAvi Kivity 	report("xchg 6", R_AX | R_DI,
3086055ea1fSAvi Kivity 	       outregs.eax == inregs.edi && outregs.edi == inregs.eax);
3097d36db35SAvi Kivity 
31018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test7);
3116055ea1fSAvi Kivity 	report("xchg 7", R_AX | R_BP,
3126055ea1fSAvi Kivity 	       outregs.eax == inregs.ebp && outregs.ebp == inregs.eax);
3137d36db35SAvi Kivity 
31418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xchg_test8);
3156055ea1fSAvi Kivity 	report("xchg 8", R_AX | R_SP,
3166055ea1fSAvi Kivity 	       outregs.eax == inregs.esp && outregs.esp == inregs.eax);
3177d36db35SAvi Kivity }
3187d36db35SAvi Kivity 
3192e3f9f1fSThomas Huth static void test_shld(void)
3207d36db35SAvi Kivity {
3217d36db35SAvi Kivity 	MK_INSN(shld_test, "shld $8,%edx,%eax\n\t");
3227d36db35SAvi Kivity 
323*bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0xbe, .edx = 0xef000000 });
324*bd62e289SBill Wendling 
32518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_shld_test);
3266055ea1fSAvi Kivity 	report("shld", ~0, outregs.eax == 0xbeef);
3277d36db35SAvi Kivity }
3287d36db35SAvi Kivity 
3292e3f9f1fSThomas Huth static void test_mov_imm(void)
3307d36db35SAvi Kivity {
3317d36db35SAvi Kivity 	MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax");
3327d36db35SAvi Kivity 	MK_INSN(mov_r16_imm_1, "mov $1234, %ax");
3337d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_1, "mov $0x12, %ah");
3347d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_2, "mov $0x34, %al");
3357d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t");
3367d36db35SAvi Kivity 
337*bd62e289SBill Wendling 	init_inregs(NULL);
33818253fdeSAvi Kivity 
33918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r16_imm_1);
3406055ea1fSAvi Kivity 	report("mov 1", R_AX, outregs.eax == 1234);
3417d36db35SAvi Kivity 
3427d36db35SAvi Kivity 	/* test mov $imm, %eax */
34318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r32_imm_1);
3446055ea1fSAvi Kivity 	report("mov 2", R_AX, outregs.eax == 1234567890);
3457d36db35SAvi Kivity 
3467d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
34718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_1);
3486055ea1fSAvi Kivity 	report("mov 3", R_AX, outregs.eax == 0x1200);
3497d36db35SAvi Kivity 
35018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_2);
3516055ea1fSAvi Kivity 	report("mov 4", R_AX, outregs.eax == 0x34);
3527d36db35SAvi Kivity 
35318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mov_r8_imm_3);
3546055ea1fSAvi Kivity 	report("mov 5", R_AX, outregs.eax == 0x1234);
3557d36db35SAvi Kivity }
3567d36db35SAvi Kivity 
3572e3f9f1fSThomas Huth static void test_sub_imm(void)
3587d36db35SAvi Kivity {
3597d36db35SAvi Kivity 	MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t");
3607d36db35SAvi Kivity 	MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t");
3617d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t");
3627d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t");
3637d36db35SAvi Kivity 
364*bd62e289SBill Wendling 	init_inregs(NULL);
36518253fdeSAvi Kivity 
36618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r16_imm_1);
3676055ea1fSAvi Kivity 	report("sub 1", R_AX, outregs.eax == 1224);
3687d36db35SAvi Kivity 
3697d36db35SAvi Kivity 	/* test mov $imm, %eax */
37018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r32_imm_1);
3716055ea1fSAvi Kivity 	report("sub 2", R_AX, outregs.eax == 1234567880);
3727d36db35SAvi Kivity 
3737d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
37418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_1);
3756055ea1fSAvi Kivity 	report("sub 3", R_AX, outregs.eax == 0x0200);
3767d36db35SAvi Kivity 
37718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sub_r8_imm_2);
3786055ea1fSAvi Kivity 	report("sub 4", R_AX, outregs.eax == 0x24);
3797d36db35SAvi Kivity }
3807d36db35SAvi Kivity 
3812e3f9f1fSThomas Huth static void test_xor_imm(void)
3827d36db35SAvi Kivity {
3837d36db35SAvi Kivity 	MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t");
3847d36db35SAvi Kivity 	MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t");
3857d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t");
3867d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t");
3877d36db35SAvi Kivity 
388*bd62e289SBill Wendling 	init_inregs(NULL);
38918253fdeSAvi Kivity 
39018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r16_imm_1);
3916055ea1fSAvi Kivity 	report("xor 1", R_AX, outregs.eax == 0);
3927d36db35SAvi Kivity 
3937d36db35SAvi Kivity 	/* test mov $imm, %eax */
39418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r32_imm_1);
3956055ea1fSAvi Kivity 	report("xor 2", R_AX, outregs.eax == 0);
3967d36db35SAvi Kivity 
3977d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
39818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_1);
3996055ea1fSAvi Kivity 	report("xor 3", R_AX, outregs.eax == 0);
4007d36db35SAvi Kivity 
40118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_xor_r8_imm_2);
4026055ea1fSAvi Kivity 	report("xor 4", R_AX, outregs.eax == 0);
4037d36db35SAvi Kivity }
4047d36db35SAvi Kivity 
4052e3f9f1fSThomas Huth static void test_cmp_imm(void)
4067d36db35SAvi Kivity {
4077d36db35SAvi Kivity 	MK_INSN(cmp_test1, "mov $0x34, %al\n\t"
4087d36db35SAvi Kivity 			   "cmp $0x34, %al\n\t");
4097d36db35SAvi Kivity 	MK_INSN(cmp_test2, "mov $0x34, %al\n\t"
4107d36db35SAvi Kivity 			   "cmp $0x39, %al\n\t");
4117d36db35SAvi Kivity 	MK_INSN(cmp_test3, "mov $0x34, %al\n\t"
4127d36db35SAvi Kivity 			   "cmp $0x24, %al\n\t");
4137d36db35SAvi Kivity 
414*bd62e289SBill Wendling 	init_inregs(NULL);
41518253fdeSAvi Kivity 
4167d36db35SAvi Kivity 	/* test cmp imm8 with AL */
4177d36db35SAvi Kivity 	/* ZF: (bit 6) Zero Flag becomes 1 if an operation results
4187d36db35SAvi Kivity 	 * in a 0 writeback, or 0 register
4197d36db35SAvi Kivity 	 */
42018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test1);
4216055ea1fSAvi Kivity 	report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6));
4227d36db35SAvi Kivity 
42318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test2);
4246055ea1fSAvi Kivity 	report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0);
4257d36db35SAvi Kivity 
42618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cmp_test3);
4276055ea1fSAvi Kivity 	report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0);
4287d36db35SAvi Kivity }
4297d36db35SAvi Kivity 
4302e3f9f1fSThomas Huth static void test_add_imm(void)
4317d36db35SAvi Kivity {
4327d36db35SAvi Kivity 	MK_INSN(add_test1, "mov $0x43211234, %eax \n\t"
4337d36db35SAvi Kivity 			   "add $0x12344321, %eax \n\t");
4347d36db35SAvi Kivity 	MK_INSN(add_test2, "mov $0x12, %eax \n\t"
4357d36db35SAvi Kivity 			   "add $0x21, %al\n\t");
4367d36db35SAvi Kivity 
437*bd62e289SBill Wendling 	init_inregs(NULL);
43818253fdeSAvi Kivity 
43918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test1);
4406055ea1fSAvi Kivity 	report("add 1", ~0, outregs.eax == 0x55555555);
4417d36db35SAvi Kivity 
44218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_add_test2);
4436055ea1fSAvi Kivity 	report("add 2", ~0, outregs.eax == 0x33);
4447d36db35SAvi Kivity }
4457d36db35SAvi Kivity 
4462e3f9f1fSThomas Huth static void test_eflags_insn(void)
4477d36db35SAvi Kivity {
4487d36db35SAvi Kivity 	MK_INSN(clc, "clc");
449b3261e48SMohammed Gamal 	MK_INSN(stc, "stc");
4507d36db35SAvi Kivity 	MK_INSN(cli, "cli");
4517d36db35SAvi Kivity 	MK_INSN(sti, "sti");
4527d36db35SAvi Kivity 	MK_INSN(cld, "cld");
4537d36db35SAvi Kivity 	MK_INSN(std, "std");
4547d36db35SAvi Kivity 
455*bd62e289SBill Wendling 	init_inregs(NULL);
45618253fdeSAvi Kivity 
45718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_clc);
4586055ea1fSAvi Kivity 	report("clc", ~0, (outregs.eflags & 1) == 0);
4597d36db35SAvi Kivity 
46018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_stc);
4616055ea1fSAvi Kivity 	report("stc", ~0, (outregs.eflags & 1) == 1);
462b3261e48SMohammed Gamal 
46318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cli);
4646055ea1fSAvi Kivity 	report("cli", ~0, !(outregs.eflags & (1 << 9)));
4657d36db35SAvi Kivity 
46618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_sti);
4676055ea1fSAvi Kivity 	report("sti", ~0, outregs.eflags & (1 << 9));
4687d36db35SAvi Kivity 
46918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cld);
4706055ea1fSAvi Kivity 	report("cld", ~0, !(outregs.eflags & (1 << 10)));
4717d36db35SAvi Kivity 
47218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_std);
4736055ea1fSAvi Kivity 	report("std", ~0, (outregs.eflags & (1 << 10)));
4747d36db35SAvi Kivity }
4757d36db35SAvi Kivity 
4762e3f9f1fSThomas Huth static void test_io(void)
4777d36db35SAvi Kivity {
4787d36db35SAvi Kivity 	MK_INSN(io_test1, "mov $0xff, %al \n\t"
4797d36db35SAvi Kivity 		          "out %al, $0xe0 \n\t"
4807d36db35SAvi Kivity 		          "mov $0x00, %al \n\t"
4817d36db35SAvi Kivity 			  "in $0xe0, %al \n\t");
4827d36db35SAvi Kivity 	MK_INSN(io_test2, "mov $0xffff, %ax \n\t"
4837d36db35SAvi Kivity 			  "out %ax, $0xe0 \n\t"
4847d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
4857d36db35SAvi Kivity 			  "in $0xe0, %ax \n\t");
4867d36db35SAvi Kivity 	MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t"
4877d36db35SAvi Kivity 			  "out %eax, $0xe0 \n\t"
4887d36db35SAvi Kivity 			  "mov $0x000000, %eax \n\t"
4897d36db35SAvi Kivity 			  "in $0xe0, %eax \n\t");
4907d36db35SAvi Kivity 	MK_INSN(io_test4, "mov $0xe0, %dx \n\t"
4917d36db35SAvi Kivity 			  "mov $0xff, %al \n\t"
4927d36db35SAvi Kivity 			  "out %al, %dx \n\t"
4937d36db35SAvi Kivity 			  "mov $0x00, %al \n\t"
4947d36db35SAvi Kivity 			  "in %dx, %al \n\t");
4957d36db35SAvi Kivity 	MK_INSN(io_test5, "mov $0xe0, %dx \n\t"
4967d36db35SAvi Kivity 			  "mov $0xffff, %ax \n\t"
4977d36db35SAvi Kivity 			  "out %ax, %dx \n\t"
4987d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
4997d36db35SAvi Kivity 			  "in %dx, %ax \n\t");
5007d36db35SAvi Kivity 	MK_INSN(io_test6, "mov $0xe0, %dx \n\t"
5017d36db35SAvi Kivity 			  "mov $0xffffffff, %eax \n\t"
5027d36db35SAvi Kivity 			  "out %eax, %dx \n\t"
5037d36db35SAvi Kivity 			  "mov $0x00000000, %eax \n\t"
5047d36db35SAvi Kivity 			  "in %dx, %eax \n\t");
5057d36db35SAvi Kivity 
506*bd62e289SBill Wendling 	init_inregs(NULL);
50718253fdeSAvi Kivity 
50818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test1);
5096055ea1fSAvi Kivity 	report("pio 1", R_AX, outregs.eax == 0xff);
5107d36db35SAvi Kivity 
51118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test2);
5126055ea1fSAvi Kivity 	report("pio 2", R_AX, outregs.eax == 0xffff);
5137d36db35SAvi Kivity 
51418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test3);
5156055ea1fSAvi Kivity 	report("pio 3", R_AX, outregs.eax == 0xffffffff);
5167d36db35SAvi Kivity 
51718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test4);
5186055ea1fSAvi Kivity 	report("pio 4", R_AX|R_DX, outregs.eax == 0xff);
5197d36db35SAvi Kivity 
52018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test5);
5216055ea1fSAvi Kivity 	report("pio 5", R_AX|R_DX, outregs.eax == 0xffff);
5227d36db35SAvi Kivity 
52318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_io_test6);
5246055ea1fSAvi Kivity 	report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff);
5257d36db35SAvi Kivity }
5267d36db35SAvi Kivity 
527c0b7268dSAvi Kivity asm ("retf: lretw");
5282e3f9f1fSThomas Huth extern void retf(void);
529c0b7268dSAvi Kivity 
5304f66bc86SBruce Rogers asm ("retf_imm: lretw $10");
5312e3f9f1fSThomas Huth extern void retf_imm(void);
5324f66bc86SBruce Rogers 
5332e3f9f1fSThomas Huth static void test_call(void)
5347d36db35SAvi Kivity {
535c0b7268dSAvi Kivity 	u32 addr;
5367d36db35SAvi Kivity 
5377d36db35SAvi Kivity 	MK_INSN(call1, "mov $test_function, %eax \n\t"
5387d36db35SAvi Kivity 		       "call *%eax\n\t");
5397d36db35SAvi Kivity 	MK_INSN(call_near1, "jmp 2f\n\t"
5407d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5417d36db35SAvi Kivity 			    "ret\n\t"
5427d36db35SAvi Kivity 			    "2: call 1b\t");
5437d36db35SAvi Kivity 	MK_INSN(call_near2, "call 1f\n\t"
5447d36db35SAvi Kivity 			    "jmp 2f\n\t"
5457d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
5467d36db35SAvi Kivity 			    "ret\n\t"
5477d36db35SAvi Kivity 			    "2:\t");
548c0b7268dSAvi Kivity 	MK_INSN(call_far1,  "lcallw *(%ebx)\n\t");
549556d2680SWei Yongjun 	MK_INSN(call_far2,  "lcallw $0, $retf\n\t");
550c6061817SAvi Kivity 	MK_INSN(ret_imm,    "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b");
5514f66bc86SBruce Rogers 	MK_INSN(retf_imm,   "sub $10, %sp; lcallw $0, $retf_imm");
5527d36db35SAvi Kivity 
553*bd62e289SBill Wendling 	init_inregs(NULL);
554*bd62e289SBill Wendling 
55518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call1);
5566055ea1fSAvi Kivity 	report("call 1", R_AX, outregs.eax == 0x1234);
5577d36db35SAvi Kivity 
55818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near1);
5596055ea1fSAvi Kivity 	report("call near 1", R_AX, outregs.eax == 0x1234);
5607d36db35SAvi Kivity 
56118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_near2);
5626055ea1fSAvi Kivity 	report("call near 2", R_AX, outregs.eax == 0x1234);
563c0b7268dSAvi Kivity 
564c0b7268dSAvi Kivity 	addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f);
565c0b7268dSAvi Kivity 	inregs.ebx = (unsigned)&addr;
56618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_call_far1);
5676055ea1fSAvi Kivity 	report("call far 1", 0, 1);
568c6061817SAvi Kivity 
569556d2680SWei Yongjun 	exec_in_big_real_mode(&insn_call_far2);
570556d2680SWei Yongjun 	report("call far 2", 0, 1);
571556d2680SWei Yongjun 
57218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_ret_imm);
5736055ea1fSAvi Kivity 	report("ret imm 1", 0, 1);
5744f66bc86SBruce Rogers 
5754f66bc86SBruce Rogers 	exec_in_big_real_mode(&insn_retf_imm);
5764f66bc86SBruce Rogers 	report("retf imm 1", 0, 1);
5777d36db35SAvi Kivity }
5787d36db35SAvi Kivity 
5792e3f9f1fSThomas Huth static void test_jcc_short(void)
5807d36db35SAvi Kivity {
5817d36db35SAvi Kivity 	MK_INSN(jnz_short1, "jnz 1f\n\t"
5827d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
5837d36db35SAvi Kivity 		            "1:\n\t");
5847d36db35SAvi Kivity 	MK_INSN(jnz_short2, "1:\n\t"
5857d36db35SAvi Kivity 			    "cmp $0x1234, %eax\n\t"
5867d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
5877d36db35SAvi Kivity 		            "jnz 1b\n\t");
5887d36db35SAvi Kivity 	MK_INSN(jmp_short1, "jmp 1f\n\t"
5897d36db35SAvi Kivity 		      "mov $0x1234, %eax\n\t"
5907d36db35SAvi Kivity 		      "1:\n\t");
5917d36db35SAvi Kivity 
592*bd62e289SBill Wendling 	init_inregs(NULL);
5937d36db35SAvi Kivity 
59418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short1);
5956055ea1fSAvi Kivity 	report("jnz short 1", ~0, 1);
59618253fdeSAvi Kivity 
59718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_short2);
5986055ea1fSAvi Kivity 	report("jnz short 2", R_AX, (outregs.eflags & (1 << 6)));
5997d36db35SAvi Kivity 
60018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_short1);
6016055ea1fSAvi Kivity 	report("jmp short 1", ~0, 1);
6027d36db35SAvi Kivity }
6037d36db35SAvi Kivity 
6042e3f9f1fSThomas Huth static void test_jcc_near(void)
6057d36db35SAvi Kivity {
6067d36db35SAvi Kivity 	/* encode near jmp manually. gas will not do it if offsets < 127 byte */
6077d36db35SAvi Kivity 	MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t"
6087d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
6097d36db35SAvi Kivity 	MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t"
6107d36db35SAvi Kivity 			   "mov $0x1234, %eax\n\t"
6117d36db35SAvi Kivity 		           ".byte 0x0f, 0x85, 0xf0, 0xff\n\t");
6127d36db35SAvi Kivity 	MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t"
6137d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
6147d36db35SAvi Kivity 
615*bd62e289SBill Wendling 	init_inregs(NULL);
6167d36db35SAvi Kivity 
61718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near1);
6186055ea1fSAvi Kivity 	report("jnz near 1", 0, 1);
61918253fdeSAvi Kivity 
62018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jnz_near2);
6216055ea1fSAvi Kivity 	report("jnz near 2", R_AX, outregs.eflags & (1 << 6));
6227d36db35SAvi Kivity 
62318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_jmp_near1);
6246055ea1fSAvi Kivity 	report("jmp near 1", 0, 1);
6257d36db35SAvi Kivity }
6267d36db35SAvi Kivity 
6272e3f9f1fSThomas Huth static void test_long_jmp(void)
6287d36db35SAvi Kivity {
6297d36db35SAvi Kivity 	MK_INSN(long_jmp, "call 1f\n\t"
6307d36db35SAvi Kivity 			  "jmp 2f\n\t"
6317d36db35SAvi Kivity 			  "1: jmp $0, $test_function\n\t"
6327d36db35SAvi Kivity 		          "2:\n\t");
633*bd62e289SBill Wendling 
634*bd62e289SBill Wendling 	init_inregs(NULL);
635*bd62e289SBill Wendling 
63618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_long_jmp);
6376055ea1fSAvi Kivity 	report("jmp far 1", R_AX, outregs.eax == 0x1234);
6387d36db35SAvi Kivity }
639fa74f8a6SMohammed Gamal 
6402e3f9f1fSThomas Huth static void test_push_pop(void)
6417d36db35SAvi Kivity {
6427d36db35SAvi Kivity 	MK_INSN(push32, "mov $0x12345678, %eax\n\t"
6437d36db35SAvi Kivity 			"push %eax\n\t"
6447d36db35SAvi Kivity 			"pop %ebx\n\t");
6457d36db35SAvi Kivity 	MK_INSN(push16, "mov $0x1234, %ax\n\t"
6467d36db35SAvi Kivity 			"push %ax\n\t"
6477d36db35SAvi Kivity 			"pop %bx\n\t");
6487d36db35SAvi Kivity 
6497d36db35SAvi Kivity 	MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten
6507d36db35SAvi Kivity 			 "mov $0x123, %ax\n\t"
6517d36db35SAvi Kivity 			 "mov %ax, %es\n\t"
6527d36db35SAvi Kivity 			 "push %es\n\t"
6537d36db35SAvi Kivity 			 "pop %bx \n\t"
6547d36db35SAvi Kivity 			 );
6557d36db35SAvi Kivity 	MK_INSN(pop_es, "push %ax\n\t"
6567d36db35SAvi Kivity 			"pop %es\n\t"
6577d36db35SAvi Kivity 			"mov %es, %bx\n\t"
6587d36db35SAvi Kivity 			);
6597d36db35SAvi Kivity 	MK_INSN(push_pop_ss, "push %ss\n\t"
6607d36db35SAvi Kivity 			     "pushw %ax\n\t"
6617d36db35SAvi Kivity 			     "popw %ss\n\t"
6627d36db35SAvi Kivity 			     "mov %ss, %bx\n\t"
6637d36db35SAvi Kivity 			     "pop %ss\n\t"
6647d36db35SAvi Kivity 			);
6657d36db35SAvi Kivity 	MK_INSN(push_pop_fs, "push %fs\n\t"
6667d36db35SAvi Kivity 			     "pushl %eax\n\t"
6677d36db35SAvi Kivity 			     "popl %fs\n\t"
6687d36db35SAvi Kivity 			     "mov %fs, %ebx\n\t"
6697d36db35SAvi Kivity 			     "pop %fs\n\t"
6707d36db35SAvi Kivity 			);
67109b657b6SAvi Kivity 	MK_INSN(push_pop_high_esp_bits,
67209b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
67309b657b6SAvi Kivity 		"push %ax; \n\t"
67409b657b6SAvi Kivity 		"xor $0x12340000, %esp \n\t"
67509b657b6SAvi Kivity 		"pop %bx");
6767d36db35SAvi Kivity 
677*bd62e289SBill Wendling 	init_inregs(NULL);
67818253fdeSAvi Kivity 
67918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push32);
6806055ea1fSAvi Kivity 	report("push/pop 1", R_AX|R_BX,
6816055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x12345678);
6827d36db35SAvi Kivity 
68318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push16);
6846055ea1fSAvi Kivity 	report("push/pop 2", R_AX|R_BX,
6856055ea1fSAvi Kivity 	       outregs.eax == outregs.ebx && outregs.eax == 0x1234);
6867d36db35SAvi Kivity 
68718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_es);
6886055ea1fSAvi Kivity 	report("push/pop 3", R_AX|R_BX,
6896055ea1fSAvi Kivity 	       outregs.ebx == outregs.eax && outregs.eax == 0x123);
6907d36db35SAvi Kivity 
69118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pop_es);
6926055ea1fSAvi Kivity 	report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax);
6937d36db35SAvi Kivity 
69418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_ss);
6956055ea1fSAvi Kivity 	report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax);
6967d36db35SAvi Kivity 
69718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_fs);
6986055ea1fSAvi Kivity 	report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax);
69909b657b6SAvi Kivity 
70009b657b6SAvi Kivity 	inregs.eax = 0x9977;
70109b657b6SAvi Kivity 	inregs.ebx = 0x7799;
70209b657b6SAvi Kivity 	exec_in_big_real_mode(&insn_push_pop_high_esp_bits);
70309b657b6SAvi Kivity 	report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977);
7047d36db35SAvi Kivity }
7057d36db35SAvi Kivity 
7062e3f9f1fSThomas Huth static void test_null(void)
7077d36db35SAvi Kivity {
708d4dc402cSAvi Kivity 	MK_INSN(null, "");
709d4dc402cSAvi Kivity 
710*bd62e289SBill Wendling 	init_inregs(NULL);
71118253fdeSAvi Kivity 
71218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_null);
7136055ea1fSAvi Kivity 	report("null", 0, 1);
7147d36db35SAvi Kivity }
7157d36db35SAvi Kivity 
7162e3f9f1fSThomas Huth static void test_pusha_popa(void)
7177d36db35SAvi Kivity {
7187d36db35SAvi Kivity 	MK_INSN(pusha, "pusha\n\t"
7197d36db35SAvi Kivity 		       "pop %edi\n\t"
7207d36db35SAvi Kivity 		       "pop %esi\n\t"
7217d36db35SAvi Kivity 		       "pop %ebp\n\t"
7227d36db35SAvi Kivity 		       "add $4, %esp\n\t"
7237d36db35SAvi Kivity 		       "pop %ebx\n\t"
7247d36db35SAvi Kivity 		       "pop %edx\n\t"
7257d36db35SAvi Kivity 		       "pop %ecx\n\t"
7267d36db35SAvi Kivity 		       "pop %eax\n\t"
7277d36db35SAvi Kivity 		       );
7287d36db35SAvi Kivity 
7297d36db35SAvi Kivity 	MK_INSN(popa, "push %eax\n\t"
7307d36db35SAvi Kivity 		      "push %ecx\n\t"
7317d36db35SAvi Kivity 		      "push %edx\n\t"
7327d36db35SAvi Kivity 		      "push %ebx\n\t"
7337d36db35SAvi Kivity 		      "push %esp\n\t"
7347d36db35SAvi Kivity 		      "push %ebp\n\t"
7357d36db35SAvi Kivity 		      "push %esi\n\t"
7367d36db35SAvi Kivity 		      "push %edi\n\t"
7377d36db35SAvi Kivity 		      "popa\n\t"
7387d36db35SAvi Kivity 		      );
7397d36db35SAvi Kivity 
740*bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6 });
7417d36db35SAvi Kivity 
74218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_pusha);
7436055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
74418253fdeSAvi Kivity 
74518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_popa);
7466055ea1fSAvi Kivity 	report("pusha/popa 1", 0, 1);
7477d36db35SAvi Kivity }
7487d36db35SAvi Kivity 
7492e3f9f1fSThomas Huth static void test_iret(void)
7507d36db35SAvi Kivity {
7517d36db35SAvi Kivity 	MK_INSN(iret32, "pushf\n\t"
7527d36db35SAvi Kivity 			"pushl %cs\n\t"
7537d36db35SAvi Kivity 			"call 1f\n\t" /* a near call will push eip onto the stack */
7547d36db35SAvi Kivity 			"jmp 2f\n\t"
7557d36db35SAvi Kivity 			"1: iret\n\t"
7567d36db35SAvi Kivity 			"2:\n\t"
7577d36db35SAvi Kivity 		     );
7587d36db35SAvi Kivity 
7597d36db35SAvi Kivity 	MK_INSN(iret16, "pushfw\n\t"
7607d36db35SAvi Kivity 			"pushw %cs\n\t"
7617d36db35SAvi Kivity 			"callw 1f\n\t"
7627d36db35SAvi Kivity 			"jmp 2f\n\t"
7637d36db35SAvi Kivity 			"1: iretw\n\t"
7647d36db35SAvi Kivity 			"2:\n\t");
7657d36db35SAvi Kivity 
7667d36db35SAvi Kivity 	MK_INSN(iret_flags32, "pushfl\n\t"
7677d36db35SAvi Kivity 			      "popl %eax\n\t"
7687d36db35SAvi Kivity 			      "andl $~0x2, %eax\n\t"
769964942e8SNadav Amit 			      "orl $0xffc18028, %eax\n\t"
7707d36db35SAvi Kivity 			      "pushl %eax\n\t"
7717d36db35SAvi Kivity 			      "pushl %cs\n\t"
7727d36db35SAvi Kivity 			      "call 1f\n\t"
7737d36db35SAvi Kivity 			      "jmp 2f\n\t"
7747d36db35SAvi Kivity 			      "1: iret\n\t"
7757d36db35SAvi Kivity 			      "2:\n\t");
7767d36db35SAvi Kivity 
7777d36db35SAvi Kivity 	MK_INSN(iret_flags16, "pushfw\n\t"
7787d36db35SAvi Kivity 			      "popw %ax\n\t"
7797d36db35SAvi Kivity 			      "and $~0x2, %ax\n\t"
7807d36db35SAvi Kivity 			      "or $0x8028, %ax\n\t"
7817d36db35SAvi Kivity 			      "pushw %ax\n\t"
7827d36db35SAvi Kivity 			      "pushw %cs\n\t"
7837d36db35SAvi Kivity 			      "callw 1f\n\t"
7847d36db35SAvi Kivity 			      "jmp 2f\n\t"
7857d36db35SAvi Kivity 			      "1: iretw\n\t"
7867d36db35SAvi Kivity 			      "2:\n\t");
7877d36db35SAvi Kivity 
788*bd62e289SBill Wendling 	init_inregs(NULL);
7897d36db35SAvi Kivity 
79018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret32);
7916055ea1fSAvi Kivity 	report("iret 1", 0, 1);
7927d36db35SAvi Kivity 
79318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret16);
7946055ea1fSAvi Kivity 	report("iret 2", 0, 1);
7957d36db35SAvi Kivity 
79618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags32);
7976055ea1fSAvi Kivity 	report("iret 3", R_AX, 1);
798964942e8SNadav Amit 	report("rflags.rf", ~0, !(outregs.eflags & (1 << 16)));
79918253fdeSAvi Kivity 
80018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_iret_flags16);
8016055ea1fSAvi Kivity 	report("iret 4", R_AX, 1);
8027d36db35SAvi Kivity }
8037d36db35SAvi Kivity 
8042e3f9f1fSThomas Huth static void test_int(void)
80596b9ca1eSMohammed Gamal {
806*bd62e289SBill Wendling 	init_inregs(NULL);
80796b9ca1eSMohammed Gamal 
80896b9ca1eSMohammed Gamal 	*(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */
80996b9ca1eSMohammed Gamal 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
81096b9ca1eSMohammed Gamal 
81196b9ca1eSMohammed Gamal 	MK_INSN(int11, "int $0x11\n\t");
81296b9ca1eSMohammed Gamal 
81318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_int11);
8146055ea1fSAvi Kivity 	report("int 1", 0, 1);
81596b9ca1eSMohammed Gamal }
81696b9ca1eSMohammed Gamal 
8172e3f9f1fSThomas Huth static void test_imul(void)
818fa74f8a6SMohammed Gamal {
819fa74f8a6SMohammed Gamal 	MK_INSN(imul8_1, "mov $2, %al\n\t"
820fa74f8a6SMohammed Gamal 			"mov $-4, %cx\n\t"
821fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
822fa74f8a6SMohammed Gamal 
823fa74f8a6SMohammed Gamal 	MK_INSN(imul16_1, "mov $2, %ax\n\t"
824fa74f8a6SMohammed Gamal 		      "mov $-4, %cx\n\t"
825fa74f8a6SMohammed Gamal 		      "imul %cx\n\t");
826fa74f8a6SMohammed Gamal 
827fa74f8a6SMohammed Gamal 	MK_INSN(imul32_1, "mov $2, %eax\n\t"
828fa74f8a6SMohammed Gamal 		       "mov $-4, %ecx\n\t"
829fa74f8a6SMohammed Gamal 		       "imul %ecx\n\t");
830fa74f8a6SMohammed Gamal 
831fa74f8a6SMohammed Gamal 	MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t"
832fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
833fa74f8a6SMohammed Gamal 			"imul %cl\n\t");
834fa74f8a6SMohammed Gamal 
835fa74f8a6SMohammed Gamal 	MK_INSN(imul16_2, "mov $2, %ax\n\t"
836fa74f8a6SMohammed Gamal 			"mov $4, %cx\n\t"
837fa74f8a6SMohammed Gamal 			"imul %cx\n\t");
838fa74f8a6SMohammed Gamal 
839fa74f8a6SMohammed Gamal 	MK_INSN(imul32_2, "mov $2, %eax\n\t"
840fa74f8a6SMohammed Gamal 			"mov $4, %ecx\n\t"
841fa74f8a6SMohammed Gamal 			"imul %ecx\n\t");
842fa74f8a6SMohammed Gamal 
843*bd62e289SBill Wendling 	init_inregs(NULL);
84418253fdeSAvi Kivity 
84518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_1);
8466055ea1fSAvi Kivity 	report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8);
847fa74f8a6SMohammed Gamal 
84818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_1);
8496055ea1fSAvi Kivity 	report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8);
850fa74f8a6SMohammed Gamal 
85118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_1);
8526055ea1fSAvi Kivity 	report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8);
853fa74f8a6SMohammed Gamal 
85418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul8_2);
8556055ea1fSAvi Kivity 	report("imul 4", R_AX | R_CX | R_DX,
8566055ea1fSAvi Kivity 	       (outregs.eax & 0xffff) == 8
85781050840SAvi Kivity 	       && (outregs.eax & 0xffff0000) == 0x12340000);
858fa74f8a6SMohammed Gamal 
85918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul16_2);
8606055ea1fSAvi Kivity 	report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8);
861fa74f8a6SMohammed Gamal 
86218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_imul32_2);
8636055ea1fSAvi Kivity 	report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8);
864fa74f8a6SMohammed Gamal }
865fa74f8a6SMohammed Gamal 
8662e3f9f1fSThomas Huth static void test_mul(void)
86759317bd1SMohammed Gamal {
86859317bd1SMohammed Gamal 	MK_INSN(mul8, "mov $2, %al\n\t"
86959317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
87059317bd1SMohammed Gamal 			"imul %cl\n\t");
87159317bd1SMohammed Gamal 
87259317bd1SMohammed Gamal 	MK_INSN(mul16, "mov $2, %ax\n\t"
87359317bd1SMohammed Gamal 			"mov $4, %cx\n\t"
87459317bd1SMohammed Gamal 			"imul %cx\n\t");
87559317bd1SMohammed Gamal 
87659317bd1SMohammed Gamal 	MK_INSN(mul32, "mov $2, %eax\n\t"
87759317bd1SMohammed Gamal 			"mov $4, %ecx\n\t"
87859317bd1SMohammed Gamal 			"imul %ecx\n\t");
87959317bd1SMohammed Gamal 
880*bd62e289SBill Wendling 	init_inregs(NULL);
88118253fdeSAvi Kivity 
88218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul8);
8836055ea1fSAvi Kivity 	report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8);
88459317bd1SMohammed Gamal 
88518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul16);
8866055ea1fSAvi Kivity 	report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8);
88759317bd1SMohammed Gamal 
88818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_mul32);
8896055ea1fSAvi Kivity 	report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8);
89059317bd1SMohammed Gamal }
89159317bd1SMohammed Gamal 
8922e3f9f1fSThomas Huth static void test_div(void)
8930d4c7614SMohammed Gamal {
8940d4c7614SMohammed Gamal 	MK_INSN(div8, "mov $257, %ax\n\t"
8950d4c7614SMohammed Gamal 			"mov $2, %cl\n\t"
8960d4c7614SMohammed Gamal 			"div %cl\n\t");
8970d4c7614SMohammed Gamal 
8980d4c7614SMohammed Gamal 	MK_INSN(div16, "mov $512, %ax\n\t"
8990d4c7614SMohammed Gamal 			"mov $5, %cx\n\t"
9000d4c7614SMohammed Gamal 			"div %cx\n\t");
9010d4c7614SMohammed Gamal 
9020d4c7614SMohammed Gamal 	MK_INSN(div32, "mov $512, %eax\n\t"
9030d4c7614SMohammed Gamal 			"mov $5, %ecx\n\t"
9040d4c7614SMohammed Gamal 			"div %ecx\n\t");
9050d4c7614SMohammed Gamal 
906*bd62e289SBill Wendling 	init_inregs(NULL);
90718253fdeSAvi Kivity 
90818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div8);
9096055ea1fSAvi Kivity 	report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384);
9100d4c7614SMohammed Gamal 
91118253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div16);
9126055ea1fSAvi Kivity 	report("div 2", R_AX | R_CX | R_DX,
9136055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
9140d4c7614SMohammed Gamal 
91518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_div32);
9166055ea1fSAvi Kivity 	report("div 3", R_AX | R_CX | R_DX,
9176055ea1fSAvi Kivity 	       outregs.eax == 102 && outregs.edx == 2);
9180d4c7614SMohammed Gamal }
9190d4c7614SMohammed Gamal 
9202e3f9f1fSThomas Huth static void test_idiv(void)
9210d4c7614SMohammed Gamal {
9220d4c7614SMohammed Gamal 	MK_INSN(idiv8, "mov $256, %ax\n\t"
9230d4c7614SMohammed Gamal 			"mov $-2, %cl\n\t"
9240d4c7614SMohammed Gamal 			"idiv %cl\n\t");
9250d4c7614SMohammed Gamal 
9260d4c7614SMohammed Gamal 	MK_INSN(idiv16, "mov $512, %ax\n\t"
9270d4c7614SMohammed Gamal 			"mov $-2, %cx\n\t"
9280d4c7614SMohammed Gamal 			"idiv %cx\n\t");
9290d4c7614SMohammed Gamal 
9300d4c7614SMohammed Gamal 	MK_INSN(idiv32, "mov $512, %eax\n\t"
9310d4c7614SMohammed Gamal 			"mov $-2, %ecx\n\t"
9320d4c7614SMohammed Gamal 			"idiv %ecx\n\t");
9330d4c7614SMohammed Gamal 
934*bd62e289SBill Wendling 	init_inregs(NULL);
93518253fdeSAvi Kivity 
93618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv8);
9376055ea1fSAvi Kivity 	report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128);
9380d4c7614SMohammed Gamal 
93918253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv16);
9406055ea1fSAvi Kivity 	report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256);
9410d4c7614SMohammed Gamal 
94218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_idiv32);
9436055ea1fSAvi Kivity 	report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256);
9440d4c7614SMohammed Gamal }
9450d4c7614SMohammed Gamal 
9462e3f9f1fSThomas Huth static void test_cbw(void)
9476e293cf5SWei Yongjun {
9486e293cf5SWei Yongjun 	MK_INSN(cbw, "mov $0xFE, %eax \n\t"
9496e293cf5SWei Yongjun 		     "cbw\n\t");
9506e293cf5SWei Yongjun 	MK_INSN(cwde, "mov $0xFFFE, %eax \n\t"
9516e293cf5SWei Yongjun 		      "cwde\n\t");
9526e293cf5SWei Yongjun 
953*bd62e289SBill Wendling 	init_inregs(NULL);
95418253fdeSAvi Kivity 
95518253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cbw);
9566055ea1fSAvi Kivity 	report("cbq 1", ~0, outregs.eax == 0xFFFE);
9576e293cf5SWei Yongjun 
95818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwde);
9596055ea1fSAvi Kivity 	report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE);
9606e293cf5SWei Yongjun }
9616e293cf5SWei Yongjun 
9622e3f9f1fSThomas Huth static void test_loopcc(void)
963eacef4e2SWei Yongjun {
964eacef4e2SWei Yongjun 	MK_INSN(loop, "mov $10, %ecx\n\t"
965eacef4e2SWei Yongjun 		      "1: inc %eax\n\t"
966eacef4e2SWei Yongjun 		      "loop 1b\n\t");
967eacef4e2SWei Yongjun 
968eacef4e2SWei Yongjun 	MK_INSN(loope, "mov $10, %ecx\n\t"
969eacef4e2SWei Yongjun 		       "mov $1, %eax\n\t"
970eacef4e2SWei Yongjun 		       "1: dec %eax\n\t"
971eacef4e2SWei Yongjun 		       "loope 1b\n\t");
972eacef4e2SWei Yongjun 
973eacef4e2SWei Yongjun 	MK_INSN(loopne, "mov $10, %ecx\n\t"
974eacef4e2SWei Yongjun 		        "mov $5, %eax\n\t"
975eacef4e2SWei Yongjun 		        "1: dec %eax\n\t"
976eacef4e2SWei Yongjun 			"loopne 1b\n\t");
977eacef4e2SWei Yongjun 
978*bd62e289SBill Wendling 	init_inregs(NULL);
979eacef4e2SWei Yongjun 
98018253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loop);
9816055ea1fSAvi Kivity 	report("LOOPcc short 1", R_AX, outregs.eax == 10);
98218253fdeSAvi Kivity 
98318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loope);
9846055ea1fSAvi Kivity 	report("LOOPcc short 2", R_AX | R_CX,
9856055ea1fSAvi Kivity 	       outregs.eax == -1 && outregs.ecx == 8);
986eacef4e2SWei Yongjun 
98718253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_loopne);
9886055ea1fSAvi Kivity 	report("LOOPcc short 3", R_AX | R_CX,
9896055ea1fSAvi Kivity 	       outregs.eax == 0 && outregs.ecx == 5);
990eacef4e2SWei Yongjun }
991eacef4e2SWei Yongjun 
992b274feedSAvi Kivity static void test_das(void)
993b274feedSAvi Kivity {
994b274feedSAvi Kivity     short i;
99581050840SAvi Kivity     u16 nr_fail = 0;
996b274feedSAvi Kivity     static unsigned test_cases[1024] = {
997b274feedSAvi Kivity         0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00,
998b274feedSAvi Kivity         0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01,
999b274feedSAvi Kivity         0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02,
1000b274feedSAvi Kivity         0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03,
1001b274feedSAvi Kivity         0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04,
1002b274feedSAvi Kivity         0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05,
1003b274feedSAvi Kivity         0x06000606, 0x8701a606, 0x56100006, 0x9711a006,
1004b274feedSAvi Kivity         0x02000707, 0x8301a707, 0x12100107, 0x9311a107,
1005b274feedSAvi Kivity         0x02000808, 0x8301a808, 0x12100208, 0x9311a208,
1006b274feedSAvi Kivity         0x06000909, 0x8701a909, 0x16100309, 0x9711a309,
1007b274feedSAvi Kivity         0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a,
1008b274feedSAvi Kivity         0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b,
1009b274feedSAvi Kivity         0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c,
1010b274feedSAvi Kivity         0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d,
1011b274feedSAvi Kivity         0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e,
1012b274feedSAvi Kivity         0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f,
1013b274feedSAvi Kivity         0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10,
1014b274feedSAvi Kivity         0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11,
1015b274feedSAvi Kivity         0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12,
1016b274feedSAvi Kivity         0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13,
1017b274feedSAvi Kivity         0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14,
1018b274feedSAvi Kivity         0x02001515, 0x8301b515, 0x16100f15, 0x9711af15,
1019b274feedSAvi Kivity         0x02001616, 0x8301b616, 0x12101016, 0x9311b016,
1020b274feedSAvi Kivity         0x06001717, 0x8701b717, 0x16101117, 0x9711b117,
1021b274feedSAvi Kivity         0x06001818, 0x8701b818, 0x16101218, 0x9711b218,
1022b274feedSAvi Kivity         0x02001919, 0x8301b919, 0x12101319, 0x9311b319,
1023b274feedSAvi Kivity         0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a,
1024b274feedSAvi Kivity         0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b,
1025b274feedSAvi Kivity         0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c,
1026b274feedSAvi Kivity         0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d,
1027b274feedSAvi Kivity         0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e,
1028b274feedSAvi Kivity         0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f,
1029b274feedSAvi Kivity         0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20,
1030b274feedSAvi Kivity         0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21,
1031b274feedSAvi Kivity         0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22,
1032b274feedSAvi Kivity         0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23,
1033b274feedSAvi Kivity         0x06002424, 0x8301c424, 0x16101e24, 0x9711be24,
1034b274feedSAvi Kivity         0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25,
1035b274feedSAvi Kivity         0x02002626, 0x8701c626, 0x12102026, 0x9711c026,
1036b274feedSAvi Kivity         0x06002727, 0x8301c727, 0x16102127, 0x9311c127,
1037b274feedSAvi Kivity         0x06002828, 0x8301c828, 0x16102228, 0x9311c228,
1038b274feedSAvi Kivity         0x02002929, 0x8701c929, 0x12102329, 0x9711c329,
1039b274feedSAvi Kivity         0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a,
1040b274feedSAvi Kivity         0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b,
1041b274feedSAvi Kivity         0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c,
1042b274feedSAvi Kivity         0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d,
1043b274feedSAvi Kivity         0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e,
1044b274feedSAvi Kivity         0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f,
1045b274feedSAvi Kivity         0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30,
1046b274feedSAvi Kivity         0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31,
1047b274feedSAvi Kivity         0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32,
1048b274feedSAvi Kivity         0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33,
1049b274feedSAvi Kivity         0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34,
1050b274feedSAvi Kivity         0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35,
1051b274feedSAvi Kivity         0x06003636, 0x8301d636, 0x16103036, 0x9311d036,
1052b274feedSAvi Kivity         0x02003737, 0x8701d737, 0x12103137, 0x9711d137,
1053b274feedSAvi Kivity         0x02003838, 0x8701d838, 0x12103238, 0x9711d238,
1054b274feedSAvi Kivity         0x06003939, 0x8301d939, 0x16103339, 0x9311d339,
1055b274feedSAvi Kivity         0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a,
1056b274feedSAvi Kivity         0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b,
1057b274feedSAvi Kivity         0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c,
1058b274feedSAvi Kivity         0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d,
1059b274feedSAvi Kivity         0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e,
1060b274feedSAvi Kivity         0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f,
1061b274feedSAvi Kivity         0x02004040, 0x8301e040, 0x16103a40, 0x9311da40,
1062b274feedSAvi Kivity         0x06004141, 0x8701e141, 0x12103b41, 0x9711db41,
1063b274feedSAvi Kivity         0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42,
1064b274feedSAvi Kivity         0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43,
1065b274feedSAvi Kivity         0x06004444, 0x8701e444, 0x12103e44, 0x9711de44,
1066b274feedSAvi Kivity         0x02004545, 0x8301e545, 0x16103f45, 0x9311df45,
1067b274feedSAvi Kivity         0x02004646, 0x8301e646, 0x12104046, 0x9311e046,
1068b274feedSAvi Kivity         0x06004747, 0x8701e747, 0x16104147, 0x9711e147,
1069b274feedSAvi Kivity         0x06004848, 0x8701e848, 0x16104248, 0x9711e248,
1070b274feedSAvi Kivity         0x02004949, 0x8301e949, 0x12104349, 0x9311e349,
1071b274feedSAvi Kivity         0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a,
1072b274feedSAvi Kivity         0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b,
1073b274feedSAvi Kivity         0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c,
1074b274feedSAvi Kivity         0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d,
1075b274feedSAvi Kivity         0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e,
1076b274feedSAvi Kivity         0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f,
1077b274feedSAvi Kivity         0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50,
1078b274feedSAvi Kivity         0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51,
1079b274feedSAvi Kivity         0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52,
1080b274feedSAvi Kivity         0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53,
1081b274feedSAvi Kivity         0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54,
1082b274feedSAvi Kivity         0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55,
1083b274feedSAvi Kivity         0x06005656, 0x8701f656, 0x16105056, 0x9711f056,
1084b274feedSAvi Kivity         0x02005757, 0x8301f757, 0x12105157, 0x9311f157,
1085b274feedSAvi Kivity         0x02005858, 0x8301f858, 0x12105258, 0x9311f258,
1086b274feedSAvi Kivity         0x06005959, 0x8701f959, 0x16105359, 0x9711f359,
1087b274feedSAvi Kivity         0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a,
1088b274feedSAvi Kivity         0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b,
1089b274feedSAvi Kivity         0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c,
1090b274feedSAvi Kivity         0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d,
1091b274feedSAvi Kivity         0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e,
1092b274feedSAvi Kivity         0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f,
1093b274feedSAvi Kivity         0x06006060, 0x47010060, 0x16105a60, 0x9711fa60,
1094b274feedSAvi Kivity         0x02006161, 0x03010161, 0x12105b61, 0x9311fb61,
1095b274feedSAvi Kivity         0x02006262, 0x03010262, 0x16105c62, 0x9711fc62,
1096b274feedSAvi Kivity         0x06006363, 0x07010363, 0x12105d63, 0x9311fd63,
1097b274feedSAvi Kivity         0x02006464, 0x03010464, 0x12105e64, 0x9311fe64,
1098b274feedSAvi Kivity         0x06006565, 0x07010565, 0x16105f65, 0x9711ff65,
1099b274feedSAvi Kivity         0x06006666, 0x07010666, 0x16106066, 0x57110066,
1100b274feedSAvi Kivity         0x02006767, 0x03010767, 0x12106167, 0x13110167,
1101b274feedSAvi Kivity         0x02006868, 0x03010868, 0x12106268, 0x13110268,
1102b274feedSAvi Kivity         0x06006969, 0x07010969, 0x16106369, 0x17110369,
1103b274feedSAvi Kivity         0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a,
1104b274feedSAvi Kivity         0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b,
1105b274feedSAvi Kivity         0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c,
1106b274feedSAvi Kivity         0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d,
1107b274feedSAvi Kivity         0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e,
1108b274feedSAvi Kivity         0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f,
1109b274feedSAvi Kivity         0x02007070, 0x03011070, 0x16106a70, 0x17110a70,
1110b274feedSAvi Kivity         0x06007171, 0x07011171, 0x12106b71, 0x13110b71,
1111b274feedSAvi Kivity         0x06007272, 0x07011272, 0x16106c72, 0x17110c72,
1112b274feedSAvi Kivity         0x02007373, 0x03011373, 0x12106d73, 0x13110d73,
1113b274feedSAvi Kivity         0x06007474, 0x07011474, 0x12106e74, 0x13110e74,
1114b274feedSAvi Kivity         0x02007575, 0x03011575, 0x16106f75, 0x17110f75,
1115b274feedSAvi Kivity         0x02007676, 0x03011676, 0x12107076, 0x13111076,
1116b274feedSAvi Kivity         0x06007777, 0x07011777, 0x16107177, 0x17111177,
1117b274feedSAvi Kivity         0x06007878, 0x07011878, 0x16107278, 0x17111278,
1118b274feedSAvi Kivity         0x02007979, 0x03011979, 0x12107379, 0x13111379,
1119b274feedSAvi Kivity         0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a,
1120b274feedSAvi Kivity         0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b,
1121b274feedSAvi Kivity         0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c,
1122b274feedSAvi Kivity         0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d,
1123b274feedSAvi Kivity         0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e,
1124b274feedSAvi Kivity         0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f,
1125b274feedSAvi Kivity         0x82008080, 0x03012080, 0x12107a80, 0x13111a80,
1126b274feedSAvi Kivity         0x86008181, 0x07012181, 0x16107b81, 0x17111b81,
1127b274feedSAvi Kivity         0x86008282, 0x07012282, 0x12107c82, 0x13111c82,
1128b274feedSAvi Kivity         0x82008383, 0x03012383, 0x16107d83, 0x17111d83,
1129b274feedSAvi Kivity         0x86008484, 0x07012484, 0x16107e84, 0x17111e84,
1130b274feedSAvi Kivity         0x82008585, 0x03012585, 0x12107f85, 0x13111f85,
1131b274feedSAvi Kivity         0x82008686, 0x03012686, 0x92108086, 0x13112086,
1132b274feedSAvi Kivity         0x86008787, 0x07012787, 0x96108187, 0x17112187,
1133b274feedSAvi Kivity         0x86008888, 0x07012888, 0x96108288, 0x17112288,
1134b274feedSAvi Kivity         0x82008989, 0x03012989, 0x92108389, 0x13112389,
1135b274feedSAvi Kivity         0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a,
1136b274feedSAvi Kivity         0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b,
1137b274feedSAvi Kivity         0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c,
1138b274feedSAvi Kivity         0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d,
1139b274feedSAvi Kivity         0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e,
1140b274feedSAvi Kivity         0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f,
1141b274feedSAvi Kivity         0x86009090, 0x07013090, 0x92108a90, 0x13112a90,
1142b274feedSAvi Kivity         0x82009191, 0x03013191, 0x96108b91, 0x17112b91,
1143b274feedSAvi Kivity         0x82009292, 0x03013292, 0x92108c92, 0x13112c92,
1144b274feedSAvi Kivity         0x86009393, 0x07013393, 0x96108d93, 0x17112d93,
1145b274feedSAvi Kivity         0x82009494, 0x03013494, 0x96108e94, 0x17112e94,
1146b274feedSAvi Kivity         0x86009595, 0x07013595, 0x92108f95, 0x13112f95,
1147b274feedSAvi Kivity         0x86009696, 0x07013696, 0x96109096, 0x17113096,
1148b274feedSAvi Kivity         0x82009797, 0x03013797, 0x92109197, 0x13113197,
1149b274feedSAvi Kivity         0x82009898, 0x03013898, 0x92109298, 0x13113298,
1150b274feedSAvi Kivity         0x86009999, 0x07013999, 0x96109399, 0x17113399,
1151b274feedSAvi Kivity         0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a,
1152b274feedSAvi Kivity         0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b,
1153b274feedSAvi Kivity         0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c,
1154b274feedSAvi Kivity         0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d,
1155b274feedSAvi Kivity         0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e,
1156b274feedSAvi Kivity         0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f,
1157b274feedSAvi Kivity         0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0,
1158b274feedSAvi Kivity         0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1,
1159b274feedSAvi Kivity         0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2,
1160b274feedSAvi Kivity         0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3,
1161b274feedSAvi Kivity         0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4,
1162b274feedSAvi Kivity         0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5,
1163b274feedSAvi Kivity         0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6,
1164b274feedSAvi Kivity         0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7,
1165b274feedSAvi Kivity         0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8,
1166b274feedSAvi Kivity         0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9,
1167b274feedSAvi Kivity         0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa,
1168b274feedSAvi Kivity         0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab,
1169b274feedSAvi Kivity         0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac,
1170b274feedSAvi Kivity         0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad,
1171b274feedSAvi Kivity         0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae,
1172b274feedSAvi Kivity         0x130049af, 0x130149af, 0x131049af, 0x131149af,
1173b274feedSAvi Kivity         0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0,
1174b274feedSAvi Kivity         0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1,
1175b274feedSAvi Kivity         0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2,
1176b274feedSAvi Kivity         0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3,
1177b274feedSAvi Kivity         0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4,
1178b274feedSAvi Kivity         0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5,
1179b274feedSAvi Kivity         0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6,
1180b274feedSAvi Kivity         0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7,
1181b274feedSAvi Kivity         0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8,
1182b274feedSAvi Kivity         0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9,
1183b274feedSAvi Kivity         0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba,
1184b274feedSAvi Kivity         0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb,
1185b274feedSAvi Kivity         0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc,
1186b274feedSAvi Kivity         0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd,
1187b274feedSAvi Kivity         0x130058be, 0x130158be, 0x131058be, 0x131158be,
1188b274feedSAvi Kivity         0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf,
1189b274feedSAvi Kivity         0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0,
1190b274feedSAvi Kivity         0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1,
1191b274feedSAvi Kivity         0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2,
1192b274feedSAvi Kivity         0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3,
1193b274feedSAvi Kivity         0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4,
1194b274feedSAvi Kivity         0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5,
1195b274feedSAvi Kivity         0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6,
1196b274feedSAvi Kivity         0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7,
1197b274feedSAvi Kivity         0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8,
1198b274feedSAvi Kivity         0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9,
1199b274feedSAvi Kivity         0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca,
1200b274feedSAvi Kivity         0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb,
1201b274feedSAvi Kivity         0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc,
1202b274feedSAvi Kivity         0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd,
1203b274feedSAvi Kivity         0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce,
1204b274feedSAvi Kivity         0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf,
1205b274feedSAvi Kivity         0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0,
1206b274feedSAvi Kivity         0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1,
1207b274feedSAvi Kivity         0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2,
1208b274feedSAvi Kivity         0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3,
1209b274feedSAvi Kivity         0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4,
1210b274feedSAvi Kivity         0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5,
1211b274feedSAvi Kivity         0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6,
1212b274feedSAvi Kivity         0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7,
1213b274feedSAvi Kivity         0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8,
1214b274feedSAvi Kivity         0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9,
1215b274feedSAvi Kivity         0x170074da, 0x170174da, 0x171074da, 0x171174da,
1216b274feedSAvi Kivity         0x130075db, 0x130175db, 0x131075db, 0x131175db,
1217b274feedSAvi Kivity         0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc,
1218b274feedSAvi Kivity         0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd,
1219b274feedSAvi Kivity         0x170078de, 0x170178de, 0x171078de, 0x171178de,
1220b274feedSAvi Kivity         0x130079df, 0x130179df, 0x131079df, 0x131179df,
1221b274feedSAvi Kivity         0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0,
1222b274feedSAvi Kivity         0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1,
1223b274feedSAvi Kivity         0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2,
1224b274feedSAvi Kivity         0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3,
1225b274feedSAvi Kivity         0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4,
1226b274feedSAvi Kivity         0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5,
1227b274feedSAvi Kivity         0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6,
1228b274feedSAvi Kivity         0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7,
1229b274feedSAvi Kivity         0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8,
1230b274feedSAvi Kivity         0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9,
1231b274feedSAvi Kivity         0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea,
1232b274feedSAvi Kivity         0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb,
1233b274feedSAvi Kivity         0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec,
1234b274feedSAvi Kivity         0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed,
1235b274feedSAvi Kivity         0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee,
1236b274feedSAvi Kivity         0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef,
1237b274feedSAvi Kivity         0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0,
1238b274feedSAvi Kivity         0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1,
1239b274feedSAvi Kivity         0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2,
1240b274feedSAvi Kivity         0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3,
1241b274feedSAvi Kivity         0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4,
1242b274feedSAvi Kivity         0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5,
1243b274feedSAvi Kivity         0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6,
1244b274feedSAvi Kivity         0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7,
1245b274feedSAvi Kivity         0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8,
1246b274feedSAvi Kivity         0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9,
1247b274feedSAvi Kivity         0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa,
1248b274feedSAvi Kivity         0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb,
1249b274feedSAvi Kivity         0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc,
1250b274feedSAvi Kivity         0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd,
1251b274feedSAvi Kivity         0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe,
1252b274feedSAvi Kivity         0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff,
1253b274feedSAvi Kivity     };
1254b274feedSAvi Kivity 
1255b274feedSAvi Kivity     MK_INSN(das, "das");
1256b274feedSAvi Kivity 
1257*bd62e289SBill Wendling     init_inregs(NULL);
125818253fdeSAvi Kivity 
1259b274feedSAvi Kivity     for (i = 0; i < 1024; ++i) {
1260b274feedSAvi Kivity         unsigned tmp = test_cases[i];
1261b274feedSAvi Kivity         inregs.eax = tmp & 0xff;
1262b274feedSAvi Kivity         inregs.eflags = (tmp >> 16) & 0xff;
126318253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_das);
126418253fdeSAvi Kivity 	if (!regs_equal(R_AX)
1265b274feedSAvi Kivity             || outregs.eax != ((tmp >> 8) & 0xff)
1266b274feedSAvi Kivity             || (outregs.eflags & 0xff) != (tmp >> 24)) {
126781050840SAvi Kivity 	    ++nr_fail;
126881050840SAvi Kivity 	    break;
1269b274feedSAvi Kivity         }
1270b274feedSAvi Kivity     }
12716055ea1fSAvi Kivity     report("DAS", ~0, nr_fail == 0);
1272b274feedSAvi Kivity }
1273b274feedSAvi Kivity 
12742e3f9f1fSThomas Huth static void test_cwd_cdq(void)
12750cbd5b06SMohammed Gamal {
12760cbd5b06SMohammed Gamal 	/* Sign-bit set */
12770cbd5b06SMohammed Gamal 	MK_INSN(cwd_1, "mov $0x8000, %ax\n\t"
12780cbd5b06SMohammed Gamal 		       "cwd\n\t");
12790cbd5b06SMohammed Gamal 
12800cbd5b06SMohammed Gamal 	/* Sign-bit not set */
12810cbd5b06SMohammed Gamal 	MK_INSN(cwd_2, "mov $0x1000, %ax\n\t"
12820cbd5b06SMohammed Gamal 		       "cwd\n\t");
12830cbd5b06SMohammed Gamal 
12840cbd5b06SMohammed Gamal 	/* Sign-bit set */
12850cbd5b06SMohammed Gamal 	MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t"
12860cbd5b06SMohammed Gamal 		       "cdq\n\t");
12870cbd5b06SMohammed Gamal 
12880cbd5b06SMohammed Gamal 	/* Sign-bit not set */
12890cbd5b06SMohammed Gamal 	MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t"
12900cbd5b06SMohammed Gamal 		       "cdq\n\t");
12910cbd5b06SMohammed Gamal 
1292*bd62e289SBill Wendling 	init_inregs(NULL);
129318253fdeSAvi Kivity 
129418253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_1);
12956055ea1fSAvi Kivity 	report("cwd 1", R_AX | R_DX,
12966055ea1fSAvi Kivity 	       outregs.eax == 0x8000 && outregs.edx == 0xffff);
12970cbd5b06SMohammed Gamal 
129818253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cwd_2);
12996055ea1fSAvi Kivity 	report("cwd 2", R_AX | R_DX,
13006055ea1fSAvi Kivity 	       outregs.eax == 0x1000 && outregs.edx == 0);
13010cbd5b06SMohammed Gamal 
130218253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_1);
13036055ea1fSAvi Kivity 	report("cdq 1", R_AX | R_DX,
13046055ea1fSAvi Kivity 	       outregs.eax == 0x80000000 && outregs.edx == 0xffffffff);
13050cbd5b06SMohammed Gamal 
130618253fdeSAvi Kivity 	exec_in_big_real_mode(&insn_cdq_2);
13076055ea1fSAvi Kivity 	report("cdq 2", R_AX | R_DX,
13086055ea1fSAvi Kivity 	       outregs.eax == 0x10000000 && outregs.edx == 0);
13090cbd5b06SMohammed Gamal }
13100cbd5b06SMohammed Gamal 
131137f51a4aSWei Yongjun static struct {
131237f51a4aSWei Yongjun         void *address;
131337f51a4aSWei Yongjun         unsigned short sel;
131437f51a4aSWei Yongjun } __attribute__((packed)) desc = {
131537f51a4aSWei Yongjun 	(void *)0x1234,
131637f51a4aSWei Yongjun 	0x10,
131737f51a4aSWei Yongjun };
131837f51a4aSWei Yongjun 
13192e3f9f1fSThomas Huth static void test_lds_lss(void)
132037f51a4aSWei Yongjun {
1321*bd62e289SBill Wendling 	init_inregs(&(struct regs){ .ebx = (unsigned long)&desc });
132237f51a4aSWei Yongjun 
132337f51a4aSWei Yongjun 	MK_INSN(lds, "push %ds\n\t"
132437f51a4aSWei Yongjun 		     "lds (%ebx), %eax\n\t"
132537f51a4aSWei Yongjun 		     "mov %ds, %ebx\n\t"
132637f51a4aSWei Yongjun 		     "pop %ds\n\t");
132737f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lds);
132837f51a4aSWei Yongjun 	report("lds", R_AX | R_BX,
132937f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
133037f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
133137f51a4aSWei Yongjun 
1332eb6687a2SBill Wendling 	MK_INSN(les, "les (%ebx), %eax\n\t"
1333eb6687a2SBill Wendling 		     "mov %es, %ebx\n\t");
133437f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_les);
133537f51a4aSWei Yongjun 	report("les", R_AX | R_BX,
133637f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
133737f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
133837f51a4aSWei Yongjun 
133937f51a4aSWei Yongjun 	MK_INSN(lfs, "push %fs\n\t"
134037f51a4aSWei Yongjun 		     "lfs (%ebx), %eax\n\t"
134137f51a4aSWei Yongjun 		     "mov %fs, %ebx\n\t"
134237f51a4aSWei Yongjun 		     "pop %fs\n\t");
134337f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lfs);
134437f51a4aSWei Yongjun 	report("lfs", R_AX | R_BX,
134537f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
134637f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
134737f51a4aSWei Yongjun 
134837f51a4aSWei Yongjun 	MK_INSN(lgs, "push %gs\n\t"
134937f51a4aSWei Yongjun 		     "lgs (%ebx), %eax\n\t"
135037f51a4aSWei Yongjun 		     "mov %gs, %ebx\n\t"
135137f51a4aSWei Yongjun 		     "pop %gs\n\t");
135237f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lgs);
135337f51a4aSWei Yongjun 	report("lgs", R_AX | R_BX,
135437f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
135537f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
135637f51a4aSWei Yongjun 
135737f51a4aSWei Yongjun 	MK_INSN(lss, "push %ss\n\t"
135837f51a4aSWei Yongjun 		     "lss (%ebx), %eax\n\t"
135937f51a4aSWei Yongjun 		     "mov %ss, %ebx\n\t"
136037f51a4aSWei Yongjun 		     "pop %ss\n\t");
136137f51a4aSWei Yongjun 	exec_in_big_real_mode(&insn_lss);
136237f51a4aSWei Yongjun 	report("lss", R_AX | R_BX,
136337f51a4aSWei Yongjun 		outregs.eax == (unsigned long)desc.address &&
136437f51a4aSWei Yongjun 		outregs.ebx == desc.sel);
136537f51a4aSWei Yongjun }
136637f51a4aSWei Yongjun 
13672e3f9f1fSThomas Huth static void test_jcxz(void)
1368b1c7c575SWei Yongjun {
1369b1c7c575SWei Yongjun 	MK_INSN(jcxz1, "jcxz 1f\n\t"
1370b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1371b1c7c575SWei Yongjun 		       "1:\n\t");
1372b1c7c575SWei Yongjun 	MK_INSN(jcxz2, "mov $0x100, %ecx\n\t"
1373b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1374b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1375b1c7c575SWei Yongjun 		       "mov $0, %ecx\n\t"
1376b1c7c575SWei Yongjun 		       "1:\n\t");
1377b1c7c575SWei Yongjun 	MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t"
1378b1c7c575SWei Yongjun 		       "jcxz 1f\n\t"
1379b1c7c575SWei Yongjun 		       "mov $0x1234, %eax\n\t"
1380b1c7c575SWei Yongjun 		       "1:\n\t");
1381b1c7c575SWei Yongjun 	MK_INSN(jecxz1, "jecxz 1f\n\t"
1382b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1383b1c7c575SWei Yongjun 			"1:\n\t");
1384b1c7c575SWei Yongjun 	MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t"
1385b1c7c575SWei Yongjun 			"jecxz 1f\n\t"
1386b1c7c575SWei Yongjun 			"mov $0x1234, %eax\n\t"
1387b1c7c575SWei Yongjun 			"mov $0, %ecx\n\t"
1388b1c7c575SWei Yongjun 			"1:\n\t");
1389b1c7c575SWei Yongjun 
1390*bd62e289SBill Wendling 	init_inregs(NULL);
1391b1c7c575SWei Yongjun 
1392b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz1);
1393b1c7c575SWei Yongjun 	report("jcxz short 1", 0, 1);
1394b1c7c575SWei Yongjun 
1395b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz2);
1396b1c7c575SWei Yongjun 	report("jcxz short 2", R_AX, outregs.eax == 0x1234);
1397b1c7c575SWei Yongjun 
1398b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jcxz3);
1399b1c7c575SWei Yongjun 	report("jcxz short 3", R_CX, outregs.ecx == 0x10000);
1400b1c7c575SWei Yongjun 
1401b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz1);
1402b1c7c575SWei Yongjun 	report("jecxz short 1", 0, 1);
1403b1c7c575SWei Yongjun 
1404b1c7c575SWei Yongjun 	exec_in_big_real_mode(&insn_jecxz2);
1405b1c7c575SWei Yongjun 	report("jecxz short 2", R_AX, outregs.eax == 0x1234);
1406b1c7c575SWei Yongjun }
1407b1c7c575SWei Yongjun 
14088f578e98SAvi Kivity static void test_cpuid(void)
14098f578e98SAvi Kivity {
14108f578e98SAvi Kivity     MK_INSN(cpuid, "cpuid");
14118f578e98SAvi Kivity     unsigned function = 0x1234;
14128f578e98SAvi Kivity     unsigned eax, ebx, ecx, edx;
14138f578e98SAvi Kivity 
1414*bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = function });
1415*bd62e289SBill Wendling 
1416*bd62e289SBill Wendling     eax = inregs.eax;
1417*bd62e289SBill Wendling     ecx = inregs.ecx;
1418674d2dbeSPaolo Bonzini     asm("cpuid" : "+a"(eax), "=b"(ebx), "+c"(ecx), "=d"(edx));
14198f578e98SAvi Kivity     exec_in_big_real_mode(&insn_cpuid);
14208f578e98SAvi Kivity     report("cpuid", R_AX|R_BX|R_CX|R_DX,
14218f578e98SAvi Kivity 	   outregs.eax == eax && outregs.ebx == ebx
14228f578e98SAvi Kivity 	   && outregs.ecx == ecx && outregs.edx == edx);
14238f578e98SAvi Kivity }
14248f578e98SAvi Kivity 
1425ed93f43bSAvi Kivity static void test_ss_base_for_esp_ebp(void)
1426ed93f43bSAvi Kivity {
1427ed93f43bSAvi Kivity     MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss");
1428ed93f43bSAvi Kivity     MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss");
1429ed93f43bSAvi Kivity     static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 };
1430ed93f43bSAvi Kivity 
1431*bd62e289SBill Wendling     init_inregs(&(struct regs){ .ebx = 1, .ebp = (unsigned)array });
1432*bd62e289SBill Wendling 
1433ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel1);
1434ed93f43bSAvi Kivity     report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321);
1435*bd62e289SBill Wendling 
1436ed93f43bSAvi Kivity     inregs.ebx = 1;
1437ed93f43bSAvi Kivity     inregs.ebp = (unsigned)array;
1438ed93f43bSAvi Kivity     inregs.edi = 0;
1439ed93f43bSAvi Kivity     exec_in_big_real_mode(&insn_ssrel2);
1440ed93f43bSAvi Kivity     report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321);
1441ed93f43bSAvi Kivity }
1442ed93f43bSAvi Kivity 
1443975ca087SPeter Feiner extern unsigned long long r_gdt[];
1444975ca087SPeter Feiner 
1445c2281fa4SAvi Kivity static void test_sgdt_sidt(void)
1446c2281fa4SAvi Kivity {
1447c2281fa4SAvi Kivity     MK_INSN(sgdt, "sgdtw (%eax)");
1448c2281fa4SAvi Kivity     MK_INSN(sidt, "sidtw (%eax)");
1449975ca087SPeter Feiner     struct table_descr x, y;
1450c2281fa4SAvi Kivity 
1451*bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = (unsigned)&y });
1452*bd62e289SBill Wendling 
1453c2281fa4SAvi Kivity     asm volatile("sgdtw %0" : "=m"(x));
1454c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sgdt);
1455975ca087SPeter Feiner     report("sgdt", 0, x.limit == y.limit && x.base == y.base);
1456c2281fa4SAvi Kivity 
1457c2281fa4SAvi Kivity     inregs.eax = (unsigned)&y;
1458c2281fa4SAvi Kivity     asm volatile("sidtw %0" : "=m"(x));
1459c2281fa4SAvi Kivity     exec_in_big_real_mode(&insn_sidt);
1460975ca087SPeter Feiner     report("sidt", 0, x.limit == y.limit && x.base == y.base);
1461c2281fa4SAvi Kivity }
1462c2281fa4SAvi Kivity 
146388b6dac4SPaolo Bonzini static void test_sahf(void)
146488b6dac4SPaolo Bonzini {
146588b6dac4SPaolo Bonzini     MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw");
146688b6dac4SPaolo Bonzini 
1467*bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0xfd00 });
1468*bd62e289SBill Wendling 
146988b6dac4SPaolo Bonzini     exec_in_big_real_mode(&insn_sahf);
147088b6dac4SPaolo Bonzini     report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7));
147188b6dac4SPaolo Bonzini }
147288b6dac4SPaolo Bonzini 
14737ae3645aSAvi Kivity static void test_lahf(void)
14747ae3645aSAvi Kivity {
14757ae3645aSAvi Kivity     MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf");
14767ae3645aSAvi Kivity 
1477*bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0xc7 });
1478*bd62e289SBill Wendling 
14797ae3645aSAvi Kivity     exec_in_big_real_mode(&insn_lahf);
14807ae3645aSAvi Kivity     report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax);
14817ae3645aSAvi Kivity }
14827ae3645aSAvi Kivity 
1483fd9ea640SAvi Kivity static void test_movzx_movsx(void)
1484fd9ea640SAvi Kivity {
1485fd9ea640SAvi Kivity     MK_INSN(movsx, "movsx %al, %ebx");
1486fd9ea640SAvi Kivity     MK_INSN(movzx, "movzx %al, %ebx");
14873013e079SGleb Natapov     MK_INSN(movzsah, "movsx %ah, %ebx");
14883013e079SGleb Natapov     MK_INSN(movzxah, "movzx %ah, %ebx");
1489fd9ea640SAvi Kivity 
1490*bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x1234569c });
1491*bd62e289SBill Wendling 
1492fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movsx);
1493fd9ea640SAvi Kivity     report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax);
1494fd9ea640SAvi Kivity     exec_in_big_real_mode(&insn_movzx);
1495fd9ea640SAvi Kivity     report("movzx", R_BX, outregs.ebx == (unsigned char)inregs.eax);
14963013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzsah);
14973013e079SGleb Natapov     report("movsx ah", R_BX, outregs.ebx == (signed char)(inregs.eax>>8));
14983013e079SGleb Natapov     exec_in_big_real_mode(&insn_movzxah);
14993013e079SGleb Natapov     report("movzx ah", R_BX, outregs.ebx == (unsigned char)(inregs.eax >> 8));
1500fd9ea640SAvi Kivity }
1501fd9ea640SAvi Kivity 
1502b493b2e8SAvi Kivity static void test_bswap(void)
1503b493b2e8SAvi Kivity {
1504b493b2e8SAvi Kivity     MK_INSN(bswap, "bswap %ecx");
1505b493b2e8SAvi Kivity 
1506*bd62e289SBill Wendling     init_inregs(&(struct regs){ .ecx = 0x12345678 });
1507*bd62e289SBill Wendling 
1508b493b2e8SAvi Kivity     exec_in_big_real_mode(&insn_bswap);
1509b493b2e8SAvi Kivity     report("bswap", R_CX, outregs.ecx == 0x78563412);
1510b493b2e8SAvi Kivity }
1511b493b2e8SAvi Kivity 
15128cd86387SGleb Natapov static void test_aad(void)
15138cd86387SGleb Natapov {
15148cd86387SGleb Natapov     MK_INSN(aad, "aad");
15158cd86387SGleb Natapov 
1516*bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x12345678 });
1517*bd62e289SBill Wendling 
15188cd86387SGleb Natapov     exec_in_big_real_mode(&insn_aad);
15198cd86387SGleb Natapov     report("aad", R_AX, outregs.eax == 0x123400d4);
15208cd86387SGleb Natapov }
15218cd86387SGleb Natapov 
15222a9b5718SPaolo Bonzini static void test_aam(void)
15232a9b5718SPaolo Bonzini {
15242a9b5718SPaolo Bonzini     MK_INSN(aam, "aam");
15252a9b5718SPaolo Bonzini 
1526*bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x76543210 });
1527*bd62e289SBill Wendling 
15282a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_aam);
15292a9b5718SPaolo Bonzini     report("aam", R_AX, outregs.eax == 0x76540106);
15302a9b5718SPaolo Bonzini }
15312a9b5718SPaolo Bonzini 
15322a9b5718SPaolo Bonzini static void test_xlat(void)
15332a9b5718SPaolo Bonzini {
15342a9b5718SPaolo Bonzini     MK_INSN(xlat, "xlat");
15352a9b5718SPaolo Bonzini     u8 table[256];
15362a9b5718SPaolo Bonzini     int i;
15372a9b5718SPaolo Bonzini 
15382a9b5718SPaolo Bonzini     for (i = 0; i < 256; i++) {
15392a9b5718SPaolo Bonzini         table[i] = i + 1;
15402a9b5718SPaolo Bonzini     }
15412a9b5718SPaolo Bonzini 
1542*bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x89abcdef, .ebx = (u32)table });
1543*bd62e289SBill Wendling 
15442a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_xlat);
15452a9b5718SPaolo Bonzini     report("xlat", R_AX, outregs.eax == 0x89abcdf0);
15462a9b5718SPaolo Bonzini }
15472a9b5718SPaolo Bonzini 
15482a9b5718SPaolo Bonzini static void test_salc(void)
15492a9b5718SPaolo Bonzini {
15502a9b5718SPaolo Bonzini     MK_INSN(clc_salc, "clc; .byte 0xd6");
15512a9b5718SPaolo Bonzini     MK_INSN(stc_salc, "stc; .byte 0xd6");
15522a9b5718SPaolo Bonzini 
1553*bd62e289SBill Wendling     init_inregs(&(struct regs){ .eax = 0x12345678 });
1554*bd62e289SBill Wendling 
15552a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_clc_salc);
15562a9b5718SPaolo Bonzini     report("salc (1)", R_AX, outregs.eax == 0x12345600);
15572a9b5718SPaolo Bonzini     exec_in_big_real_mode(&insn_stc_salc);
15582a9b5718SPaolo Bonzini     report("salc (2)", R_AX, outregs.eax == 0x123456ff);
15592a9b5718SPaolo Bonzini }
15602a9b5718SPaolo Bonzini 
15610987db7aSGleb Natapov static void test_fninit(void)
15620987db7aSGleb Natapov {
15630987db7aSGleb Natapov 	u16 fcw = -1, fsw = -1;
15640987db7aSGleb Natapov 	MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)");
15650987db7aSGleb Natapov 
1566*bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = (u32)&fsw, .ebx = (u32)&fcw });
15670987db7aSGleb Natapov 
15680987db7aSGleb Natapov 	exec_in_big_real_mode(&insn_fninit);
15690987db7aSGleb Natapov 	report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f);
15700987db7aSGleb Natapov }
15710987db7aSGleb Natapov 
15721a4c03a0SArthur Chunqi Li static void test_nopl(void)
15731a4c03a0SArthur Chunqi Li {
15741a4c03a0SArthur Chunqi Li 	MK_INSN(nopl1, ".byte 0x90\n\r"); // 1 byte nop
15751a4c03a0SArthur Chunqi Li 	MK_INSN(nopl2, ".byte 0x66, 0x90\n\r"); // 2 bytes nop
15761a4c03a0SArthur Chunqi Li 	MK_INSN(nopl3, ".byte 0x0f, 0x1f, 0x00\n\r"); // 3 bytes nop
15771a4c03a0SArthur Chunqi Li 	MK_INSN(nopl4, ".byte 0x0f, 0x1f, 0x40, 0x00\n\r"); // 4 bytes nop
15781a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl1);
15791a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl2);
15801a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl3);
15811a4c03a0SArthur Chunqi Li 	exec_in_big_real_mode(&insn_nopl4);
15821a4c03a0SArthur Chunqi Li 	report("nopl", 0, 1);
15831a4c03a0SArthur Chunqi Li }
15841a4c03a0SArthur Chunqi Li 
1585b5105e8bSPaolo Bonzini static u32 perf_baseline;
1586b5105e8bSPaolo Bonzini 
15877505ea23SPaolo Bonzini #define PERF_COUNT 1000000
1588b5105e8bSPaolo Bonzini 
1589b5105e8bSPaolo Bonzini #define MK_INSN_PERF(name, insn)                                \
1590b5105e8bSPaolo Bonzini 	MK_INSN(name, "rdtsc; mov %eax, %ebx; mov %edx, %esi\n" \
1591b5105e8bSPaolo Bonzini 		      "1:" insn "\n"                            \
15927505ea23SPaolo Bonzini 		      ".byte 0x67; loop 1b\n"                   \
1593b5105e8bSPaolo Bonzini 		      "rdtsc");
1594b5105e8bSPaolo Bonzini 
1595b5105e8bSPaolo Bonzini static u32 cycles_in_big_real_mode(struct insn_desc *insn)
1596b5105e8bSPaolo Bonzini {
1597b5105e8bSPaolo Bonzini 	u64 start, end;
1598b5105e8bSPaolo Bonzini 
1599*bd62e289SBill Wendling 	init_inregs(&(struct regs){ .ecx = PERF_COUNT });
1600*bd62e289SBill Wendling 
1601b5105e8bSPaolo Bonzini 	exec_in_big_real_mode(insn);
1602b5105e8bSPaolo Bonzini 	start = ((u64)outregs.esi << 32) | outregs.ebx;
1603b5105e8bSPaolo Bonzini 	end = ((u64)outregs.edx << 32) | outregs.eax;
1604b5105e8bSPaolo Bonzini 
1605b5105e8bSPaolo Bonzini 	return end - start;
1606b5105e8bSPaolo Bonzini }
1607b5105e8bSPaolo Bonzini 
1608b5105e8bSPaolo Bonzini static void test_perf_loop(void)
1609b5105e8bSPaolo Bonzini {
1610b5105e8bSPaolo Bonzini 	/*
1611b5105e8bSPaolo Bonzini 	 * This test runs simple instructions that should roughly take the
1612b5105e8bSPaolo Bonzini 	 * the same time to emulate: PERF_COUNT iterations of "loop" and 3
1613b5105e8bSPaolo Bonzini 	 * setup instructions.  Other performance tests can run PERF_COUNT
1614b5105e8bSPaolo Bonzini 	 * iterations of the same instruction and subtract the cycle count
1615b5105e8bSPaolo Bonzini 	 * of this test.
1616b5105e8bSPaolo Bonzini 	 */
1617b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_loop, "");
1618b5105e8bSPaolo Bonzini 	perf_baseline = cycles_in_big_real_mode(&insn_perf_loop);
1619b5105e8bSPaolo Bonzini 	print_serial_u32(perf_baseline / (PERF_COUNT + 3));
1620b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated jump instruction\n");
1621b5105e8bSPaolo Bonzini }
1622b5105e8bSPaolo Bonzini 
1623b5105e8bSPaolo Bonzini static void test_perf_mov(void)
1624b5105e8bSPaolo Bonzini {
1625b5105e8bSPaolo Bonzini 	u32 cyc;
1626b5105e8bSPaolo Bonzini 
1627b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_move, "mov %esi, %edi");
1628b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_move);
1629b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1630b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated move instruction\n");
1631b5105e8bSPaolo Bonzini }
1632b5105e8bSPaolo Bonzini 
1633b5105e8bSPaolo Bonzini static void test_perf_arith(void)
1634b5105e8bSPaolo Bonzini {
1635b5105e8bSPaolo Bonzini 	u32 cyc;
1636b5105e8bSPaolo Bonzini 
1637b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_arith, "add $4, %edi");
1638b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_arith);
1639b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1640b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated arithmetic instruction\n");
1641b5105e8bSPaolo Bonzini }
1642b5105e8bSPaolo Bonzini 
1643b5105e8bSPaolo Bonzini static void test_perf_memory_load(void)
1644b5105e8bSPaolo Bonzini {
1645b5105e8bSPaolo Bonzini 	u32 cyc, tmp;
1646b5105e8bSPaolo Bonzini 
1647b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_memory_load, "cmp $0, (%edi)");
1648*bd62e289SBill Wendling 
1649*bd62e289SBill Wendling 	init_inregs(&(struct regs){ .edi = (u32)&tmp });
1650*bd62e289SBill Wendling 
1651b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_load);
1652b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1653b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated memory load instruction\n");
1654b5105e8bSPaolo Bonzini }
1655b5105e8bSPaolo Bonzini 
16569306cb8eSPaolo Bonzini static void test_perf_memory_store(void)
16579306cb8eSPaolo Bonzini {
16589306cb8eSPaolo Bonzini 	u32 cyc, tmp;
16599306cb8eSPaolo Bonzini 
16609306cb8eSPaolo Bonzini 	MK_INSN_PERF(perf_memory_store, "mov %ax, (%edi)");
1661*bd62e289SBill Wendling 
1662*bd62e289SBill Wendling 	init_inregs(&(struct regs){ .edi = (u32)&tmp });
1663*bd62e289SBill Wendling 
16649306cb8eSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_store);
16659306cb8eSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
16669306cb8eSPaolo Bonzini 	print_serial(" cycles/emulated memory store instruction\n");
16679306cb8eSPaolo Bonzini }
16689306cb8eSPaolo Bonzini 
1669b5105e8bSPaolo Bonzini static void test_perf_memory_rmw(void)
1670b5105e8bSPaolo Bonzini {
1671b5105e8bSPaolo Bonzini 	u32 cyc, tmp;
1672b5105e8bSPaolo Bonzini 
1673b5105e8bSPaolo Bonzini 	MK_INSN_PERF(perf_memory_rmw, "add $1, (%edi)");
1674*bd62e289SBill Wendling 
1675*bd62e289SBill Wendling 	init_inregs(&(struct regs){ .edi = (u32)&tmp });
1676*bd62e289SBill Wendling 
1677b5105e8bSPaolo Bonzini 	cyc = cycles_in_big_real_mode(&insn_perf_memory_rmw);
1678b5105e8bSPaolo Bonzini 	print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
1679b5105e8bSPaolo Bonzini 	print_serial(" cycles/emulated memory RMW instruction\n");
1680b5105e8bSPaolo Bonzini }
1681b5105e8bSPaolo Bonzini 
16822e3f9f1fSThomas Huth static void test_dr_mod(void)
16830a5701edSNadav Amit {
16840a5701edSNadav Amit 	MK_INSN(drmod, "movl %ebx, %dr0\n\t"
16850a5701edSNadav Amit 		       ".byte 0x0f \n\t .byte 0x21 \n\t .byte 0x0\n\t");
1686*bd62e289SBill Wendling 
1687*bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0xdead, .ebx = 0xaced });
1688*bd62e289SBill Wendling 
16890a5701edSNadav Amit 	exec_in_big_real_mode(&insn_drmod);
16900a5701edSNadav Amit 	report("mov dr with mod bits", R_AX | R_BX, outregs.eax == 0xaced);
16910a5701edSNadav Amit }
16920a5701edSNadav Amit 
16932e3f9f1fSThomas Huth static void test_smsw(void)
169499ee878cSNadav Amit {
169599ee878cSNadav Amit 	MK_INSN(smsw, "movl %cr0, %ebx\n\t"
169699ee878cSNadav Amit 		      "movl %ebx, %ecx\n\t"
169799ee878cSNadav Amit 		      "or $0x40000000, %ebx\n\t"
169899ee878cSNadav Amit 		      "movl %ebx, %cr0\n\t"
169999ee878cSNadav Amit 		      "smswl %eax\n\t"
170099ee878cSNadav Amit 		      "movl %ecx, %cr0\n\t");
1701*bd62e289SBill Wendling 
1702*bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0x12345678 });
1703*bd62e289SBill Wendling 
170499ee878cSNadav Amit 	exec_in_big_real_mode(&insn_smsw);
170599ee878cSNadav Amit 	report("smsw", R_AX | R_BX | R_CX, outregs.eax == outregs.ebx);
170699ee878cSNadav Amit }
170799ee878cSNadav Amit 
17082e3f9f1fSThomas Huth static void test_xadd(void)
17097bee560dSNadav Amit {
17107bee560dSNadav Amit 	MK_INSN(xadd, "xaddl %eax, %eax\n\t");
1711*bd62e289SBill Wendling 
1712*bd62e289SBill Wendling 	init_inregs(&(struct regs){ .eax = 0x12345678 });
1713*bd62e289SBill Wendling 
17147bee560dSNadav Amit 	exec_in_big_real_mode(&insn_xadd);
17157bee560dSNadav Amit 	report("xadd", R_AX, outregs.eax == inregs.eax * 2);
17167bee560dSNadav Amit }
17177bee560dSNadav Amit 
171899ee878cSNadav Amit 
17197d36db35SAvi Kivity void realmode_start(void)
17207d36db35SAvi Kivity {
17217d36db35SAvi Kivity 	test_null();
17227d36db35SAvi Kivity 
17237d36db35SAvi Kivity 	test_shld();
17247d36db35SAvi Kivity 	test_push_pop();
17257d36db35SAvi Kivity 	test_pusha_popa();
17267d36db35SAvi Kivity 	test_mov_imm();
17277d36db35SAvi Kivity 	test_cmp_imm();
17287d36db35SAvi Kivity 	test_add_imm();
17297d36db35SAvi Kivity 	test_sub_imm();
17307d36db35SAvi Kivity 	test_xor_imm();
17317d36db35SAvi Kivity 	test_io();
17327d36db35SAvi Kivity 	test_eflags_insn();
17337d36db35SAvi Kivity 	test_jcc_short();
17347d36db35SAvi Kivity 	test_jcc_near();
17357d36db35SAvi Kivity 	/* test_call() uses short jump so call it after testing jcc */
17367d36db35SAvi Kivity 	test_call();
17377d36db35SAvi Kivity 	/* long jmp test uses call near so test it after testing call */
17387d36db35SAvi Kivity 	test_long_jmp();
17397d36db35SAvi Kivity 	test_xchg();
17407d36db35SAvi Kivity 	test_iret();
174196b9ca1eSMohammed Gamal 	test_int();
1742fa74f8a6SMohammed Gamal 	test_imul();
174359317bd1SMohammed Gamal 	test_mul();
17440d4c7614SMohammed Gamal 	test_div();
17450d4c7614SMohammed Gamal 	test_idiv();
1746eacef4e2SWei Yongjun 	test_loopcc();
17476e293cf5SWei Yongjun 	test_cbw();
17480cbd5b06SMohammed Gamal 	test_cwd_cdq();
1749b274feedSAvi Kivity 	test_das();
175037f51a4aSWei Yongjun 	test_lds_lss();
1751b1c7c575SWei Yongjun 	test_jcxz();
17528f578e98SAvi Kivity 	test_cpuid();
1753ed93f43bSAvi Kivity 	test_ss_base_for_esp_ebp();
1754c2281fa4SAvi Kivity 	test_sgdt_sidt();
17557ae3645aSAvi Kivity 	test_lahf();
175688b6dac4SPaolo Bonzini 	test_sahf();
1757fd9ea640SAvi Kivity 	test_movzx_movsx();
1758b493b2e8SAvi Kivity 	test_bswap();
17598cd86387SGleb Natapov 	test_aad();
17602a9b5718SPaolo Bonzini 	test_aam();
17612a9b5718SPaolo Bonzini 	test_xlat();
17622a9b5718SPaolo Bonzini 	test_salc();
17630987db7aSGleb Natapov 	test_fninit();
17640a5701edSNadav Amit 	test_dr_mod();
176599ee878cSNadav Amit 	test_smsw();
17661a4c03a0SArthur Chunqi Li 	test_nopl();
17677bee560dSNadav Amit 	test_xadd();
1768b5105e8bSPaolo Bonzini 	test_perf_loop();
1769b5105e8bSPaolo Bonzini 	test_perf_mov();
1770b5105e8bSPaolo Bonzini 	test_perf_arith();
1771b5105e8bSPaolo Bonzini 	test_perf_memory_load();
17729306cb8eSPaolo Bonzini 	test_perf_memory_store();
1773b5105e8bSPaolo Bonzini 	test_perf_memory_rmw();
17747d36db35SAvi Kivity 
1775b393fe28SNadav Amit 	exit(failed);
17767d36db35SAvi Kivity }
17777d36db35SAvi Kivity 
17787d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff };
17797d36db35SAvi Kivity 
1780975ca087SPeter Feiner struct table_descr r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt };
17817d36db35SAvi Kivity 
17827d36db35SAvi Kivity asm(
17837d36db35SAvi Kivity 	".section .init \n\t"
17847d36db35SAvi Kivity 
17857d36db35SAvi Kivity 	".code32 \n\t"
17867d36db35SAvi Kivity 
17877d36db35SAvi Kivity 	"mb_magic = 0x1BADB002 \n\t"
17887d36db35SAvi Kivity 	"mb_flags = 0x0 \n\t"
17897d36db35SAvi Kivity 
17907d36db35SAvi Kivity 	"# multiboot header \n\t"
17917d36db35SAvi Kivity 	".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t"
17927d36db35SAvi Kivity 
17937d36db35SAvi Kivity 	".globl start \n\t"
17947d36db35SAvi Kivity 	".data \n\t"
17957d36db35SAvi Kivity 	". = . + 4096 \n\t"
17967d36db35SAvi Kivity 	"stacktop: \n\t"
17977d36db35SAvi Kivity 
17987d36db35SAvi Kivity 	".text \n\t"
17997d36db35SAvi Kivity 	"start: \n\t"
18007d36db35SAvi Kivity 	"lgdt r_gdt_descr \n\t"
18017d36db35SAvi Kivity 	"ljmp $8, $1f; 1: \n\t"
18027d36db35SAvi Kivity 	".code16gcc \n\t"
18037d36db35SAvi Kivity 	"mov $16, %eax \n\t"
18047d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
18057d36db35SAvi Kivity 	"mov %ax, %es \n\t"
18067d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
18077d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
18087d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
18097d36db35SAvi Kivity 	"mov %cr0, %eax \n\t"
18107d36db35SAvi Kivity 	"btc $0, %eax \n\t"
18117d36db35SAvi Kivity 	"mov %eax, %cr0 \n\t"
18127d36db35SAvi Kivity 	"ljmp $0, $realmode_entry \n\t"
18137d36db35SAvi Kivity 
18147d36db35SAvi Kivity 	"realmode_entry: \n\t"
18157d36db35SAvi Kivity 
18167d36db35SAvi Kivity 	"xor %ax, %ax \n\t"
18177d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
18187d36db35SAvi Kivity 	"mov %ax, %es \n\t"
18197d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
18207d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
18217d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
18227d36db35SAvi Kivity 	"mov $stacktop, %esp\n\t"
18237d36db35SAvi Kivity 	"ljmp $0, $realmode_start \n\t"
18247d36db35SAvi Kivity 
18257d36db35SAvi Kivity 	".code16gcc \n\t"
18267d36db35SAvi Kivity 	);
1827