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 142e3f9f1fSThomas Huth void realmode_start(void); 157d36db35SAvi Kivity void test_function(void); 167d36db35SAvi Kivity 177d36db35SAvi Kivity asm( 187d36db35SAvi Kivity "test_function: \n\t" 197d36db35SAvi Kivity "mov $0x1234, %eax \n\t" 207d36db35SAvi Kivity "ret" 217d36db35SAvi Kivity ); 227d36db35SAvi Kivity 237d36db35SAvi Kivity static int strlen(const char *str) 247d36db35SAvi Kivity { 257d36db35SAvi Kivity int n; 267d36db35SAvi Kivity 277d36db35SAvi Kivity for (n = 0; *str; ++str) 287d36db35SAvi Kivity ++n; 297d36db35SAvi Kivity return n; 307d36db35SAvi Kivity } 317d36db35SAvi Kivity 32f366255fSPaolo Bonzini static void outb(u8 data, u16 port) 33f366255fSPaolo Bonzini { 34f366255fSPaolo Bonzini asm volatile("out %0, %1" : : "a"(data), "d"(port)); 35f366255fSPaolo Bonzini } 36f366255fSPaolo Bonzini 37f366255fSPaolo Bonzini #ifdef USE_SERIAL 38f366255fSPaolo Bonzini static int serial_iobase = 0x3f8; 39f366255fSPaolo Bonzini static int serial_inited = 0; 40f366255fSPaolo Bonzini 41f366255fSPaolo Bonzini static u8 inb(u16 port) 42f366255fSPaolo Bonzini { 43f366255fSPaolo Bonzini u8 data; 44f366255fSPaolo Bonzini asm volatile("in %1, %0" : "=a"(data) : "d"(port)); 45f366255fSPaolo Bonzini return data; 46f366255fSPaolo Bonzini } 47f366255fSPaolo Bonzini 48f366255fSPaolo Bonzini static void serial_outb(char ch) 49f366255fSPaolo Bonzini { 50f366255fSPaolo Bonzini u8 lsr; 51f366255fSPaolo Bonzini 52f366255fSPaolo Bonzini do { 53f366255fSPaolo Bonzini lsr = inb(serial_iobase + 0x05); 54f366255fSPaolo Bonzini } while (!(lsr & 0x20)); 55f366255fSPaolo Bonzini 56f366255fSPaolo Bonzini outb(ch, serial_iobase + 0x00); 57f366255fSPaolo Bonzini } 58f366255fSPaolo Bonzini 59f366255fSPaolo Bonzini static void serial_init(void) 60f366255fSPaolo Bonzini { 61f366255fSPaolo Bonzini u8 lcr; 62f366255fSPaolo Bonzini 63f366255fSPaolo Bonzini /* set DLAB */ 64f366255fSPaolo Bonzini lcr = inb(serial_iobase + 0x03); 65f366255fSPaolo Bonzini lcr |= 0x80; 66f366255fSPaolo Bonzini outb(lcr, serial_iobase + 0x03); 67f366255fSPaolo Bonzini 68f366255fSPaolo Bonzini /* set baud rate to 115200 */ 69f366255fSPaolo Bonzini outb(0x01, serial_iobase + 0x00); 70f366255fSPaolo Bonzini outb(0x00, serial_iobase + 0x01); 71f366255fSPaolo Bonzini 72f366255fSPaolo Bonzini /* clear DLAB */ 73f366255fSPaolo Bonzini lcr = inb(serial_iobase + 0x03); 74f366255fSPaolo Bonzini lcr &= ~0x80; 75f366255fSPaolo Bonzini outb(lcr, serial_iobase + 0x03); 76f366255fSPaolo Bonzini } 77f366255fSPaolo Bonzini #endif 78f366255fSPaolo Bonzini 797d36db35SAvi Kivity static void print_serial(const char *buf) 807d36db35SAvi Kivity { 817d36db35SAvi Kivity unsigned long len = strlen(buf); 82f366255fSPaolo Bonzini #ifdef USE_SERIAL 83f366255fSPaolo Bonzini unsigned long i; 84f366255fSPaolo Bonzini if (!serial_inited) { 85f366255fSPaolo Bonzini serial_init(); 86f366255fSPaolo Bonzini serial_inited = 1; 87f366255fSPaolo Bonzini } 887d36db35SAvi Kivity 89f366255fSPaolo Bonzini for (i = 0; i < len; i++) { 90f366255fSPaolo Bonzini serial_outb(buf[i]); 91f366255fSPaolo Bonzini } 92f366255fSPaolo Bonzini #else 935edbb9aeSPaolo Bonzini asm volatile ("addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1)); 94f366255fSPaolo Bonzini #endif 957d36db35SAvi Kivity } 967d36db35SAvi Kivity 97b5105e8bSPaolo Bonzini static void print_serial_u32(u32 value) 98b5105e8bSPaolo Bonzini { 99b5105e8bSPaolo Bonzini char n[12], *p; 100b5105e8bSPaolo Bonzini p = &n[11]; 101b5105e8bSPaolo Bonzini *p = 0; 102b5105e8bSPaolo Bonzini do { 103b5105e8bSPaolo Bonzini *--p = '0' + (value % 10); 104b5105e8bSPaolo Bonzini value /= 10; 105b5105e8bSPaolo Bonzini } while (value > 0); 106b5105e8bSPaolo Bonzini print_serial(p); 107b5105e8bSPaolo Bonzini } 108b5105e8bSPaolo Bonzini 109b393fe28SNadav Amit static int failed; 110b393fe28SNadav Amit 1117d36db35SAvi Kivity static void exit(int code) 1127d36db35SAvi Kivity { 113f366255fSPaolo Bonzini outb(code, 0xf4); 1147d36db35SAvi Kivity } 1157d36db35SAvi Kivity 1167d36db35SAvi Kivity struct regs { 1177d36db35SAvi Kivity u32 eax, ebx, ecx, edx; 1187d36db35SAvi Kivity u32 esi, edi, esp, ebp; 1197d36db35SAvi Kivity u32 eip, eflags; 1207d36db35SAvi Kivity }; 1217d36db35SAvi Kivity 122975ca087SPeter Feiner struct table_descr { 123975ca087SPeter Feiner u16 limit; 124975ca087SPeter Feiner void *base; 125975ca087SPeter Feiner } __attribute__((packed)); 126975ca087SPeter Feiner 1277d36db35SAvi Kivity static u64 gdt[] = { 1287d36db35SAvi Kivity 0, 1297d36db35SAvi Kivity 0x00cf9b000000ffffull, // flat 32-bit code segment 1307d36db35SAvi Kivity 0x00cf93000000ffffull, // flat 32-bit data segment 1317d36db35SAvi Kivity }; 1327d36db35SAvi Kivity 133975ca087SPeter Feiner static struct table_descr gdt_descr = { 1347d36db35SAvi Kivity sizeof(gdt) - 1, 1357d36db35SAvi Kivity gdt, 1367d36db35SAvi Kivity }; 1377d36db35SAvi Kivity 138d4dc402cSAvi Kivity struct insn_desc { 139d4dc402cSAvi Kivity u16 ptr; 140d4dc402cSAvi Kivity u16 len; 141d4dc402cSAvi Kivity }; 142d4dc402cSAvi Kivity 14318253fdeSAvi Kivity static struct regs inregs, outregs; 14418253fdeSAvi Kivity 14518253fdeSAvi Kivity static void exec_in_big_real_mode(struct insn_desc *insn) 1467d36db35SAvi Kivity { 1477d36db35SAvi Kivity unsigned long tmp; 1487d36db35SAvi Kivity static struct regs save; 1497d36db35SAvi Kivity int i; 1507d36db35SAvi Kivity extern u8 test_insn[], test_insn_end[]; 1517d36db35SAvi Kivity 152d4dc402cSAvi Kivity for (i = 0; i < insn->len; ++i) 153d4dc402cSAvi Kivity test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i]; 1547d36db35SAvi Kivity for (; i < test_insn_end - test_insn; ++i) 1557d36db35SAvi Kivity test_insn[i] = 0x90; // nop 1567d36db35SAvi Kivity 15718253fdeSAvi Kivity save = inregs; 1587d36db35SAvi Kivity asm volatile( 1597d36db35SAvi Kivity "lgdtl %[gdt_descr] \n\t" 1607d36db35SAvi Kivity "mov %%cr0, %[tmp] \n\t" 1617d36db35SAvi Kivity "or $1, %[tmp] \n\t" 1627d36db35SAvi Kivity "mov %[tmp], %%cr0 \n\t" 1637d36db35SAvi Kivity "mov %[bigseg], %%gs \n\t" 1647d36db35SAvi Kivity "and $-2, %[tmp] \n\t" 1657d36db35SAvi Kivity "mov %[tmp], %%cr0 \n\t" 1667d36db35SAvi Kivity 167*eb6687a2SBill Wendling /* Save ES, because it is clobbered by some tests. */ 168*eb6687a2SBill Wendling "pushw %%es \n\t" 169*eb6687a2SBill Wendling 17032001692SAvi Kivity "pushw %[save]+36; popfw \n\t" 1717d36db35SAvi Kivity "xchg %%eax, %[save]+0 \n\t" 1727d36db35SAvi Kivity "xchg %%ebx, %[save]+4 \n\t" 1737d36db35SAvi Kivity "xchg %%ecx, %[save]+8 \n\t" 1747d36db35SAvi Kivity "xchg %%edx, %[save]+12 \n\t" 1757d36db35SAvi Kivity "xchg %%esi, %[save]+16 \n\t" 1767d36db35SAvi Kivity "xchg %%edi, %[save]+20 \n\t" 1777d36db35SAvi Kivity "xchg %%esp, %[save]+24 \n\t" 1787d36db35SAvi Kivity "xchg %%ebp, %[save]+28 \n\t" 1797d36db35SAvi Kivity 1807d36db35SAvi Kivity "test_insn: . = . + 32\n\t" 1817d36db35SAvi Kivity "test_insn_end: \n\t" 1827d36db35SAvi Kivity 1837d36db35SAvi Kivity "xchg %%eax, %[save]+0 \n\t" 1847d36db35SAvi Kivity "xchg %%ebx, %[save]+4 \n\t" 1857d36db35SAvi Kivity "xchg %%ecx, %[save]+8 \n\t" 1867d36db35SAvi Kivity "xchg %%edx, %[save]+12 \n\t" 1877d36db35SAvi Kivity "xchg %%esi, %[save]+16 \n\t" 1887d36db35SAvi Kivity "xchg %%edi, %[save]+20 \n\t" 1897d36db35SAvi Kivity "xchg %%esp, %[save]+24 \n\t" 1907d36db35SAvi Kivity "xchg %%ebp, %[save]+28 \n\t" 1917d36db35SAvi Kivity 1927d36db35SAvi Kivity /* Save EFLAGS in outregs*/ 1937d36db35SAvi Kivity "pushfl \n\t" 1947d36db35SAvi Kivity "popl %[save]+36 \n\t" 1957d36db35SAvi Kivity 196*eb6687a2SBill Wendling /* Restore ES for future rep string operations. */ 197*eb6687a2SBill Wendling "popw %%es \n\t" 198*eb6687a2SBill Wendling 1995edbb9aeSPaolo Bonzini /* Restore DF for the harness code */ 2005edbb9aeSPaolo Bonzini "cld\n\t" 2017d36db35SAvi Kivity "xor %[tmp], %[tmp] \n\t" 2027d36db35SAvi Kivity "mov %[tmp], %%gs \n\t" 2037d36db35SAvi Kivity : [tmp]"=&r"(tmp), [save]"+m"(save) 2047d36db35SAvi Kivity : [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16) 2057d36db35SAvi Kivity : "cc", "memory" 2067d36db35SAvi Kivity ); 20718253fdeSAvi Kivity outregs = save; 2087d36db35SAvi Kivity } 2097d36db35SAvi Kivity 2107d36db35SAvi Kivity #define R_AX 1 2117d36db35SAvi Kivity #define R_BX 2 2127d36db35SAvi Kivity #define R_CX 4 2137d36db35SAvi Kivity #define R_DX 8 2147d36db35SAvi Kivity #define R_SI 16 2157d36db35SAvi Kivity #define R_DI 32 2167d36db35SAvi Kivity #define R_SP 64 2177d36db35SAvi Kivity #define R_BP 128 2187d36db35SAvi Kivity 2192e3f9f1fSThomas Huth static int regs_equal(int ignore) 2207d36db35SAvi Kivity { 22118253fdeSAvi Kivity const u32 *p1 = &inregs.eax, *p2 = &outregs.eax; // yuck 2227d36db35SAvi Kivity int i; 2237d36db35SAvi Kivity 2247d36db35SAvi Kivity for (i = 0; i < 8; ++i) 2257d36db35SAvi Kivity if (!(ignore & (1 << i)) && p1[i] != p2[i]) 2267d36db35SAvi Kivity return 0; 2277d36db35SAvi Kivity return 1; 2287d36db35SAvi Kivity } 2297d36db35SAvi Kivity 2306055ea1fSAvi Kivity static void report(const char *name, u16 regs_ignore, _Bool ok) 23181050840SAvi Kivity { 2326055ea1fSAvi Kivity if (!regs_equal(regs_ignore)) { 2336055ea1fSAvi Kivity ok = 0; 2346055ea1fSAvi Kivity } 23581050840SAvi Kivity print_serial(ok ? "PASS: " : "FAIL: "); 23681050840SAvi Kivity print_serial(name); 23781050840SAvi Kivity print_serial("\n"); 238b393fe28SNadav Amit if (!ok) 239b393fe28SNadav Amit failed = 1; 24081050840SAvi Kivity } 24181050840SAvi Kivity 2427d36db35SAvi Kivity #define MK_INSN(name, str) \ 2437d36db35SAvi Kivity asm ( \ 244d4dc402cSAvi Kivity ".pushsection .data.insn \n\t" \ 245d4dc402cSAvi Kivity "insn_" #name ": \n\t" \ 246d4dc402cSAvi Kivity ".word 1001f, 1002f - 1001f \n\t" \ 247d4dc402cSAvi Kivity ".popsection \n\t" \ 248d4dc402cSAvi Kivity ".pushsection .text.insn, \"ax\" \n\t" \ 249d4dc402cSAvi Kivity "1001: \n\t" \ 250d4dc402cSAvi Kivity "insn_code_" #name ": " str " \n\t" \ 251d4dc402cSAvi Kivity "1002: \n\t" \ 252d4dc402cSAvi Kivity ".popsection" \ 2537d36db35SAvi Kivity ); \ 254d4dc402cSAvi Kivity extern struct insn_desc insn_##name; 2557d36db35SAvi Kivity 2562e3f9f1fSThomas Huth static void test_xchg(void) 2577d36db35SAvi Kivity { 2587d36db35SAvi Kivity MK_INSN(xchg_test1, "xchg %eax,%eax\n\t"); 2597d36db35SAvi Kivity MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t"); 2607d36db35SAvi Kivity MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t"); 2617d36db35SAvi Kivity MK_INSN(xchg_test4, "xchg %eax,%edx\n\t"); 2627d36db35SAvi Kivity MK_INSN(xchg_test5, "xchg %eax,%esi\n\t"); 2637d36db35SAvi Kivity MK_INSN(xchg_test6, "xchg %eax,%edi\n\t"); 2647d36db35SAvi Kivity MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t"); 2657d36db35SAvi Kivity MK_INSN(xchg_test8, "xchg %eax,%esp\n\t"); 2667d36db35SAvi Kivity 26718253fdeSAvi Kivity inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7}; 2687d36db35SAvi Kivity 26918253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test1); 2706055ea1fSAvi Kivity report("xchg 1", 0, 1); 27118253fdeSAvi Kivity 27218253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test2); 2736055ea1fSAvi Kivity report("xchg 2", R_AX | R_BX, 2746055ea1fSAvi Kivity outregs.eax == inregs.ebx && outregs.ebx == inregs.eax); 2757d36db35SAvi Kivity 27618253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test3); 2776055ea1fSAvi Kivity report("xchg 3", R_AX | R_CX, 2786055ea1fSAvi Kivity outregs.eax == inregs.ecx && outregs.ecx == inregs.eax); 2797d36db35SAvi Kivity 28018253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test4); 2816055ea1fSAvi Kivity report("xchg 4", R_AX | R_DX, 2826055ea1fSAvi Kivity outregs.eax == inregs.edx && outregs.edx == inregs.eax); 2837d36db35SAvi Kivity 28418253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test5); 2856055ea1fSAvi Kivity report("xchg 5", R_AX | R_SI, 2866055ea1fSAvi Kivity outregs.eax == inregs.esi && outregs.esi == inregs.eax); 2877d36db35SAvi Kivity 28818253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test6); 2896055ea1fSAvi Kivity report("xchg 6", R_AX | R_DI, 2906055ea1fSAvi Kivity outregs.eax == inregs.edi && outregs.edi == inregs.eax); 2917d36db35SAvi Kivity 29218253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test7); 2936055ea1fSAvi Kivity report("xchg 7", R_AX | R_BP, 2946055ea1fSAvi Kivity outregs.eax == inregs.ebp && outregs.ebp == inregs.eax); 2957d36db35SAvi Kivity 29618253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test8); 2976055ea1fSAvi Kivity report("xchg 8", R_AX | R_SP, 2986055ea1fSAvi Kivity outregs.eax == inregs.esp && outregs.esp == inregs.eax); 2997d36db35SAvi Kivity } 3007d36db35SAvi Kivity 3012e3f9f1fSThomas Huth static void test_shld(void) 3027d36db35SAvi Kivity { 3037d36db35SAvi Kivity MK_INSN(shld_test, "shld $8,%edx,%eax\n\t"); 3047d36db35SAvi Kivity 30518253fdeSAvi Kivity inregs = (struct regs){ .eax = 0xbe, .edx = 0xef000000 }; 30618253fdeSAvi Kivity exec_in_big_real_mode(&insn_shld_test); 3076055ea1fSAvi Kivity report("shld", ~0, outregs.eax == 0xbeef); 3087d36db35SAvi Kivity } 3097d36db35SAvi Kivity 3102e3f9f1fSThomas Huth static void test_mov_imm(void) 3117d36db35SAvi Kivity { 3127d36db35SAvi Kivity MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax"); 3137d36db35SAvi Kivity MK_INSN(mov_r16_imm_1, "mov $1234, %ax"); 3147d36db35SAvi Kivity MK_INSN(mov_r8_imm_1, "mov $0x12, %ah"); 3157d36db35SAvi Kivity MK_INSN(mov_r8_imm_2, "mov $0x34, %al"); 3167d36db35SAvi Kivity MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t"); 3177d36db35SAvi Kivity 31818253fdeSAvi Kivity inregs = (struct regs){ 0 }; 31918253fdeSAvi Kivity 32018253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r16_imm_1); 3216055ea1fSAvi Kivity report("mov 1", R_AX, outregs.eax == 1234); 3227d36db35SAvi Kivity 3237d36db35SAvi Kivity /* test mov $imm, %eax */ 32418253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r32_imm_1); 3256055ea1fSAvi Kivity report("mov 2", R_AX, outregs.eax == 1234567890); 3267d36db35SAvi Kivity 3277d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 32818253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_1); 3296055ea1fSAvi Kivity report("mov 3", R_AX, outregs.eax == 0x1200); 3307d36db35SAvi Kivity 33118253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_2); 3326055ea1fSAvi Kivity report("mov 4", R_AX, outregs.eax == 0x34); 3337d36db35SAvi Kivity 33418253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_3); 3356055ea1fSAvi Kivity report("mov 5", R_AX, outregs.eax == 0x1234); 3367d36db35SAvi Kivity } 3377d36db35SAvi Kivity 3382e3f9f1fSThomas Huth static void test_sub_imm(void) 3397d36db35SAvi Kivity { 3407d36db35SAvi Kivity MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t"); 3417d36db35SAvi Kivity MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t"); 3427d36db35SAvi Kivity MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t"); 3437d36db35SAvi Kivity MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t"); 3447d36db35SAvi Kivity 34518253fdeSAvi Kivity inregs = (struct regs){ 0 }; 34618253fdeSAvi Kivity 34718253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r16_imm_1); 3486055ea1fSAvi Kivity report("sub 1", R_AX, outregs.eax == 1224); 3497d36db35SAvi Kivity 3507d36db35SAvi Kivity /* test mov $imm, %eax */ 35118253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r32_imm_1); 3526055ea1fSAvi Kivity report("sub 2", R_AX, outregs.eax == 1234567880); 3537d36db35SAvi Kivity 3547d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 35518253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r8_imm_1); 3566055ea1fSAvi Kivity report("sub 3", R_AX, outregs.eax == 0x0200); 3577d36db35SAvi Kivity 35818253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r8_imm_2); 3596055ea1fSAvi Kivity report("sub 4", R_AX, outregs.eax == 0x24); 3607d36db35SAvi Kivity } 3617d36db35SAvi Kivity 3622e3f9f1fSThomas Huth static void test_xor_imm(void) 3637d36db35SAvi Kivity { 3647d36db35SAvi Kivity MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t"); 3657d36db35SAvi Kivity MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t"); 3667d36db35SAvi Kivity MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t"); 3677d36db35SAvi Kivity MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t"); 3687d36db35SAvi Kivity 36918253fdeSAvi Kivity inregs = (struct regs){ 0 }; 37018253fdeSAvi Kivity 37118253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r16_imm_1); 3726055ea1fSAvi Kivity report("xor 1", R_AX, outregs.eax == 0); 3737d36db35SAvi Kivity 3747d36db35SAvi Kivity /* test mov $imm, %eax */ 37518253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r32_imm_1); 3766055ea1fSAvi Kivity report("xor 2", R_AX, outregs.eax == 0); 3777d36db35SAvi Kivity 3787d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 37918253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r8_imm_1); 3806055ea1fSAvi Kivity report("xor 3", R_AX, outregs.eax == 0); 3817d36db35SAvi Kivity 38218253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r8_imm_2); 3836055ea1fSAvi Kivity report("xor 4", R_AX, outregs.eax == 0); 3847d36db35SAvi Kivity } 3857d36db35SAvi Kivity 3862e3f9f1fSThomas Huth static void test_cmp_imm(void) 3877d36db35SAvi Kivity { 3887d36db35SAvi Kivity MK_INSN(cmp_test1, "mov $0x34, %al\n\t" 3897d36db35SAvi Kivity "cmp $0x34, %al\n\t"); 3907d36db35SAvi Kivity MK_INSN(cmp_test2, "mov $0x34, %al\n\t" 3917d36db35SAvi Kivity "cmp $0x39, %al\n\t"); 3927d36db35SAvi Kivity MK_INSN(cmp_test3, "mov $0x34, %al\n\t" 3937d36db35SAvi Kivity "cmp $0x24, %al\n\t"); 3947d36db35SAvi Kivity 39518253fdeSAvi Kivity inregs = (struct regs){ 0 }; 39618253fdeSAvi Kivity 3977d36db35SAvi Kivity /* test cmp imm8 with AL */ 3987d36db35SAvi Kivity /* ZF: (bit 6) Zero Flag becomes 1 if an operation results 3997d36db35SAvi Kivity * in a 0 writeback, or 0 register 4007d36db35SAvi Kivity */ 40118253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test1); 4026055ea1fSAvi Kivity report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6)); 4037d36db35SAvi Kivity 40418253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test2); 4056055ea1fSAvi Kivity report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0); 4067d36db35SAvi Kivity 40718253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test3); 4086055ea1fSAvi Kivity report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0); 4097d36db35SAvi Kivity } 4107d36db35SAvi Kivity 4112e3f9f1fSThomas Huth static void test_add_imm(void) 4127d36db35SAvi Kivity { 4137d36db35SAvi Kivity MK_INSN(add_test1, "mov $0x43211234, %eax \n\t" 4147d36db35SAvi Kivity "add $0x12344321, %eax \n\t"); 4157d36db35SAvi Kivity MK_INSN(add_test2, "mov $0x12, %eax \n\t" 4167d36db35SAvi Kivity "add $0x21, %al\n\t"); 4177d36db35SAvi Kivity 41818253fdeSAvi Kivity inregs = (struct regs){ 0 }; 41918253fdeSAvi Kivity 42018253fdeSAvi Kivity exec_in_big_real_mode(&insn_add_test1); 4216055ea1fSAvi Kivity report("add 1", ~0, outregs.eax == 0x55555555); 4227d36db35SAvi Kivity 42318253fdeSAvi Kivity exec_in_big_real_mode(&insn_add_test2); 4246055ea1fSAvi Kivity report("add 2", ~0, outregs.eax == 0x33); 4257d36db35SAvi Kivity } 4267d36db35SAvi Kivity 4272e3f9f1fSThomas Huth static void test_eflags_insn(void) 4287d36db35SAvi Kivity { 4297d36db35SAvi Kivity MK_INSN(clc, "clc"); 430b3261e48SMohammed Gamal MK_INSN(stc, "stc"); 4317d36db35SAvi Kivity MK_INSN(cli, "cli"); 4327d36db35SAvi Kivity MK_INSN(sti, "sti"); 4337d36db35SAvi Kivity MK_INSN(cld, "cld"); 4347d36db35SAvi Kivity MK_INSN(std, "std"); 4357d36db35SAvi Kivity 43618253fdeSAvi Kivity inregs = (struct regs){ 0 }; 43718253fdeSAvi Kivity 43818253fdeSAvi Kivity exec_in_big_real_mode(&insn_clc); 4396055ea1fSAvi Kivity report("clc", ~0, (outregs.eflags & 1) == 0); 4407d36db35SAvi Kivity 44118253fdeSAvi Kivity exec_in_big_real_mode(&insn_stc); 4426055ea1fSAvi Kivity report("stc", ~0, (outregs.eflags & 1) == 1); 443b3261e48SMohammed Gamal 44418253fdeSAvi Kivity exec_in_big_real_mode(&insn_cli); 4456055ea1fSAvi Kivity report("cli", ~0, !(outregs.eflags & (1 << 9))); 4467d36db35SAvi Kivity 44718253fdeSAvi Kivity exec_in_big_real_mode(&insn_sti); 4486055ea1fSAvi Kivity report("sti", ~0, outregs.eflags & (1 << 9)); 4497d36db35SAvi Kivity 45018253fdeSAvi Kivity exec_in_big_real_mode(&insn_cld); 4516055ea1fSAvi Kivity report("cld", ~0, !(outregs.eflags & (1 << 10))); 4527d36db35SAvi Kivity 45318253fdeSAvi Kivity exec_in_big_real_mode(&insn_std); 4546055ea1fSAvi Kivity report("std", ~0, (outregs.eflags & (1 << 10))); 4557d36db35SAvi Kivity } 4567d36db35SAvi Kivity 4572e3f9f1fSThomas Huth static void test_io(void) 4587d36db35SAvi Kivity { 4597d36db35SAvi Kivity MK_INSN(io_test1, "mov $0xff, %al \n\t" 4607d36db35SAvi Kivity "out %al, $0xe0 \n\t" 4617d36db35SAvi Kivity "mov $0x00, %al \n\t" 4627d36db35SAvi Kivity "in $0xe0, %al \n\t"); 4637d36db35SAvi Kivity MK_INSN(io_test2, "mov $0xffff, %ax \n\t" 4647d36db35SAvi Kivity "out %ax, $0xe0 \n\t" 4657d36db35SAvi Kivity "mov $0x0000, %ax \n\t" 4667d36db35SAvi Kivity "in $0xe0, %ax \n\t"); 4677d36db35SAvi Kivity MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t" 4687d36db35SAvi Kivity "out %eax, $0xe0 \n\t" 4697d36db35SAvi Kivity "mov $0x000000, %eax \n\t" 4707d36db35SAvi Kivity "in $0xe0, %eax \n\t"); 4717d36db35SAvi Kivity MK_INSN(io_test4, "mov $0xe0, %dx \n\t" 4727d36db35SAvi Kivity "mov $0xff, %al \n\t" 4737d36db35SAvi Kivity "out %al, %dx \n\t" 4747d36db35SAvi Kivity "mov $0x00, %al \n\t" 4757d36db35SAvi Kivity "in %dx, %al \n\t"); 4767d36db35SAvi Kivity MK_INSN(io_test5, "mov $0xe0, %dx \n\t" 4777d36db35SAvi Kivity "mov $0xffff, %ax \n\t" 4787d36db35SAvi Kivity "out %ax, %dx \n\t" 4797d36db35SAvi Kivity "mov $0x0000, %ax \n\t" 4807d36db35SAvi Kivity "in %dx, %ax \n\t"); 4817d36db35SAvi Kivity MK_INSN(io_test6, "mov $0xe0, %dx \n\t" 4827d36db35SAvi Kivity "mov $0xffffffff, %eax \n\t" 4837d36db35SAvi Kivity "out %eax, %dx \n\t" 4847d36db35SAvi Kivity "mov $0x00000000, %eax \n\t" 4857d36db35SAvi Kivity "in %dx, %eax \n\t"); 4867d36db35SAvi Kivity 48718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 48818253fdeSAvi Kivity 48918253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test1); 4906055ea1fSAvi Kivity report("pio 1", R_AX, outregs.eax == 0xff); 4917d36db35SAvi Kivity 49218253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test2); 4936055ea1fSAvi Kivity report("pio 2", R_AX, outregs.eax == 0xffff); 4947d36db35SAvi Kivity 49518253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test3); 4966055ea1fSAvi Kivity report("pio 3", R_AX, outregs.eax == 0xffffffff); 4977d36db35SAvi Kivity 49818253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test4); 4996055ea1fSAvi Kivity report("pio 4", R_AX|R_DX, outregs.eax == 0xff); 5007d36db35SAvi Kivity 50118253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test5); 5026055ea1fSAvi Kivity report("pio 5", R_AX|R_DX, outregs.eax == 0xffff); 5037d36db35SAvi Kivity 50418253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test6); 5056055ea1fSAvi Kivity report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff); 5067d36db35SAvi Kivity } 5077d36db35SAvi Kivity 508c0b7268dSAvi Kivity asm ("retf: lretw"); 5092e3f9f1fSThomas Huth extern void retf(void); 510c0b7268dSAvi Kivity 5114f66bc86SBruce Rogers asm ("retf_imm: lretw $10"); 5122e3f9f1fSThomas Huth extern void retf_imm(void); 5134f66bc86SBruce Rogers 5142e3f9f1fSThomas Huth static void test_call(void) 5157d36db35SAvi Kivity { 5167d36db35SAvi Kivity u32 esp[16]; 517c0b7268dSAvi Kivity u32 addr; 5187d36db35SAvi Kivity 51918253fdeSAvi Kivity inregs = (struct regs){ 0 }; 52047086996SBill Wendling inregs.esp = (u32)&esp[ARRAY_SIZE(esp)]; 5217d36db35SAvi Kivity 5227d36db35SAvi Kivity MK_INSN(call1, "mov $test_function, %eax \n\t" 5237d36db35SAvi Kivity "call *%eax\n\t"); 5247d36db35SAvi Kivity MK_INSN(call_near1, "jmp 2f\n\t" 5257d36db35SAvi Kivity "1: mov $0x1234, %eax\n\t" 5267d36db35SAvi Kivity "ret\n\t" 5277d36db35SAvi Kivity "2: call 1b\t"); 5287d36db35SAvi Kivity MK_INSN(call_near2, "call 1f\n\t" 5297d36db35SAvi Kivity "jmp 2f\n\t" 5307d36db35SAvi Kivity "1: mov $0x1234, %eax\n\t" 5317d36db35SAvi Kivity "ret\n\t" 5327d36db35SAvi Kivity "2:\t"); 533c0b7268dSAvi Kivity MK_INSN(call_far1, "lcallw *(%ebx)\n\t"); 534556d2680SWei Yongjun MK_INSN(call_far2, "lcallw $0, $retf\n\t"); 535c6061817SAvi Kivity MK_INSN(ret_imm, "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b"); 5364f66bc86SBruce Rogers MK_INSN(retf_imm, "sub $10, %sp; lcallw $0, $retf_imm"); 5377d36db35SAvi Kivity 53818253fdeSAvi Kivity exec_in_big_real_mode(&insn_call1); 5396055ea1fSAvi Kivity report("call 1", R_AX, outregs.eax == 0x1234); 5407d36db35SAvi Kivity 54118253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_near1); 5426055ea1fSAvi Kivity report("call near 1", R_AX, outregs.eax == 0x1234); 5437d36db35SAvi Kivity 54418253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_near2); 5456055ea1fSAvi Kivity report("call near 2", R_AX, outregs.eax == 0x1234); 546c0b7268dSAvi Kivity 547c0b7268dSAvi Kivity addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f); 548c0b7268dSAvi Kivity inregs.ebx = (unsigned)&addr; 54918253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_far1); 5506055ea1fSAvi Kivity report("call far 1", 0, 1); 551c6061817SAvi Kivity 552556d2680SWei Yongjun exec_in_big_real_mode(&insn_call_far2); 553556d2680SWei Yongjun report("call far 2", 0, 1); 554556d2680SWei Yongjun 55518253fdeSAvi Kivity exec_in_big_real_mode(&insn_ret_imm); 5566055ea1fSAvi Kivity report("ret imm 1", 0, 1); 5574f66bc86SBruce Rogers 5584f66bc86SBruce Rogers exec_in_big_real_mode(&insn_retf_imm); 5594f66bc86SBruce Rogers report("retf imm 1", 0, 1); 5607d36db35SAvi Kivity } 5617d36db35SAvi Kivity 5622e3f9f1fSThomas Huth static void test_jcc_short(void) 5637d36db35SAvi Kivity { 5647d36db35SAvi Kivity MK_INSN(jnz_short1, "jnz 1f\n\t" 5657d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5667d36db35SAvi Kivity "1:\n\t"); 5677d36db35SAvi Kivity MK_INSN(jnz_short2, "1:\n\t" 5687d36db35SAvi Kivity "cmp $0x1234, %eax\n\t" 5697d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5707d36db35SAvi Kivity "jnz 1b\n\t"); 5717d36db35SAvi Kivity MK_INSN(jmp_short1, "jmp 1f\n\t" 5727d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5737d36db35SAvi Kivity "1:\n\t"); 5747d36db35SAvi Kivity 57518253fdeSAvi Kivity inregs = (struct regs){ 0 }; 5767d36db35SAvi Kivity 57718253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_short1); 5786055ea1fSAvi Kivity report("jnz short 1", ~0, 1); 57918253fdeSAvi Kivity 58018253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_short2); 5816055ea1fSAvi Kivity report("jnz short 2", R_AX, (outregs.eflags & (1 << 6))); 5827d36db35SAvi Kivity 58318253fdeSAvi Kivity exec_in_big_real_mode(&insn_jmp_short1); 5846055ea1fSAvi Kivity report("jmp short 1", ~0, 1); 5857d36db35SAvi Kivity } 5867d36db35SAvi Kivity 5872e3f9f1fSThomas Huth static void test_jcc_near(void) 5887d36db35SAvi Kivity { 5897d36db35SAvi Kivity /* encode near jmp manually. gas will not do it if offsets < 127 byte */ 5907d36db35SAvi Kivity MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t" 5917d36db35SAvi Kivity "mov $0x1234, %eax\n\t"); 5927d36db35SAvi Kivity MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t" 5937d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5947d36db35SAvi Kivity ".byte 0x0f, 0x85, 0xf0, 0xff\n\t"); 5957d36db35SAvi Kivity MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t" 5967d36db35SAvi Kivity "mov $0x1234, %eax\n\t"); 5977d36db35SAvi Kivity 59818253fdeSAvi Kivity inregs = (struct regs){ 0 }; 5997d36db35SAvi Kivity 60018253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_near1); 6016055ea1fSAvi Kivity report("jnz near 1", 0, 1); 60218253fdeSAvi Kivity 60318253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_near2); 6046055ea1fSAvi Kivity report("jnz near 2", R_AX, outregs.eflags & (1 << 6)); 6057d36db35SAvi Kivity 60618253fdeSAvi Kivity exec_in_big_real_mode(&insn_jmp_near1); 6076055ea1fSAvi Kivity report("jmp near 1", 0, 1); 6087d36db35SAvi Kivity } 6097d36db35SAvi Kivity 6102e3f9f1fSThomas Huth static void test_long_jmp(void) 6117d36db35SAvi Kivity { 6127d36db35SAvi Kivity u32 esp[16]; 6137d36db35SAvi Kivity 61418253fdeSAvi Kivity inregs = (struct regs){ 0 }; 615074766aeSPaolo Bonzini inregs.esp = (u32)&esp[ARRAY_SIZE(esp)]; 6167d36db35SAvi Kivity MK_INSN(long_jmp, "call 1f\n\t" 6177d36db35SAvi Kivity "jmp 2f\n\t" 6187d36db35SAvi Kivity "1: jmp $0, $test_function\n\t" 6197d36db35SAvi Kivity "2:\n\t"); 62018253fdeSAvi Kivity exec_in_big_real_mode(&insn_long_jmp); 6216055ea1fSAvi Kivity report("jmp far 1", R_AX, outregs.eax == 0x1234); 6227d36db35SAvi Kivity } 623fa74f8a6SMohammed Gamal 6242e3f9f1fSThomas Huth static void test_push_pop(void) 6257d36db35SAvi Kivity { 6267d36db35SAvi Kivity MK_INSN(push32, "mov $0x12345678, %eax\n\t" 6277d36db35SAvi Kivity "push %eax\n\t" 6287d36db35SAvi Kivity "pop %ebx\n\t"); 6297d36db35SAvi Kivity MK_INSN(push16, "mov $0x1234, %ax\n\t" 6307d36db35SAvi Kivity "push %ax\n\t" 6317d36db35SAvi Kivity "pop %bx\n\t"); 6327d36db35SAvi Kivity 6337d36db35SAvi Kivity MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten 6347d36db35SAvi Kivity "mov $0x123, %ax\n\t" 6357d36db35SAvi Kivity "mov %ax, %es\n\t" 6367d36db35SAvi Kivity "push %es\n\t" 6377d36db35SAvi Kivity "pop %bx \n\t" 6387d36db35SAvi Kivity ); 6397d36db35SAvi Kivity MK_INSN(pop_es, "push %ax\n\t" 6407d36db35SAvi Kivity "pop %es\n\t" 6417d36db35SAvi Kivity "mov %es, %bx\n\t" 6427d36db35SAvi Kivity ); 6437d36db35SAvi Kivity MK_INSN(push_pop_ss, "push %ss\n\t" 6447d36db35SAvi Kivity "pushw %ax\n\t" 6457d36db35SAvi Kivity "popw %ss\n\t" 6467d36db35SAvi Kivity "mov %ss, %bx\n\t" 6477d36db35SAvi Kivity "pop %ss\n\t" 6487d36db35SAvi Kivity ); 6497d36db35SAvi Kivity MK_INSN(push_pop_fs, "push %fs\n\t" 6507d36db35SAvi Kivity "pushl %eax\n\t" 6517d36db35SAvi Kivity "popl %fs\n\t" 6527d36db35SAvi Kivity "mov %fs, %ebx\n\t" 6537d36db35SAvi Kivity "pop %fs\n\t" 6547d36db35SAvi Kivity ); 65509b657b6SAvi Kivity MK_INSN(push_pop_high_esp_bits, 65609b657b6SAvi Kivity "xor $0x12340000, %esp \n\t" 65709b657b6SAvi Kivity "push %ax; \n\t" 65809b657b6SAvi Kivity "xor $0x12340000, %esp \n\t" 65909b657b6SAvi Kivity "pop %bx"); 6607d36db35SAvi Kivity 66118253fdeSAvi Kivity inregs = (struct regs){ 0 }; 66218253fdeSAvi Kivity 66318253fdeSAvi Kivity exec_in_big_real_mode(&insn_push32); 6646055ea1fSAvi Kivity report("push/pop 1", R_AX|R_BX, 6656055ea1fSAvi Kivity outregs.eax == outregs.ebx && outregs.eax == 0x12345678); 6667d36db35SAvi Kivity 66718253fdeSAvi Kivity exec_in_big_real_mode(&insn_push16); 6686055ea1fSAvi Kivity report("push/pop 2", R_AX|R_BX, 6696055ea1fSAvi Kivity outregs.eax == outregs.ebx && outregs.eax == 0x1234); 6707d36db35SAvi Kivity 67118253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_es); 6726055ea1fSAvi Kivity report("push/pop 3", R_AX|R_BX, 6736055ea1fSAvi Kivity outregs.ebx == outregs.eax && outregs.eax == 0x123); 6747d36db35SAvi Kivity 67518253fdeSAvi Kivity exec_in_big_real_mode(&insn_pop_es); 6766055ea1fSAvi Kivity report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax); 6777d36db35SAvi Kivity 67818253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_pop_ss); 6796055ea1fSAvi Kivity report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax); 6807d36db35SAvi Kivity 68118253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_pop_fs); 6826055ea1fSAvi Kivity report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax); 68309b657b6SAvi Kivity 68409b657b6SAvi Kivity inregs.eax = 0x9977; 68509b657b6SAvi Kivity inregs.ebx = 0x7799; 68609b657b6SAvi Kivity exec_in_big_real_mode(&insn_push_pop_high_esp_bits); 68709b657b6SAvi Kivity report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977); 6887d36db35SAvi Kivity } 6897d36db35SAvi Kivity 6902e3f9f1fSThomas Huth static void test_null(void) 6917d36db35SAvi Kivity { 692d4dc402cSAvi Kivity MK_INSN(null, ""); 693d4dc402cSAvi Kivity 69418253fdeSAvi Kivity inregs = (struct regs){ 0 }; 69518253fdeSAvi Kivity 69618253fdeSAvi Kivity exec_in_big_real_mode(&insn_null); 6976055ea1fSAvi Kivity report("null", 0, 1); 6987d36db35SAvi Kivity } 6997d36db35SAvi Kivity 7007d36db35SAvi Kivity struct { 7017d36db35SAvi Kivity char stack[500]; 7027d36db35SAvi Kivity char top[]; 7037d36db35SAvi Kivity } tmp_stack; 7047d36db35SAvi Kivity 7052e3f9f1fSThomas Huth static void test_pusha_popa(void) 7067d36db35SAvi Kivity { 7077d36db35SAvi Kivity MK_INSN(pusha, "pusha\n\t" 7087d36db35SAvi Kivity "pop %edi\n\t" 7097d36db35SAvi Kivity "pop %esi\n\t" 7107d36db35SAvi Kivity "pop %ebp\n\t" 7117d36db35SAvi Kivity "add $4, %esp\n\t" 7127d36db35SAvi Kivity "pop %ebx\n\t" 7137d36db35SAvi Kivity "pop %edx\n\t" 7147d36db35SAvi Kivity "pop %ecx\n\t" 7157d36db35SAvi Kivity "pop %eax\n\t" 7167d36db35SAvi Kivity ); 7177d36db35SAvi Kivity 7187d36db35SAvi Kivity MK_INSN(popa, "push %eax\n\t" 7197d36db35SAvi Kivity "push %ecx\n\t" 7207d36db35SAvi Kivity "push %edx\n\t" 7217d36db35SAvi Kivity "push %ebx\n\t" 7227d36db35SAvi Kivity "push %esp\n\t" 7237d36db35SAvi Kivity "push %ebp\n\t" 7247d36db35SAvi Kivity "push %esi\n\t" 7257d36db35SAvi Kivity "push %edi\n\t" 7267d36db35SAvi Kivity "popa\n\t" 7277d36db35SAvi Kivity ); 7287d36db35SAvi Kivity 72918253fdeSAvi Kivity inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top }; 7307d36db35SAvi Kivity 73118253fdeSAvi Kivity exec_in_big_real_mode(&insn_pusha); 7326055ea1fSAvi Kivity report("pusha/popa 1", 0, 1); 73318253fdeSAvi Kivity 73418253fdeSAvi Kivity exec_in_big_real_mode(&insn_popa); 7356055ea1fSAvi Kivity report("pusha/popa 1", 0, 1); 7367d36db35SAvi Kivity } 7377d36db35SAvi Kivity 7382e3f9f1fSThomas Huth static void test_iret(void) 7397d36db35SAvi Kivity { 7407d36db35SAvi Kivity MK_INSN(iret32, "pushf\n\t" 7417d36db35SAvi Kivity "pushl %cs\n\t" 7427d36db35SAvi Kivity "call 1f\n\t" /* a near call will push eip onto the stack */ 7437d36db35SAvi Kivity "jmp 2f\n\t" 7447d36db35SAvi Kivity "1: iret\n\t" 7457d36db35SAvi Kivity "2:\n\t" 7467d36db35SAvi Kivity ); 7477d36db35SAvi Kivity 7487d36db35SAvi Kivity MK_INSN(iret16, "pushfw\n\t" 7497d36db35SAvi Kivity "pushw %cs\n\t" 7507d36db35SAvi Kivity "callw 1f\n\t" 7517d36db35SAvi Kivity "jmp 2f\n\t" 7527d36db35SAvi Kivity "1: iretw\n\t" 7537d36db35SAvi Kivity "2:\n\t"); 7547d36db35SAvi Kivity 7557d36db35SAvi Kivity MK_INSN(iret_flags32, "pushfl\n\t" 7567d36db35SAvi Kivity "popl %eax\n\t" 7577d36db35SAvi Kivity "andl $~0x2, %eax\n\t" 758964942e8SNadav Amit "orl $0xffc18028, %eax\n\t" 7597d36db35SAvi Kivity "pushl %eax\n\t" 7607d36db35SAvi Kivity "pushl %cs\n\t" 7617d36db35SAvi Kivity "call 1f\n\t" 7627d36db35SAvi Kivity "jmp 2f\n\t" 7637d36db35SAvi Kivity "1: iret\n\t" 7647d36db35SAvi Kivity "2:\n\t"); 7657d36db35SAvi Kivity 7667d36db35SAvi Kivity MK_INSN(iret_flags16, "pushfw\n\t" 7677d36db35SAvi Kivity "popw %ax\n\t" 7687d36db35SAvi Kivity "and $~0x2, %ax\n\t" 7697d36db35SAvi Kivity "or $0x8028, %ax\n\t" 7707d36db35SAvi Kivity "pushw %ax\n\t" 7717d36db35SAvi Kivity "pushw %cs\n\t" 7727d36db35SAvi Kivity "callw 1f\n\t" 7737d36db35SAvi Kivity "jmp 2f\n\t" 7747d36db35SAvi Kivity "1: iretw\n\t" 7757d36db35SAvi Kivity "2:\n\t"); 7767d36db35SAvi Kivity 77718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 7787d36db35SAvi Kivity 77918253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret32); 7806055ea1fSAvi Kivity report("iret 1", 0, 1); 7817d36db35SAvi Kivity 78218253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret16); 7836055ea1fSAvi Kivity report("iret 2", 0, 1); 7847d36db35SAvi Kivity 78518253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret_flags32); 7866055ea1fSAvi Kivity report("iret 3", R_AX, 1); 787964942e8SNadav Amit report("rflags.rf", ~0, !(outregs.eflags & (1 << 16))); 78818253fdeSAvi Kivity 78918253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret_flags16); 7906055ea1fSAvi Kivity report("iret 4", R_AX, 1); 7917d36db35SAvi Kivity } 7927d36db35SAvi Kivity 7932e3f9f1fSThomas Huth static void test_int(void) 79496b9ca1eSMohammed Gamal { 79518253fdeSAvi Kivity inregs = (struct regs){ 0 }; 79696b9ca1eSMohammed Gamal 79796b9ca1eSMohammed Gamal *(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */ 79896b9ca1eSMohammed Gamal *(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */ 79996b9ca1eSMohammed Gamal 80096b9ca1eSMohammed Gamal MK_INSN(int11, "int $0x11\n\t"); 80196b9ca1eSMohammed Gamal 80218253fdeSAvi Kivity exec_in_big_real_mode(&insn_int11); 8036055ea1fSAvi Kivity report("int 1", 0, 1); 80496b9ca1eSMohammed Gamal } 80596b9ca1eSMohammed Gamal 8062e3f9f1fSThomas Huth static void test_imul(void) 807fa74f8a6SMohammed Gamal { 808fa74f8a6SMohammed Gamal MK_INSN(imul8_1, "mov $2, %al\n\t" 809fa74f8a6SMohammed Gamal "mov $-4, %cx\n\t" 810fa74f8a6SMohammed Gamal "imul %cl\n\t"); 811fa74f8a6SMohammed Gamal 812fa74f8a6SMohammed Gamal MK_INSN(imul16_1, "mov $2, %ax\n\t" 813fa74f8a6SMohammed Gamal "mov $-4, %cx\n\t" 814fa74f8a6SMohammed Gamal "imul %cx\n\t"); 815fa74f8a6SMohammed Gamal 816fa74f8a6SMohammed Gamal MK_INSN(imul32_1, "mov $2, %eax\n\t" 817fa74f8a6SMohammed Gamal "mov $-4, %ecx\n\t" 818fa74f8a6SMohammed Gamal "imul %ecx\n\t"); 819fa74f8a6SMohammed Gamal 820fa74f8a6SMohammed Gamal MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t" 821fa74f8a6SMohammed Gamal "mov $4, %cx\n\t" 822fa74f8a6SMohammed Gamal "imul %cl\n\t"); 823fa74f8a6SMohammed Gamal 824fa74f8a6SMohammed Gamal MK_INSN(imul16_2, "mov $2, %ax\n\t" 825fa74f8a6SMohammed Gamal "mov $4, %cx\n\t" 826fa74f8a6SMohammed Gamal "imul %cx\n\t"); 827fa74f8a6SMohammed Gamal 828fa74f8a6SMohammed Gamal MK_INSN(imul32_2, "mov $2, %eax\n\t" 829fa74f8a6SMohammed Gamal "mov $4, %ecx\n\t" 830fa74f8a6SMohammed Gamal "imul %ecx\n\t"); 831fa74f8a6SMohammed Gamal 83218253fdeSAvi Kivity inregs = (struct regs){ 0 }; 83318253fdeSAvi Kivity 83418253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul8_1); 8356055ea1fSAvi Kivity report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8); 836fa74f8a6SMohammed Gamal 83718253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul16_1); 8386055ea1fSAvi Kivity report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8); 839fa74f8a6SMohammed Gamal 84018253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul32_1); 8416055ea1fSAvi Kivity report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8); 842fa74f8a6SMohammed Gamal 84318253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul8_2); 8446055ea1fSAvi Kivity report("imul 4", R_AX | R_CX | R_DX, 8456055ea1fSAvi Kivity (outregs.eax & 0xffff) == 8 84681050840SAvi Kivity && (outregs.eax & 0xffff0000) == 0x12340000); 847fa74f8a6SMohammed Gamal 84818253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul16_2); 8496055ea1fSAvi Kivity report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8); 850fa74f8a6SMohammed Gamal 85118253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul32_2); 8526055ea1fSAvi Kivity report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8); 853fa74f8a6SMohammed Gamal } 854fa74f8a6SMohammed Gamal 8552e3f9f1fSThomas Huth static void test_mul(void) 85659317bd1SMohammed Gamal { 85759317bd1SMohammed Gamal MK_INSN(mul8, "mov $2, %al\n\t" 85859317bd1SMohammed Gamal "mov $4, %cx\n\t" 85959317bd1SMohammed Gamal "imul %cl\n\t"); 86059317bd1SMohammed Gamal 86159317bd1SMohammed Gamal MK_INSN(mul16, "mov $2, %ax\n\t" 86259317bd1SMohammed Gamal "mov $4, %cx\n\t" 86359317bd1SMohammed Gamal "imul %cx\n\t"); 86459317bd1SMohammed Gamal 86559317bd1SMohammed Gamal MK_INSN(mul32, "mov $2, %eax\n\t" 86659317bd1SMohammed Gamal "mov $4, %ecx\n\t" 86759317bd1SMohammed Gamal "imul %ecx\n\t"); 86859317bd1SMohammed Gamal 86918253fdeSAvi Kivity inregs = (struct regs){ 0 }; 87018253fdeSAvi Kivity 87118253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul8); 8726055ea1fSAvi Kivity report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8); 87359317bd1SMohammed Gamal 87418253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul16); 8756055ea1fSAvi Kivity report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8); 87659317bd1SMohammed Gamal 87718253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul32); 8786055ea1fSAvi Kivity report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8); 87959317bd1SMohammed Gamal } 88059317bd1SMohammed Gamal 8812e3f9f1fSThomas Huth static void test_div(void) 8820d4c7614SMohammed Gamal { 8830d4c7614SMohammed Gamal MK_INSN(div8, "mov $257, %ax\n\t" 8840d4c7614SMohammed Gamal "mov $2, %cl\n\t" 8850d4c7614SMohammed Gamal "div %cl\n\t"); 8860d4c7614SMohammed Gamal 8870d4c7614SMohammed Gamal MK_INSN(div16, "mov $512, %ax\n\t" 8880d4c7614SMohammed Gamal "mov $5, %cx\n\t" 8890d4c7614SMohammed Gamal "div %cx\n\t"); 8900d4c7614SMohammed Gamal 8910d4c7614SMohammed Gamal MK_INSN(div32, "mov $512, %eax\n\t" 8920d4c7614SMohammed Gamal "mov $5, %ecx\n\t" 8930d4c7614SMohammed Gamal "div %ecx\n\t"); 8940d4c7614SMohammed Gamal 89518253fdeSAvi Kivity inregs = (struct regs){ 0 }; 89618253fdeSAvi Kivity 89718253fdeSAvi Kivity exec_in_big_real_mode(&insn_div8); 8986055ea1fSAvi Kivity report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384); 8990d4c7614SMohammed Gamal 90018253fdeSAvi Kivity exec_in_big_real_mode(&insn_div16); 9016055ea1fSAvi Kivity report("div 2", R_AX | R_CX | R_DX, 9026055ea1fSAvi Kivity outregs.eax == 102 && outregs.edx == 2); 9030d4c7614SMohammed Gamal 90418253fdeSAvi Kivity exec_in_big_real_mode(&insn_div32); 9056055ea1fSAvi Kivity report("div 3", R_AX | R_CX | R_DX, 9066055ea1fSAvi Kivity outregs.eax == 102 && outregs.edx == 2); 9070d4c7614SMohammed Gamal } 9080d4c7614SMohammed Gamal 9092e3f9f1fSThomas Huth static void test_idiv(void) 9100d4c7614SMohammed Gamal { 9110d4c7614SMohammed Gamal MK_INSN(idiv8, "mov $256, %ax\n\t" 9120d4c7614SMohammed Gamal "mov $-2, %cl\n\t" 9130d4c7614SMohammed Gamal "idiv %cl\n\t"); 9140d4c7614SMohammed Gamal 9150d4c7614SMohammed Gamal MK_INSN(idiv16, "mov $512, %ax\n\t" 9160d4c7614SMohammed Gamal "mov $-2, %cx\n\t" 9170d4c7614SMohammed Gamal "idiv %cx\n\t"); 9180d4c7614SMohammed Gamal 9190d4c7614SMohammed Gamal MK_INSN(idiv32, "mov $512, %eax\n\t" 9200d4c7614SMohammed Gamal "mov $-2, %ecx\n\t" 9210d4c7614SMohammed Gamal "idiv %ecx\n\t"); 9220d4c7614SMohammed Gamal 92318253fdeSAvi Kivity inregs = (struct regs){ 0 }; 92418253fdeSAvi Kivity 92518253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv8); 9266055ea1fSAvi Kivity report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128); 9270d4c7614SMohammed Gamal 92818253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv16); 9296055ea1fSAvi Kivity report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256); 9300d4c7614SMohammed Gamal 93118253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv32); 9326055ea1fSAvi Kivity report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256); 9330d4c7614SMohammed Gamal } 9340d4c7614SMohammed Gamal 9352e3f9f1fSThomas Huth static void test_cbw(void) 9366e293cf5SWei Yongjun { 9376e293cf5SWei Yongjun MK_INSN(cbw, "mov $0xFE, %eax \n\t" 9386e293cf5SWei Yongjun "cbw\n\t"); 9396e293cf5SWei Yongjun MK_INSN(cwde, "mov $0xFFFE, %eax \n\t" 9406e293cf5SWei Yongjun "cwde\n\t"); 9416e293cf5SWei Yongjun 94218253fdeSAvi Kivity inregs = (struct regs){ 0 }; 94318253fdeSAvi Kivity 94418253fdeSAvi Kivity exec_in_big_real_mode(&insn_cbw); 9456055ea1fSAvi Kivity report("cbq 1", ~0, outregs.eax == 0xFFFE); 9466e293cf5SWei Yongjun 94718253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwde); 9486055ea1fSAvi Kivity report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE); 9496e293cf5SWei Yongjun } 9506e293cf5SWei Yongjun 9512e3f9f1fSThomas Huth static void test_loopcc(void) 952eacef4e2SWei Yongjun { 953eacef4e2SWei Yongjun MK_INSN(loop, "mov $10, %ecx\n\t" 954eacef4e2SWei Yongjun "1: inc %eax\n\t" 955eacef4e2SWei Yongjun "loop 1b\n\t"); 956eacef4e2SWei Yongjun 957eacef4e2SWei Yongjun MK_INSN(loope, "mov $10, %ecx\n\t" 958eacef4e2SWei Yongjun "mov $1, %eax\n\t" 959eacef4e2SWei Yongjun "1: dec %eax\n\t" 960eacef4e2SWei Yongjun "loope 1b\n\t"); 961eacef4e2SWei Yongjun 962eacef4e2SWei Yongjun MK_INSN(loopne, "mov $10, %ecx\n\t" 963eacef4e2SWei Yongjun "mov $5, %eax\n\t" 964eacef4e2SWei Yongjun "1: dec %eax\n\t" 965eacef4e2SWei Yongjun "loopne 1b\n\t"); 966eacef4e2SWei Yongjun 96718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 968eacef4e2SWei Yongjun 96918253fdeSAvi Kivity exec_in_big_real_mode(&insn_loop); 9706055ea1fSAvi Kivity report("LOOPcc short 1", R_AX, outregs.eax == 10); 97118253fdeSAvi Kivity 97218253fdeSAvi Kivity exec_in_big_real_mode(&insn_loope); 9736055ea1fSAvi Kivity report("LOOPcc short 2", R_AX | R_CX, 9746055ea1fSAvi Kivity outregs.eax == -1 && outregs.ecx == 8); 975eacef4e2SWei Yongjun 97618253fdeSAvi Kivity exec_in_big_real_mode(&insn_loopne); 9776055ea1fSAvi Kivity report("LOOPcc short 3", R_AX | R_CX, 9786055ea1fSAvi Kivity outregs.eax == 0 && outregs.ecx == 5); 979eacef4e2SWei Yongjun } 980eacef4e2SWei Yongjun 981b274feedSAvi Kivity static void test_das(void) 982b274feedSAvi Kivity { 983b274feedSAvi Kivity short i; 98481050840SAvi Kivity u16 nr_fail = 0; 985b274feedSAvi Kivity static unsigned test_cases[1024] = { 986b274feedSAvi Kivity 0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00, 987b274feedSAvi Kivity 0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01, 988b274feedSAvi Kivity 0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02, 989b274feedSAvi Kivity 0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03, 990b274feedSAvi Kivity 0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04, 991b274feedSAvi Kivity 0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05, 992b274feedSAvi Kivity 0x06000606, 0x8701a606, 0x56100006, 0x9711a006, 993b274feedSAvi Kivity 0x02000707, 0x8301a707, 0x12100107, 0x9311a107, 994b274feedSAvi Kivity 0x02000808, 0x8301a808, 0x12100208, 0x9311a208, 995b274feedSAvi Kivity 0x06000909, 0x8701a909, 0x16100309, 0x9711a309, 996b274feedSAvi Kivity 0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a, 997b274feedSAvi Kivity 0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b, 998b274feedSAvi Kivity 0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c, 999b274feedSAvi Kivity 0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d, 1000b274feedSAvi Kivity 0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e, 1001b274feedSAvi Kivity 0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f, 1002b274feedSAvi Kivity 0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10, 1003b274feedSAvi Kivity 0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11, 1004b274feedSAvi Kivity 0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12, 1005b274feedSAvi Kivity 0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13, 1006b274feedSAvi Kivity 0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14, 1007b274feedSAvi Kivity 0x02001515, 0x8301b515, 0x16100f15, 0x9711af15, 1008b274feedSAvi Kivity 0x02001616, 0x8301b616, 0x12101016, 0x9311b016, 1009b274feedSAvi Kivity 0x06001717, 0x8701b717, 0x16101117, 0x9711b117, 1010b274feedSAvi Kivity 0x06001818, 0x8701b818, 0x16101218, 0x9711b218, 1011b274feedSAvi Kivity 0x02001919, 0x8301b919, 0x12101319, 0x9311b319, 1012b274feedSAvi Kivity 0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a, 1013b274feedSAvi Kivity 0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b, 1014b274feedSAvi Kivity 0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c, 1015b274feedSAvi Kivity 0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d, 1016b274feedSAvi Kivity 0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e, 1017b274feedSAvi Kivity 0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f, 1018b274feedSAvi Kivity 0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20, 1019b274feedSAvi Kivity 0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21, 1020b274feedSAvi Kivity 0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22, 1021b274feedSAvi Kivity 0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23, 1022b274feedSAvi Kivity 0x06002424, 0x8301c424, 0x16101e24, 0x9711be24, 1023b274feedSAvi Kivity 0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25, 1024b274feedSAvi Kivity 0x02002626, 0x8701c626, 0x12102026, 0x9711c026, 1025b274feedSAvi Kivity 0x06002727, 0x8301c727, 0x16102127, 0x9311c127, 1026b274feedSAvi Kivity 0x06002828, 0x8301c828, 0x16102228, 0x9311c228, 1027b274feedSAvi Kivity 0x02002929, 0x8701c929, 0x12102329, 0x9711c329, 1028b274feedSAvi Kivity 0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a, 1029b274feedSAvi Kivity 0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b, 1030b274feedSAvi Kivity 0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c, 1031b274feedSAvi Kivity 0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d, 1032b274feedSAvi Kivity 0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e, 1033b274feedSAvi Kivity 0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f, 1034b274feedSAvi Kivity 0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30, 1035b274feedSAvi Kivity 0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31, 1036b274feedSAvi Kivity 0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32, 1037b274feedSAvi Kivity 0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33, 1038b274feedSAvi Kivity 0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34, 1039b274feedSAvi Kivity 0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35, 1040b274feedSAvi Kivity 0x06003636, 0x8301d636, 0x16103036, 0x9311d036, 1041b274feedSAvi Kivity 0x02003737, 0x8701d737, 0x12103137, 0x9711d137, 1042b274feedSAvi Kivity 0x02003838, 0x8701d838, 0x12103238, 0x9711d238, 1043b274feedSAvi Kivity 0x06003939, 0x8301d939, 0x16103339, 0x9311d339, 1044b274feedSAvi Kivity 0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a, 1045b274feedSAvi Kivity 0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b, 1046b274feedSAvi Kivity 0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c, 1047b274feedSAvi Kivity 0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d, 1048b274feedSAvi Kivity 0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e, 1049b274feedSAvi Kivity 0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f, 1050b274feedSAvi Kivity 0x02004040, 0x8301e040, 0x16103a40, 0x9311da40, 1051b274feedSAvi Kivity 0x06004141, 0x8701e141, 0x12103b41, 0x9711db41, 1052b274feedSAvi Kivity 0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42, 1053b274feedSAvi Kivity 0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43, 1054b274feedSAvi Kivity 0x06004444, 0x8701e444, 0x12103e44, 0x9711de44, 1055b274feedSAvi Kivity 0x02004545, 0x8301e545, 0x16103f45, 0x9311df45, 1056b274feedSAvi Kivity 0x02004646, 0x8301e646, 0x12104046, 0x9311e046, 1057b274feedSAvi Kivity 0x06004747, 0x8701e747, 0x16104147, 0x9711e147, 1058b274feedSAvi Kivity 0x06004848, 0x8701e848, 0x16104248, 0x9711e248, 1059b274feedSAvi Kivity 0x02004949, 0x8301e949, 0x12104349, 0x9311e349, 1060b274feedSAvi Kivity 0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a, 1061b274feedSAvi Kivity 0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b, 1062b274feedSAvi Kivity 0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c, 1063b274feedSAvi Kivity 0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d, 1064b274feedSAvi Kivity 0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e, 1065b274feedSAvi Kivity 0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f, 1066b274feedSAvi Kivity 0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50, 1067b274feedSAvi Kivity 0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51, 1068b274feedSAvi Kivity 0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52, 1069b274feedSAvi Kivity 0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53, 1070b274feedSAvi Kivity 0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54, 1071b274feedSAvi Kivity 0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55, 1072b274feedSAvi Kivity 0x06005656, 0x8701f656, 0x16105056, 0x9711f056, 1073b274feedSAvi Kivity 0x02005757, 0x8301f757, 0x12105157, 0x9311f157, 1074b274feedSAvi Kivity 0x02005858, 0x8301f858, 0x12105258, 0x9311f258, 1075b274feedSAvi Kivity 0x06005959, 0x8701f959, 0x16105359, 0x9711f359, 1076b274feedSAvi Kivity 0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a, 1077b274feedSAvi Kivity 0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b, 1078b274feedSAvi Kivity 0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c, 1079b274feedSAvi Kivity 0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d, 1080b274feedSAvi Kivity 0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e, 1081b274feedSAvi Kivity 0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f, 1082b274feedSAvi Kivity 0x06006060, 0x47010060, 0x16105a60, 0x9711fa60, 1083b274feedSAvi Kivity 0x02006161, 0x03010161, 0x12105b61, 0x9311fb61, 1084b274feedSAvi Kivity 0x02006262, 0x03010262, 0x16105c62, 0x9711fc62, 1085b274feedSAvi Kivity 0x06006363, 0x07010363, 0x12105d63, 0x9311fd63, 1086b274feedSAvi Kivity 0x02006464, 0x03010464, 0x12105e64, 0x9311fe64, 1087b274feedSAvi Kivity 0x06006565, 0x07010565, 0x16105f65, 0x9711ff65, 1088b274feedSAvi Kivity 0x06006666, 0x07010666, 0x16106066, 0x57110066, 1089b274feedSAvi Kivity 0x02006767, 0x03010767, 0x12106167, 0x13110167, 1090b274feedSAvi Kivity 0x02006868, 0x03010868, 0x12106268, 0x13110268, 1091b274feedSAvi Kivity 0x06006969, 0x07010969, 0x16106369, 0x17110369, 1092b274feedSAvi Kivity 0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a, 1093b274feedSAvi Kivity 0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b, 1094b274feedSAvi Kivity 0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c, 1095b274feedSAvi Kivity 0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d, 1096b274feedSAvi Kivity 0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e, 1097b274feedSAvi Kivity 0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f, 1098b274feedSAvi Kivity 0x02007070, 0x03011070, 0x16106a70, 0x17110a70, 1099b274feedSAvi Kivity 0x06007171, 0x07011171, 0x12106b71, 0x13110b71, 1100b274feedSAvi Kivity 0x06007272, 0x07011272, 0x16106c72, 0x17110c72, 1101b274feedSAvi Kivity 0x02007373, 0x03011373, 0x12106d73, 0x13110d73, 1102b274feedSAvi Kivity 0x06007474, 0x07011474, 0x12106e74, 0x13110e74, 1103b274feedSAvi Kivity 0x02007575, 0x03011575, 0x16106f75, 0x17110f75, 1104b274feedSAvi Kivity 0x02007676, 0x03011676, 0x12107076, 0x13111076, 1105b274feedSAvi Kivity 0x06007777, 0x07011777, 0x16107177, 0x17111177, 1106b274feedSAvi Kivity 0x06007878, 0x07011878, 0x16107278, 0x17111278, 1107b274feedSAvi Kivity 0x02007979, 0x03011979, 0x12107379, 0x13111379, 1108b274feedSAvi Kivity 0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a, 1109b274feedSAvi Kivity 0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b, 1110b274feedSAvi Kivity 0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c, 1111b274feedSAvi Kivity 0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d, 1112b274feedSAvi Kivity 0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e, 1113b274feedSAvi Kivity 0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f, 1114b274feedSAvi Kivity 0x82008080, 0x03012080, 0x12107a80, 0x13111a80, 1115b274feedSAvi Kivity 0x86008181, 0x07012181, 0x16107b81, 0x17111b81, 1116b274feedSAvi Kivity 0x86008282, 0x07012282, 0x12107c82, 0x13111c82, 1117b274feedSAvi Kivity 0x82008383, 0x03012383, 0x16107d83, 0x17111d83, 1118b274feedSAvi Kivity 0x86008484, 0x07012484, 0x16107e84, 0x17111e84, 1119b274feedSAvi Kivity 0x82008585, 0x03012585, 0x12107f85, 0x13111f85, 1120b274feedSAvi Kivity 0x82008686, 0x03012686, 0x92108086, 0x13112086, 1121b274feedSAvi Kivity 0x86008787, 0x07012787, 0x96108187, 0x17112187, 1122b274feedSAvi Kivity 0x86008888, 0x07012888, 0x96108288, 0x17112288, 1123b274feedSAvi Kivity 0x82008989, 0x03012989, 0x92108389, 0x13112389, 1124b274feedSAvi Kivity 0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a, 1125b274feedSAvi Kivity 0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b, 1126b274feedSAvi Kivity 0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c, 1127b274feedSAvi Kivity 0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d, 1128b274feedSAvi Kivity 0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e, 1129b274feedSAvi Kivity 0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f, 1130b274feedSAvi Kivity 0x86009090, 0x07013090, 0x92108a90, 0x13112a90, 1131b274feedSAvi Kivity 0x82009191, 0x03013191, 0x96108b91, 0x17112b91, 1132b274feedSAvi Kivity 0x82009292, 0x03013292, 0x92108c92, 0x13112c92, 1133b274feedSAvi Kivity 0x86009393, 0x07013393, 0x96108d93, 0x17112d93, 1134b274feedSAvi Kivity 0x82009494, 0x03013494, 0x96108e94, 0x17112e94, 1135b274feedSAvi Kivity 0x86009595, 0x07013595, 0x92108f95, 0x13112f95, 1136b274feedSAvi Kivity 0x86009696, 0x07013696, 0x96109096, 0x17113096, 1137b274feedSAvi Kivity 0x82009797, 0x03013797, 0x92109197, 0x13113197, 1138b274feedSAvi Kivity 0x82009898, 0x03013898, 0x92109298, 0x13113298, 1139b274feedSAvi Kivity 0x86009999, 0x07013999, 0x96109399, 0x17113399, 1140b274feedSAvi Kivity 0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a, 1141b274feedSAvi Kivity 0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b, 1142b274feedSAvi Kivity 0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c, 1143b274feedSAvi Kivity 0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d, 1144b274feedSAvi Kivity 0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e, 1145b274feedSAvi Kivity 0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f, 1146b274feedSAvi Kivity 0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0, 1147b274feedSAvi Kivity 0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1, 1148b274feedSAvi Kivity 0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2, 1149b274feedSAvi Kivity 0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3, 1150b274feedSAvi Kivity 0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4, 1151b274feedSAvi Kivity 0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5, 1152b274feedSAvi Kivity 0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6, 1153b274feedSAvi Kivity 0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7, 1154b274feedSAvi Kivity 0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8, 1155b274feedSAvi Kivity 0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9, 1156b274feedSAvi Kivity 0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa, 1157b274feedSAvi Kivity 0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab, 1158b274feedSAvi Kivity 0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac, 1159b274feedSAvi Kivity 0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad, 1160b274feedSAvi Kivity 0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae, 1161b274feedSAvi Kivity 0x130049af, 0x130149af, 0x131049af, 0x131149af, 1162b274feedSAvi Kivity 0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0, 1163b274feedSAvi Kivity 0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1, 1164b274feedSAvi Kivity 0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2, 1165b274feedSAvi Kivity 0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3, 1166b274feedSAvi Kivity 0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4, 1167b274feedSAvi Kivity 0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5, 1168b274feedSAvi Kivity 0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6, 1169b274feedSAvi Kivity 0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7, 1170b274feedSAvi Kivity 0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8, 1171b274feedSAvi Kivity 0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9, 1172b274feedSAvi Kivity 0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba, 1173b274feedSAvi Kivity 0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb, 1174b274feedSAvi Kivity 0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc, 1175b274feedSAvi Kivity 0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd, 1176b274feedSAvi Kivity 0x130058be, 0x130158be, 0x131058be, 0x131158be, 1177b274feedSAvi Kivity 0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf, 1178b274feedSAvi Kivity 0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0, 1179b274feedSAvi Kivity 0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1, 1180b274feedSAvi Kivity 0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2, 1181b274feedSAvi Kivity 0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3, 1182b274feedSAvi Kivity 0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4, 1183b274feedSAvi Kivity 0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5, 1184b274feedSAvi Kivity 0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6, 1185b274feedSAvi Kivity 0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7, 1186b274feedSAvi Kivity 0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8, 1187b274feedSAvi Kivity 0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9, 1188b274feedSAvi Kivity 0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca, 1189b274feedSAvi Kivity 0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb, 1190b274feedSAvi Kivity 0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc, 1191b274feedSAvi Kivity 0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd, 1192b274feedSAvi Kivity 0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce, 1193b274feedSAvi Kivity 0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf, 1194b274feedSAvi Kivity 0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0, 1195b274feedSAvi Kivity 0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1, 1196b274feedSAvi Kivity 0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2, 1197b274feedSAvi Kivity 0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3, 1198b274feedSAvi Kivity 0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4, 1199b274feedSAvi Kivity 0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5, 1200b274feedSAvi Kivity 0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6, 1201b274feedSAvi Kivity 0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7, 1202b274feedSAvi Kivity 0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8, 1203b274feedSAvi Kivity 0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9, 1204b274feedSAvi Kivity 0x170074da, 0x170174da, 0x171074da, 0x171174da, 1205b274feedSAvi Kivity 0x130075db, 0x130175db, 0x131075db, 0x131175db, 1206b274feedSAvi Kivity 0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc, 1207b274feedSAvi Kivity 0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd, 1208b274feedSAvi Kivity 0x170078de, 0x170178de, 0x171078de, 0x171178de, 1209b274feedSAvi Kivity 0x130079df, 0x130179df, 0x131079df, 0x131179df, 1210b274feedSAvi Kivity 0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0, 1211b274feedSAvi Kivity 0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1, 1212b274feedSAvi Kivity 0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2, 1213b274feedSAvi Kivity 0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3, 1214b274feedSAvi Kivity 0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4, 1215b274feedSAvi Kivity 0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5, 1216b274feedSAvi Kivity 0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6, 1217b274feedSAvi Kivity 0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7, 1218b274feedSAvi Kivity 0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8, 1219b274feedSAvi Kivity 0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9, 1220b274feedSAvi Kivity 0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea, 1221b274feedSAvi Kivity 0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb, 1222b274feedSAvi Kivity 0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec, 1223b274feedSAvi Kivity 0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed, 1224b274feedSAvi Kivity 0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee, 1225b274feedSAvi Kivity 0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef, 1226b274feedSAvi Kivity 0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0, 1227b274feedSAvi Kivity 0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1, 1228b274feedSAvi Kivity 0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2, 1229b274feedSAvi Kivity 0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3, 1230b274feedSAvi Kivity 0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4, 1231b274feedSAvi Kivity 0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5, 1232b274feedSAvi Kivity 0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6, 1233b274feedSAvi Kivity 0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7, 1234b274feedSAvi Kivity 0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8, 1235b274feedSAvi Kivity 0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9, 1236b274feedSAvi Kivity 0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa, 1237b274feedSAvi Kivity 0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb, 1238b274feedSAvi Kivity 0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc, 1239b274feedSAvi Kivity 0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd, 1240b274feedSAvi Kivity 0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe, 1241b274feedSAvi Kivity 0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff, 1242b274feedSAvi Kivity }; 1243b274feedSAvi Kivity 1244b274feedSAvi Kivity MK_INSN(das, "das"); 1245b274feedSAvi Kivity 124618253fdeSAvi Kivity inregs = (struct regs){ 0 }; 124718253fdeSAvi Kivity 1248b274feedSAvi Kivity for (i = 0; i < 1024; ++i) { 1249b274feedSAvi Kivity unsigned tmp = test_cases[i]; 1250b274feedSAvi Kivity inregs.eax = tmp & 0xff; 1251b274feedSAvi Kivity inregs.eflags = (tmp >> 16) & 0xff; 125218253fdeSAvi Kivity exec_in_big_real_mode(&insn_das); 125318253fdeSAvi Kivity if (!regs_equal(R_AX) 1254b274feedSAvi Kivity || outregs.eax != ((tmp >> 8) & 0xff) 1255b274feedSAvi Kivity || (outregs.eflags & 0xff) != (tmp >> 24)) { 125681050840SAvi Kivity ++nr_fail; 125781050840SAvi Kivity break; 1258b274feedSAvi Kivity } 1259b274feedSAvi Kivity } 12606055ea1fSAvi Kivity report("DAS", ~0, nr_fail == 0); 1261b274feedSAvi Kivity } 1262b274feedSAvi Kivity 12632e3f9f1fSThomas Huth static void test_cwd_cdq(void) 12640cbd5b06SMohammed Gamal { 12650cbd5b06SMohammed Gamal /* Sign-bit set */ 12660cbd5b06SMohammed Gamal MK_INSN(cwd_1, "mov $0x8000, %ax\n\t" 12670cbd5b06SMohammed Gamal "cwd\n\t"); 12680cbd5b06SMohammed Gamal 12690cbd5b06SMohammed Gamal /* Sign-bit not set */ 12700cbd5b06SMohammed Gamal MK_INSN(cwd_2, "mov $0x1000, %ax\n\t" 12710cbd5b06SMohammed Gamal "cwd\n\t"); 12720cbd5b06SMohammed Gamal 12730cbd5b06SMohammed Gamal /* Sign-bit set */ 12740cbd5b06SMohammed Gamal MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t" 12750cbd5b06SMohammed Gamal "cdq\n\t"); 12760cbd5b06SMohammed Gamal 12770cbd5b06SMohammed Gamal /* Sign-bit not set */ 12780cbd5b06SMohammed Gamal MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t" 12790cbd5b06SMohammed Gamal "cdq\n\t"); 12800cbd5b06SMohammed Gamal 128118253fdeSAvi Kivity inregs = (struct regs){ 0 }; 128218253fdeSAvi Kivity 128318253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwd_1); 12846055ea1fSAvi Kivity report("cwd 1", R_AX | R_DX, 12856055ea1fSAvi Kivity outregs.eax == 0x8000 && outregs.edx == 0xffff); 12860cbd5b06SMohammed Gamal 128718253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwd_2); 12886055ea1fSAvi Kivity report("cwd 2", R_AX | R_DX, 12896055ea1fSAvi Kivity outregs.eax == 0x1000 && outregs.edx == 0); 12900cbd5b06SMohammed Gamal 129118253fdeSAvi Kivity exec_in_big_real_mode(&insn_cdq_1); 12926055ea1fSAvi Kivity report("cdq 1", R_AX | R_DX, 12936055ea1fSAvi Kivity outregs.eax == 0x80000000 && outregs.edx == 0xffffffff); 12940cbd5b06SMohammed Gamal 129518253fdeSAvi Kivity exec_in_big_real_mode(&insn_cdq_2); 12966055ea1fSAvi Kivity report("cdq 2", R_AX | R_DX, 12976055ea1fSAvi Kivity outregs.eax == 0x10000000 && outregs.edx == 0); 12980cbd5b06SMohammed Gamal } 12990cbd5b06SMohammed Gamal 130037f51a4aSWei Yongjun static struct { 130137f51a4aSWei Yongjun void *address; 130237f51a4aSWei Yongjun unsigned short sel; 130337f51a4aSWei Yongjun } __attribute__((packed)) desc = { 130437f51a4aSWei Yongjun (void *)0x1234, 130537f51a4aSWei Yongjun 0x10, 130637f51a4aSWei Yongjun }; 130737f51a4aSWei Yongjun 13082e3f9f1fSThomas Huth static void test_lds_lss(void) 130937f51a4aSWei Yongjun { 131037f51a4aSWei Yongjun inregs = (struct regs){ .ebx = (unsigned long)&desc }; 131137f51a4aSWei Yongjun 131237f51a4aSWei Yongjun MK_INSN(lds, "push %ds\n\t" 131337f51a4aSWei Yongjun "lds (%ebx), %eax\n\t" 131437f51a4aSWei Yongjun "mov %ds, %ebx\n\t" 131537f51a4aSWei Yongjun "pop %ds\n\t"); 131637f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lds); 131737f51a4aSWei Yongjun report("lds", R_AX | R_BX, 131837f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 131937f51a4aSWei Yongjun outregs.ebx == desc.sel); 132037f51a4aSWei Yongjun 1321*eb6687a2SBill Wendling MK_INSN(les, "les (%ebx), %eax\n\t" 1322*eb6687a2SBill Wendling "mov %es, %ebx\n\t"); 132337f51a4aSWei Yongjun exec_in_big_real_mode(&insn_les); 132437f51a4aSWei Yongjun report("les", R_AX | R_BX, 132537f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 132637f51a4aSWei Yongjun outregs.ebx == desc.sel); 132737f51a4aSWei Yongjun 132837f51a4aSWei Yongjun MK_INSN(lfs, "push %fs\n\t" 132937f51a4aSWei Yongjun "lfs (%ebx), %eax\n\t" 133037f51a4aSWei Yongjun "mov %fs, %ebx\n\t" 133137f51a4aSWei Yongjun "pop %fs\n\t"); 133237f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lfs); 133337f51a4aSWei Yongjun report("lfs", R_AX | R_BX, 133437f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 133537f51a4aSWei Yongjun outregs.ebx == desc.sel); 133637f51a4aSWei Yongjun 133737f51a4aSWei Yongjun MK_INSN(lgs, "push %gs\n\t" 133837f51a4aSWei Yongjun "lgs (%ebx), %eax\n\t" 133937f51a4aSWei Yongjun "mov %gs, %ebx\n\t" 134037f51a4aSWei Yongjun "pop %gs\n\t"); 134137f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lgs); 134237f51a4aSWei Yongjun report("lgs", R_AX | R_BX, 134337f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 134437f51a4aSWei Yongjun outregs.ebx == desc.sel); 134537f51a4aSWei Yongjun 134637f51a4aSWei Yongjun MK_INSN(lss, "push %ss\n\t" 134737f51a4aSWei Yongjun "lss (%ebx), %eax\n\t" 134837f51a4aSWei Yongjun "mov %ss, %ebx\n\t" 134937f51a4aSWei Yongjun "pop %ss\n\t"); 135037f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lss); 135137f51a4aSWei Yongjun report("lss", R_AX | R_BX, 135237f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 135337f51a4aSWei Yongjun outregs.ebx == desc.sel); 135437f51a4aSWei Yongjun } 135537f51a4aSWei Yongjun 13562e3f9f1fSThomas Huth static void test_jcxz(void) 1357b1c7c575SWei Yongjun { 1358b1c7c575SWei Yongjun MK_INSN(jcxz1, "jcxz 1f\n\t" 1359b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1360b1c7c575SWei Yongjun "1:\n\t"); 1361b1c7c575SWei Yongjun MK_INSN(jcxz2, "mov $0x100, %ecx\n\t" 1362b1c7c575SWei Yongjun "jcxz 1f\n\t" 1363b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1364b1c7c575SWei Yongjun "mov $0, %ecx\n\t" 1365b1c7c575SWei Yongjun "1:\n\t"); 1366b1c7c575SWei Yongjun MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t" 1367b1c7c575SWei Yongjun "jcxz 1f\n\t" 1368b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1369b1c7c575SWei Yongjun "1:\n\t"); 1370b1c7c575SWei Yongjun MK_INSN(jecxz1, "jecxz 1f\n\t" 1371b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1372b1c7c575SWei Yongjun "1:\n\t"); 1373b1c7c575SWei Yongjun MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t" 1374b1c7c575SWei Yongjun "jecxz 1f\n\t" 1375b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1376b1c7c575SWei Yongjun "mov $0, %ecx\n\t" 1377b1c7c575SWei Yongjun "1:\n\t"); 1378b1c7c575SWei Yongjun 1379b1c7c575SWei Yongjun inregs = (struct regs){ 0 }; 1380b1c7c575SWei Yongjun 1381b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jcxz1); 1382b1c7c575SWei Yongjun report("jcxz short 1", 0, 1); 1383b1c7c575SWei Yongjun 1384b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jcxz2); 1385b1c7c575SWei Yongjun report("jcxz short 2", R_AX, outregs.eax == 0x1234); 1386b1c7c575SWei Yongjun 1387b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jcxz3); 1388b1c7c575SWei Yongjun report("jcxz short 3", R_CX, outregs.ecx == 0x10000); 1389b1c7c575SWei Yongjun 1390b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jecxz1); 1391b1c7c575SWei Yongjun report("jecxz short 1", 0, 1); 1392b1c7c575SWei Yongjun 1393b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jecxz2); 1394b1c7c575SWei Yongjun report("jecxz short 2", R_AX, outregs.eax == 0x1234); 1395b1c7c575SWei Yongjun } 1396b1c7c575SWei Yongjun 13978f578e98SAvi Kivity static void test_cpuid(void) 13988f578e98SAvi Kivity { 13998f578e98SAvi Kivity MK_INSN(cpuid, "cpuid"); 14008f578e98SAvi Kivity unsigned function = 0x1234; 14018f578e98SAvi Kivity unsigned eax, ebx, ecx, edx; 14028f578e98SAvi Kivity 14038f578e98SAvi Kivity inregs.eax = eax = function; 140418ba9083SGleb Natapov inregs.ecx = ecx = 0; 1405674d2dbeSPaolo Bonzini asm("cpuid" : "+a"(eax), "=b"(ebx), "+c"(ecx), "=d"(edx)); 14068f578e98SAvi Kivity exec_in_big_real_mode(&insn_cpuid); 14078f578e98SAvi Kivity report("cpuid", R_AX|R_BX|R_CX|R_DX, 14088f578e98SAvi Kivity outregs.eax == eax && outregs.ebx == ebx 14098f578e98SAvi Kivity && outregs.ecx == ecx && outregs.edx == edx); 14108f578e98SAvi Kivity } 14118f578e98SAvi Kivity 1412ed93f43bSAvi Kivity static void test_ss_base_for_esp_ebp(void) 1413ed93f43bSAvi Kivity { 1414ed93f43bSAvi Kivity MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss"); 1415ed93f43bSAvi Kivity MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss"); 1416ed93f43bSAvi Kivity static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 }; 1417ed93f43bSAvi Kivity 1418ed93f43bSAvi Kivity inregs.ebx = 1; 1419ed93f43bSAvi Kivity inregs.ebp = (unsigned)array; 1420ed93f43bSAvi Kivity exec_in_big_real_mode(&insn_ssrel1); 1421ed93f43bSAvi Kivity report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321); 1422ed93f43bSAvi Kivity inregs.ebx = 1; 1423ed93f43bSAvi Kivity inregs.ebp = (unsigned)array; 1424ed93f43bSAvi Kivity inregs.edi = 0; 1425ed93f43bSAvi Kivity exec_in_big_real_mode(&insn_ssrel2); 1426ed93f43bSAvi Kivity report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321); 1427ed93f43bSAvi Kivity } 1428ed93f43bSAvi Kivity 1429975ca087SPeter Feiner extern unsigned long long r_gdt[]; 1430975ca087SPeter Feiner 1431c2281fa4SAvi Kivity static void test_sgdt_sidt(void) 1432c2281fa4SAvi Kivity { 1433c2281fa4SAvi Kivity MK_INSN(sgdt, "sgdtw (%eax)"); 1434c2281fa4SAvi Kivity MK_INSN(sidt, "sidtw (%eax)"); 1435975ca087SPeter Feiner struct table_descr x, y; 1436c2281fa4SAvi Kivity 1437c2281fa4SAvi Kivity inregs.eax = (unsigned)&y; 1438c2281fa4SAvi Kivity asm volatile("sgdtw %0" : "=m"(x)); 1439c2281fa4SAvi Kivity exec_in_big_real_mode(&insn_sgdt); 1440975ca087SPeter Feiner report("sgdt", 0, x.limit == y.limit && x.base == y.base); 1441c2281fa4SAvi Kivity 1442c2281fa4SAvi Kivity inregs.eax = (unsigned)&y; 1443c2281fa4SAvi Kivity asm volatile("sidtw %0" : "=m"(x)); 1444c2281fa4SAvi Kivity exec_in_big_real_mode(&insn_sidt); 1445975ca087SPeter Feiner report("sidt", 0, x.limit == y.limit && x.base == y.base); 1446c2281fa4SAvi Kivity } 1447c2281fa4SAvi Kivity 144888b6dac4SPaolo Bonzini static void test_sahf(void) 144988b6dac4SPaolo Bonzini { 145088b6dac4SPaolo Bonzini MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw"); 145188b6dac4SPaolo Bonzini 145288b6dac4SPaolo Bonzini inregs.eax = 0xfd00; 145388b6dac4SPaolo Bonzini exec_in_big_real_mode(&insn_sahf); 145488b6dac4SPaolo Bonzini report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7)); 145588b6dac4SPaolo Bonzini } 145688b6dac4SPaolo Bonzini 14577ae3645aSAvi Kivity static void test_lahf(void) 14587ae3645aSAvi Kivity { 14597ae3645aSAvi Kivity MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf"); 14607ae3645aSAvi Kivity 14617ae3645aSAvi Kivity inregs.eax = 0xc7; 14627ae3645aSAvi Kivity exec_in_big_real_mode(&insn_lahf); 14637ae3645aSAvi Kivity report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax); 14647ae3645aSAvi Kivity } 14657ae3645aSAvi Kivity 1466fd9ea640SAvi Kivity static void test_movzx_movsx(void) 1467fd9ea640SAvi Kivity { 1468fd9ea640SAvi Kivity MK_INSN(movsx, "movsx %al, %ebx"); 1469fd9ea640SAvi Kivity MK_INSN(movzx, "movzx %al, %ebx"); 14703013e079SGleb Natapov MK_INSN(movzsah, "movsx %ah, %ebx"); 14713013e079SGleb Natapov MK_INSN(movzxah, "movzx %ah, %ebx"); 1472fd9ea640SAvi Kivity 1473fd9ea640SAvi Kivity inregs.eax = 0x1234569c; 14743013e079SGleb Natapov inregs.esp = 0xffff; 1475fd9ea640SAvi Kivity exec_in_big_real_mode(&insn_movsx); 1476fd9ea640SAvi Kivity report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax); 1477fd9ea640SAvi Kivity exec_in_big_real_mode(&insn_movzx); 1478fd9ea640SAvi Kivity report("movzx", R_BX, outregs.ebx == (unsigned char)inregs.eax); 14793013e079SGleb Natapov exec_in_big_real_mode(&insn_movzsah); 14803013e079SGleb Natapov report("movsx ah", R_BX, outregs.ebx == (signed char)(inregs.eax>>8)); 14813013e079SGleb Natapov exec_in_big_real_mode(&insn_movzxah); 14823013e079SGleb Natapov report("movzx ah", R_BX, outregs.ebx == (unsigned char)(inregs.eax >> 8)); 1483fd9ea640SAvi Kivity } 1484fd9ea640SAvi Kivity 1485b493b2e8SAvi Kivity static void test_bswap(void) 1486b493b2e8SAvi Kivity { 1487b493b2e8SAvi Kivity MK_INSN(bswap, "bswap %ecx"); 1488b493b2e8SAvi Kivity 1489b493b2e8SAvi Kivity inregs.ecx = 0x12345678; 1490b493b2e8SAvi Kivity exec_in_big_real_mode(&insn_bswap); 1491b493b2e8SAvi Kivity report("bswap", R_CX, outregs.ecx == 0x78563412); 1492b493b2e8SAvi Kivity } 1493b493b2e8SAvi Kivity 14948cd86387SGleb Natapov static void test_aad(void) 14958cd86387SGleb Natapov { 14968cd86387SGleb Natapov MK_INSN(aad, "aad"); 14978cd86387SGleb Natapov 14988cd86387SGleb Natapov inregs.eax = 0x12345678; 14998cd86387SGleb Natapov exec_in_big_real_mode(&insn_aad); 15008cd86387SGleb Natapov report("aad", R_AX, outregs.eax == 0x123400d4); 15018cd86387SGleb Natapov } 15028cd86387SGleb Natapov 15032a9b5718SPaolo Bonzini static void test_aam(void) 15042a9b5718SPaolo Bonzini { 15052a9b5718SPaolo Bonzini MK_INSN(aam, "aam"); 15062a9b5718SPaolo Bonzini 15072a9b5718SPaolo Bonzini inregs.eax = 0x76543210; 15082a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_aam); 15092a9b5718SPaolo Bonzini report("aam", R_AX, outregs.eax == 0x76540106); 15102a9b5718SPaolo Bonzini } 15112a9b5718SPaolo Bonzini 15122a9b5718SPaolo Bonzini static void test_xlat(void) 15132a9b5718SPaolo Bonzini { 15142a9b5718SPaolo Bonzini MK_INSN(xlat, "xlat"); 15152a9b5718SPaolo Bonzini u8 table[256]; 15162a9b5718SPaolo Bonzini int i; 15172a9b5718SPaolo Bonzini 15182a9b5718SPaolo Bonzini for (i = 0; i < 256; i++) { 15192a9b5718SPaolo Bonzini table[i] = i + 1; 15202a9b5718SPaolo Bonzini } 15212a9b5718SPaolo Bonzini 15222a9b5718SPaolo Bonzini inregs.eax = 0x89abcdef; 15232a9b5718SPaolo Bonzini inregs.ebx = (u32)table; 15242a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_xlat); 15252a9b5718SPaolo Bonzini report("xlat", R_AX, outregs.eax == 0x89abcdf0); 15262a9b5718SPaolo Bonzini } 15272a9b5718SPaolo Bonzini 15282a9b5718SPaolo Bonzini static void test_salc(void) 15292a9b5718SPaolo Bonzini { 15302a9b5718SPaolo Bonzini MK_INSN(clc_salc, "clc; .byte 0xd6"); 15312a9b5718SPaolo Bonzini MK_INSN(stc_salc, "stc; .byte 0xd6"); 15322a9b5718SPaolo Bonzini 15332a9b5718SPaolo Bonzini inregs.eax = 0x12345678; 15342a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_clc_salc); 15352a9b5718SPaolo Bonzini report("salc (1)", R_AX, outregs.eax == 0x12345600); 15362a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_stc_salc); 15372a9b5718SPaolo Bonzini report("salc (2)", R_AX, outregs.eax == 0x123456ff); 15382a9b5718SPaolo Bonzini } 15392a9b5718SPaolo Bonzini 15400987db7aSGleb Natapov static void test_fninit(void) 15410987db7aSGleb Natapov { 15420987db7aSGleb Natapov u16 fcw = -1, fsw = -1; 15430987db7aSGleb Natapov MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)"); 15440987db7aSGleb Natapov 15450987db7aSGleb Natapov inregs.eax = (u32)&fsw; 15460987db7aSGleb Natapov inregs.ebx = (u32)&fcw; 15470987db7aSGleb Natapov 15480987db7aSGleb Natapov exec_in_big_real_mode(&insn_fninit); 15490987db7aSGleb Natapov report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f); 15500987db7aSGleb Natapov } 15510987db7aSGleb Natapov 15521a4c03a0SArthur Chunqi Li static void test_nopl(void) 15531a4c03a0SArthur Chunqi Li { 15541a4c03a0SArthur Chunqi Li MK_INSN(nopl1, ".byte 0x90\n\r"); // 1 byte nop 15551a4c03a0SArthur Chunqi Li MK_INSN(nopl2, ".byte 0x66, 0x90\n\r"); // 2 bytes nop 15561a4c03a0SArthur Chunqi Li MK_INSN(nopl3, ".byte 0x0f, 0x1f, 0x00\n\r"); // 3 bytes nop 15571a4c03a0SArthur Chunqi Li MK_INSN(nopl4, ".byte 0x0f, 0x1f, 0x40, 0x00\n\r"); // 4 bytes nop 15581a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl1); 15591a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl2); 15601a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl3); 15611a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl4); 15621a4c03a0SArthur Chunqi Li report("nopl", 0, 1); 15631a4c03a0SArthur Chunqi Li } 15641a4c03a0SArthur Chunqi Li 1565b5105e8bSPaolo Bonzini static u32 perf_baseline; 1566b5105e8bSPaolo Bonzini 15677505ea23SPaolo Bonzini #define PERF_COUNT 1000000 1568b5105e8bSPaolo Bonzini 1569b5105e8bSPaolo Bonzini #define MK_INSN_PERF(name, insn) \ 1570b5105e8bSPaolo Bonzini MK_INSN(name, "rdtsc; mov %eax, %ebx; mov %edx, %esi\n" \ 1571b5105e8bSPaolo Bonzini "1:" insn "\n" \ 15727505ea23SPaolo Bonzini ".byte 0x67; loop 1b\n" \ 1573b5105e8bSPaolo Bonzini "rdtsc"); 1574b5105e8bSPaolo Bonzini 1575b5105e8bSPaolo Bonzini static u32 cycles_in_big_real_mode(struct insn_desc *insn) 1576b5105e8bSPaolo Bonzini { 1577b5105e8bSPaolo Bonzini u64 start, end; 1578b5105e8bSPaolo Bonzini 1579b5105e8bSPaolo Bonzini inregs.ecx = PERF_COUNT; 1580b5105e8bSPaolo Bonzini exec_in_big_real_mode(insn); 1581b5105e8bSPaolo Bonzini start = ((u64)outregs.esi << 32) | outregs.ebx; 1582b5105e8bSPaolo Bonzini end = ((u64)outregs.edx << 32) | outregs.eax; 1583b5105e8bSPaolo Bonzini 1584b5105e8bSPaolo Bonzini return end - start; 1585b5105e8bSPaolo Bonzini } 1586b5105e8bSPaolo Bonzini 1587b5105e8bSPaolo Bonzini static void test_perf_loop(void) 1588b5105e8bSPaolo Bonzini { 1589b5105e8bSPaolo Bonzini /* 1590b5105e8bSPaolo Bonzini * This test runs simple instructions that should roughly take the 1591b5105e8bSPaolo Bonzini * the same time to emulate: PERF_COUNT iterations of "loop" and 3 1592b5105e8bSPaolo Bonzini * setup instructions. Other performance tests can run PERF_COUNT 1593b5105e8bSPaolo Bonzini * iterations of the same instruction and subtract the cycle count 1594b5105e8bSPaolo Bonzini * of this test. 1595b5105e8bSPaolo Bonzini */ 1596b5105e8bSPaolo Bonzini MK_INSN_PERF(perf_loop, ""); 1597b5105e8bSPaolo Bonzini perf_baseline = cycles_in_big_real_mode(&insn_perf_loop); 1598b5105e8bSPaolo Bonzini print_serial_u32(perf_baseline / (PERF_COUNT + 3)); 1599b5105e8bSPaolo Bonzini print_serial(" cycles/emulated jump instruction\n"); 1600b5105e8bSPaolo Bonzini } 1601b5105e8bSPaolo Bonzini 1602b5105e8bSPaolo Bonzini static void test_perf_mov(void) 1603b5105e8bSPaolo Bonzini { 1604b5105e8bSPaolo Bonzini u32 cyc; 1605b5105e8bSPaolo Bonzini 1606b5105e8bSPaolo Bonzini MK_INSN_PERF(perf_move, "mov %esi, %edi"); 1607b5105e8bSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_move); 1608b5105e8bSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 1609b5105e8bSPaolo Bonzini print_serial(" cycles/emulated move instruction\n"); 1610b5105e8bSPaolo Bonzini } 1611b5105e8bSPaolo Bonzini 1612b5105e8bSPaolo Bonzini static void test_perf_arith(void) 1613b5105e8bSPaolo Bonzini { 1614b5105e8bSPaolo Bonzini u32 cyc; 1615b5105e8bSPaolo Bonzini 1616b5105e8bSPaolo Bonzini MK_INSN_PERF(perf_arith, "add $4, %edi"); 1617b5105e8bSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_arith); 1618b5105e8bSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 1619b5105e8bSPaolo Bonzini print_serial(" cycles/emulated arithmetic instruction\n"); 1620b5105e8bSPaolo Bonzini } 1621b5105e8bSPaolo Bonzini 1622b5105e8bSPaolo Bonzini static void test_perf_memory_load(void) 1623b5105e8bSPaolo Bonzini { 1624b5105e8bSPaolo Bonzini u32 cyc, tmp; 1625b5105e8bSPaolo Bonzini 1626b5105e8bSPaolo Bonzini MK_INSN_PERF(perf_memory_load, "cmp $0, (%edi)"); 1627b5105e8bSPaolo Bonzini inregs.edi = (u32)&tmp; 1628b5105e8bSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_memory_load); 1629b5105e8bSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 1630b5105e8bSPaolo Bonzini print_serial(" cycles/emulated memory load instruction\n"); 1631b5105e8bSPaolo Bonzini } 1632b5105e8bSPaolo Bonzini 16339306cb8eSPaolo Bonzini static void test_perf_memory_store(void) 16349306cb8eSPaolo Bonzini { 16359306cb8eSPaolo Bonzini u32 cyc, tmp; 16369306cb8eSPaolo Bonzini 16379306cb8eSPaolo Bonzini MK_INSN_PERF(perf_memory_store, "mov %ax, (%edi)"); 16389306cb8eSPaolo Bonzini inregs.edi = (u32)&tmp; 16399306cb8eSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_memory_store); 16409306cb8eSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 16419306cb8eSPaolo Bonzini print_serial(" cycles/emulated memory store instruction\n"); 16429306cb8eSPaolo Bonzini } 16439306cb8eSPaolo Bonzini 1644b5105e8bSPaolo Bonzini static void test_perf_memory_rmw(void) 1645b5105e8bSPaolo Bonzini { 1646b5105e8bSPaolo Bonzini u32 cyc, tmp; 1647b5105e8bSPaolo Bonzini 1648b5105e8bSPaolo Bonzini MK_INSN_PERF(perf_memory_rmw, "add $1, (%edi)"); 1649b5105e8bSPaolo Bonzini inregs.edi = (u32)&tmp; 1650b5105e8bSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_memory_rmw); 1651b5105e8bSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 1652b5105e8bSPaolo Bonzini print_serial(" cycles/emulated memory RMW instruction\n"); 1653b5105e8bSPaolo Bonzini } 1654b5105e8bSPaolo Bonzini 16552e3f9f1fSThomas Huth static void test_dr_mod(void) 16560a5701edSNadav Amit { 16570a5701edSNadav Amit MK_INSN(drmod, "movl %ebx, %dr0\n\t" 16580a5701edSNadav Amit ".byte 0x0f \n\t .byte 0x21 \n\t .byte 0x0\n\t"); 16590a5701edSNadav Amit inregs.eax = 0xdead; 16600a5701edSNadav Amit inregs.ebx = 0xaced; 16610a5701edSNadav Amit exec_in_big_real_mode(&insn_drmod); 16620a5701edSNadav Amit report("mov dr with mod bits", R_AX | R_BX, outregs.eax == 0xaced); 16630a5701edSNadav Amit } 16640a5701edSNadav Amit 16652e3f9f1fSThomas Huth static void test_smsw(void) 166699ee878cSNadav Amit { 166799ee878cSNadav Amit MK_INSN(smsw, "movl %cr0, %ebx\n\t" 166899ee878cSNadav Amit "movl %ebx, %ecx\n\t" 166999ee878cSNadav Amit "or $0x40000000, %ebx\n\t" 167099ee878cSNadav Amit "movl %ebx, %cr0\n\t" 167199ee878cSNadav Amit "smswl %eax\n\t" 167299ee878cSNadav Amit "movl %ecx, %cr0\n\t"); 167399ee878cSNadav Amit inregs.eax = 0x12345678; 167499ee878cSNadav Amit exec_in_big_real_mode(&insn_smsw); 167599ee878cSNadav Amit report("smsw", R_AX | R_BX | R_CX, outregs.eax == outregs.ebx); 167699ee878cSNadav Amit } 167799ee878cSNadav Amit 16782e3f9f1fSThomas Huth static void test_xadd(void) 16797bee560dSNadav Amit { 16807bee560dSNadav Amit MK_INSN(xadd, "xaddl %eax, %eax\n\t"); 16817bee560dSNadav Amit inregs.eax = 0x12345678; 16827bee560dSNadav Amit exec_in_big_real_mode(&insn_xadd); 16837bee560dSNadav Amit report("xadd", R_AX, outregs.eax == inregs.eax * 2); 16847bee560dSNadav Amit } 16857bee560dSNadav Amit 168699ee878cSNadav Amit 16877d36db35SAvi Kivity void realmode_start(void) 16887d36db35SAvi Kivity { 16897d36db35SAvi Kivity test_null(); 16907d36db35SAvi Kivity 16917d36db35SAvi Kivity test_shld(); 16927d36db35SAvi Kivity test_push_pop(); 16937d36db35SAvi Kivity test_pusha_popa(); 16947d36db35SAvi Kivity test_mov_imm(); 16957d36db35SAvi Kivity test_cmp_imm(); 16967d36db35SAvi Kivity test_add_imm(); 16977d36db35SAvi Kivity test_sub_imm(); 16987d36db35SAvi Kivity test_xor_imm(); 16997d36db35SAvi Kivity test_io(); 17007d36db35SAvi Kivity test_eflags_insn(); 17017d36db35SAvi Kivity test_jcc_short(); 17027d36db35SAvi Kivity test_jcc_near(); 17037d36db35SAvi Kivity /* test_call() uses short jump so call it after testing jcc */ 17047d36db35SAvi Kivity test_call(); 17057d36db35SAvi Kivity /* long jmp test uses call near so test it after testing call */ 17067d36db35SAvi Kivity test_long_jmp(); 17077d36db35SAvi Kivity test_xchg(); 17087d36db35SAvi Kivity test_iret(); 170996b9ca1eSMohammed Gamal test_int(); 1710fa74f8a6SMohammed Gamal test_imul(); 171159317bd1SMohammed Gamal test_mul(); 17120d4c7614SMohammed Gamal test_div(); 17130d4c7614SMohammed Gamal test_idiv(); 1714eacef4e2SWei Yongjun test_loopcc(); 17156e293cf5SWei Yongjun test_cbw(); 17160cbd5b06SMohammed Gamal test_cwd_cdq(); 1717b274feedSAvi Kivity test_das(); 171837f51a4aSWei Yongjun test_lds_lss(); 1719b1c7c575SWei Yongjun test_jcxz(); 17208f578e98SAvi Kivity test_cpuid(); 1721ed93f43bSAvi Kivity test_ss_base_for_esp_ebp(); 1722c2281fa4SAvi Kivity test_sgdt_sidt(); 17237ae3645aSAvi Kivity test_lahf(); 172488b6dac4SPaolo Bonzini test_sahf(); 1725fd9ea640SAvi Kivity test_movzx_movsx(); 1726b493b2e8SAvi Kivity test_bswap(); 17278cd86387SGleb Natapov test_aad(); 17282a9b5718SPaolo Bonzini test_aam(); 17292a9b5718SPaolo Bonzini test_xlat(); 17302a9b5718SPaolo Bonzini test_salc(); 17310987db7aSGleb Natapov test_fninit(); 17320a5701edSNadav Amit test_dr_mod(); 173399ee878cSNadav Amit test_smsw(); 17341a4c03a0SArthur Chunqi Li test_nopl(); 17357bee560dSNadav Amit test_xadd(); 1736b5105e8bSPaolo Bonzini test_perf_loop(); 1737b5105e8bSPaolo Bonzini test_perf_mov(); 1738b5105e8bSPaolo Bonzini test_perf_arith(); 1739b5105e8bSPaolo Bonzini test_perf_memory_load(); 17409306cb8eSPaolo Bonzini test_perf_memory_store(); 1741b5105e8bSPaolo Bonzini test_perf_memory_rmw(); 17427d36db35SAvi Kivity 1743b393fe28SNadav Amit exit(failed); 17447d36db35SAvi Kivity } 17457d36db35SAvi Kivity 17467d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff }; 17477d36db35SAvi Kivity 1748975ca087SPeter Feiner struct table_descr r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt }; 17497d36db35SAvi Kivity 17507d36db35SAvi Kivity asm( 17517d36db35SAvi Kivity ".section .init \n\t" 17527d36db35SAvi Kivity 17537d36db35SAvi Kivity ".code32 \n\t" 17547d36db35SAvi Kivity 17557d36db35SAvi Kivity "mb_magic = 0x1BADB002 \n\t" 17567d36db35SAvi Kivity "mb_flags = 0x0 \n\t" 17577d36db35SAvi Kivity 17587d36db35SAvi Kivity "# multiboot header \n\t" 17597d36db35SAvi Kivity ".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t" 17607d36db35SAvi Kivity 17617d36db35SAvi Kivity ".globl start \n\t" 17627d36db35SAvi Kivity ".data \n\t" 17637d36db35SAvi Kivity ". = . + 4096 \n\t" 17647d36db35SAvi Kivity "stacktop: \n\t" 17657d36db35SAvi Kivity 17667d36db35SAvi Kivity ".text \n\t" 17677d36db35SAvi Kivity "start: \n\t" 17687d36db35SAvi Kivity "lgdt r_gdt_descr \n\t" 17697d36db35SAvi Kivity "ljmp $8, $1f; 1: \n\t" 17707d36db35SAvi Kivity ".code16gcc \n\t" 17717d36db35SAvi Kivity "mov $16, %eax \n\t" 17727d36db35SAvi Kivity "mov %ax, %ds \n\t" 17737d36db35SAvi Kivity "mov %ax, %es \n\t" 17747d36db35SAvi Kivity "mov %ax, %fs \n\t" 17757d36db35SAvi Kivity "mov %ax, %gs \n\t" 17767d36db35SAvi Kivity "mov %ax, %ss \n\t" 17777d36db35SAvi Kivity "mov %cr0, %eax \n\t" 17787d36db35SAvi Kivity "btc $0, %eax \n\t" 17797d36db35SAvi Kivity "mov %eax, %cr0 \n\t" 17807d36db35SAvi Kivity "ljmp $0, $realmode_entry \n\t" 17817d36db35SAvi Kivity 17827d36db35SAvi Kivity "realmode_entry: \n\t" 17837d36db35SAvi Kivity 17847d36db35SAvi Kivity "xor %ax, %ax \n\t" 17857d36db35SAvi Kivity "mov %ax, %ds \n\t" 17867d36db35SAvi Kivity "mov %ax, %es \n\t" 17877d36db35SAvi Kivity "mov %ax, %ss \n\t" 17887d36db35SAvi Kivity "mov %ax, %fs \n\t" 17897d36db35SAvi Kivity "mov %ax, %gs \n\t" 17907d36db35SAvi Kivity "mov $stacktop, %esp\n\t" 17917d36db35SAvi Kivity "ljmp $0, $realmode_start \n\t" 17927d36db35SAvi Kivity 17937d36db35SAvi Kivity ".code16gcc \n\t" 17947d36db35SAvi Kivity ); 1795