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