1f366255fSPaolo Bonzini #ifndef USE_SERIAL 2f366255fSPaolo Bonzini #define USE_SERIAL 3f366255fSPaolo Bonzini #endif 4f366255fSPaolo Bonzini 57d36db35SAvi Kivity asm(".code16gcc"); 67d36db35SAvi Kivity 77d36db35SAvi Kivity typedef unsigned char u8; 87d36db35SAvi Kivity typedef unsigned short u16; 97d36db35SAvi Kivity typedef unsigned u32; 107d36db35SAvi Kivity typedef unsigned long long u64; 117d36db35SAvi Kivity 12*2e3f9f1fSThomas Huth void realmode_start(void); 137d36db35SAvi Kivity void test_function(void); 147d36db35SAvi Kivity 157d36db35SAvi Kivity asm( 167d36db35SAvi Kivity "test_function: \n\t" 177d36db35SAvi Kivity "mov $0x1234, %eax \n\t" 187d36db35SAvi Kivity "ret" 197d36db35SAvi Kivity ); 207d36db35SAvi Kivity 217d36db35SAvi Kivity static int strlen(const char *str) 227d36db35SAvi Kivity { 237d36db35SAvi Kivity int n; 247d36db35SAvi Kivity 257d36db35SAvi Kivity for (n = 0; *str; ++str) 267d36db35SAvi Kivity ++n; 277d36db35SAvi Kivity return n; 287d36db35SAvi Kivity } 297d36db35SAvi Kivity 30f366255fSPaolo Bonzini static void outb(u8 data, u16 port) 31f366255fSPaolo Bonzini { 32f366255fSPaolo Bonzini asm volatile("out %0, %1" : : "a"(data), "d"(port)); 33f366255fSPaolo Bonzini } 34f366255fSPaolo Bonzini 35f366255fSPaolo Bonzini #ifdef USE_SERIAL 36f366255fSPaolo Bonzini static int serial_iobase = 0x3f8; 37f366255fSPaolo Bonzini static int serial_inited = 0; 38f366255fSPaolo Bonzini 39f366255fSPaolo Bonzini static u8 inb(u16 port) 40f366255fSPaolo Bonzini { 41f366255fSPaolo Bonzini u8 data; 42f366255fSPaolo Bonzini asm volatile("in %1, %0" : "=a"(data) : "d"(port)); 43f366255fSPaolo Bonzini return data; 44f366255fSPaolo Bonzini } 45f366255fSPaolo Bonzini 46f366255fSPaolo Bonzini static void serial_outb(char ch) 47f366255fSPaolo Bonzini { 48f366255fSPaolo Bonzini u8 lsr; 49f366255fSPaolo Bonzini 50f366255fSPaolo Bonzini do { 51f366255fSPaolo Bonzini lsr = inb(serial_iobase + 0x05); 52f366255fSPaolo Bonzini } while (!(lsr & 0x20)); 53f366255fSPaolo Bonzini 54f366255fSPaolo Bonzini outb(ch, serial_iobase + 0x00); 55f366255fSPaolo Bonzini } 56f366255fSPaolo Bonzini 57f366255fSPaolo Bonzini static void serial_init(void) 58f366255fSPaolo Bonzini { 59f366255fSPaolo Bonzini u8 lcr; 60f366255fSPaolo Bonzini 61f366255fSPaolo Bonzini /* set DLAB */ 62f366255fSPaolo Bonzini lcr = inb(serial_iobase + 0x03); 63f366255fSPaolo Bonzini lcr |= 0x80; 64f366255fSPaolo Bonzini outb(lcr, serial_iobase + 0x03); 65f366255fSPaolo Bonzini 66f366255fSPaolo Bonzini /* set baud rate to 115200 */ 67f366255fSPaolo Bonzini outb(0x01, serial_iobase + 0x00); 68f366255fSPaolo Bonzini outb(0x00, serial_iobase + 0x01); 69f366255fSPaolo Bonzini 70f366255fSPaolo Bonzini /* clear DLAB */ 71f366255fSPaolo Bonzini lcr = inb(serial_iobase + 0x03); 72f366255fSPaolo Bonzini lcr &= ~0x80; 73f366255fSPaolo Bonzini outb(lcr, serial_iobase + 0x03); 74f366255fSPaolo Bonzini } 75f366255fSPaolo Bonzini #endif 76f366255fSPaolo Bonzini 777d36db35SAvi Kivity static void print_serial(const char *buf) 787d36db35SAvi Kivity { 797d36db35SAvi Kivity unsigned long len = strlen(buf); 80f366255fSPaolo Bonzini #ifdef USE_SERIAL 81f366255fSPaolo Bonzini unsigned long i; 82f366255fSPaolo Bonzini if (!serial_inited) { 83f366255fSPaolo Bonzini serial_init(); 84f366255fSPaolo Bonzini serial_inited = 1; 85f366255fSPaolo Bonzini } 867d36db35SAvi Kivity 87f366255fSPaolo Bonzini for (i = 0; i < len; i++) { 88f366255fSPaolo Bonzini serial_outb(buf[i]); 89f366255fSPaolo Bonzini } 90f366255fSPaolo Bonzini #else 915edbb9aeSPaolo Bonzini asm volatile ("addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1)); 92f366255fSPaolo Bonzini #endif 937d36db35SAvi Kivity } 947d36db35SAvi Kivity 95b5105e8bSPaolo Bonzini static void print_serial_u32(u32 value) 96b5105e8bSPaolo Bonzini { 97b5105e8bSPaolo Bonzini char n[12], *p; 98b5105e8bSPaolo Bonzini p = &n[11]; 99b5105e8bSPaolo Bonzini *p = 0; 100b5105e8bSPaolo Bonzini do { 101b5105e8bSPaolo Bonzini *--p = '0' + (value % 10); 102b5105e8bSPaolo Bonzini value /= 10; 103b5105e8bSPaolo Bonzini } while (value > 0); 104b5105e8bSPaolo Bonzini print_serial(p); 105b5105e8bSPaolo Bonzini } 106b5105e8bSPaolo Bonzini 107b393fe28SNadav Amit static int failed; 108b393fe28SNadav Amit 1097d36db35SAvi Kivity static void exit(int code) 1107d36db35SAvi Kivity { 111f366255fSPaolo Bonzini outb(code, 0xf4); 1127d36db35SAvi Kivity } 1137d36db35SAvi Kivity 1147d36db35SAvi Kivity struct regs { 1157d36db35SAvi Kivity u32 eax, ebx, ecx, edx; 1167d36db35SAvi Kivity u32 esi, edi, esp, ebp; 1177d36db35SAvi Kivity u32 eip, eflags; 1187d36db35SAvi Kivity }; 1197d36db35SAvi Kivity 120975ca087SPeter Feiner struct table_descr { 121975ca087SPeter Feiner u16 limit; 122975ca087SPeter Feiner void *base; 123975ca087SPeter Feiner } __attribute__((packed)); 124975ca087SPeter Feiner 1257d36db35SAvi Kivity static u64 gdt[] = { 1267d36db35SAvi Kivity 0, 1277d36db35SAvi Kivity 0x00cf9b000000ffffull, // flat 32-bit code segment 1287d36db35SAvi Kivity 0x00cf93000000ffffull, // flat 32-bit data segment 1297d36db35SAvi Kivity }; 1307d36db35SAvi Kivity 131975ca087SPeter Feiner static struct table_descr gdt_descr = { 1327d36db35SAvi Kivity sizeof(gdt) - 1, 1337d36db35SAvi Kivity gdt, 1347d36db35SAvi Kivity }; 1357d36db35SAvi Kivity 136d4dc402cSAvi Kivity struct insn_desc { 137d4dc402cSAvi Kivity u16 ptr; 138d4dc402cSAvi Kivity u16 len; 139d4dc402cSAvi Kivity }; 140d4dc402cSAvi Kivity 14118253fdeSAvi Kivity static struct regs inregs, outregs; 14218253fdeSAvi Kivity 14318253fdeSAvi Kivity static void exec_in_big_real_mode(struct insn_desc *insn) 1447d36db35SAvi Kivity { 1457d36db35SAvi Kivity unsigned long tmp; 1467d36db35SAvi Kivity static struct regs save; 1477d36db35SAvi Kivity int i; 1487d36db35SAvi Kivity extern u8 test_insn[], test_insn_end[]; 1497d36db35SAvi Kivity 150d4dc402cSAvi Kivity for (i = 0; i < insn->len; ++i) 151d4dc402cSAvi Kivity test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i]; 1527d36db35SAvi Kivity for (; i < test_insn_end - test_insn; ++i) 1537d36db35SAvi Kivity test_insn[i] = 0x90; // nop 1547d36db35SAvi Kivity 15518253fdeSAvi Kivity save = inregs; 1567d36db35SAvi Kivity asm volatile( 1577d36db35SAvi Kivity "lgdtl %[gdt_descr] \n\t" 1587d36db35SAvi Kivity "mov %%cr0, %[tmp] \n\t" 1597d36db35SAvi Kivity "or $1, %[tmp] \n\t" 1607d36db35SAvi Kivity "mov %[tmp], %%cr0 \n\t" 1617d36db35SAvi Kivity "mov %[bigseg], %%gs \n\t" 1627d36db35SAvi Kivity "and $-2, %[tmp] \n\t" 1637d36db35SAvi Kivity "mov %[tmp], %%cr0 \n\t" 1647d36db35SAvi Kivity 16532001692SAvi Kivity "pushw %[save]+36; popfw \n\t" 1667d36db35SAvi Kivity "xchg %%eax, %[save]+0 \n\t" 1677d36db35SAvi Kivity "xchg %%ebx, %[save]+4 \n\t" 1687d36db35SAvi Kivity "xchg %%ecx, %[save]+8 \n\t" 1697d36db35SAvi Kivity "xchg %%edx, %[save]+12 \n\t" 1707d36db35SAvi Kivity "xchg %%esi, %[save]+16 \n\t" 1717d36db35SAvi Kivity "xchg %%edi, %[save]+20 \n\t" 1727d36db35SAvi Kivity "xchg %%esp, %[save]+24 \n\t" 1737d36db35SAvi Kivity "xchg %%ebp, %[save]+28 \n\t" 1747d36db35SAvi Kivity 1757d36db35SAvi Kivity "test_insn: . = . + 32\n\t" 1767d36db35SAvi Kivity "test_insn_end: \n\t" 1777d36db35SAvi Kivity 1787d36db35SAvi Kivity "xchg %%eax, %[save]+0 \n\t" 1797d36db35SAvi Kivity "xchg %%ebx, %[save]+4 \n\t" 1807d36db35SAvi Kivity "xchg %%ecx, %[save]+8 \n\t" 1817d36db35SAvi Kivity "xchg %%edx, %[save]+12 \n\t" 1827d36db35SAvi Kivity "xchg %%esi, %[save]+16 \n\t" 1837d36db35SAvi Kivity "xchg %%edi, %[save]+20 \n\t" 1847d36db35SAvi Kivity "xchg %%esp, %[save]+24 \n\t" 1857d36db35SAvi Kivity "xchg %%ebp, %[save]+28 \n\t" 1867d36db35SAvi Kivity 1877d36db35SAvi Kivity /* Save EFLAGS in outregs*/ 1887d36db35SAvi Kivity "pushfl \n\t" 1897d36db35SAvi Kivity "popl %[save]+36 \n\t" 1907d36db35SAvi Kivity 1915edbb9aeSPaolo Bonzini /* Restore DF for the harness code */ 1925edbb9aeSPaolo Bonzini "cld\n\t" 1937d36db35SAvi Kivity "xor %[tmp], %[tmp] \n\t" 1947d36db35SAvi Kivity "mov %[tmp], %%gs \n\t" 1957d36db35SAvi Kivity : [tmp]"=&r"(tmp), [save]"+m"(save) 1967d36db35SAvi Kivity : [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16) 1977d36db35SAvi Kivity : "cc", "memory" 1987d36db35SAvi Kivity ); 19918253fdeSAvi Kivity outregs = save; 2007d36db35SAvi Kivity } 2017d36db35SAvi Kivity 2027d36db35SAvi Kivity #define R_AX 1 2037d36db35SAvi Kivity #define R_BX 2 2047d36db35SAvi Kivity #define R_CX 4 2057d36db35SAvi Kivity #define R_DX 8 2067d36db35SAvi Kivity #define R_SI 16 2077d36db35SAvi Kivity #define R_DI 32 2087d36db35SAvi Kivity #define R_SP 64 2097d36db35SAvi Kivity #define R_BP 128 2107d36db35SAvi Kivity 211*2e3f9f1fSThomas Huth static int regs_equal(int ignore) 2127d36db35SAvi Kivity { 21318253fdeSAvi Kivity const u32 *p1 = &inregs.eax, *p2 = &outregs.eax; // yuck 2147d36db35SAvi Kivity int i; 2157d36db35SAvi Kivity 2167d36db35SAvi Kivity for (i = 0; i < 8; ++i) 2177d36db35SAvi Kivity if (!(ignore & (1 << i)) && p1[i] != p2[i]) 2187d36db35SAvi Kivity return 0; 2197d36db35SAvi Kivity return 1; 2207d36db35SAvi Kivity } 2217d36db35SAvi Kivity 2226055ea1fSAvi Kivity static void report(const char *name, u16 regs_ignore, _Bool ok) 22381050840SAvi Kivity { 2246055ea1fSAvi Kivity if (!regs_equal(regs_ignore)) { 2256055ea1fSAvi Kivity ok = 0; 2266055ea1fSAvi Kivity } 22781050840SAvi Kivity print_serial(ok ? "PASS: " : "FAIL: "); 22881050840SAvi Kivity print_serial(name); 22981050840SAvi Kivity print_serial("\n"); 230b393fe28SNadav Amit if (!ok) 231b393fe28SNadav Amit failed = 1; 23281050840SAvi Kivity } 23381050840SAvi Kivity 2347d36db35SAvi Kivity #define MK_INSN(name, str) \ 2357d36db35SAvi Kivity asm ( \ 236d4dc402cSAvi Kivity ".pushsection .data.insn \n\t" \ 237d4dc402cSAvi Kivity "insn_" #name ": \n\t" \ 238d4dc402cSAvi Kivity ".word 1001f, 1002f - 1001f \n\t" \ 239d4dc402cSAvi Kivity ".popsection \n\t" \ 240d4dc402cSAvi Kivity ".pushsection .text.insn, \"ax\" \n\t" \ 241d4dc402cSAvi Kivity "1001: \n\t" \ 242d4dc402cSAvi Kivity "insn_code_" #name ": " str " \n\t" \ 243d4dc402cSAvi Kivity "1002: \n\t" \ 244d4dc402cSAvi Kivity ".popsection" \ 2457d36db35SAvi Kivity ); \ 246d4dc402cSAvi Kivity extern struct insn_desc insn_##name; 2477d36db35SAvi Kivity 248*2e3f9f1fSThomas Huth static void test_xchg(void) 2497d36db35SAvi Kivity { 2507d36db35SAvi Kivity MK_INSN(xchg_test1, "xchg %eax,%eax\n\t"); 2517d36db35SAvi Kivity MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t"); 2527d36db35SAvi Kivity MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t"); 2537d36db35SAvi Kivity MK_INSN(xchg_test4, "xchg %eax,%edx\n\t"); 2547d36db35SAvi Kivity MK_INSN(xchg_test5, "xchg %eax,%esi\n\t"); 2557d36db35SAvi Kivity MK_INSN(xchg_test6, "xchg %eax,%edi\n\t"); 2567d36db35SAvi Kivity MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t"); 2577d36db35SAvi Kivity MK_INSN(xchg_test8, "xchg %eax,%esp\n\t"); 2587d36db35SAvi Kivity 25918253fdeSAvi Kivity inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7}; 2607d36db35SAvi Kivity 26118253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test1); 2626055ea1fSAvi Kivity report("xchg 1", 0, 1); 26318253fdeSAvi Kivity 26418253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test2); 2656055ea1fSAvi Kivity report("xchg 2", R_AX | R_BX, 2666055ea1fSAvi Kivity outregs.eax == inregs.ebx && outregs.ebx == inregs.eax); 2677d36db35SAvi Kivity 26818253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test3); 2696055ea1fSAvi Kivity report("xchg 3", R_AX | R_CX, 2706055ea1fSAvi Kivity outregs.eax == inregs.ecx && outregs.ecx == inregs.eax); 2717d36db35SAvi Kivity 27218253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test4); 2736055ea1fSAvi Kivity report("xchg 4", R_AX | R_DX, 2746055ea1fSAvi Kivity outregs.eax == inregs.edx && outregs.edx == inregs.eax); 2757d36db35SAvi Kivity 27618253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test5); 2776055ea1fSAvi Kivity report("xchg 5", R_AX | R_SI, 2786055ea1fSAvi Kivity outregs.eax == inregs.esi && outregs.esi == inregs.eax); 2797d36db35SAvi Kivity 28018253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test6); 2816055ea1fSAvi Kivity report("xchg 6", R_AX | R_DI, 2826055ea1fSAvi Kivity outregs.eax == inregs.edi && outregs.edi == inregs.eax); 2837d36db35SAvi Kivity 28418253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test7); 2856055ea1fSAvi Kivity report("xchg 7", R_AX | R_BP, 2866055ea1fSAvi Kivity outregs.eax == inregs.ebp && outregs.ebp == inregs.eax); 2877d36db35SAvi Kivity 28818253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test8); 2896055ea1fSAvi Kivity report("xchg 8", R_AX | R_SP, 2906055ea1fSAvi Kivity outregs.eax == inregs.esp && outregs.esp == inregs.eax); 2917d36db35SAvi Kivity } 2927d36db35SAvi Kivity 293*2e3f9f1fSThomas Huth static void test_shld(void) 2947d36db35SAvi Kivity { 2957d36db35SAvi Kivity MK_INSN(shld_test, "shld $8,%edx,%eax\n\t"); 2967d36db35SAvi Kivity 29718253fdeSAvi Kivity inregs = (struct regs){ .eax = 0xbe, .edx = 0xef000000 }; 29818253fdeSAvi Kivity exec_in_big_real_mode(&insn_shld_test); 2996055ea1fSAvi Kivity report("shld", ~0, outregs.eax == 0xbeef); 3007d36db35SAvi Kivity } 3017d36db35SAvi Kivity 302*2e3f9f1fSThomas Huth static void test_mov_imm(void) 3037d36db35SAvi Kivity { 3047d36db35SAvi Kivity MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax"); 3057d36db35SAvi Kivity MK_INSN(mov_r16_imm_1, "mov $1234, %ax"); 3067d36db35SAvi Kivity MK_INSN(mov_r8_imm_1, "mov $0x12, %ah"); 3077d36db35SAvi Kivity MK_INSN(mov_r8_imm_2, "mov $0x34, %al"); 3087d36db35SAvi Kivity MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t"); 3097d36db35SAvi Kivity 31018253fdeSAvi Kivity inregs = (struct regs){ 0 }; 31118253fdeSAvi Kivity 31218253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r16_imm_1); 3136055ea1fSAvi Kivity report("mov 1", R_AX, outregs.eax == 1234); 3147d36db35SAvi Kivity 3157d36db35SAvi Kivity /* test mov $imm, %eax */ 31618253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r32_imm_1); 3176055ea1fSAvi Kivity report("mov 2", R_AX, outregs.eax == 1234567890); 3187d36db35SAvi Kivity 3197d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 32018253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_1); 3216055ea1fSAvi Kivity report("mov 3", R_AX, outregs.eax == 0x1200); 3227d36db35SAvi Kivity 32318253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_2); 3246055ea1fSAvi Kivity report("mov 4", R_AX, outregs.eax == 0x34); 3257d36db35SAvi Kivity 32618253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_3); 3276055ea1fSAvi Kivity report("mov 5", R_AX, outregs.eax == 0x1234); 3287d36db35SAvi Kivity } 3297d36db35SAvi Kivity 330*2e3f9f1fSThomas Huth static void test_sub_imm(void) 3317d36db35SAvi Kivity { 3327d36db35SAvi Kivity MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t"); 3337d36db35SAvi Kivity MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t"); 3347d36db35SAvi Kivity MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t"); 3357d36db35SAvi Kivity MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t"); 3367d36db35SAvi Kivity 33718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 33818253fdeSAvi Kivity 33918253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r16_imm_1); 3406055ea1fSAvi Kivity report("sub 1", R_AX, outregs.eax == 1224); 3417d36db35SAvi Kivity 3427d36db35SAvi Kivity /* test mov $imm, %eax */ 34318253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r32_imm_1); 3446055ea1fSAvi Kivity report("sub 2", R_AX, outregs.eax == 1234567880); 3457d36db35SAvi Kivity 3467d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 34718253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r8_imm_1); 3486055ea1fSAvi Kivity report("sub 3", R_AX, outregs.eax == 0x0200); 3497d36db35SAvi Kivity 35018253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r8_imm_2); 3516055ea1fSAvi Kivity report("sub 4", R_AX, outregs.eax == 0x24); 3527d36db35SAvi Kivity } 3537d36db35SAvi Kivity 354*2e3f9f1fSThomas Huth static void test_xor_imm(void) 3557d36db35SAvi Kivity { 3567d36db35SAvi Kivity MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t"); 3577d36db35SAvi Kivity MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t"); 3587d36db35SAvi Kivity MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t"); 3597d36db35SAvi Kivity MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t"); 3607d36db35SAvi Kivity 36118253fdeSAvi Kivity inregs = (struct regs){ 0 }; 36218253fdeSAvi Kivity 36318253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r16_imm_1); 3646055ea1fSAvi Kivity report("xor 1", R_AX, outregs.eax == 0); 3657d36db35SAvi Kivity 3667d36db35SAvi Kivity /* test mov $imm, %eax */ 36718253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r32_imm_1); 3686055ea1fSAvi Kivity report("xor 2", R_AX, outregs.eax == 0); 3697d36db35SAvi Kivity 3707d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 37118253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r8_imm_1); 3726055ea1fSAvi Kivity report("xor 3", R_AX, outregs.eax == 0); 3737d36db35SAvi Kivity 37418253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r8_imm_2); 3756055ea1fSAvi Kivity report("xor 4", R_AX, outregs.eax == 0); 3767d36db35SAvi Kivity } 3777d36db35SAvi Kivity 378*2e3f9f1fSThomas Huth static void test_cmp_imm(void) 3797d36db35SAvi Kivity { 3807d36db35SAvi Kivity MK_INSN(cmp_test1, "mov $0x34, %al\n\t" 3817d36db35SAvi Kivity "cmp $0x34, %al\n\t"); 3827d36db35SAvi Kivity MK_INSN(cmp_test2, "mov $0x34, %al\n\t" 3837d36db35SAvi Kivity "cmp $0x39, %al\n\t"); 3847d36db35SAvi Kivity MK_INSN(cmp_test3, "mov $0x34, %al\n\t" 3857d36db35SAvi Kivity "cmp $0x24, %al\n\t"); 3867d36db35SAvi Kivity 38718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 38818253fdeSAvi Kivity 3897d36db35SAvi Kivity /* test cmp imm8 with AL */ 3907d36db35SAvi Kivity /* ZF: (bit 6) Zero Flag becomes 1 if an operation results 3917d36db35SAvi Kivity * in a 0 writeback, or 0 register 3927d36db35SAvi Kivity */ 39318253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test1); 3946055ea1fSAvi Kivity report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6)); 3957d36db35SAvi Kivity 39618253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test2); 3976055ea1fSAvi Kivity report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0); 3987d36db35SAvi Kivity 39918253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test3); 4006055ea1fSAvi Kivity report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0); 4017d36db35SAvi Kivity } 4027d36db35SAvi Kivity 403*2e3f9f1fSThomas Huth static void test_add_imm(void) 4047d36db35SAvi Kivity { 4057d36db35SAvi Kivity MK_INSN(add_test1, "mov $0x43211234, %eax \n\t" 4067d36db35SAvi Kivity "add $0x12344321, %eax \n\t"); 4077d36db35SAvi Kivity MK_INSN(add_test2, "mov $0x12, %eax \n\t" 4087d36db35SAvi Kivity "add $0x21, %al\n\t"); 4097d36db35SAvi Kivity 41018253fdeSAvi Kivity inregs = (struct regs){ 0 }; 41118253fdeSAvi Kivity 41218253fdeSAvi Kivity exec_in_big_real_mode(&insn_add_test1); 4136055ea1fSAvi Kivity report("add 1", ~0, outregs.eax == 0x55555555); 4147d36db35SAvi Kivity 41518253fdeSAvi Kivity exec_in_big_real_mode(&insn_add_test2); 4166055ea1fSAvi Kivity report("add 2", ~0, outregs.eax == 0x33); 4177d36db35SAvi Kivity } 4187d36db35SAvi Kivity 419*2e3f9f1fSThomas Huth static void test_eflags_insn(void) 4207d36db35SAvi Kivity { 4217d36db35SAvi Kivity MK_INSN(clc, "clc"); 422b3261e48SMohammed Gamal MK_INSN(stc, "stc"); 4237d36db35SAvi Kivity MK_INSN(cli, "cli"); 4247d36db35SAvi Kivity MK_INSN(sti, "sti"); 4257d36db35SAvi Kivity MK_INSN(cld, "cld"); 4267d36db35SAvi Kivity MK_INSN(std, "std"); 4277d36db35SAvi Kivity 42818253fdeSAvi Kivity inregs = (struct regs){ 0 }; 42918253fdeSAvi Kivity 43018253fdeSAvi Kivity exec_in_big_real_mode(&insn_clc); 4316055ea1fSAvi Kivity report("clc", ~0, (outregs.eflags & 1) == 0); 4327d36db35SAvi Kivity 43318253fdeSAvi Kivity exec_in_big_real_mode(&insn_stc); 4346055ea1fSAvi Kivity report("stc", ~0, (outregs.eflags & 1) == 1); 435b3261e48SMohammed Gamal 43618253fdeSAvi Kivity exec_in_big_real_mode(&insn_cli); 4376055ea1fSAvi Kivity report("cli", ~0, !(outregs.eflags & (1 << 9))); 4387d36db35SAvi Kivity 43918253fdeSAvi Kivity exec_in_big_real_mode(&insn_sti); 4406055ea1fSAvi Kivity report("sti", ~0, outregs.eflags & (1 << 9)); 4417d36db35SAvi Kivity 44218253fdeSAvi Kivity exec_in_big_real_mode(&insn_cld); 4436055ea1fSAvi Kivity report("cld", ~0, !(outregs.eflags & (1 << 10))); 4447d36db35SAvi Kivity 44518253fdeSAvi Kivity exec_in_big_real_mode(&insn_std); 4466055ea1fSAvi Kivity report("std", ~0, (outregs.eflags & (1 << 10))); 4477d36db35SAvi Kivity } 4487d36db35SAvi Kivity 449*2e3f9f1fSThomas Huth static void test_io(void) 4507d36db35SAvi Kivity { 4517d36db35SAvi Kivity MK_INSN(io_test1, "mov $0xff, %al \n\t" 4527d36db35SAvi Kivity "out %al, $0xe0 \n\t" 4537d36db35SAvi Kivity "mov $0x00, %al \n\t" 4547d36db35SAvi Kivity "in $0xe0, %al \n\t"); 4557d36db35SAvi Kivity MK_INSN(io_test2, "mov $0xffff, %ax \n\t" 4567d36db35SAvi Kivity "out %ax, $0xe0 \n\t" 4577d36db35SAvi Kivity "mov $0x0000, %ax \n\t" 4587d36db35SAvi Kivity "in $0xe0, %ax \n\t"); 4597d36db35SAvi Kivity MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t" 4607d36db35SAvi Kivity "out %eax, $0xe0 \n\t" 4617d36db35SAvi Kivity "mov $0x000000, %eax \n\t" 4627d36db35SAvi Kivity "in $0xe0, %eax \n\t"); 4637d36db35SAvi Kivity MK_INSN(io_test4, "mov $0xe0, %dx \n\t" 4647d36db35SAvi Kivity "mov $0xff, %al \n\t" 4657d36db35SAvi Kivity "out %al, %dx \n\t" 4667d36db35SAvi Kivity "mov $0x00, %al \n\t" 4677d36db35SAvi Kivity "in %dx, %al \n\t"); 4687d36db35SAvi Kivity MK_INSN(io_test5, "mov $0xe0, %dx \n\t" 4697d36db35SAvi Kivity "mov $0xffff, %ax \n\t" 4707d36db35SAvi Kivity "out %ax, %dx \n\t" 4717d36db35SAvi Kivity "mov $0x0000, %ax \n\t" 4727d36db35SAvi Kivity "in %dx, %ax \n\t"); 4737d36db35SAvi Kivity MK_INSN(io_test6, "mov $0xe0, %dx \n\t" 4747d36db35SAvi Kivity "mov $0xffffffff, %eax \n\t" 4757d36db35SAvi Kivity "out %eax, %dx \n\t" 4767d36db35SAvi Kivity "mov $0x00000000, %eax \n\t" 4777d36db35SAvi Kivity "in %dx, %eax \n\t"); 4787d36db35SAvi Kivity 47918253fdeSAvi Kivity inregs = (struct regs){ 0 }; 48018253fdeSAvi Kivity 48118253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test1); 4826055ea1fSAvi Kivity report("pio 1", R_AX, outregs.eax == 0xff); 4837d36db35SAvi Kivity 48418253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test2); 4856055ea1fSAvi Kivity report("pio 2", R_AX, outregs.eax == 0xffff); 4867d36db35SAvi Kivity 48718253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test3); 4886055ea1fSAvi Kivity report("pio 3", R_AX, outregs.eax == 0xffffffff); 4897d36db35SAvi Kivity 49018253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test4); 4916055ea1fSAvi Kivity report("pio 4", R_AX|R_DX, outregs.eax == 0xff); 4927d36db35SAvi Kivity 49318253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test5); 4946055ea1fSAvi Kivity report("pio 5", R_AX|R_DX, outregs.eax == 0xffff); 4957d36db35SAvi Kivity 49618253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test6); 4976055ea1fSAvi Kivity report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff); 4987d36db35SAvi Kivity } 4997d36db35SAvi Kivity 500c0b7268dSAvi Kivity asm ("retf: lretw"); 501*2e3f9f1fSThomas Huth extern void retf(void); 502c0b7268dSAvi Kivity 5034f66bc86SBruce Rogers asm ("retf_imm: lretw $10"); 504*2e3f9f1fSThomas Huth extern void retf_imm(void); 5054f66bc86SBruce Rogers 506*2e3f9f1fSThomas Huth static void test_call(void) 5077d36db35SAvi Kivity { 5087d36db35SAvi Kivity u32 esp[16]; 509c0b7268dSAvi Kivity u32 addr; 5107d36db35SAvi Kivity 51118253fdeSAvi Kivity inregs = (struct regs){ 0 }; 5127d36db35SAvi Kivity inregs.esp = (u32)esp; 5137d36db35SAvi Kivity 5147d36db35SAvi Kivity MK_INSN(call1, "mov $test_function, %eax \n\t" 5157d36db35SAvi Kivity "call *%eax\n\t"); 5167d36db35SAvi Kivity MK_INSN(call_near1, "jmp 2f\n\t" 5177d36db35SAvi Kivity "1: mov $0x1234, %eax\n\t" 5187d36db35SAvi Kivity "ret\n\t" 5197d36db35SAvi Kivity "2: call 1b\t"); 5207d36db35SAvi Kivity MK_INSN(call_near2, "call 1f\n\t" 5217d36db35SAvi Kivity "jmp 2f\n\t" 5227d36db35SAvi Kivity "1: mov $0x1234, %eax\n\t" 5237d36db35SAvi Kivity "ret\n\t" 5247d36db35SAvi Kivity "2:\t"); 525c0b7268dSAvi Kivity MK_INSN(call_far1, "lcallw *(%ebx)\n\t"); 526556d2680SWei Yongjun MK_INSN(call_far2, "lcallw $0, $retf\n\t"); 527c6061817SAvi Kivity MK_INSN(ret_imm, "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b"); 5284f66bc86SBruce Rogers MK_INSN(retf_imm, "sub $10, %sp; lcallw $0, $retf_imm"); 5297d36db35SAvi Kivity 53018253fdeSAvi Kivity exec_in_big_real_mode(&insn_call1); 5316055ea1fSAvi Kivity report("call 1", R_AX, outregs.eax == 0x1234); 5327d36db35SAvi Kivity 53318253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_near1); 5346055ea1fSAvi Kivity report("call near 1", R_AX, outregs.eax == 0x1234); 5357d36db35SAvi Kivity 53618253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_near2); 5376055ea1fSAvi Kivity report("call near 2", R_AX, outregs.eax == 0x1234); 538c0b7268dSAvi Kivity 539c0b7268dSAvi Kivity addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f); 540c0b7268dSAvi Kivity inregs.ebx = (unsigned)&addr; 54118253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_far1); 5426055ea1fSAvi Kivity report("call far 1", 0, 1); 543c6061817SAvi Kivity 544556d2680SWei Yongjun exec_in_big_real_mode(&insn_call_far2); 545556d2680SWei Yongjun report("call far 2", 0, 1); 546556d2680SWei Yongjun 54718253fdeSAvi Kivity exec_in_big_real_mode(&insn_ret_imm); 5486055ea1fSAvi Kivity report("ret imm 1", 0, 1); 5494f66bc86SBruce Rogers 5504f66bc86SBruce Rogers exec_in_big_real_mode(&insn_retf_imm); 5514f66bc86SBruce Rogers report("retf imm 1", 0, 1); 5527d36db35SAvi Kivity } 5537d36db35SAvi Kivity 554*2e3f9f1fSThomas Huth static void test_jcc_short(void) 5557d36db35SAvi Kivity { 5567d36db35SAvi Kivity MK_INSN(jnz_short1, "jnz 1f\n\t" 5577d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5587d36db35SAvi Kivity "1:\n\t"); 5597d36db35SAvi Kivity MK_INSN(jnz_short2, "1:\n\t" 5607d36db35SAvi Kivity "cmp $0x1234, %eax\n\t" 5617d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5627d36db35SAvi Kivity "jnz 1b\n\t"); 5637d36db35SAvi Kivity MK_INSN(jmp_short1, "jmp 1f\n\t" 5647d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5657d36db35SAvi Kivity "1:\n\t"); 5667d36db35SAvi Kivity 56718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 5687d36db35SAvi Kivity 56918253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_short1); 5706055ea1fSAvi Kivity report("jnz short 1", ~0, 1); 57118253fdeSAvi Kivity 57218253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_short2); 5736055ea1fSAvi Kivity report("jnz short 2", R_AX, (outregs.eflags & (1 << 6))); 5747d36db35SAvi Kivity 57518253fdeSAvi Kivity exec_in_big_real_mode(&insn_jmp_short1); 5766055ea1fSAvi Kivity report("jmp short 1", ~0, 1); 5777d36db35SAvi Kivity } 5787d36db35SAvi Kivity 579*2e3f9f1fSThomas Huth static void test_jcc_near(void) 5807d36db35SAvi Kivity { 5817d36db35SAvi Kivity /* encode near jmp manually. gas will not do it if offsets < 127 byte */ 5827d36db35SAvi Kivity MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t" 5837d36db35SAvi Kivity "mov $0x1234, %eax\n\t"); 5847d36db35SAvi Kivity MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t" 5857d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5867d36db35SAvi Kivity ".byte 0x0f, 0x85, 0xf0, 0xff\n\t"); 5877d36db35SAvi Kivity MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t" 5887d36db35SAvi Kivity "mov $0x1234, %eax\n\t"); 5897d36db35SAvi Kivity 59018253fdeSAvi Kivity inregs = (struct regs){ 0 }; 5917d36db35SAvi Kivity 59218253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_near1); 5936055ea1fSAvi Kivity report("jnz near 1", 0, 1); 59418253fdeSAvi Kivity 59518253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_near2); 5966055ea1fSAvi Kivity report("jnz near 2", R_AX, outregs.eflags & (1 << 6)); 5977d36db35SAvi Kivity 59818253fdeSAvi Kivity exec_in_big_real_mode(&insn_jmp_near1); 5996055ea1fSAvi Kivity report("jmp near 1", 0, 1); 6007d36db35SAvi Kivity } 6017d36db35SAvi Kivity 602*2e3f9f1fSThomas Huth static void test_long_jmp(void) 6037d36db35SAvi Kivity { 6047d36db35SAvi Kivity u32 esp[16]; 6057d36db35SAvi Kivity 60618253fdeSAvi Kivity inregs = (struct regs){ 0 }; 6074aa22949SAvi Kivity inregs.esp = (u32)(esp+16); 6087d36db35SAvi Kivity MK_INSN(long_jmp, "call 1f\n\t" 6097d36db35SAvi Kivity "jmp 2f\n\t" 6107d36db35SAvi Kivity "1: jmp $0, $test_function\n\t" 6117d36db35SAvi Kivity "2:\n\t"); 61218253fdeSAvi Kivity exec_in_big_real_mode(&insn_long_jmp); 6136055ea1fSAvi Kivity report("jmp far 1", R_AX, outregs.eax == 0x1234); 6147d36db35SAvi Kivity } 615fa74f8a6SMohammed Gamal 616*2e3f9f1fSThomas Huth static void test_push_pop(void) 6177d36db35SAvi Kivity { 6187d36db35SAvi Kivity MK_INSN(push32, "mov $0x12345678, %eax\n\t" 6197d36db35SAvi Kivity "push %eax\n\t" 6207d36db35SAvi Kivity "pop %ebx\n\t"); 6217d36db35SAvi Kivity MK_INSN(push16, "mov $0x1234, %ax\n\t" 6227d36db35SAvi Kivity "push %ax\n\t" 6237d36db35SAvi Kivity "pop %bx\n\t"); 6247d36db35SAvi Kivity 6257d36db35SAvi Kivity MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten 6267d36db35SAvi Kivity "mov $0x123, %ax\n\t" 6277d36db35SAvi Kivity "mov %ax, %es\n\t" 6287d36db35SAvi Kivity "push %es\n\t" 6297d36db35SAvi Kivity "pop %bx \n\t" 6307d36db35SAvi Kivity ); 6317d36db35SAvi Kivity MK_INSN(pop_es, "push %ax\n\t" 6327d36db35SAvi Kivity "pop %es\n\t" 6337d36db35SAvi Kivity "mov %es, %bx\n\t" 6347d36db35SAvi Kivity ); 6357d36db35SAvi Kivity MK_INSN(push_pop_ss, "push %ss\n\t" 6367d36db35SAvi Kivity "pushw %ax\n\t" 6377d36db35SAvi Kivity "popw %ss\n\t" 6387d36db35SAvi Kivity "mov %ss, %bx\n\t" 6397d36db35SAvi Kivity "pop %ss\n\t" 6407d36db35SAvi Kivity ); 6417d36db35SAvi Kivity MK_INSN(push_pop_fs, "push %fs\n\t" 6427d36db35SAvi Kivity "pushl %eax\n\t" 6437d36db35SAvi Kivity "popl %fs\n\t" 6447d36db35SAvi Kivity "mov %fs, %ebx\n\t" 6457d36db35SAvi Kivity "pop %fs\n\t" 6467d36db35SAvi Kivity ); 64709b657b6SAvi Kivity MK_INSN(push_pop_high_esp_bits, 64809b657b6SAvi Kivity "xor $0x12340000, %esp \n\t" 64909b657b6SAvi Kivity "push %ax; \n\t" 65009b657b6SAvi Kivity "xor $0x12340000, %esp \n\t" 65109b657b6SAvi Kivity "pop %bx"); 6527d36db35SAvi Kivity 65318253fdeSAvi Kivity inregs = (struct regs){ 0 }; 65418253fdeSAvi Kivity 65518253fdeSAvi Kivity exec_in_big_real_mode(&insn_push32); 6566055ea1fSAvi Kivity report("push/pop 1", R_AX|R_BX, 6576055ea1fSAvi Kivity outregs.eax == outregs.ebx && outregs.eax == 0x12345678); 6587d36db35SAvi Kivity 65918253fdeSAvi Kivity exec_in_big_real_mode(&insn_push16); 6606055ea1fSAvi Kivity report("push/pop 2", R_AX|R_BX, 6616055ea1fSAvi Kivity outregs.eax == outregs.ebx && outregs.eax == 0x1234); 6627d36db35SAvi Kivity 66318253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_es); 6646055ea1fSAvi Kivity report("push/pop 3", R_AX|R_BX, 6656055ea1fSAvi Kivity outregs.ebx == outregs.eax && outregs.eax == 0x123); 6667d36db35SAvi Kivity 66718253fdeSAvi Kivity exec_in_big_real_mode(&insn_pop_es); 6686055ea1fSAvi Kivity report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax); 6697d36db35SAvi Kivity 67018253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_pop_ss); 6716055ea1fSAvi Kivity report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax); 6727d36db35SAvi Kivity 67318253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_pop_fs); 6746055ea1fSAvi Kivity report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax); 67509b657b6SAvi Kivity 67609b657b6SAvi Kivity inregs.eax = 0x9977; 67709b657b6SAvi Kivity inregs.ebx = 0x7799; 67809b657b6SAvi Kivity exec_in_big_real_mode(&insn_push_pop_high_esp_bits); 67909b657b6SAvi Kivity report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977); 6807d36db35SAvi Kivity } 6817d36db35SAvi Kivity 682*2e3f9f1fSThomas Huth static void test_null(void) 6837d36db35SAvi Kivity { 684d4dc402cSAvi Kivity MK_INSN(null, ""); 685d4dc402cSAvi Kivity 68618253fdeSAvi Kivity inregs = (struct regs){ 0 }; 68718253fdeSAvi Kivity 68818253fdeSAvi Kivity exec_in_big_real_mode(&insn_null); 6896055ea1fSAvi Kivity report("null", 0, 1); 6907d36db35SAvi Kivity } 6917d36db35SAvi Kivity 6927d36db35SAvi Kivity struct { 6937d36db35SAvi Kivity char stack[500]; 6947d36db35SAvi Kivity char top[]; 6957d36db35SAvi Kivity } tmp_stack; 6967d36db35SAvi Kivity 697*2e3f9f1fSThomas Huth static void test_pusha_popa(void) 6987d36db35SAvi Kivity { 6997d36db35SAvi Kivity MK_INSN(pusha, "pusha\n\t" 7007d36db35SAvi Kivity "pop %edi\n\t" 7017d36db35SAvi Kivity "pop %esi\n\t" 7027d36db35SAvi Kivity "pop %ebp\n\t" 7037d36db35SAvi Kivity "add $4, %esp\n\t" 7047d36db35SAvi Kivity "pop %ebx\n\t" 7057d36db35SAvi Kivity "pop %edx\n\t" 7067d36db35SAvi Kivity "pop %ecx\n\t" 7077d36db35SAvi Kivity "pop %eax\n\t" 7087d36db35SAvi Kivity ); 7097d36db35SAvi Kivity 7107d36db35SAvi Kivity MK_INSN(popa, "push %eax\n\t" 7117d36db35SAvi Kivity "push %ecx\n\t" 7127d36db35SAvi Kivity "push %edx\n\t" 7137d36db35SAvi Kivity "push %ebx\n\t" 7147d36db35SAvi Kivity "push %esp\n\t" 7157d36db35SAvi Kivity "push %ebp\n\t" 7167d36db35SAvi Kivity "push %esi\n\t" 7177d36db35SAvi Kivity "push %edi\n\t" 7187d36db35SAvi Kivity "popa\n\t" 7197d36db35SAvi Kivity ); 7207d36db35SAvi Kivity 72118253fdeSAvi Kivity inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top }; 7227d36db35SAvi Kivity 72318253fdeSAvi Kivity exec_in_big_real_mode(&insn_pusha); 7246055ea1fSAvi Kivity report("pusha/popa 1", 0, 1); 72518253fdeSAvi Kivity 72618253fdeSAvi Kivity exec_in_big_real_mode(&insn_popa); 7276055ea1fSAvi Kivity report("pusha/popa 1", 0, 1); 7287d36db35SAvi Kivity } 7297d36db35SAvi Kivity 730*2e3f9f1fSThomas Huth static void test_iret(void) 7317d36db35SAvi Kivity { 7327d36db35SAvi Kivity MK_INSN(iret32, "pushf\n\t" 7337d36db35SAvi Kivity "pushl %cs\n\t" 7347d36db35SAvi Kivity "call 1f\n\t" /* a near call will push eip onto the stack */ 7357d36db35SAvi Kivity "jmp 2f\n\t" 7367d36db35SAvi Kivity "1: iret\n\t" 7377d36db35SAvi Kivity "2:\n\t" 7387d36db35SAvi Kivity ); 7397d36db35SAvi Kivity 7407d36db35SAvi Kivity MK_INSN(iret16, "pushfw\n\t" 7417d36db35SAvi Kivity "pushw %cs\n\t" 7427d36db35SAvi Kivity "callw 1f\n\t" 7437d36db35SAvi Kivity "jmp 2f\n\t" 7447d36db35SAvi Kivity "1: iretw\n\t" 7457d36db35SAvi Kivity "2:\n\t"); 7467d36db35SAvi Kivity 7477d36db35SAvi Kivity MK_INSN(iret_flags32, "pushfl\n\t" 7487d36db35SAvi Kivity "popl %eax\n\t" 7497d36db35SAvi Kivity "andl $~0x2, %eax\n\t" 750964942e8SNadav Amit "orl $0xffc18028, %eax\n\t" 7517d36db35SAvi Kivity "pushl %eax\n\t" 7527d36db35SAvi Kivity "pushl %cs\n\t" 7537d36db35SAvi Kivity "call 1f\n\t" 7547d36db35SAvi Kivity "jmp 2f\n\t" 7557d36db35SAvi Kivity "1: iret\n\t" 7567d36db35SAvi Kivity "2:\n\t"); 7577d36db35SAvi Kivity 7587d36db35SAvi Kivity MK_INSN(iret_flags16, "pushfw\n\t" 7597d36db35SAvi Kivity "popw %ax\n\t" 7607d36db35SAvi Kivity "and $~0x2, %ax\n\t" 7617d36db35SAvi Kivity "or $0x8028, %ax\n\t" 7627d36db35SAvi Kivity "pushw %ax\n\t" 7637d36db35SAvi Kivity "pushw %cs\n\t" 7647d36db35SAvi Kivity "callw 1f\n\t" 7657d36db35SAvi Kivity "jmp 2f\n\t" 7667d36db35SAvi Kivity "1: iretw\n\t" 7677d36db35SAvi Kivity "2:\n\t"); 7687d36db35SAvi Kivity 76918253fdeSAvi Kivity inregs = (struct regs){ 0 }; 7707d36db35SAvi Kivity 77118253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret32); 7726055ea1fSAvi Kivity report("iret 1", 0, 1); 7737d36db35SAvi Kivity 77418253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret16); 7756055ea1fSAvi Kivity report("iret 2", 0, 1); 7767d36db35SAvi Kivity 77718253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret_flags32); 7786055ea1fSAvi Kivity report("iret 3", R_AX, 1); 779964942e8SNadav Amit report("rflags.rf", ~0, !(outregs.eflags & (1 << 16))); 78018253fdeSAvi Kivity 78118253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret_flags16); 7826055ea1fSAvi Kivity report("iret 4", R_AX, 1); 7837d36db35SAvi Kivity } 7847d36db35SAvi Kivity 785*2e3f9f1fSThomas Huth static void test_int(void) 78696b9ca1eSMohammed Gamal { 78718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 78896b9ca1eSMohammed Gamal 78996b9ca1eSMohammed Gamal *(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */ 79096b9ca1eSMohammed Gamal *(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */ 79196b9ca1eSMohammed Gamal 79296b9ca1eSMohammed Gamal MK_INSN(int11, "int $0x11\n\t"); 79396b9ca1eSMohammed Gamal 79418253fdeSAvi Kivity exec_in_big_real_mode(&insn_int11); 7956055ea1fSAvi Kivity report("int 1", 0, 1); 79696b9ca1eSMohammed Gamal } 79796b9ca1eSMohammed Gamal 798*2e3f9f1fSThomas Huth static void test_imul(void) 799fa74f8a6SMohammed Gamal { 800fa74f8a6SMohammed Gamal MK_INSN(imul8_1, "mov $2, %al\n\t" 801fa74f8a6SMohammed Gamal "mov $-4, %cx\n\t" 802fa74f8a6SMohammed Gamal "imul %cl\n\t"); 803fa74f8a6SMohammed Gamal 804fa74f8a6SMohammed Gamal MK_INSN(imul16_1, "mov $2, %ax\n\t" 805fa74f8a6SMohammed Gamal "mov $-4, %cx\n\t" 806fa74f8a6SMohammed Gamal "imul %cx\n\t"); 807fa74f8a6SMohammed Gamal 808fa74f8a6SMohammed Gamal MK_INSN(imul32_1, "mov $2, %eax\n\t" 809fa74f8a6SMohammed Gamal "mov $-4, %ecx\n\t" 810fa74f8a6SMohammed Gamal "imul %ecx\n\t"); 811fa74f8a6SMohammed Gamal 812fa74f8a6SMohammed Gamal MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t" 813fa74f8a6SMohammed Gamal "mov $4, %cx\n\t" 814fa74f8a6SMohammed Gamal "imul %cl\n\t"); 815fa74f8a6SMohammed Gamal 816fa74f8a6SMohammed Gamal MK_INSN(imul16_2, "mov $2, %ax\n\t" 817fa74f8a6SMohammed Gamal "mov $4, %cx\n\t" 818fa74f8a6SMohammed Gamal "imul %cx\n\t"); 819fa74f8a6SMohammed Gamal 820fa74f8a6SMohammed Gamal MK_INSN(imul32_2, "mov $2, %eax\n\t" 821fa74f8a6SMohammed Gamal "mov $4, %ecx\n\t" 822fa74f8a6SMohammed Gamal "imul %ecx\n\t"); 823fa74f8a6SMohammed Gamal 82418253fdeSAvi Kivity inregs = (struct regs){ 0 }; 82518253fdeSAvi Kivity 82618253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul8_1); 8276055ea1fSAvi Kivity report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8); 828fa74f8a6SMohammed Gamal 82918253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul16_1); 8306055ea1fSAvi Kivity report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8); 831fa74f8a6SMohammed Gamal 83218253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul32_1); 8336055ea1fSAvi Kivity report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8); 834fa74f8a6SMohammed Gamal 83518253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul8_2); 8366055ea1fSAvi Kivity report("imul 4", R_AX | R_CX | R_DX, 8376055ea1fSAvi Kivity (outregs.eax & 0xffff) == 8 83881050840SAvi Kivity && (outregs.eax & 0xffff0000) == 0x12340000); 839fa74f8a6SMohammed Gamal 84018253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul16_2); 8416055ea1fSAvi Kivity report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8); 842fa74f8a6SMohammed Gamal 84318253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul32_2); 8446055ea1fSAvi Kivity report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8); 845fa74f8a6SMohammed Gamal } 846fa74f8a6SMohammed Gamal 847*2e3f9f1fSThomas Huth static void test_mul(void) 84859317bd1SMohammed Gamal { 84959317bd1SMohammed Gamal MK_INSN(mul8, "mov $2, %al\n\t" 85059317bd1SMohammed Gamal "mov $4, %cx\n\t" 85159317bd1SMohammed Gamal "imul %cl\n\t"); 85259317bd1SMohammed Gamal 85359317bd1SMohammed Gamal MK_INSN(mul16, "mov $2, %ax\n\t" 85459317bd1SMohammed Gamal "mov $4, %cx\n\t" 85559317bd1SMohammed Gamal "imul %cx\n\t"); 85659317bd1SMohammed Gamal 85759317bd1SMohammed Gamal MK_INSN(mul32, "mov $2, %eax\n\t" 85859317bd1SMohammed Gamal "mov $4, %ecx\n\t" 85959317bd1SMohammed Gamal "imul %ecx\n\t"); 86059317bd1SMohammed Gamal 86118253fdeSAvi Kivity inregs = (struct regs){ 0 }; 86218253fdeSAvi Kivity 86318253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul8); 8646055ea1fSAvi Kivity report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8); 86559317bd1SMohammed Gamal 86618253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul16); 8676055ea1fSAvi Kivity report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8); 86859317bd1SMohammed Gamal 86918253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul32); 8706055ea1fSAvi Kivity report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8); 87159317bd1SMohammed Gamal } 87259317bd1SMohammed Gamal 873*2e3f9f1fSThomas Huth static void test_div(void) 8740d4c7614SMohammed Gamal { 8750d4c7614SMohammed Gamal MK_INSN(div8, "mov $257, %ax\n\t" 8760d4c7614SMohammed Gamal "mov $2, %cl\n\t" 8770d4c7614SMohammed Gamal "div %cl\n\t"); 8780d4c7614SMohammed Gamal 8790d4c7614SMohammed Gamal MK_INSN(div16, "mov $512, %ax\n\t" 8800d4c7614SMohammed Gamal "mov $5, %cx\n\t" 8810d4c7614SMohammed Gamal "div %cx\n\t"); 8820d4c7614SMohammed Gamal 8830d4c7614SMohammed Gamal MK_INSN(div32, "mov $512, %eax\n\t" 8840d4c7614SMohammed Gamal "mov $5, %ecx\n\t" 8850d4c7614SMohammed Gamal "div %ecx\n\t"); 8860d4c7614SMohammed Gamal 88718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 88818253fdeSAvi Kivity 88918253fdeSAvi Kivity exec_in_big_real_mode(&insn_div8); 8906055ea1fSAvi Kivity report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384); 8910d4c7614SMohammed Gamal 89218253fdeSAvi Kivity exec_in_big_real_mode(&insn_div16); 8936055ea1fSAvi Kivity report("div 2", R_AX | R_CX | R_DX, 8946055ea1fSAvi Kivity outregs.eax == 102 && outregs.edx == 2); 8950d4c7614SMohammed Gamal 89618253fdeSAvi Kivity exec_in_big_real_mode(&insn_div32); 8976055ea1fSAvi Kivity report("div 3", R_AX | R_CX | R_DX, 8986055ea1fSAvi Kivity outregs.eax == 102 && outregs.edx == 2); 8990d4c7614SMohammed Gamal } 9000d4c7614SMohammed Gamal 901*2e3f9f1fSThomas Huth static void test_idiv(void) 9020d4c7614SMohammed Gamal { 9030d4c7614SMohammed Gamal MK_INSN(idiv8, "mov $256, %ax\n\t" 9040d4c7614SMohammed Gamal "mov $-2, %cl\n\t" 9050d4c7614SMohammed Gamal "idiv %cl\n\t"); 9060d4c7614SMohammed Gamal 9070d4c7614SMohammed Gamal MK_INSN(idiv16, "mov $512, %ax\n\t" 9080d4c7614SMohammed Gamal "mov $-2, %cx\n\t" 9090d4c7614SMohammed Gamal "idiv %cx\n\t"); 9100d4c7614SMohammed Gamal 9110d4c7614SMohammed Gamal MK_INSN(idiv32, "mov $512, %eax\n\t" 9120d4c7614SMohammed Gamal "mov $-2, %ecx\n\t" 9130d4c7614SMohammed Gamal "idiv %ecx\n\t"); 9140d4c7614SMohammed Gamal 91518253fdeSAvi Kivity inregs = (struct regs){ 0 }; 91618253fdeSAvi Kivity 91718253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv8); 9186055ea1fSAvi Kivity report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128); 9190d4c7614SMohammed Gamal 92018253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv16); 9216055ea1fSAvi Kivity report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256); 9220d4c7614SMohammed Gamal 92318253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv32); 9246055ea1fSAvi Kivity report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256); 9250d4c7614SMohammed Gamal } 9260d4c7614SMohammed Gamal 927*2e3f9f1fSThomas Huth static void test_cbw(void) 9286e293cf5SWei Yongjun { 9296e293cf5SWei Yongjun MK_INSN(cbw, "mov $0xFE, %eax \n\t" 9306e293cf5SWei Yongjun "cbw\n\t"); 9316e293cf5SWei Yongjun MK_INSN(cwde, "mov $0xFFFE, %eax \n\t" 9326e293cf5SWei Yongjun "cwde\n\t"); 9336e293cf5SWei Yongjun 93418253fdeSAvi Kivity inregs = (struct regs){ 0 }; 93518253fdeSAvi Kivity 93618253fdeSAvi Kivity exec_in_big_real_mode(&insn_cbw); 9376055ea1fSAvi Kivity report("cbq 1", ~0, outregs.eax == 0xFFFE); 9386e293cf5SWei Yongjun 93918253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwde); 9406055ea1fSAvi Kivity report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE); 9416e293cf5SWei Yongjun } 9426e293cf5SWei Yongjun 943*2e3f9f1fSThomas Huth static void test_loopcc(void) 944eacef4e2SWei Yongjun { 945eacef4e2SWei Yongjun MK_INSN(loop, "mov $10, %ecx\n\t" 946eacef4e2SWei Yongjun "1: inc %eax\n\t" 947eacef4e2SWei Yongjun "loop 1b\n\t"); 948eacef4e2SWei Yongjun 949eacef4e2SWei Yongjun MK_INSN(loope, "mov $10, %ecx\n\t" 950eacef4e2SWei Yongjun "mov $1, %eax\n\t" 951eacef4e2SWei Yongjun "1: dec %eax\n\t" 952eacef4e2SWei Yongjun "loope 1b\n\t"); 953eacef4e2SWei Yongjun 954eacef4e2SWei Yongjun MK_INSN(loopne, "mov $10, %ecx\n\t" 955eacef4e2SWei Yongjun "mov $5, %eax\n\t" 956eacef4e2SWei Yongjun "1: dec %eax\n\t" 957eacef4e2SWei Yongjun "loopne 1b\n\t"); 958eacef4e2SWei Yongjun 95918253fdeSAvi Kivity inregs = (struct regs){ 0 }; 960eacef4e2SWei Yongjun 96118253fdeSAvi Kivity exec_in_big_real_mode(&insn_loop); 9626055ea1fSAvi Kivity report("LOOPcc short 1", R_AX, outregs.eax == 10); 96318253fdeSAvi Kivity 96418253fdeSAvi Kivity exec_in_big_real_mode(&insn_loope); 9656055ea1fSAvi Kivity report("LOOPcc short 2", R_AX | R_CX, 9666055ea1fSAvi Kivity outregs.eax == -1 && outregs.ecx == 8); 967eacef4e2SWei Yongjun 96818253fdeSAvi Kivity exec_in_big_real_mode(&insn_loopne); 9696055ea1fSAvi Kivity report("LOOPcc short 3", R_AX | R_CX, 9706055ea1fSAvi Kivity outregs.eax == 0 && outregs.ecx == 5); 971eacef4e2SWei Yongjun } 972eacef4e2SWei Yongjun 973b274feedSAvi Kivity static void test_das(void) 974b274feedSAvi Kivity { 975b274feedSAvi Kivity short i; 97681050840SAvi Kivity u16 nr_fail = 0; 977b274feedSAvi Kivity static unsigned test_cases[1024] = { 978b274feedSAvi Kivity 0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00, 979b274feedSAvi Kivity 0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01, 980b274feedSAvi Kivity 0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02, 981b274feedSAvi Kivity 0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03, 982b274feedSAvi Kivity 0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04, 983b274feedSAvi Kivity 0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05, 984b274feedSAvi Kivity 0x06000606, 0x8701a606, 0x56100006, 0x9711a006, 985b274feedSAvi Kivity 0x02000707, 0x8301a707, 0x12100107, 0x9311a107, 986b274feedSAvi Kivity 0x02000808, 0x8301a808, 0x12100208, 0x9311a208, 987b274feedSAvi Kivity 0x06000909, 0x8701a909, 0x16100309, 0x9711a309, 988b274feedSAvi Kivity 0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a, 989b274feedSAvi Kivity 0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b, 990b274feedSAvi Kivity 0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c, 991b274feedSAvi Kivity 0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d, 992b274feedSAvi Kivity 0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e, 993b274feedSAvi Kivity 0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f, 994b274feedSAvi Kivity 0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10, 995b274feedSAvi Kivity 0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11, 996b274feedSAvi Kivity 0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12, 997b274feedSAvi Kivity 0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13, 998b274feedSAvi Kivity 0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14, 999b274feedSAvi Kivity 0x02001515, 0x8301b515, 0x16100f15, 0x9711af15, 1000b274feedSAvi Kivity 0x02001616, 0x8301b616, 0x12101016, 0x9311b016, 1001b274feedSAvi Kivity 0x06001717, 0x8701b717, 0x16101117, 0x9711b117, 1002b274feedSAvi Kivity 0x06001818, 0x8701b818, 0x16101218, 0x9711b218, 1003b274feedSAvi Kivity 0x02001919, 0x8301b919, 0x12101319, 0x9311b319, 1004b274feedSAvi Kivity 0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a, 1005b274feedSAvi Kivity 0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b, 1006b274feedSAvi Kivity 0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c, 1007b274feedSAvi Kivity 0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d, 1008b274feedSAvi Kivity 0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e, 1009b274feedSAvi Kivity 0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f, 1010b274feedSAvi Kivity 0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20, 1011b274feedSAvi Kivity 0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21, 1012b274feedSAvi Kivity 0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22, 1013b274feedSAvi Kivity 0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23, 1014b274feedSAvi Kivity 0x06002424, 0x8301c424, 0x16101e24, 0x9711be24, 1015b274feedSAvi Kivity 0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25, 1016b274feedSAvi Kivity 0x02002626, 0x8701c626, 0x12102026, 0x9711c026, 1017b274feedSAvi Kivity 0x06002727, 0x8301c727, 0x16102127, 0x9311c127, 1018b274feedSAvi Kivity 0x06002828, 0x8301c828, 0x16102228, 0x9311c228, 1019b274feedSAvi Kivity 0x02002929, 0x8701c929, 0x12102329, 0x9711c329, 1020b274feedSAvi Kivity 0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a, 1021b274feedSAvi Kivity 0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b, 1022b274feedSAvi Kivity 0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c, 1023b274feedSAvi Kivity 0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d, 1024b274feedSAvi Kivity 0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e, 1025b274feedSAvi Kivity 0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f, 1026b274feedSAvi Kivity 0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30, 1027b274feedSAvi Kivity 0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31, 1028b274feedSAvi Kivity 0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32, 1029b274feedSAvi Kivity 0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33, 1030b274feedSAvi Kivity 0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34, 1031b274feedSAvi Kivity 0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35, 1032b274feedSAvi Kivity 0x06003636, 0x8301d636, 0x16103036, 0x9311d036, 1033b274feedSAvi Kivity 0x02003737, 0x8701d737, 0x12103137, 0x9711d137, 1034b274feedSAvi Kivity 0x02003838, 0x8701d838, 0x12103238, 0x9711d238, 1035b274feedSAvi Kivity 0x06003939, 0x8301d939, 0x16103339, 0x9311d339, 1036b274feedSAvi Kivity 0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a, 1037b274feedSAvi Kivity 0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b, 1038b274feedSAvi Kivity 0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c, 1039b274feedSAvi Kivity 0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d, 1040b274feedSAvi Kivity 0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e, 1041b274feedSAvi Kivity 0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f, 1042b274feedSAvi Kivity 0x02004040, 0x8301e040, 0x16103a40, 0x9311da40, 1043b274feedSAvi Kivity 0x06004141, 0x8701e141, 0x12103b41, 0x9711db41, 1044b274feedSAvi Kivity 0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42, 1045b274feedSAvi Kivity 0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43, 1046b274feedSAvi Kivity 0x06004444, 0x8701e444, 0x12103e44, 0x9711de44, 1047b274feedSAvi Kivity 0x02004545, 0x8301e545, 0x16103f45, 0x9311df45, 1048b274feedSAvi Kivity 0x02004646, 0x8301e646, 0x12104046, 0x9311e046, 1049b274feedSAvi Kivity 0x06004747, 0x8701e747, 0x16104147, 0x9711e147, 1050b274feedSAvi Kivity 0x06004848, 0x8701e848, 0x16104248, 0x9711e248, 1051b274feedSAvi Kivity 0x02004949, 0x8301e949, 0x12104349, 0x9311e349, 1052b274feedSAvi Kivity 0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a, 1053b274feedSAvi Kivity 0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b, 1054b274feedSAvi Kivity 0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c, 1055b274feedSAvi Kivity 0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d, 1056b274feedSAvi Kivity 0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e, 1057b274feedSAvi Kivity 0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f, 1058b274feedSAvi Kivity 0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50, 1059b274feedSAvi Kivity 0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51, 1060b274feedSAvi Kivity 0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52, 1061b274feedSAvi Kivity 0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53, 1062b274feedSAvi Kivity 0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54, 1063b274feedSAvi Kivity 0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55, 1064b274feedSAvi Kivity 0x06005656, 0x8701f656, 0x16105056, 0x9711f056, 1065b274feedSAvi Kivity 0x02005757, 0x8301f757, 0x12105157, 0x9311f157, 1066b274feedSAvi Kivity 0x02005858, 0x8301f858, 0x12105258, 0x9311f258, 1067b274feedSAvi Kivity 0x06005959, 0x8701f959, 0x16105359, 0x9711f359, 1068b274feedSAvi Kivity 0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a, 1069b274feedSAvi Kivity 0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b, 1070b274feedSAvi Kivity 0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c, 1071b274feedSAvi Kivity 0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d, 1072b274feedSAvi Kivity 0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e, 1073b274feedSAvi Kivity 0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f, 1074b274feedSAvi Kivity 0x06006060, 0x47010060, 0x16105a60, 0x9711fa60, 1075b274feedSAvi Kivity 0x02006161, 0x03010161, 0x12105b61, 0x9311fb61, 1076b274feedSAvi Kivity 0x02006262, 0x03010262, 0x16105c62, 0x9711fc62, 1077b274feedSAvi Kivity 0x06006363, 0x07010363, 0x12105d63, 0x9311fd63, 1078b274feedSAvi Kivity 0x02006464, 0x03010464, 0x12105e64, 0x9311fe64, 1079b274feedSAvi Kivity 0x06006565, 0x07010565, 0x16105f65, 0x9711ff65, 1080b274feedSAvi Kivity 0x06006666, 0x07010666, 0x16106066, 0x57110066, 1081b274feedSAvi Kivity 0x02006767, 0x03010767, 0x12106167, 0x13110167, 1082b274feedSAvi Kivity 0x02006868, 0x03010868, 0x12106268, 0x13110268, 1083b274feedSAvi Kivity 0x06006969, 0x07010969, 0x16106369, 0x17110369, 1084b274feedSAvi Kivity 0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a, 1085b274feedSAvi Kivity 0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b, 1086b274feedSAvi Kivity 0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c, 1087b274feedSAvi Kivity 0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d, 1088b274feedSAvi Kivity 0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e, 1089b274feedSAvi Kivity 0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f, 1090b274feedSAvi Kivity 0x02007070, 0x03011070, 0x16106a70, 0x17110a70, 1091b274feedSAvi Kivity 0x06007171, 0x07011171, 0x12106b71, 0x13110b71, 1092b274feedSAvi Kivity 0x06007272, 0x07011272, 0x16106c72, 0x17110c72, 1093b274feedSAvi Kivity 0x02007373, 0x03011373, 0x12106d73, 0x13110d73, 1094b274feedSAvi Kivity 0x06007474, 0x07011474, 0x12106e74, 0x13110e74, 1095b274feedSAvi Kivity 0x02007575, 0x03011575, 0x16106f75, 0x17110f75, 1096b274feedSAvi Kivity 0x02007676, 0x03011676, 0x12107076, 0x13111076, 1097b274feedSAvi Kivity 0x06007777, 0x07011777, 0x16107177, 0x17111177, 1098b274feedSAvi Kivity 0x06007878, 0x07011878, 0x16107278, 0x17111278, 1099b274feedSAvi Kivity 0x02007979, 0x03011979, 0x12107379, 0x13111379, 1100b274feedSAvi Kivity 0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a, 1101b274feedSAvi Kivity 0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b, 1102b274feedSAvi Kivity 0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c, 1103b274feedSAvi Kivity 0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d, 1104b274feedSAvi Kivity 0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e, 1105b274feedSAvi Kivity 0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f, 1106b274feedSAvi Kivity 0x82008080, 0x03012080, 0x12107a80, 0x13111a80, 1107b274feedSAvi Kivity 0x86008181, 0x07012181, 0x16107b81, 0x17111b81, 1108b274feedSAvi Kivity 0x86008282, 0x07012282, 0x12107c82, 0x13111c82, 1109b274feedSAvi Kivity 0x82008383, 0x03012383, 0x16107d83, 0x17111d83, 1110b274feedSAvi Kivity 0x86008484, 0x07012484, 0x16107e84, 0x17111e84, 1111b274feedSAvi Kivity 0x82008585, 0x03012585, 0x12107f85, 0x13111f85, 1112b274feedSAvi Kivity 0x82008686, 0x03012686, 0x92108086, 0x13112086, 1113b274feedSAvi Kivity 0x86008787, 0x07012787, 0x96108187, 0x17112187, 1114b274feedSAvi Kivity 0x86008888, 0x07012888, 0x96108288, 0x17112288, 1115b274feedSAvi Kivity 0x82008989, 0x03012989, 0x92108389, 0x13112389, 1116b274feedSAvi Kivity 0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a, 1117b274feedSAvi Kivity 0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b, 1118b274feedSAvi Kivity 0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c, 1119b274feedSAvi Kivity 0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d, 1120b274feedSAvi Kivity 0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e, 1121b274feedSAvi Kivity 0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f, 1122b274feedSAvi Kivity 0x86009090, 0x07013090, 0x92108a90, 0x13112a90, 1123b274feedSAvi Kivity 0x82009191, 0x03013191, 0x96108b91, 0x17112b91, 1124b274feedSAvi Kivity 0x82009292, 0x03013292, 0x92108c92, 0x13112c92, 1125b274feedSAvi Kivity 0x86009393, 0x07013393, 0x96108d93, 0x17112d93, 1126b274feedSAvi Kivity 0x82009494, 0x03013494, 0x96108e94, 0x17112e94, 1127b274feedSAvi Kivity 0x86009595, 0x07013595, 0x92108f95, 0x13112f95, 1128b274feedSAvi Kivity 0x86009696, 0x07013696, 0x96109096, 0x17113096, 1129b274feedSAvi Kivity 0x82009797, 0x03013797, 0x92109197, 0x13113197, 1130b274feedSAvi Kivity 0x82009898, 0x03013898, 0x92109298, 0x13113298, 1131b274feedSAvi Kivity 0x86009999, 0x07013999, 0x96109399, 0x17113399, 1132b274feedSAvi Kivity 0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a, 1133b274feedSAvi Kivity 0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b, 1134b274feedSAvi Kivity 0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c, 1135b274feedSAvi Kivity 0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d, 1136b274feedSAvi Kivity 0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e, 1137b274feedSAvi Kivity 0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f, 1138b274feedSAvi Kivity 0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0, 1139b274feedSAvi Kivity 0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1, 1140b274feedSAvi Kivity 0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2, 1141b274feedSAvi Kivity 0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3, 1142b274feedSAvi Kivity 0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4, 1143b274feedSAvi Kivity 0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5, 1144b274feedSAvi Kivity 0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6, 1145b274feedSAvi Kivity 0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7, 1146b274feedSAvi Kivity 0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8, 1147b274feedSAvi Kivity 0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9, 1148b274feedSAvi Kivity 0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa, 1149b274feedSAvi Kivity 0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab, 1150b274feedSAvi Kivity 0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac, 1151b274feedSAvi Kivity 0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad, 1152b274feedSAvi Kivity 0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae, 1153b274feedSAvi Kivity 0x130049af, 0x130149af, 0x131049af, 0x131149af, 1154b274feedSAvi Kivity 0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0, 1155b274feedSAvi Kivity 0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1, 1156b274feedSAvi Kivity 0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2, 1157b274feedSAvi Kivity 0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3, 1158b274feedSAvi Kivity 0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4, 1159b274feedSAvi Kivity 0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5, 1160b274feedSAvi Kivity 0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6, 1161b274feedSAvi Kivity 0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7, 1162b274feedSAvi Kivity 0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8, 1163b274feedSAvi Kivity 0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9, 1164b274feedSAvi Kivity 0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba, 1165b274feedSAvi Kivity 0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb, 1166b274feedSAvi Kivity 0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc, 1167b274feedSAvi Kivity 0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd, 1168b274feedSAvi Kivity 0x130058be, 0x130158be, 0x131058be, 0x131158be, 1169b274feedSAvi Kivity 0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf, 1170b274feedSAvi Kivity 0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0, 1171b274feedSAvi Kivity 0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1, 1172b274feedSAvi Kivity 0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2, 1173b274feedSAvi Kivity 0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3, 1174b274feedSAvi Kivity 0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4, 1175b274feedSAvi Kivity 0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5, 1176b274feedSAvi Kivity 0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6, 1177b274feedSAvi Kivity 0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7, 1178b274feedSAvi Kivity 0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8, 1179b274feedSAvi Kivity 0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9, 1180b274feedSAvi Kivity 0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca, 1181b274feedSAvi Kivity 0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb, 1182b274feedSAvi Kivity 0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc, 1183b274feedSAvi Kivity 0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd, 1184b274feedSAvi Kivity 0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce, 1185b274feedSAvi Kivity 0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf, 1186b274feedSAvi Kivity 0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0, 1187b274feedSAvi Kivity 0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1, 1188b274feedSAvi Kivity 0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2, 1189b274feedSAvi Kivity 0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3, 1190b274feedSAvi Kivity 0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4, 1191b274feedSAvi Kivity 0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5, 1192b274feedSAvi Kivity 0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6, 1193b274feedSAvi Kivity 0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7, 1194b274feedSAvi Kivity 0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8, 1195b274feedSAvi Kivity 0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9, 1196b274feedSAvi Kivity 0x170074da, 0x170174da, 0x171074da, 0x171174da, 1197b274feedSAvi Kivity 0x130075db, 0x130175db, 0x131075db, 0x131175db, 1198b274feedSAvi Kivity 0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc, 1199b274feedSAvi Kivity 0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd, 1200b274feedSAvi Kivity 0x170078de, 0x170178de, 0x171078de, 0x171178de, 1201b274feedSAvi Kivity 0x130079df, 0x130179df, 0x131079df, 0x131179df, 1202b274feedSAvi Kivity 0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0, 1203b274feedSAvi Kivity 0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1, 1204b274feedSAvi Kivity 0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2, 1205b274feedSAvi Kivity 0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3, 1206b274feedSAvi Kivity 0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4, 1207b274feedSAvi Kivity 0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5, 1208b274feedSAvi Kivity 0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6, 1209b274feedSAvi Kivity 0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7, 1210b274feedSAvi Kivity 0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8, 1211b274feedSAvi Kivity 0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9, 1212b274feedSAvi Kivity 0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea, 1213b274feedSAvi Kivity 0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb, 1214b274feedSAvi Kivity 0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec, 1215b274feedSAvi Kivity 0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed, 1216b274feedSAvi Kivity 0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee, 1217b274feedSAvi Kivity 0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef, 1218b274feedSAvi Kivity 0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0, 1219b274feedSAvi Kivity 0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1, 1220b274feedSAvi Kivity 0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2, 1221b274feedSAvi Kivity 0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3, 1222b274feedSAvi Kivity 0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4, 1223b274feedSAvi Kivity 0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5, 1224b274feedSAvi Kivity 0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6, 1225b274feedSAvi Kivity 0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7, 1226b274feedSAvi Kivity 0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8, 1227b274feedSAvi Kivity 0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9, 1228b274feedSAvi Kivity 0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa, 1229b274feedSAvi Kivity 0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb, 1230b274feedSAvi Kivity 0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc, 1231b274feedSAvi Kivity 0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd, 1232b274feedSAvi Kivity 0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe, 1233b274feedSAvi Kivity 0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff, 1234b274feedSAvi Kivity }; 1235b274feedSAvi Kivity 1236b274feedSAvi Kivity MK_INSN(das, "das"); 1237b274feedSAvi Kivity 123818253fdeSAvi Kivity inregs = (struct regs){ 0 }; 123918253fdeSAvi Kivity 1240b274feedSAvi Kivity for (i = 0; i < 1024; ++i) { 1241b274feedSAvi Kivity unsigned tmp = test_cases[i]; 1242b274feedSAvi Kivity inregs.eax = tmp & 0xff; 1243b274feedSAvi Kivity inregs.eflags = (tmp >> 16) & 0xff; 124418253fdeSAvi Kivity exec_in_big_real_mode(&insn_das); 124518253fdeSAvi Kivity if (!regs_equal(R_AX) 1246b274feedSAvi Kivity || outregs.eax != ((tmp >> 8) & 0xff) 1247b274feedSAvi Kivity || (outregs.eflags & 0xff) != (tmp >> 24)) { 124881050840SAvi Kivity ++nr_fail; 124981050840SAvi Kivity break; 1250b274feedSAvi Kivity } 1251b274feedSAvi Kivity } 12526055ea1fSAvi Kivity report("DAS", ~0, nr_fail == 0); 1253b274feedSAvi Kivity } 1254b274feedSAvi Kivity 1255*2e3f9f1fSThomas Huth static void test_cwd_cdq(void) 12560cbd5b06SMohammed Gamal { 12570cbd5b06SMohammed Gamal /* Sign-bit set */ 12580cbd5b06SMohammed Gamal MK_INSN(cwd_1, "mov $0x8000, %ax\n\t" 12590cbd5b06SMohammed Gamal "cwd\n\t"); 12600cbd5b06SMohammed Gamal 12610cbd5b06SMohammed Gamal /* Sign-bit not set */ 12620cbd5b06SMohammed Gamal MK_INSN(cwd_2, "mov $0x1000, %ax\n\t" 12630cbd5b06SMohammed Gamal "cwd\n\t"); 12640cbd5b06SMohammed Gamal 12650cbd5b06SMohammed Gamal /* Sign-bit set */ 12660cbd5b06SMohammed Gamal MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t" 12670cbd5b06SMohammed Gamal "cdq\n\t"); 12680cbd5b06SMohammed Gamal 12690cbd5b06SMohammed Gamal /* Sign-bit not set */ 12700cbd5b06SMohammed Gamal MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t" 12710cbd5b06SMohammed Gamal "cdq\n\t"); 12720cbd5b06SMohammed Gamal 127318253fdeSAvi Kivity inregs = (struct regs){ 0 }; 127418253fdeSAvi Kivity 127518253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwd_1); 12766055ea1fSAvi Kivity report("cwd 1", R_AX | R_DX, 12776055ea1fSAvi Kivity outregs.eax == 0x8000 && outregs.edx == 0xffff); 12780cbd5b06SMohammed Gamal 127918253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwd_2); 12806055ea1fSAvi Kivity report("cwd 2", R_AX | R_DX, 12816055ea1fSAvi Kivity outregs.eax == 0x1000 && outregs.edx == 0); 12820cbd5b06SMohammed Gamal 128318253fdeSAvi Kivity exec_in_big_real_mode(&insn_cdq_1); 12846055ea1fSAvi Kivity report("cdq 1", R_AX | R_DX, 12856055ea1fSAvi Kivity outregs.eax == 0x80000000 && outregs.edx == 0xffffffff); 12860cbd5b06SMohammed Gamal 128718253fdeSAvi Kivity exec_in_big_real_mode(&insn_cdq_2); 12886055ea1fSAvi Kivity report("cdq 2", R_AX | R_DX, 12896055ea1fSAvi Kivity outregs.eax == 0x10000000 && outregs.edx == 0); 12900cbd5b06SMohammed Gamal } 12910cbd5b06SMohammed Gamal 129237f51a4aSWei Yongjun static struct { 129337f51a4aSWei Yongjun void *address; 129437f51a4aSWei Yongjun unsigned short sel; 129537f51a4aSWei Yongjun } __attribute__((packed)) desc = { 129637f51a4aSWei Yongjun (void *)0x1234, 129737f51a4aSWei Yongjun 0x10, 129837f51a4aSWei Yongjun }; 129937f51a4aSWei Yongjun 1300*2e3f9f1fSThomas Huth static void test_lds_lss(void) 130137f51a4aSWei Yongjun { 130237f51a4aSWei Yongjun inregs = (struct regs){ .ebx = (unsigned long)&desc }; 130337f51a4aSWei Yongjun 130437f51a4aSWei Yongjun MK_INSN(lds, "push %ds\n\t" 130537f51a4aSWei Yongjun "lds (%ebx), %eax\n\t" 130637f51a4aSWei Yongjun "mov %ds, %ebx\n\t" 130737f51a4aSWei Yongjun "pop %ds\n\t"); 130837f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lds); 130937f51a4aSWei Yongjun report("lds", R_AX | R_BX, 131037f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 131137f51a4aSWei Yongjun outregs.ebx == desc.sel); 131237f51a4aSWei Yongjun 131337f51a4aSWei Yongjun MK_INSN(les, "push %es\n\t" 131437f51a4aSWei Yongjun "les (%ebx), %eax\n\t" 131537f51a4aSWei Yongjun "mov %es, %ebx\n\t" 131637f51a4aSWei Yongjun "pop %es\n\t"); 131737f51a4aSWei Yongjun exec_in_big_real_mode(&insn_les); 131837f51a4aSWei Yongjun report("les", R_AX | R_BX, 131937f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 132037f51a4aSWei Yongjun outregs.ebx == desc.sel); 132137f51a4aSWei Yongjun 132237f51a4aSWei Yongjun MK_INSN(lfs, "push %fs\n\t" 132337f51a4aSWei Yongjun "lfs (%ebx), %eax\n\t" 132437f51a4aSWei Yongjun "mov %fs, %ebx\n\t" 132537f51a4aSWei Yongjun "pop %fs\n\t"); 132637f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lfs); 132737f51a4aSWei Yongjun report("lfs", R_AX | R_BX, 132837f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 132937f51a4aSWei Yongjun outregs.ebx == desc.sel); 133037f51a4aSWei Yongjun 133137f51a4aSWei Yongjun MK_INSN(lgs, "push %gs\n\t" 133237f51a4aSWei Yongjun "lgs (%ebx), %eax\n\t" 133337f51a4aSWei Yongjun "mov %gs, %ebx\n\t" 133437f51a4aSWei Yongjun "pop %gs\n\t"); 133537f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lgs); 133637f51a4aSWei Yongjun report("lgs", R_AX | R_BX, 133737f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 133837f51a4aSWei Yongjun outregs.ebx == desc.sel); 133937f51a4aSWei Yongjun 134037f51a4aSWei Yongjun MK_INSN(lss, "push %ss\n\t" 134137f51a4aSWei Yongjun "lss (%ebx), %eax\n\t" 134237f51a4aSWei Yongjun "mov %ss, %ebx\n\t" 134337f51a4aSWei Yongjun "pop %ss\n\t"); 134437f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lss); 134537f51a4aSWei Yongjun report("lss", R_AX | R_BX, 134637f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 134737f51a4aSWei Yongjun outregs.ebx == desc.sel); 134837f51a4aSWei Yongjun } 134937f51a4aSWei Yongjun 1350*2e3f9f1fSThomas Huth static void test_jcxz(void) 1351b1c7c575SWei Yongjun { 1352b1c7c575SWei Yongjun MK_INSN(jcxz1, "jcxz 1f\n\t" 1353b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1354b1c7c575SWei Yongjun "1:\n\t"); 1355b1c7c575SWei Yongjun MK_INSN(jcxz2, "mov $0x100, %ecx\n\t" 1356b1c7c575SWei Yongjun "jcxz 1f\n\t" 1357b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1358b1c7c575SWei Yongjun "mov $0, %ecx\n\t" 1359b1c7c575SWei Yongjun "1:\n\t"); 1360b1c7c575SWei Yongjun MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t" 1361b1c7c575SWei Yongjun "jcxz 1f\n\t" 1362b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1363b1c7c575SWei Yongjun "1:\n\t"); 1364b1c7c575SWei Yongjun MK_INSN(jecxz1, "jecxz 1f\n\t" 1365b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1366b1c7c575SWei Yongjun "1:\n\t"); 1367b1c7c575SWei Yongjun MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t" 1368b1c7c575SWei Yongjun "jecxz 1f\n\t" 1369b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1370b1c7c575SWei Yongjun "mov $0, %ecx\n\t" 1371b1c7c575SWei Yongjun "1:\n\t"); 1372b1c7c575SWei Yongjun 1373b1c7c575SWei Yongjun inregs = (struct regs){ 0 }; 1374b1c7c575SWei Yongjun 1375b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jcxz1); 1376b1c7c575SWei Yongjun report("jcxz short 1", 0, 1); 1377b1c7c575SWei Yongjun 1378b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jcxz2); 1379b1c7c575SWei Yongjun report("jcxz short 2", R_AX, outregs.eax == 0x1234); 1380b1c7c575SWei Yongjun 1381b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jcxz3); 1382b1c7c575SWei Yongjun report("jcxz short 3", R_CX, outregs.ecx == 0x10000); 1383b1c7c575SWei Yongjun 1384b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jecxz1); 1385b1c7c575SWei Yongjun report("jecxz short 1", 0, 1); 1386b1c7c575SWei Yongjun 1387b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jecxz2); 1388b1c7c575SWei Yongjun report("jecxz short 2", R_AX, outregs.eax == 0x1234); 1389b1c7c575SWei Yongjun } 1390b1c7c575SWei Yongjun 13918f578e98SAvi Kivity static void test_cpuid(void) 13928f578e98SAvi Kivity { 13938f578e98SAvi Kivity MK_INSN(cpuid, "cpuid"); 13948f578e98SAvi Kivity unsigned function = 0x1234; 13958f578e98SAvi Kivity unsigned eax, ebx, ecx, edx; 13968f578e98SAvi Kivity 13978f578e98SAvi Kivity inregs.eax = eax = function; 139818ba9083SGleb Natapov inregs.ecx = ecx = 0; 1399674d2dbeSPaolo Bonzini asm("cpuid" : "+a"(eax), "=b"(ebx), "+c"(ecx), "=d"(edx)); 14008f578e98SAvi Kivity exec_in_big_real_mode(&insn_cpuid); 14018f578e98SAvi Kivity report("cpuid", R_AX|R_BX|R_CX|R_DX, 14028f578e98SAvi Kivity outregs.eax == eax && outregs.ebx == ebx 14038f578e98SAvi Kivity && outregs.ecx == ecx && outregs.edx == edx); 14048f578e98SAvi Kivity } 14058f578e98SAvi Kivity 1406ed93f43bSAvi Kivity static void test_ss_base_for_esp_ebp(void) 1407ed93f43bSAvi Kivity { 1408ed93f43bSAvi Kivity MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss"); 1409ed93f43bSAvi Kivity MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss"); 1410ed93f43bSAvi Kivity static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 }; 1411ed93f43bSAvi Kivity 1412ed93f43bSAvi Kivity inregs.ebx = 1; 1413ed93f43bSAvi Kivity inregs.ebp = (unsigned)array; 1414ed93f43bSAvi Kivity exec_in_big_real_mode(&insn_ssrel1); 1415ed93f43bSAvi Kivity report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321); 1416ed93f43bSAvi Kivity inregs.ebx = 1; 1417ed93f43bSAvi Kivity inregs.ebp = (unsigned)array; 1418ed93f43bSAvi Kivity inregs.edi = 0; 1419ed93f43bSAvi Kivity exec_in_big_real_mode(&insn_ssrel2); 1420ed93f43bSAvi Kivity report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321); 1421ed93f43bSAvi Kivity } 1422ed93f43bSAvi Kivity 1423975ca087SPeter Feiner extern unsigned long long r_gdt[]; 1424975ca087SPeter Feiner 1425c2281fa4SAvi Kivity static void test_sgdt_sidt(void) 1426c2281fa4SAvi Kivity { 1427c2281fa4SAvi Kivity MK_INSN(sgdt, "sgdtw (%eax)"); 1428c2281fa4SAvi Kivity MK_INSN(sidt, "sidtw (%eax)"); 1429975ca087SPeter Feiner struct table_descr x, y; 1430c2281fa4SAvi Kivity 1431c2281fa4SAvi Kivity inregs.eax = (unsigned)&y; 1432c2281fa4SAvi Kivity asm volatile("sgdtw %0" : "=m"(x)); 1433c2281fa4SAvi Kivity exec_in_big_real_mode(&insn_sgdt); 1434975ca087SPeter Feiner report("sgdt", 0, x.limit == y.limit && x.base == y.base); 1435c2281fa4SAvi Kivity 1436c2281fa4SAvi Kivity inregs.eax = (unsigned)&y; 1437c2281fa4SAvi Kivity asm volatile("sidtw %0" : "=m"(x)); 1438c2281fa4SAvi Kivity exec_in_big_real_mode(&insn_sidt); 1439975ca087SPeter Feiner report("sidt", 0, x.limit == y.limit && x.base == y.base); 1440c2281fa4SAvi Kivity } 1441c2281fa4SAvi Kivity 144288b6dac4SPaolo Bonzini static void test_sahf(void) 144388b6dac4SPaolo Bonzini { 144488b6dac4SPaolo Bonzini MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw"); 144588b6dac4SPaolo Bonzini 144688b6dac4SPaolo Bonzini inregs.eax = 0xfd00; 144788b6dac4SPaolo Bonzini exec_in_big_real_mode(&insn_sahf); 144888b6dac4SPaolo Bonzini report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7)); 144988b6dac4SPaolo Bonzini } 145088b6dac4SPaolo Bonzini 14517ae3645aSAvi Kivity static void test_lahf(void) 14527ae3645aSAvi Kivity { 14537ae3645aSAvi Kivity MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf"); 14547ae3645aSAvi Kivity 14557ae3645aSAvi Kivity inregs.eax = 0xc7; 14567ae3645aSAvi Kivity exec_in_big_real_mode(&insn_lahf); 14577ae3645aSAvi Kivity report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax); 14587ae3645aSAvi Kivity } 14597ae3645aSAvi Kivity 1460fd9ea640SAvi Kivity static void test_movzx_movsx(void) 1461fd9ea640SAvi Kivity { 1462fd9ea640SAvi Kivity MK_INSN(movsx, "movsx %al, %ebx"); 1463fd9ea640SAvi Kivity MK_INSN(movzx, "movzx %al, %ebx"); 14643013e079SGleb Natapov MK_INSN(movzsah, "movsx %ah, %ebx"); 14653013e079SGleb Natapov MK_INSN(movzxah, "movzx %ah, %ebx"); 1466fd9ea640SAvi Kivity 1467fd9ea640SAvi Kivity inregs.eax = 0x1234569c; 14683013e079SGleb Natapov inregs.esp = 0xffff; 1469fd9ea640SAvi Kivity exec_in_big_real_mode(&insn_movsx); 1470fd9ea640SAvi Kivity report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax); 1471fd9ea640SAvi Kivity exec_in_big_real_mode(&insn_movzx); 1472fd9ea640SAvi Kivity report("movzx", R_BX, outregs.ebx == (unsigned char)inregs.eax); 14733013e079SGleb Natapov exec_in_big_real_mode(&insn_movzsah); 14743013e079SGleb Natapov report("movsx ah", R_BX, outregs.ebx == (signed char)(inregs.eax>>8)); 14753013e079SGleb Natapov exec_in_big_real_mode(&insn_movzxah); 14763013e079SGleb Natapov report("movzx ah", R_BX, outregs.ebx == (unsigned char)(inregs.eax >> 8)); 1477fd9ea640SAvi Kivity } 1478fd9ea640SAvi Kivity 1479b493b2e8SAvi Kivity static void test_bswap(void) 1480b493b2e8SAvi Kivity { 1481b493b2e8SAvi Kivity MK_INSN(bswap, "bswap %ecx"); 1482b493b2e8SAvi Kivity 1483b493b2e8SAvi Kivity inregs.ecx = 0x12345678; 1484b493b2e8SAvi Kivity exec_in_big_real_mode(&insn_bswap); 1485b493b2e8SAvi Kivity report("bswap", R_CX, outregs.ecx == 0x78563412); 1486b493b2e8SAvi Kivity } 1487b493b2e8SAvi Kivity 14888cd86387SGleb Natapov static void test_aad(void) 14898cd86387SGleb Natapov { 14908cd86387SGleb Natapov MK_INSN(aad, "aad"); 14918cd86387SGleb Natapov 14928cd86387SGleb Natapov inregs.eax = 0x12345678; 14938cd86387SGleb Natapov exec_in_big_real_mode(&insn_aad); 14948cd86387SGleb Natapov report("aad", R_AX, outregs.eax == 0x123400d4); 14958cd86387SGleb Natapov } 14968cd86387SGleb Natapov 14972a9b5718SPaolo Bonzini static void test_aam(void) 14982a9b5718SPaolo Bonzini { 14992a9b5718SPaolo Bonzini MK_INSN(aam, "aam"); 15002a9b5718SPaolo Bonzini 15012a9b5718SPaolo Bonzini inregs.eax = 0x76543210; 15022a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_aam); 15032a9b5718SPaolo Bonzini report("aam", R_AX, outregs.eax == 0x76540106); 15042a9b5718SPaolo Bonzini } 15052a9b5718SPaolo Bonzini 15062a9b5718SPaolo Bonzini static void test_xlat(void) 15072a9b5718SPaolo Bonzini { 15082a9b5718SPaolo Bonzini MK_INSN(xlat, "xlat"); 15092a9b5718SPaolo Bonzini u8 table[256]; 15102a9b5718SPaolo Bonzini int i; 15112a9b5718SPaolo Bonzini 15122a9b5718SPaolo Bonzini for (i = 0; i < 256; i++) { 15132a9b5718SPaolo Bonzini table[i] = i + 1; 15142a9b5718SPaolo Bonzini } 15152a9b5718SPaolo Bonzini 15162a9b5718SPaolo Bonzini inregs.eax = 0x89abcdef; 15172a9b5718SPaolo Bonzini inregs.ebx = (u32)table; 15182a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_xlat); 15192a9b5718SPaolo Bonzini report("xlat", R_AX, outregs.eax == 0x89abcdf0); 15202a9b5718SPaolo Bonzini } 15212a9b5718SPaolo Bonzini 15222a9b5718SPaolo Bonzini static void test_salc(void) 15232a9b5718SPaolo Bonzini { 15242a9b5718SPaolo Bonzini MK_INSN(clc_salc, "clc; .byte 0xd6"); 15252a9b5718SPaolo Bonzini MK_INSN(stc_salc, "stc; .byte 0xd6"); 15262a9b5718SPaolo Bonzini 15272a9b5718SPaolo Bonzini inregs.eax = 0x12345678; 15282a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_clc_salc); 15292a9b5718SPaolo Bonzini report("salc (1)", R_AX, outregs.eax == 0x12345600); 15302a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_stc_salc); 15312a9b5718SPaolo Bonzini report("salc (2)", R_AX, outregs.eax == 0x123456ff); 15322a9b5718SPaolo Bonzini } 15332a9b5718SPaolo Bonzini 15340987db7aSGleb Natapov static void test_fninit(void) 15350987db7aSGleb Natapov { 15360987db7aSGleb Natapov u16 fcw = -1, fsw = -1; 15370987db7aSGleb Natapov MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)"); 15380987db7aSGleb Natapov 15390987db7aSGleb Natapov inregs.eax = (u32)&fsw; 15400987db7aSGleb Natapov inregs.ebx = (u32)&fcw; 15410987db7aSGleb Natapov 15420987db7aSGleb Natapov exec_in_big_real_mode(&insn_fninit); 15430987db7aSGleb Natapov report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f); 15440987db7aSGleb Natapov } 15450987db7aSGleb Natapov 15461a4c03a0SArthur Chunqi Li static void test_nopl(void) 15471a4c03a0SArthur Chunqi Li { 15481a4c03a0SArthur Chunqi Li MK_INSN(nopl1, ".byte 0x90\n\r"); // 1 byte nop 15491a4c03a0SArthur Chunqi Li MK_INSN(nopl2, ".byte 0x66, 0x90\n\r"); // 2 bytes nop 15501a4c03a0SArthur Chunqi Li MK_INSN(nopl3, ".byte 0x0f, 0x1f, 0x00\n\r"); // 3 bytes nop 15511a4c03a0SArthur Chunqi Li MK_INSN(nopl4, ".byte 0x0f, 0x1f, 0x40, 0x00\n\r"); // 4 bytes nop 15521a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl1); 15531a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl2); 15541a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl3); 15551a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl4); 15561a4c03a0SArthur Chunqi Li report("nopl", 0, 1); 15571a4c03a0SArthur Chunqi Li } 15581a4c03a0SArthur Chunqi Li 1559b5105e8bSPaolo Bonzini static u32 perf_baseline; 1560b5105e8bSPaolo Bonzini 15617505ea23SPaolo Bonzini #define PERF_COUNT 1000000 1562b5105e8bSPaolo Bonzini 1563b5105e8bSPaolo Bonzini #define MK_INSN_PERF(name, insn) \ 1564b5105e8bSPaolo Bonzini MK_INSN(name, "rdtsc; mov %eax, %ebx; mov %edx, %esi\n" \ 1565b5105e8bSPaolo Bonzini "1:" insn "\n" \ 15667505ea23SPaolo Bonzini ".byte 0x67; loop 1b\n" \ 1567b5105e8bSPaolo Bonzini "rdtsc"); 1568b5105e8bSPaolo Bonzini 1569b5105e8bSPaolo Bonzini static u32 cycles_in_big_real_mode(struct insn_desc *insn) 1570b5105e8bSPaolo Bonzini { 1571b5105e8bSPaolo Bonzini u64 start, end; 1572b5105e8bSPaolo Bonzini 1573b5105e8bSPaolo Bonzini inregs.ecx = PERF_COUNT; 1574b5105e8bSPaolo Bonzini exec_in_big_real_mode(insn); 1575b5105e8bSPaolo Bonzini start = ((u64)outregs.esi << 32) | outregs.ebx; 1576b5105e8bSPaolo Bonzini end = ((u64)outregs.edx << 32) | outregs.eax; 1577b5105e8bSPaolo Bonzini 1578b5105e8bSPaolo Bonzini return end - start; 1579b5105e8bSPaolo Bonzini } 1580b5105e8bSPaolo Bonzini 1581b5105e8bSPaolo Bonzini static void test_perf_loop(void) 1582b5105e8bSPaolo Bonzini { 1583b5105e8bSPaolo Bonzini /* 1584b5105e8bSPaolo Bonzini * This test runs simple instructions that should roughly take the 1585b5105e8bSPaolo Bonzini * the same time to emulate: PERF_COUNT iterations of "loop" and 3 1586b5105e8bSPaolo Bonzini * setup instructions. Other performance tests can run PERF_COUNT 1587b5105e8bSPaolo Bonzini * iterations of the same instruction and subtract the cycle count 1588b5105e8bSPaolo Bonzini * of this test. 1589b5105e8bSPaolo Bonzini */ 1590b5105e8bSPaolo Bonzini MK_INSN_PERF(perf_loop, ""); 1591b5105e8bSPaolo Bonzini perf_baseline = cycles_in_big_real_mode(&insn_perf_loop); 1592b5105e8bSPaolo Bonzini print_serial_u32(perf_baseline / (PERF_COUNT + 3)); 1593b5105e8bSPaolo Bonzini print_serial(" cycles/emulated jump instruction\n"); 1594b5105e8bSPaolo Bonzini } 1595b5105e8bSPaolo Bonzini 1596b5105e8bSPaolo Bonzini static void test_perf_mov(void) 1597b5105e8bSPaolo Bonzini { 1598b5105e8bSPaolo Bonzini u32 cyc; 1599b5105e8bSPaolo Bonzini 1600b5105e8bSPaolo Bonzini MK_INSN_PERF(perf_move, "mov %esi, %edi"); 1601b5105e8bSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_move); 1602b5105e8bSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 1603b5105e8bSPaolo Bonzini print_serial(" cycles/emulated move instruction\n"); 1604b5105e8bSPaolo Bonzini } 1605b5105e8bSPaolo Bonzini 1606b5105e8bSPaolo Bonzini static void test_perf_arith(void) 1607b5105e8bSPaolo Bonzini { 1608b5105e8bSPaolo Bonzini u32 cyc; 1609b5105e8bSPaolo Bonzini 1610b5105e8bSPaolo Bonzini MK_INSN_PERF(perf_arith, "add $4, %edi"); 1611b5105e8bSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_arith); 1612b5105e8bSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 1613b5105e8bSPaolo Bonzini print_serial(" cycles/emulated arithmetic instruction\n"); 1614b5105e8bSPaolo Bonzini } 1615b5105e8bSPaolo Bonzini 1616b5105e8bSPaolo Bonzini static void test_perf_memory_load(void) 1617b5105e8bSPaolo Bonzini { 1618b5105e8bSPaolo Bonzini u32 cyc, tmp; 1619b5105e8bSPaolo Bonzini 1620b5105e8bSPaolo Bonzini MK_INSN_PERF(perf_memory_load, "cmp $0, (%edi)"); 1621b5105e8bSPaolo Bonzini inregs.edi = (u32)&tmp; 1622b5105e8bSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_memory_load); 1623b5105e8bSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 1624b5105e8bSPaolo Bonzini print_serial(" cycles/emulated memory load instruction\n"); 1625b5105e8bSPaolo Bonzini } 1626b5105e8bSPaolo Bonzini 16279306cb8eSPaolo Bonzini static void test_perf_memory_store(void) 16289306cb8eSPaolo Bonzini { 16299306cb8eSPaolo Bonzini u32 cyc, tmp; 16309306cb8eSPaolo Bonzini 16319306cb8eSPaolo Bonzini MK_INSN_PERF(perf_memory_store, "mov %ax, (%edi)"); 16329306cb8eSPaolo Bonzini inregs.edi = (u32)&tmp; 16339306cb8eSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_memory_store); 16349306cb8eSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 16359306cb8eSPaolo Bonzini print_serial(" cycles/emulated memory store instruction\n"); 16369306cb8eSPaolo Bonzini } 16379306cb8eSPaolo Bonzini 1638b5105e8bSPaolo Bonzini static void test_perf_memory_rmw(void) 1639b5105e8bSPaolo Bonzini { 1640b5105e8bSPaolo Bonzini u32 cyc, tmp; 1641b5105e8bSPaolo Bonzini 1642b5105e8bSPaolo Bonzini MK_INSN_PERF(perf_memory_rmw, "add $1, (%edi)"); 1643b5105e8bSPaolo Bonzini inregs.edi = (u32)&tmp; 1644b5105e8bSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_memory_rmw); 1645b5105e8bSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 1646b5105e8bSPaolo Bonzini print_serial(" cycles/emulated memory RMW instruction\n"); 1647b5105e8bSPaolo Bonzini } 1648b5105e8bSPaolo Bonzini 1649*2e3f9f1fSThomas Huth static void test_dr_mod(void) 16500a5701edSNadav Amit { 16510a5701edSNadav Amit MK_INSN(drmod, "movl %ebx, %dr0\n\t" 16520a5701edSNadav Amit ".byte 0x0f \n\t .byte 0x21 \n\t .byte 0x0\n\t"); 16530a5701edSNadav Amit inregs.eax = 0xdead; 16540a5701edSNadav Amit inregs.ebx = 0xaced; 16550a5701edSNadav Amit exec_in_big_real_mode(&insn_drmod); 16560a5701edSNadav Amit report("mov dr with mod bits", R_AX | R_BX, outregs.eax == 0xaced); 16570a5701edSNadav Amit } 16580a5701edSNadav Amit 1659*2e3f9f1fSThomas Huth static void test_smsw(void) 166099ee878cSNadav Amit { 166199ee878cSNadav Amit MK_INSN(smsw, "movl %cr0, %ebx\n\t" 166299ee878cSNadav Amit "movl %ebx, %ecx\n\t" 166399ee878cSNadav Amit "or $0x40000000, %ebx\n\t" 166499ee878cSNadav Amit "movl %ebx, %cr0\n\t" 166599ee878cSNadav Amit "smswl %eax\n\t" 166699ee878cSNadav Amit "movl %ecx, %cr0\n\t"); 166799ee878cSNadav Amit inregs.eax = 0x12345678; 166899ee878cSNadav Amit exec_in_big_real_mode(&insn_smsw); 166999ee878cSNadav Amit report("smsw", R_AX | R_BX | R_CX, outregs.eax == outregs.ebx); 167099ee878cSNadav Amit } 167199ee878cSNadav Amit 1672*2e3f9f1fSThomas Huth static void test_xadd(void) 16737bee560dSNadav Amit { 16747bee560dSNadav Amit MK_INSN(xadd, "xaddl %eax, %eax\n\t"); 16757bee560dSNadav Amit inregs.eax = 0x12345678; 16767bee560dSNadav Amit exec_in_big_real_mode(&insn_xadd); 16777bee560dSNadav Amit report("xadd", R_AX, outregs.eax == inregs.eax * 2); 16787bee560dSNadav Amit } 16797bee560dSNadav Amit 168099ee878cSNadav Amit 16817d36db35SAvi Kivity void realmode_start(void) 16827d36db35SAvi Kivity { 16837d36db35SAvi Kivity test_null(); 16847d36db35SAvi Kivity 16857d36db35SAvi Kivity test_shld(); 16867d36db35SAvi Kivity test_push_pop(); 16877d36db35SAvi Kivity test_pusha_popa(); 16887d36db35SAvi Kivity test_mov_imm(); 16897d36db35SAvi Kivity test_cmp_imm(); 16907d36db35SAvi Kivity test_add_imm(); 16917d36db35SAvi Kivity test_sub_imm(); 16927d36db35SAvi Kivity test_xor_imm(); 16937d36db35SAvi Kivity test_io(); 16947d36db35SAvi Kivity test_eflags_insn(); 16957d36db35SAvi Kivity test_jcc_short(); 16967d36db35SAvi Kivity test_jcc_near(); 16977d36db35SAvi Kivity /* test_call() uses short jump so call it after testing jcc */ 16987d36db35SAvi Kivity test_call(); 16997d36db35SAvi Kivity /* long jmp test uses call near so test it after testing call */ 17007d36db35SAvi Kivity test_long_jmp(); 17017d36db35SAvi Kivity test_xchg(); 17027d36db35SAvi Kivity test_iret(); 170396b9ca1eSMohammed Gamal test_int(); 1704fa74f8a6SMohammed Gamal test_imul(); 170559317bd1SMohammed Gamal test_mul(); 17060d4c7614SMohammed Gamal test_div(); 17070d4c7614SMohammed Gamal test_idiv(); 1708eacef4e2SWei Yongjun test_loopcc(); 17096e293cf5SWei Yongjun test_cbw(); 17100cbd5b06SMohammed Gamal test_cwd_cdq(); 1711b274feedSAvi Kivity test_das(); 171237f51a4aSWei Yongjun test_lds_lss(); 1713b1c7c575SWei Yongjun test_jcxz(); 17148f578e98SAvi Kivity test_cpuid(); 1715ed93f43bSAvi Kivity test_ss_base_for_esp_ebp(); 1716c2281fa4SAvi Kivity test_sgdt_sidt(); 17177ae3645aSAvi Kivity test_lahf(); 171888b6dac4SPaolo Bonzini test_sahf(); 1719fd9ea640SAvi Kivity test_movzx_movsx(); 1720b493b2e8SAvi Kivity test_bswap(); 17218cd86387SGleb Natapov test_aad(); 17222a9b5718SPaolo Bonzini test_aam(); 17232a9b5718SPaolo Bonzini test_xlat(); 17242a9b5718SPaolo Bonzini test_salc(); 17250987db7aSGleb Natapov test_fninit(); 17260a5701edSNadav Amit test_dr_mod(); 172799ee878cSNadav Amit test_smsw(); 17281a4c03a0SArthur Chunqi Li test_nopl(); 17297bee560dSNadav Amit test_xadd(); 1730b5105e8bSPaolo Bonzini test_perf_loop(); 1731b5105e8bSPaolo Bonzini test_perf_mov(); 1732b5105e8bSPaolo Bonzini test_perf_arith(); 1733b5105e8bSPaolo Bonzini test_perf_memory_load(); 17349306cb8eSPaolo Bonzini test_perf_memory_store(); 1735b5105e8bSPaolo Bonzini test_perf_memory_rmw(); 17367d36db35SAvi Kivity 1737b393fe28SNadav Amit exit(failed); 17387d36db35SAvi Kivity } 17397d36db35SAvi Kivity 17407d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff }; 17417d36db35SAvi Kivity 1742975ca087SPeter Feiner struct table_descr r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt }; 17437d36db35SAvi Kivity 17447d36db35SAvi Kivity asm( 17457d36db35SAvi Kivity ".section .init \n\t" 17467d36db35SAvi Kivity 17477d36db35SAvi Kivity ".code32 \n\t" 17487d36db35SAvi Kivity 17497d36db35SAvi Kivity "mb_magic = 0x1BADB002 \n\t" 17507d36db35SAvi Kivity "mb_flags = 0x0 \n\t" 17517d36db35SAvi Kivity 17527d36db35SAvi Kivity "# multiboot header \n\t" 17537d36db35SAvi Kivity ".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t" 17547d36db35SAvi Kivity 17557d36db35SAvi Kivity ".globl start \n\t" 17567d36db35SAvi Kivity ".data \n\t" 17577d36db35SAvi Kivity ". = . + 4096 \n\t" 17587d36db35SAvi Kivity "stacktop: \n\t" 17597d36db35SAvi Kivity 17607d36db35SAvi Kivity ".text \n\t" 17617d36db35SAvi Kivity "start: \n\t" 17627d36db35SAvi Kivity "lgdt r_gdt_descr \n\t" 17637d36db35SAvi Kivity "ljmp $8, $1f; 1: \n\t" 17647d36db35SAvi Kivity ".code16gcc \n\t" 17657d36db35SAvi Kivity "mov $16, %eax \n\t" 17667d36db35SAvi Kivity "mov %ax, %ds \n\t" 17677d36db35SAvi Kivity "mov %ax, %es \n\t" 17687d36db35SAvi Kivity "mov %ax, %fs \n\t" 17697d36db35SAvi Kivity "mov %ax, %gs \n\t" 17707d36db35SAvi Kivity "mov %ax, %ss \n\t" 17717d36db35SAvi Kivity "mov %cr0, %eax \n\t" 17727d36db35SAvi Kivity "btc $0, %eax \n\t" 17737d36db35SAvi Kivity "mov %eax, %cr0 \n\t" 17747d36db35SAvi Kivity "ljmp $0, $realmode_entry \n\t" 17757d36db35SAvi Kivity 17767d36db35SAvi Kivity "realmode_entry: \n\t" 17777d36db35SAvi Kivity 17787d36db35SAvi Kivity "xor %ax, %ax \n\t" 17797d36db35SAvi Kivity "mov %ax, %ds \n\t" 17807d36db35SAvi Kivity "mov %ax, %es \n\t" 17817d36db35SAvi Kivity "mov %ax, %ss \n\t" 17827d36db35SAvi Kivity "mov %ax, %fs \n\t" 17837d36db35SAvi Kivity "mov %ax, %gs \n\t" 17847d36db35SAvi Kivity "mov $stacktop, %esp\n\t" 17857d36db35SAvi Kivity "ljmp $0, $realmode_start \n\t" 17867d36db35SAvi Kivity 17877d36db35SAvi Kivity ".code16gcc \n\t" 17887d36db35SAvi Kivity ); 1789