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 127d36db35SAvi Kivity void test_function(void); 137d36db35SAvi Kivity 147d36db35SAvi Kivity asm( 157d36db35SAvi Kivity "test_function: \n\t" 167d36db35SAvi Kivity "mov $0x1234, %eax \n\t" 177d36db35SAvi Kivity "ret" 187d36db35SAvi Kivity ); 197d36db35SAvi Kivity 207d36db35SAvi Kivity static int strlen(const char *str) 217d36db35SAvi Kivity { 227d36db35SAvi Kivity int n; 237d36db35SAvi Kivity 247d36db35SAvi Kivity for (n = 0; *str; ++str) 257d36db35SAvi Kivity ++n; 267d36db35SAvi Kivity return n; 277d36db35SAvi Kivity } 287d36db35SAvi Kivity 29f366255fSPaolo Bonzini static void outb(u8 data, u16 port) 30f366255fSPaolo Bonzini { 31f366255fSPaolo Bonzini asm volatile("out %0, %1" : : "a"(data), "d"(port)); 32f366255fSPaolo Bonzini } 33f366255fSPaolo Bonzini 34f366255fSPaolo Bonzini #ifdef USE_SERIAL 35f366255fSPaolo Bonzini static int serial_iobase = 0x3f8; 36f366255fSPaolo Bonzini static int serial_inited = 0; 37f366255fSPaolo Bonzini 38f366255fSPaolo Bonzini static u8 inb(u16 port) 39f366255fSPaolo Bonzini { 40f366255fSPaolo Bonzini u8 data; 41f366255fSPaolo Bonzini asm volatile("in %1, %0" : "=a"(data) : "d"(port)); 42f366255fSPaolo Bonzini return data; 43f366255fSPaolo Bonzini } 44f366255fSPaolo Bonzini 45f366255fSPaolo Bonzini static void serial_outb(char ch) 46f366255fSPaolo Bonzini { 47f366255fSPaolo Bonzini u8 lsr; 48f366255fSPaolo Bonzini 49f366255fSPaolo Bonzini do { 50f366255fSPaolo Bonzini lsr = inb(serial_iobase + 0x05); 51f366255fSPaolo Bonzini } while (!(lsr & 0x20)); 52f366255fSPaolo Bonzini 53f366255fSPaolo Bonzini outb(ch, serial_iobase + 0x00); 54f366255fSPaolo Bonzini } 55f366255fSPaolo Bonzini 56f366255fSPaolo Bonzini static void serial_init(void) 57f366255fSPaolo Bonzini { 58f366255fSPaolo Bonzini u8 lcr; 59f366255fSPaolo Bonzini 60f366255fSPaolo Bonzini /* set DLAB */ 61f366255fSPaolo Bonzini lcr = inb(serial_iobase + 0x03); 62f366255fSPaolo Bonzini lcr |= 0x80; 63f366255fSPaolo Bonzini outb(lcr, serial_iobase + 0x03); 64f366255fSPaolo Bonzini 65f366255fSPaolo Bonzini /* set baud rate to 115200 */ 66f366255fSPaolo Bonzini outb(0x01, serial_iobase + 0x00); 67f366255fSPaolo Bonzini outb(0x00, serial_iobase + 0x01); 68f366255fSPaolo Bonzini 69f366255fSPaolo Bonzini /* clear DLAB */ 70f366255fSPaolo Bonzini lcr = inb(serial_iobase + 0x03); 71f366255fSPaolo Bonzini lcr &= ~0x80; 72f366255fSPaolo Bonzini outb(lcr, serial_iobase + 0x03); 73f366255fSPaolo Bonzini } 74f366255fSPaolo Bonzini #endif 75f366255fSPaolo Bonzini 767d36db35SAvi Kivity static void print_serial(const char *buf) 777d36db35SAvi Kivity { 787d36db35SAvi Kivity unsigned long len = strlen(buf); 79f366255fSPaolo Bonzini #ifdef USE_SERIAL 80f366255fSPaolo Bonzini unsigned long i; 81f366255fSPaolo Bonzini if (!serial_inited) { 82f366255fSPaolo Bonzini serial_init(); 83f366255fSPaolo Bonzini serial_inited = 1; 84f366255fSPaolo Bonzini } 857d36db35SAvi Kivity 86f366255fSPaolo Bonzini for (i = 0; i < len; i++) { 87f366255fSPaolo Bonzini serial_outb(buf[i]); 88f366255fSPaolo Bonzini } 89f366255fSPaolo Bonzini #else 905edbb9aeSPaolo Bonzini asm volatile ("addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1)); 91f366255fSPaolo Bonzini #endif 927d36db35SAvi Kivity } 937d36db35SAvi Kivity 94b5105e8bSPaolo Bonzini static void print_serial_u32(u32 value) 95b5105e8bSPaolo Bonzini { 96b5105e8bSPaolo Bonzini char n[12], *p; 97b5105e8bSPaolo Bonzini p = &n[11]; 98b5105e8bSPaolo Bonzini *p = 0; 99b5105e8bSPaolo Bonzini do { 100b5105e8bSPaolo Bonzini *--p = '0' + (value % 10); 101b5105e8bSPaolo Bonzini value /= 10; 102b5105e8bSPaolo Bonzini } while (value > 0); 103b5105e8bSPaolo Bonzini print_serial(p); 104b5105e8bSPaolo Bonzini } 105b5105e8bSPaolo Bonzini 106b393fe28SNadav Amit static int failed; 107b393fe28SNadav Amit 1087d36db35SAvi Kivity static void exit(int code) 1097d36db35SAvi Kivity { 110f366255fSPaolo Bonzini outb(code, 0xf4); 1117d36db35SAvi Kivity } 1127d36db35SAvi Kivity 1137d36db35SAvi Kivity struct regs { 1147d36db35SAvi Kivity u32 eax, ebx, ecx, edx; 1157d36db35SAvi Kivity u32 esi, edi, esp, ebp; 1167d36db35SAvi Kivity u32 eip, eflags; 1177d36db35SAvi Kivity }; 1187d36db35SAvi Kivity 1197d36db35SAvi Kivity static u64 gdt[] = { 1207d36db35SAvi Kivity 0, 1217d36db35SAvi Kivity 0x00cf9b000000ffffull, // flat 32-bit code segment 1227d36db35SAvi Kivity 0x00cf93000000ffffull, // flat 32-bit data segment 1237d36db35SAvi Kivity }; 1247d36db35SAvi Kivity 1257d36db35SAvi Kivity static struct { 1267d36db35SAvi Kivity u16 limit; 1277d36db35SAvi Kivity void *base; 1287d36db35SAvi Kivity } __attribute__((packed)) gdt_descr = { 1297d36db35SAvi Kivity sizeof(gdt) - 1, 1307d36db35SAvi Kivity gdt, 1317d36db35SAvi Kivity }; 1327d36db35SAvi Kivity 133d4dc402cSAvi Kivity struct insn_desc { 134d4dc402cSAvi Kivity u16 ptr; 135d4dc402cSAvi Kivity u16 len; 136d4dc402cSAvi Kivity }; 137d4dc402cSAvi Kivity 13818253fdeSAvi Kivity static struct regs inregs, outregs; 13918253fdeSAvi Kivity 14018253fdeSAvi Kivity static void exec_in_big_real_mode(struct insn_desc *insn) 1417d36db35SAvi Kivity { 1427d36db35SAvi Kivity unsigned long tmp; 1437d36db35SAvi Kivity static struct regs save; 1447d36db35SAvi Kivity int i; 1457d36db35SAvi Kivity extern u8 test_insn[], test_insn_end[]; 1467d36db35SAvi Kivity 147d4dc402cSAvi Kivity for (i = 0; i < insn->len; ++i) 148d4dc402cSAvi Kivity test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i]; 1497d36db35SAvi Kivity for (; i < test_insn_end - test_insn; ++i) 1507d36db35SAvi Kivity test_insn[i] = 0x90; // nop 1517d36db35SAvi Kivity 15218253fdeSAvi Kivity save = inregs; 1537d36db35SAvi Kivity asm volatile( 1547d36db35SAvi Kivity "lgdtl %[gdt_descr] \n\t" 1557d36db35SAvi Kivity "mov %%cr0, %[tmp] \n\t" 1567d36db35SAvi Kivity "or $1, %[tmp] \n\t" 1577d36db35SAvi Kivity "mov %[tmp], %%cr0 \n\t" 1587d36db35SAvi Kivity "mov %[bigseg], %%gs \n\t" 1597d36db35SAvi Kivity "and $-2, %[tmp] \n\t" 1607d36db35SAvi Kivity "mov %[tmp], %%cr0 \n\t" 1617d36db35SAvi Kivity 16232001692SAvi Kivity "pushw %[save]+36; popfw \n\t" 1637d36db35SAvi Kivity "xchg %%eax, %[save]+0 \n\t" 1647d36db35SAvi Kivity "xchg %%ebx, %[save]+4 \n\t" 1657d36db35SAvi Kivity "xchg %%ecx, %[save]+8 \n\t" 1667d36db35SAvi Kivity "xchg %%edx, %[save]+12 \n\t" 1677d36db35SAvi Kivity "xchg %%esi, %[save]+16 \n\t" 1687d36db35SAvi Kivity "xchg %%edi, %[save]+20 \n\t" 1697d36db35SAvi Kivity "xchg %%esp, %[save]+24 \n\t" 1707d36db35SAvi Kivity "xchg %%ebp, %[save]+28 \n\t" 1717d36db35SAvi Kivity 1727d36db35SAvi Kivity "test_insn: . = . + 32\n\t" 1737d36db35SAvi Kivity "test_insn_end: \n\t" 1747d36db35SAvi Kivity 1757d36db35SAvi Kivity "xchg %%eax, %[save]+0 \n\t" 1767d36db35SAvi Kivity "xchg %%ebx, %[save]+4 \n\t" 1777d36db35SAvi Kivity "xchg %%ecx, %[save]+8 \n\t" 1787d36db35SAvi Kivity "xchg %%edx, %[save]+12 \n\t" 1797d36db35SAvi Kivity "xchg %%esi, %[save]+16 \n\t" 1807d36db35SAvi Kivity "xchg %%edi, %[save]+20 \n\t" 1817d36db35SAvi Kivity "xchg %%esp, %[save]+24 \n\t" 1827d36db35SAvi Kivity "xchg %%ebp, %[save]+28 \n\t" 1837d36db35SAvi Kivity 1847d36db35SAvi Kivity /* Save EFLAGS in outregs*/ 1857d36db35SAvi Kivity "pushfl \n\t" 1867d36db35SAvi Kivity "popl %[save]+36 \n\t" 1877d36db35SAvi Kivity 1885edbb9aeSPaolo Bonzini /* Restore DF for the harness code */ 1895edbb9aeSPaolo Bonzini "cld\n\t" 1907d36db35SAvi Kivity "xor %[tmp], %[tmp] \n\t" 1917d36db35SAvi Kivity "mov %[tmp], %%gs \n\t" 1927d36db35SAvi Kivity : [tmp]"=&r"(tmp), [save]"+m"(save) 1937d36db35SAvi Kivity : [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16) 1947d36db35SAvi Kivity : "cc", "memory" 1957d36db35SAvi Kivity ); 19618253fdeSAvi Kivity outregs = save; 1977d36db35SAvi Kivity } 1987d36db35SAvi Kivity 1997d36db35SAvi Kivity #define R_AX 1 2007d36db35SAvi Kivity #define R_BX 2 2017d36db35SAvi Kivity #define R_CX 4 2027d36db35SAvi Kivity #define R_DX 8 2037d36db35SAvi Kivity #define R_SI 16 2047d36db35SAvi Kivity #define R_DI 32 2057d36db35SAvi Kivity #define R_SP 64 2067d36db35SAvi Kivity #define R_BP 128 2077d36db35SAvi Kivity 20818253fdeSAvi Kivity int regs_equal(int ignore) 2097d36db35SAvi Kivity { 21018253fdeSAvi Kivity const u32 *p1 = &inregs.eax, *p2 = &outregs.eax; // yuck 2117d36db35SAvi Kivity int i; 2127d36db35SAvi Kivity 2137d36db35SAvi Kivity for (i = 0; i < 8; ++i) 2147d36db35SAvi Kivity if (!(ignore & (1 << i)) && p1[i] != p2[i]) 2157d36db35SAvi Kivity return 0; 2167d36db35SAvi Kivity return 1; 2177d36db35SAvi Kivity } 2187d36db35SAvi Kivity 2196055ea1fSAvi Kivity static void report(const char *name, u16 regs_ignore, _Bool ok) 22081050840SAvi Kivity { 2216055ea1fSAvi Kivity if (!regs_equal(regs_ignore)) { 2226055ea1fSAvi Kivity ok = 0; 2236055ea1fSAvi Kivity } 22481050840SAvi Kivity print_serial(ok ? "PASS: " : "FAIL: "); 22581050840SAvi Kivity print_serial(name); 22681050840SAvi Kivity print_serial("\n"); 227b393fe28SNadav Amit if (!ok) 228b393fe28SNadav Amit failed = 1; 22981050840SAvi Kivity } 23081050840SAvi Kivity 2317d36db35SAvi Kivity #define MK_INSN(name, str) \ 2327d36db35SAvi Kivity asm ( \ 233d4dc402cSAvi Kivity ".pushsection .data.insn \n\t" \ 234d4dc402cSAvi Kivity "insn_" #name ": \n\t" \ 235d4dc402cSAvi Kivity ".word 1001f, 1002f - 1001f \n\t" \ 236d4dc402cSAvi Kivity ".popsection \n\t" \ 237d4dc402cSAvi Kivity ".pushsection .text.insn, \"ax\" \n\t" \ 238d4dc402cSAvi Kivity "1001: \n\t" \ 239d4dc402cSAvi Kivity "insn_code_" #name ": " str " \n\t" \ 240d4dc402cSAvi Kivity "1002: \n\t" \ 241d4dc402cSAvi Kivity ".popsection" \ 2427d36db35SAvi Kivity ); \ 243d4dc402cSAvi Kivity extern struct insn_desc insn_##name; 2447d36db35SAvi Kivity 2457d36db35SAvi Kivity void test_xchg(void) 2467d36db35SAvi Kivity { 2477d36db35SAvi Kivity MK_INSN(xchg_test1, "xchg %eax,%eax\n\t"); 2487d36db35SAvi Kivity MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t"); 2497d36db35SAvi Kivity MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t"); 2507d36db35SAvi Kivity MK_INSN(xchg_test4, "xchg %eax,%edx\n\t"); 2517d36db35SAvi Kivity MK_INSN(xchg_test5, "xchg %eax,%esi\n\t"); 2527d36db35SAvi Kivity MK_INSN(xchg_test6, "xchg %eax,%edi\n\t"); 2537d36db35SAvi Kivity MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t"); 2547d36db35SAvi Kivity MK_INSN(xchg_test8, "xchg %eax,%esp\n\t"); 2557d36db35SAvi Kivity 25618253fdeSAvi Kivity inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7}; 2577d36db35SAvi Kivity 25818253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test1); 2596055ea1fSAvi Kivity report("xchg 1", 0, 1); 26018253fdeSAvi Kivity 26118253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test2); 2626055ea1fSAvi Kivity report("xchg 2", R_AX | R_BX, 2636055ea1fSAvi Kivity outregs.eax == inregs.ebx && outregs.ebx == inregs.eax); 2647d36db35SAvi Kivity 26518253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test3); 2666055ea1fSAvi Kivity report("xchg 3", R_AX | R_CX, 2676055ea1fSAvi Kivity outregs.eax == inregs.ecx && outregs.ecx == inregs.eax); 2687d36db35SAvi Kivity 26918253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test4); 2706055ea1fSAvi Kivity report("xchg 4", R_AX | R_DX, 2716055ea1fSAvi Kivity outregs.eax == inregs.edx && outregs.edx == inregs.eax); 2727d36db35SAvi Kivity 27318253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test5); 2746055ea1fSAvi Kivity report("xchg 5", R_AX | R_SI, 2756055ea1fSAvi Kivity outregs.eax == inregs.esi && outregs.esi == inregs.eax); 2767d36db35SAvi Kivity 27718253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test6); 2786055ea1fSAvi Kivity report("xchg 6", R_AX | R_DI, 2796055ea1fSAvi Kivity outregs.eax == inregs.edi && outregs.edi == inregs.eax); 2807d36db35SAvi Kivity 28118253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test7); 2826055ea1fSAvi Kivity report("xchg 7", R_AX | R_BP, 2836055ea1fSAvi Kivity outregs.eax == inregs.ebp && outregs.ebp == inregs.eax); 2847d36db35SAvi Kivity 28518253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test8); 2866055ea1fSAvi Kivity report("xchg 8", R_AX | R_SP, 2876055ea1fSAvi Kivity outregs.eax == inregs.esp && outregs.esp == inregs.eax); 2887d36db35SAvi Kivity } 2897d36db35SAvi Kivity 2907d36db35SAvi Kivity void test_shld(void) 2917d36db35SAvi Kivity { 2927d36db35SAvi Kivity MK_INSN(shld_test, "shld $8,%edx,%eax\n\t"); 2937d36db35SAvi Kivity 29418253fdeSAvi Kivity inregs = (struct regs){ .eax = 0xbe, .edx = 0xef000000 }; 29518253fdeSAvi Kivity exec_in_big_real_mode(&insn_shld_test); 2966055ea1fSAvi Kivity report("shld", ~0, outregs.eax == 0xbeef); 2977d36db35SAvi Kivity } 2987d36db35SAvi Kivity 2997d36db35SAvi Kivity void test_mov_imm(void) 3007d36db35SAvi Kivity { 3017d36db35SAvi Kivity MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax"); 3027d36db35SAvi Kivity MK_INSN(mov_r16_imm_1, "mov $1234, %ax"); 3037d36db35SAvi Kivity MK_INSN(mov_r8_imm_1, "mov $0x12, %ah"); 3047d36db35SAvi Kivity MK_INSN(mov_r8_imm_2, "mov $0x34, %al"); 3057d36db35SAvi Kivity MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t"); 3067d36db35SAvi Kivity 30718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 30818253fdeSAvi Kivity 30918253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r16_imm_1); 3106055ea1fSAvi Kivity report("mov 1", R_AX, outregs.eax == 1234); 3117d36db35SAvi Kivity 3127d36db35SAvi Kivity /* test mov $imm, %eax */ 31318253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r32_imm_1); 3146055ea1fSAvi Kivity report("mov 2", R_AX, outregs.eax == 1234567890); 3157d36db35SAvi Kivity 3167d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 31718253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_1); 3186055ea1fSAvi Kivity report("mov 3", R_AX, outregs.eax == 0x1200); 3197d36db35SAvi Kivity 32018253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_2); 3216055ea1fSAvi Kivity report("mov 4", R_AX, outregs.eax == 0x34); 3227d36db35SAvi Kivity 32318253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_3); 3246055ea1fSAvi Kivity report("mov 5", R_AX, outregs.eax == 0x1234); 3257d36db35SAvi Kivity } 3267d36db35SAvi Kivity 3277d36db35SAvi Kivity void test_sub_imm(void) 3287d36db35SAvi Kivity { 3297d36db35SAvi Kivity MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t"); 3307d36db35SAvi Kivity MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t"); 3317d36db35SAvi Kivity MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t"); 3327d36db35SAvi Kivity MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t"); 3337d36db35SAvi Kivity 33418253fdeSAvi Kivity inregs = (struct regs){ 0 }; 33518253fdeSAvi Kivity 33618253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r16_imm_1); 3376055ea1fSAvi Kivity report("sub 1", R_AX, outregs.eax == 1224); 3387d36db35SAvi Kivity 3397d36db35SAvi Kivity /* test mov $imm, %eax */ 34018253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r32_imm_1); 3416055ea1fSAvi Kivity report("sub 2", R_AX, outregs.eax == 1234567880); 3427d36db35SAvi Kivity 3437d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 34418253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r8_imm_1); 3456055ea1fSAvi Kivity report("sub 3", R_AX, outregs.eax == 0x0200); 3467d36db35SAvi Kivity 34718253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r8_imm_2); 3486055ea1fSAvi Kivity report("sub 4", R_AX, outregs.eax == 0x24); 3497d36db35SAvi Kivity } 3507d36db35SAvi Kivity 3517d36db35SAvi Kivity void test_xor_imm(void) 3527d36db35SAvi Kivity { 3537d36db35SAvi Kivity MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t"); 3547d36db35SAvi Kivity MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t"); 3557d36db35SAvi Kivity MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t"); 3567d36db35SAvi Kivity MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t"); 3577d36db35SAvi Kivity 35818253fdeSAvi Kivity inregs = (struct regs){ 0 }; 35918253fdeSAvi Kivity 36018253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r16_imm_1); 3616055ea1fSAvi Kivity report("xor 1", R_AX, outregs.eax == 0); 3627d36db35SAvi Kivity 3637d36db35SAvi Kivity /* test mov $imm, %eax */ 36418253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r32_imm_1); 3656055ea1fSAvi Kivity report("xor 2", R_AX, outregs.eax == 0); 3667d36db35SAvi Kivity 3677d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 36818253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r8_imm_1); 3696055ea1fSAvi Kivity report("xor 3", R_AX, outregs.eax == 0); 3707d36db35SAvi Kivity 37118253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r8_imm_2); 3726055ea1fSAvi Kivity report("xor 4", R_AX, outregs.eax == 0); 3737d36db35SAvi Kivity } 3747d36db35SAvi Kivity 3757d36db35SAvi Kivity void test_cmp_imm(void) 3767d36db35SAvi Kivity { 3777d36db35SAvi Kivity MK_INSN(cmp_test1, "mov $0x34, %al\n\t" 3787d36db35SAvi Kivity "cmp $0x34, %al\n\t"); 3797d36db35SAvi Kivity MK_INSN(cmp_test2, "mov $0x34, %al\n\t" 3807d36db35SAvi Kivity "cmp $0x39, %al\n\t"); 3817d36db35SAvi Kivity MK_INSN(cmp_test3, "mov $0x34, %al\n\t" 3827d36db35SAvi Kivity "cmp $0x24, %al\n\t"); 3837d36db35SAvi Kivity 38418253fdeSAvi Kivity inregs = (struct regs){ 0 }; 38518253fdeSAvi Kivity 3867d36db35SAvi Kivity /* test cmp imm8 with AL */ 3877d36db35SAvi Kivity /* ZF: (bit 6) Zero Flag becomes 1 if an operation results 3887d36db35SAvi Kivity * in a 0 writeback, or 0 register 3897d36db35SAvi Kivity */ 39018253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test1); 3916055ea1fSAvi Kivity report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6)); 3927d36db35SAvi Kivity 39318253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test2); 3946055ea1fSAvi Kivity report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0); 3957d36db35SAvi Kivity 39618253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test3); 3976055ea1fSAvi Kivity report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0); 3987d36db35SAvi Kivity } 3997d36db35SAvi Kivity 4007d36db35SAvi Kivity void test_add_imm(void) 4017d36db35SAvi Kivity { 4027d36db35SAvi Kivity MK_INSN(add_test1, "mov $0x43211234, %eax \n\t" 4037d36db35SAvi Kivity "add $0x12344321, %eax \n\t"); 4047d36db35SAvi Kivity MK_INSN(add_test2, "mov $0x12, %eax \n\t" 4057d36db35SAvi Kivity "add $0x21, %al\n\t"); 4067d36db35SAvi Kivity 40718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 40818253fdeSAvi Kivity 40918253fdeSAvi Kivity exec_in_big_real_mode(&insn_add_test1); 4106055ea1fSAvi Kivity report("add 1", ~0, outregs.eax == 0x55555555); 4117d36db35SAvi Kivity 41218253fdeSAvi Kivity exec_in_big_real_mode(&insn_add_test2); 4136055ea1fSAvi Kivity report("add 2", ~0, outregs.eax == 0x33); 4147d36db35SAvi Kivity } 4157d36db35SAvi Kivity 4167d36db35SAvi Kivity void test_eflags_insn(void) 4177d36db35SAvi Kivity { 4187d36db35SAvi Kivity MK_INSN(clc, "clc"); 419b3261e48SMohammed Gamal MK_INSN(stc, "stc"); 4207d36db35SAvi Kivity MK_INSN(cli, "cli"); 4217d36db35SAvi Kivity MK_INSN(sti, "sti"); 4227d36db35SAvi Kivity MK_INSN(cld, "cld"); 4237d36db35SAvi Kivity MK_INSN(std, "std"); 4247d36db35SAvi Kivity 42518253fdeSAvi Kivity inregs = (struct regs){ 0 }; 42618253fdeSAvi Kivity 42718253fdeSAvi Kivity exec_in_big_real_mode(&insn_clc); 4286055ea1fSAvi Kivity report("clc", ~0, (outregs.eflags & 1) == 0); 4297d36db35SAvi Kivity 43018253fdeSAvi Kivity exec_in_big_real_mode(&insn_stc); 4316055ea1fSAvi Kivity report("stc", ~0, (outregs.eflags & 1) == 1); 432b3261e48SMohammed Gamal 43318253fdeSAvi Kivity exec_in_big_real_mode(&insn_cli); 4346055ea1fSAvi Kivity report("cli", ~0, !(outregs.eflags & (1 << 9))); 4357d36db35SAvi Kivity 43618253fdeSAvi Kivity exec_in_big_real_mode(&insn_sti); 4376055ea1fSAvi Kivity report("sti", ~0, outregs.eflags & (1 << 9)); 4387d36db35SAvi Kivity 43918253fdeSAvi Kivity exec_in_big_real_mode(&insn_cld); 4406055ea1fSAvi Kivity report("cld", ~0, !(outregs.eflags & (1 << 10))); 4417d36db35SAvi Kivity 44218253fdeSAvi Kivity exec_in_big_real_mode(&insn_std); 4436055ea1fSAvi Kivity report("std", ~0, (outregs.eflags & (1 << 10))); 4447d36db35SAvi Kivity } 4457d36db35SAvi Kivity 4467d36db35SAvi Kivity void test_io(void) 4477d36db35SAvi Kivity { 4487d36db35SAvi Kivity MK_INSN(io_test1, "mov $0xff, %al \n\t" 4497d36db35SAvi Kivity "out %al, $0xe0 \n\t" 4507d36db35SAvi Kivity "mov $0x00, %al \n\t" 4517d36db35SAvi Kivity "in $0xe0, %al \n\t"); 4527d36db35SAvi Kivity MK_INSN(io_test2, "mov $0xffff, %ax \n\t" 4537d36db35SAvi Kivity "out %ax, $0xe0 \n\t" 4547d36db35SAvi Kivity "mov $0x0000, %ax \n\t" 4557d36db35SAvi Kivity "in $0xe0, %ax \n\t"); 4567d36db35SAvi Kivity MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t" 4577d36db35SAvi Kivity "out %eax, $0xe0 \n\t" 4587d36db35SAvi Kivity "mov $0x000000, %eax \n\t" 4597d36db35SAvi Kivity "in $0xe0, %eax \n\t"); 4607d36db35SAvi Kivity MK_INSN(io_test4, "mov $0xe0, %dx \n\t" 4617d36db35SAvi Kivity "mov $0xff, %al \n\t" 4627d36db35SAvi Kivity "out %al, %dx \n\t" 4637d36db35SAvi Kivity "mov $0x00, %al \n\t" 4647d36db35SAvi Kivity "in %dx, %al \n\t"); 4657d36db35SAvi Kivity MK_INSN(io_test5, "mov $0xe0, %dx \n\t" 4667d36db35SAvi Kivity "mov $0xffff, %ax \n\t" 4677d36db35SAvi Kivity "out %ax, %dx \n\t" 4687d36db35SAvi Kivity "mov $0x0000, %ax \n\t" 4697d36db35SAvi Kivity "in %dx, %ax \n\t"); 4707d36db35SAvi Kivity MK_INSN(io_test6, "mov $0xe0, %dx \n\t" 4717d36db35SAvi Kivity "mov $0xffffffff, %eax \n\t" 4727d36db35SAvi Kivity "out %eax, %dx \n\t" 4737d36db35SAvi Kivity "mov $0x00000000, %eax \n\t" 4747d36db35SAvi Kivity "in %dx, %eax \n\t"); 4757d36db35SAvi Kivity 47618253fdeSAvi Kivity inregs = (struct regs){ 0 }; 47718253fdeSAvi Kivity 47818253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test1); 4796055ea1fSAvi Kivity report("pio 1", R_AX, outregs.eax == 0xff); 4807d36db35SAvi Kivity 48118253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test2); 4826055ea1fSAvi Kivity report("pio 2", R_AX, outregs.eax == 0xffff); 4837d36db35SAvi Kivity 48418253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test3); 4856055ea1fSAvi Kivity report("pio 3", R_AX, outregs.eax == 0xffffffff); 4867d36db35SAvi Kivity 48718253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test4); 4886055ea1fSAvi Kivity report("pio 4", R_AX|R_DX, outregs.eax == 0xff); 4897d36db35SAvi Kivity 49018253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test5); 4916055ea1fSAvi Kivity report("pio 5", R_AX|R_DX, outregs.eax == 0xffff); 4927d36db35SAvi Kivity 49318253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test6); 4946055ea1fSAvi Kivity report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff); 4957d36db35SAvi Kivity } 4967d36db35SAvi Kivity 497c0b7268dSAvi Kivity asm ("retf: lretw"); 498c0b7268dSAvi Kivity extern void retf(); 499c0b7268dSAvi Kivity 5004f66bc86SBruce Rogers asm ("retf_imm: lretw $10"); 5014f66bc86SBruce Rogers extern void retf_imm(); 5024f66bc86SBruce Rogers 5037d36db35SAvi Kivity void test_call(void) 5047d36db35SAvi Kivity { 5057d36db35SAvi Kivity u32 esp[16]; 506c0b7268dSAvi Kivity u32 addr; 5077d36db35SAvi Kivity 50818253fdeSAvi Kivity inregs = (struct regs){ 0 }; 5097d36db35SAvi Kivity inregs.esp = (u32)esp; 5107d36db35SAvi Kivity 5117d36db35SAvi Kivity MK_INSN(call1, "mov $test_function, %eax \n\t" 5127d36db35SAvi Kivity "call *%eax\n\t"); 5137d36db35SAvi Kivity MK_INSN(call_near1, "jmp 2f\n\t" 5147d36db35SAvi Kivity "1: mov $0x1234, %eax\n\t" 5157d36db35SAvi Kivity "ret\n\t" 5167d36db35SAvi Kivity "2: call 1b\t"); 5177d36db35SAvi Kivity MK_INSN(call_near2, "call 1f\n\t" 5187d36db35SAvi Kivity "jmp 2f\n\t" 5197d36db35SAvi Kivity "1: mov $0x1234, %eax\n\t" 5207d36db35SAvi Kivity "ret\n\t" 5217d36db35SAvi Kivity "2:\t"); 522c0b7268dSAvi Kivity MK_INSN(call_far1, "lcallw *(%ebx)\n\t"); 523556d2680SWei Yongjun MK_INSN(call_far2, "lcallw $0, $retf\n\t"); 524c6061817SAvi Kivity MK_INSN(ret_imm, "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b"); 5254f66bc86SBruce Rogers MK_INSN(retf_imm, "sub $10, %sp; lcallw $0, $retf_imm"); 5267d36db35SAvi Kivity 52718253fdeSAvi Kivity exec_in_big_real_mode(&insn_call1); 5286055ea1fSAvi Kivity report("call 1", R_AX, outregs.eax == 0x1234); 5297d36db35SAvi Kivity 53018253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_near1); 5316055ea1fSAvi Kivity report("call near 1", R_AX, outregs.eax == 0x1234); 5327d36db35SAvi Kivity 53318253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_near2); 5346055ea1fSAvi Kivity report("call near 2", R_AX, outregs.eax == 0x1234); 535c0b7268dSAvi Kivity 536c0b7268dSAvi Kivity addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f); 537c0b7268dSAvi Kivity inregs.ebx = (unsigned)&addr; 53818253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_far1); 5396055ea1fSAvi Kivity report("call far 1", 0, 1); 540c6061817SAvi Kivity 541556d2680SWei Yongjun exec_in_big_real_mode(&insn_call_far2); 542556d2680SWei Yongjun report("call far 2", 0, 1); 543556d2680SWei Yongjun 54418253fdeSAvi Kivity exec_in_big_real_mode(&insn_ret_imm); 5456055ea1fSAvi Kivity report("ret imm 1", 0, 1); 5464f66bc86SBruce Rogers 5474f66bc86SBruce Rogers exec_in_big_real_mode(&insn_retf_imm); 5484f66bc86SBruce Rogers report("retf imm 1", 0, 1); 5497d36db35SAvi Kivity } 5507d36db35SAvi Kivity 5517d36db35SAvi Kivity void test_jcc_short(void) 5527d36db35SAvi Kivity { 5537d36db35SAvi Kivity MK_INSN(jnz_short1, "jnz 1f\n\t" 5547d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5557d36db35SAvi Kivity "1:\n\t"); 5567d36db35SAvi Kivity MK_INSN(jnz_short2, "1:\n\t" 5577d36db35SAvi Kivity "cmp $0x1234, %eax\n\t" 5587d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5597d36db35SAvi Kivity "jnz 1b\n\t"); 5607d36db35SAvi Kivity MK_INSN(jmp_short1, "jmp 1f\n\t" 5617d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5627d36db35SAvi Kivity "1:\n\t"); 5637d36db35SAvi Kivity 56418253fdeSAvi Kivity inregs = (struct regs){ 0 }; 5657d36db35SAvi Kivity 56618253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_short1); 5676055ea1fSAvi Kivity report("jnz short 1", ~0, 1); 56818253fdeSAvi Kivity 56918253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_short2); 5706055ea1fSAvi Kivity report("jnz short 2", R_AX, (outregs.eflags & (1 << 6))); 5717d36db35SAvi Kivity 57218253fdeSAvi Kivity exec_in_big_real_mode(&insn_jmp_short1); 5736055ea1fSAvi Kivity report("jmp short 1", ~0, 1); 5747d36db35SAvi Kivity } 5757d36db35SAvi Kivity 5767d36db35SAvi Kivity void test_jcc_near(void) 5777d36db35SAvi Kivity { 5787d36db35SAvi Kivity /* encode near jmp manually. gas will not do it if offsets < 127 byte */ 5797d36db35SAvi Kivity MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t" 5807d36db35SAvi Kivity "mov $0x1234, %eax\n\t"); 5817d36db35SAvi Kivity MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t" 5827d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5837d36db35SAvi Kivity ".byte 0x0f, 0x85, 0xf0, 0xff\n\t"); 5847d36db35SAvi Kivity MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t" 5857d36db35SAvi Kivity "mov $0x1234, %eax\n\t"); 5867d36db35SAvi Kivity 58718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 5887d36db35SAvi Kivity 58918253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_near1); 5906055ea1fSAvi Kivity report("jnz near 1", 0, 1); 59118253fdeSAvi Kivity 59218253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_near2); 5936055ea1fSAvi Kivity report("jnz near 2", R_AX, outregs.eflags & (1 << 6)); 5947d36db35SAvi Kivity 59518253fdeSAvi Kivity exec_in_big_real_mode(&insn_jmp_near1); 5966055ea1fSAvi Kivity report("jmp near 1", 0, 1); 5977d36db35SAvi Kivity } 5987d36db35SAvi Kivity 5997d36db35SAvi Kivity void test_long_jmp() 6007d36db35SAvi Kivity { 6017d36db35SAvi Kivity u32 esp[16]; 6027d36db35SAvi Kivity 60318253fdeSAvi Kivity inregs = (struct regs){ 0 }; 6044aa22949SAvi Kivity inregs.esp = (u32)(esp+16); 6057d36db35SAvi Kivity MK_INSN(long_jmp, "call 1f\n\t" 6067d36db35SAvi Kivity "jmp 2f\n\t" 6077d36db35SAvi Kivity "1: jmp $0, $test_function\n\t" 6087d36db35SAvi Kivity "2:\n\t"); 60918253fdeSAvi Kivity exec_in_big_real_mode(&insn_long_jmp); 6106055ea1fSAvi Kivity report("jmp far 1", R_AX, outregs.eax == 0x1234); 6117d36db35SAvi Kivity } 612fa74f8a6SMohammed Gamal 6137d36db35SAvi Kivity void test_push_pop() 6147d36db35SAvi Kivity { 6157d36db35SAvi Kivity MK_INSN(push32, "mov $0x12345678, %eax\n\t" 6167d36db35SAvi Kivity "push %eax\n\t" 6177d36db35SAvi Kivity "pop %ebx\n\t"); 6187d36db35SAvi Kivity MK_INSN(push16, "mov $0x1234, %ax\n\t" 6197d36db35SAvi Kivity "push %ax\n\t" 6207d36db35SAvi Kivity "pop %bx\n\t"); 6217d36db35SAvi Kivity 6227d36db35SAvi Kivity MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten 6237d36db35SAvi Kivity "mov $0x123, %ax\n\t" 6247d36db35SAvi Kivity "mov %ax, %es\n\t" 6257d36db35SAvi Kivity "push %es\n\t" 6267d36db35SAvi Kivity "pop %bx \n\t" 6277d36db35SAvi Kivity ); 6287d36db35SAvi Kivity MK_INSN(pop_es, "push %ax\n\t" 6297d36db35SAvi Kivity "pop %es\n\t" 6307d36db35SAvi Kivity "mov %es, %bx\n\t" 6317d36db35SAvi Kivity ); 6327d36db35SAvi Kivity MK_INSN(push_pop_ss, "push %ss\n\t" 6337d36db35SAvi Kivity "pushw %ax\n\t" 6347d36db35SAvi Kivity "popw %ss\n\t" 6357d36db35SAvi Kivity "mov %ss, %bx\n\t" 6367d36db35SAvi Kivity "pop %ss\n\t" 6377d36db35SAvi Kivity ); 6387d36db35SAvi Kivity MK_INSN(push_pop_fs, "push %fs\n\t" 6397d36db35SAvi Kivity "pushl %eax\n\t" 6407d36db35SAvi Kivity "popl %fs\n\t" 6417d36db35SAvi Kivity "mov %fs, %ebx\n\t" 6427d36db35SAvi Kivity "pop %fs\n\t" 6437d36db35SAvi Kivity ); 64409b657b6SAvi Kivity MK_INSN(push_pop_high_esp_bits, 64509b657b6SAvi Kivity "xor $0x12340000, %esp \n\t" 64609b657b6SAvi Kivity "push %ax; \n\t" 64709b657b6SAvi Kivity "xor $0x12340000, %esp \n\t" 64809b657b6SAvi Kivity "pop %bx"); 6497d36db35SAvi Kivity 65018253fdeSAvi Kivity inregs = (struct regs){ 0 }; 65118253fdeSAvi Kivity 65218253fdeSAvi Kivity exec_in_big_real_mode(&insn_push32); 6536055ea1fSAvi Kivity report("push/pop 1", R_AX|R_BX, 6546055ea1fSAvi Kivity outregs.eax == outregs.ebx && outregs.eax == 0x12345678); 6557d36db35SAvi Kivity 65618253fdeSAvi Kivity exec_in_big_real_mode(&insn_push16); 6576055ea1fSAvi Kivity report("push/pop 2", R_AX|R_BX, 6586055ea1fSAvi Kivity outregs.eax == outregs.ebx && outregs.eax == 0x1234); 6597d36db35SAvi Kivity 66018253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_es); 6616055ea1fSAvi Kivity report("push/pop 3", R_AX|R_BX, 6626055ea1fSAvi Kivity outregs.ebx == outregs.eax && outregs.eax == 0x123); 6637d36db35SAvi Kivity 66418253fdeSAvi Kivity exec_in_big_real_mode(&insn_pop_es); 6656055ea1fSAvi Kivity report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax); 6667d36db35SAvi Kivity 66718253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_pop_ss); 6686055ea1fSAvi Kivity report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax); 6697d36db35SAvi Kivity 67018253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_pop_fs); 6716055ea1fSAvi Kivity report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax); 67209b657b6SAvi Kivity 67309b657b6SAvi Kivity inregs.eax = 0x9977; 67409b657b6SAvi Kivity inregs.ebx = 0x7799; 67509b657b6SAvi Kivity exec_in_big_real_mode(&insn_push_pop_high_esp_bits); 67609b657b6SAvi Kivity report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977); 6777d36db35SAvi Kivity } 6787d36db35SAvi Kivity 6797d36db35SAvi Kivity void test_null(void) 6807d36db35SAvi Kivity { 681d4dc402cSAvi Kivity MK_INSN(null, ""); 682d4dc402cSAvi Kivity 68318253fdeSAvi Kivity inregs = (struct regs){ 0 }; 68418253fdeSAvi Kivity 68518253fdeSAvi Kivity exec_in_big_real_mode(&insn_null); 6866055ea1fSAvi Kivity report("null", 0, 1); 6877d36db35SAvi Kivity } 6887d36db35SAvi Kivity 6897d36db35SAvi Kivity struct { 6907d36db35SAvi Kivity char stack[500]; 6917d36db35SAvi Kivity char top[]; 6927d36db35SAvi Kivity } tmp_stack; 6937d36db35SAvi Kivity 6947d36db35SAvi Kivity void test_pusha_popa() 6957d36db35SAvi Kivity { 6967d36db35SAvi Kivity MK_INSN(pusha, "pusha\n\t" 6977d36db35SAvi Kivity "pop %edi\n\t" 6987d36db35SAvi Kivity "pop %esi\n\t" 6997d36db35SAvi Kivity "pop %ebp\n\t" 7007d36db35SAvi Kivity "add $4, %esp\n\t" 7017d36db35SAvi Kivity "pop %ebx\n\t" 7027d36db35SAvi Kivity "pop %edx\n\t" 7037d36db35SAvi Kivity "pop %ecx\n\t" 7047d36db35SAvi Kivity "pop %eax\n\t" 7057d36db35SAvi Kivity ); 7067d36db35SAvi Kivity 7077d36db35SAvi Kivity MK_INSN(popa, "push %eax\n\t" 7087d36db35SAvi Kivity "push %ecx\n\t" 7097d36db35SAvi Kivity "push %edx\n\t" 7107d36db35SAvi Kivity "push %ebx\n\t" 7117d36db35SAvi Kivity "push %esp\n\t" 7127d36db35SAvi Kivity "push %ebp\n\t" 7137d36db35SAvi Kivity "push %esi\n\t" 7147d36db35SAvi Kivity "push %edi\n\t" 7157d36db35SAvi Kivity "popa\n\t" 7167d36db35SAvi Kivity ); 7177d36db35SAvi Kivity 71818253fdeSAvi Kivity inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top }; 7197d36db35SAvi Kivity 72018253fdeSAvi Kivity exec_in_big_real_mode(&insn_pusha); 7216055ea1fSAvi Kivity report("pusha/popa 1", 0, 1); 72218253fdeSAvi Kivity 72318253fdeSAvi Kivity exec_in_big_real_mode(&insn_popa); 7246055ea1fSAvi Kivity report("pusha/popa 1", 0, 1); 7257d36db35SAvi Kivity } 7267d36db35SAvi Kivity 7277d36db35SAvi Kivity void test_iret() 7287d36db35SAvi Kivity { 7297d36db35SAvi Kivity MK_INSN(iret32, "pushf\n\t" 7307d36db35SAvi Kivity "pushl %cs\n\t" 7317d36db35SAvi Kivity "call 1f\n\t" /* a near call will push eip onto the stack */ 7327d36db35SAvi Kivity "jmp 2f\n\t" 7337d36db35SAvi Kivity "1: iret\n\t" 7347d36db35SAvi Kivity "2:\n\t" 7357d36db35SAvi Kivity ); 7367d36db35SAvi Kivity 7377d36db35SAvi Kivity MK_INSN(iret16, "pushfw\n\t" 7387d36db35SAvi Kivity "pushw %cs\n\t" 7397d36db35SAvi Kivity "callw 1f\n\t" 7407d36db35SAvi Kivity "jmp 2f\n\t" 7417d36db35SAvi Kivity "1: iretw\n\t" 7427d36db35SAvi Kivity "2:\n\t"); 7437d36db35SAvi Kivity 7447d36db35SAvi Kivity MK_INSN(iret_flags32, "pushfl\n\t" 7457d36db35SAvi Kivity "popl %eax\n\t" 7467d36db35SAvi Kivity "andl $~0x2, %eax\n\t" 747*964942e8SNadav Amit "orl $0xffc18028, %eax\n\t" 7487d36db35SAvi Kivity "pushl %eax\n\t" 7497d36db35SAvi Kivity "pushl %cs\n\t" 7507d36db35SAvi Kivity "call 1f\n\t" 7517d36db35SAvi Kivity "jmp 2f\n\t" 7527d36db35SAvi Kivity "1: iret\n\t" 7537d36db35SAvi Kivity "2:\n\t"); 7547d36db35SAvi Kivity 7557d36db35SAvi Kivity MK_INSN(iret_flags16, "pushfw\n\t" 7567d36db35SAvi Kivity "popw %ax\n\t" 7577d36db35SAvi Kivity "and $~0x2, %ax\n\t" 7587d36db35SAvi Kivity "or $0x8028, %ax\n\t" 7597d36db35SAvi Kivity "pushw %ax\n\t" 7607d36db35SAvi Kivity "pushw %cs\n\t" 7617d36db35SAvi Kivity "callw 1f\n\t" 7627d36db35SAvi Kivity "jmp 2f\n\t" 7637d36db35SAvi Kivity "1: iretw\n\t" 7647d36db35SAvi Kivity "2:\n\t"); 7657d36db35SAvi Kivity 76618253fdeSAvi Kivity inregs = (struct regs){ 0 }; 7677d36db35SAvi Kivity 76818253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret32); 7696055ea1fSAvi Kivity report("iret 1", 0, 1); 7707d36db35SAvi Kivity 77118253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret16); 7726055ea1fSAvi Kivity report("iret 2", 0, 1); 7737d36db35SAvi Kivity 77418253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret_flags32); 7756055ea1fSAvi Kivity report("iret 3", R_AX, 1); 776*964942e8SNadav Amit report("rflags.rf", ~0, !(outregs.eflags & (1 << 16))); 77718253fdeSAvi Kivity 77818253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret_flags16); 7796055ea1fSAvi Kivity report("iret 4", R_AX, 1); 7807d36db35SAvi Kivity } 7817d36db35SAvi Kivity 78296b9ca1eSMohammed Gamal void test_int() 78396b9ca1eSMohammed Gamal { 78418253fdeSAvi Kivity inregs = (struct regs){ 0 }; 78596b9ca1eSMohammed Gamal 78696b9ca1eSMohammed Gamal *(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */ 78796b9ca1eSMohammed Gamal *(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */ 78896b9ca1eSMohammed Gamal 78996b9ca1eSMohammed Gamal MK_INSN(int11, "int $0x11\n\t"); 79096b9ca1eSMohammed Gamal 79118253fdeSAvi Kivity exec_in_big_real_mode(&insn_int11); 7926055ea1fSAvi Kivity report("int 1", 0, 1); 79396b9ca1eSMohammed Gamal } 79496b9ca1eSMohammed Gamal 795fa74f8a6SMohammed Gamal void test_imul() 796fa74f8a6SMohammed Gamal { 797fa74f8a6SMohammed Gamal MK_INSN(imul8_1, "mov $2, %al\n\t" 798fa74f8a6SMohammed Gamal "mov $-4, %cx\n\t" 799fa74f8a6SMohammed Gamal "imul %cl\n\t"); 800fa74f8a6SMohammed Gamal 801fa74f8a6SMohammed Gamal MK_INSN(imul16_1, "mov $2, %ax\n\t" 802fa74f8a6SMohammed Gamal "mov $-4, %cx\n\t" 803fa74f8a6SMohammed Gamal "imul %cx\n\t"); 804fa74f8a6SMohammed Gamal 805fa74f8a6SMohammed Gamal MK_INSN(imul32_1, "mov $2, %eax\n\t" 806fa74f8a6SMohammed Gamal "mov $-4, %ecx\n\t" 807fa74f8a6SMohammed Gamal "imul %ecx\n\t"); 808fa74f8a6SMohammed Gamal 809fa74f8a6SMohammed Gamal MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t" 810fa74f8a6SMohammed Gamal "mov $4, %cx\n\t" 811fa74f8a6SMohammed Gamal "imul %cl\n\t"); 812fa74f8a6SMohammed Gamal 813fa74f8a6SMohammed Gamal MK_INSN(imul16_2, "mov $2, %ax\n\t" 814fa74f8a6SMohammed Gamal "mov $4, %cx\n\t" 815fa74f8a6SMohammed Gamal "imul %cx\n\t"); 816fa74f8a6SMohammed Gamal 817fa74f8a6SMohammed Gamal MK_INSN(imul32_2, "mov $2, %eax\n\t" 818fa74f8a6SMohammed Gamal "mov $4, %ecx\n\t" 819fa74f8a6SMohammed Gamal "imul %ecx\n\t"); 820fa74f8a6SMohammed Gamal 82118253fdeSAvi Kivity inregs = (struct regs){ 0 }; 82218253fdeSAvi Kivity 82318253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul8_1); 8246055ea1fSAvi Kivity report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8); 825fa74f8a6SMohammed Gamal 82618253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul16_1); 8276055ea1fSAvi Kivity report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8); 828fa74f8a6SMohammed Gamal 82918253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul32_1); 8306055ea1fSAvi Kivity report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8); 831fa74f8a6SMohammed Gamal 83218253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul8_2); 8336055ea1fSAvi Kivity report("imul 4", R_AX | R_CX | R_DX, 8346055ea1fSAvi Kivity (outregs.eax & 0xffff) == 8 83581050840SAvi Kivity && (outregs.eax & 0xffff0000) == 0x12340000); 836fa74f8a6SMohammed Gamal 83718253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul16_2); 8386055ea1fSAvi Kivity report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8); 839fa74f8a6SMohammed Gamal 84018253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul32_2); 8416055ea1fSAvi Kivity report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8); 842fa74f8a6SMohammed Gamal } 843fa74f8a6SMohammed Gamal 84459317bd1SMohammed Gamal void test_mul() 84559317bd1SMohammed Gamal { 84659317bd1SMohammed Gamal MK_INSN(mul8, "mov $2, %al\n\t" 84759317bd1SMohammed Gamal "mov $4, %cx\n\t" 84859317bd1SMohammed Gamal "imul %cl\n\t"); 84959317bd1SMohammed Gamal 85059317bd1SMohammed Gamal MK_INSN(mul16, "mov $2, %ax\n\t" 85159317bd1SMohammed Gamal "mov $4, %cx\n\t" 85259317bd1SMohammed Gamal "imul %cx\n\t"); 85359317bd1SMohammed Gamal 85459317bd1SMohammed Gamal MK_INSN(mul32, "mov $2, %eax\n\t" 85559317bd1SMohammed Gamal "mov $4, %ecx\n\t" 85659317bd1SMohammed Gamal "imul %ecx\n\t"); 85759317bd1SMohammed Gamal 85818253fdeSAvi Kivity inregs = (struct regs){ 0 }; 85918253fdeSAvi Kivity 86018253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul8); 8616055ea1fSAvi Kivity report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8); 86259317bd1SMohammed Gamal 86318253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul16); 8646055ea1fSAvi Kivity report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8); 86559317bd1SMohammed Gamal 86618253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul32); 8676055ea1fSAvi Kivity report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8); 86859317bd1SMohammed Gamal } 86959317bd1SMohammed Gamal 8700d4c7614SMohammed Gamal void test_div() 8710d4c7614SMohammed Gamal { 8720d4c7614SMohammed Gamal MK_INSN(div8, "mov $257, %ax\n\t" 8730d4c7614SMohammed Gamal "mov $2, %cl\n\t" 8740d4c7614SMohammed Gamal "div %cl\n\t"); 8750d4c7614SMohammed Gamal 8760d4c7614SMohammed Gamal MK_INSN(div16, "mov $512, %ax\n\t" 8770d4c7614SMohammed Gamal "mov $5, %cx\n\t" 8780d4c7614SMohammed Gamal "div %cx\n\t"); 8790d4c7614SMohammed Gamal 8800d4c7614SMohammed Gamal MK_INSN(div32, "mov $512, %eax\n\t" 8810d4c7614SMohammed Gamal "mov $5, %ecx\n\t" 8820d4c7614SMohammed Gamal "div %ecx\n\t"); 8830d4c7614SMohammed Gamal 88418253fdeSAvi Kivity inregs = (struct regs){ 0 }; 88518253fdeSAvi Kivity 88618253fdeSAvi Kivity exec_in_big_real_mode(&insn_div8); 8876055ea1fSAvi Kivity report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384); 8880d4c7614SMohammed Gamal 88918253fdeSAvi Kivity exec_in_big_real_mode(&insn_div16); 8906055ea1fSAvi Kivity report("div 2", R_AX | R_CX | R_DX, 8916055ea1fSAvi Kivity outregs.eax == 102 && outregs.edx == 2); 8920d4c7614SMohammed Gamal 89318253fdeSAvi Kivity exec_in_big_real_mode(&insn_div32); 8946055ea1fSAvi Kivity report("div 3", R_AX | R_CX | R_DX, 8956055ea1fSAvi Kivity outregs.eax == 102 && outregs.edx == 2); 8960d4c7614SMohammed Gamal } 8970d4c7614SMohammed Gamal 8980d4c7614SMohammed Gamal void test_idiv() 8990d4c7614SMohammed Gamal { 9000d4c7614SMohammed Gamal MK_INSN(idiv8, "mov $256, %ax\n\t" 9010d4c7614SMohammed Gamal "mov $-2, %cl\n\t" 9020d4c7614SMohammed Gamal "idiv %cl\n\t"); 9030d4c7614SMohammed Gamal 9040d4c7614SMohammed Gamal MK_INSN(idiv16, "mov $512, %ax\n\t" 9050d4c7614SMohammed Gamal "mov $-2, %cx\n\t" 9060d4c7614SMohammed Gamal "idiv %cx\n\t"); 9070d4c7614SMohammed Gamal 9080d4c7614SMohammed Gamal MK_INSN(idiv32, "mov $512, %eax\n\t" 9090d4c7614SMohammed Gamal "mov $-2, %ecx\n\t" 9100d4c7614SMohammed Gamal "idiv %ecx\n\t"); 9110d4c7614SMohammed Gamal 91218253fdeSAvi Kivity inregs = (struct regs){ 0 }; 91318253fdeSAvi Kivity 91418253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv8); 9156055ea1fSAvi Kivity report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128); 9160d4c7614SMohammed Gamal 91718253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv16); 9186055ea1fSAvi Kivity report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256); 9190d4c7614SMohammed Gamal 92018253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv32); 9216055ea1fSAvi Kivity report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256); 9220d4c7614SMohammed Gamal } 9230d4c7614SMohammed Gamal 9246e293cf5SWei Yongjun void test_cbw(void) 9256e293cf5SWei Yongjun { 9266e293cf5SWei Yongjun MK_INSN(cbw, "mov $0xFE, %eax \n\t" 9276e293cf5SWei Yongjun "cbw\n\t"); 9286e293cf5SWei Yongjun MK_INSN(cwde, "mov $0xFFFE, %eax \n\t" 9296e293cf5SWei Yongjun "cwde\n\t"); 9306e293cf5SWei Yongjun 93118253fdeSAvi Kivity inregs = (struct regs){ 0 }; 93218253fdeSAvi Kivity 93318253fdeSAvi Kivity exec_in_big_real_mode(&insn_cbw); 9346055ea1fSAvi Kivity report("cbq 1", ~0, outregs.eax == 0xFFFE); 9356e293cf5SWei Yongjun 93618253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwde); 9376055ea1fSAvi Kivity report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE); 9386e293cf5SWei Yongjun } 9396e293cf5SWei Yongjun 940eacef4e2SWei Yongjun void test_loopcc(void) 941eacef4e2SWei Yongjun { 942eacef4e2SWei Yongjun MK_INSN(loop, "mov $10, %ecx\n\t" 943eacef4e2SWei Yongjun "1: inc %eax\n\t" 944eacef4e2SWei Yongjun "loop 1b\n\t"); 945eacef4e2SWei Yongjun 946eacef4e2SWei Yongjun MK_INSN(loope, "mov $10, %ecx\n\t" 947eacef4e2SWei Yongjun "mov $1, %eax\n\t" 948eacef4e2SWei Yongjun "1: dec %eax\n\t" 949eacef4e2SWei Yongjun "loope 1b\n\t"); 950eacef4e2SWei Yongjun 951eacef4e2SWei Yongjun MK_INSN(loopne, "mov $10, %ecx\n\t" 952eacef4e2SWei Yongjun "mov $5, %eax\n\t" 953eacef4e2SWei Yongjun "1: dec %eax\n\t" 954eacef4e2SWei Yongjun "loopne 1b\n\t"); 955eacef4e2SWei Yongjun 95618253fdeSAvi Kivity inregs = (struct regs){ 0 }; 957eacef4e2SWei Yongjun 95818253fdeSAvi Kivity exec_in_big_real_mode(&insn_loop); 9596055ea1fSAvi Kivity report("LOOPcc short 1", R_AX, outregs.eax == 10); 96018253fdeSAvi Kivity 96118253fdeSAvi Kivity exec_in_big_real_mode(&insn_loope); 9626055ea1fSAvi Kivity report("LOOPcc short 2", R_AX | R_CX, 9636055ea1fSAvi Kivity outregs.eax == -1 && outregs.ecx == 8); 964eacef4e2SWei Yongjun 96518253fdeSAvi Kivity exec_in_big_real_mode(&insn_loopne); 9666055ea1fSAvi Kivity report("LOOPcc short 3", R_AX | R_CX, 9676055ea1fSAvi Kivity outregs.eax == 0 && outregs.ecx == 5); 968eacef4e2SWei Yongjun } 969eacef4e2SWei Yongjun 970b274feedSAvi Kivity static void test_das(void) 971b274feedSAvi Kivity { 972b274feedSAvi Kivity short i; 97381050840SAvi Kivity u16 nr_fail = 0; 974b274feedSAvi Kivity static unsigned test_cases[1024] = { 975b274feedSAvi Kivity 0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00, 976b274feedSAvi Kivity 0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01, 977b274feedSAvi Kivity 0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02, 978b274feedSAvi Kivity 0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03, 979b274feedSAvi Kivity 0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04, 980b274feedSAvi Kivity 0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05, 981b274feedSAvi Kivity 0x06000606, 0x8701a606, 0x56100006, 0x9711a006, 982b274feedSAvi Kivity 0x02000707, 0x8301a707, 0x12100107, 0x9311a107, 983b274feedSAvi Kivity 0x02000808, 0x8301a808, 0x12100208, 0x9311a208, 984b274feedSAvi Kivity 0x06000909, 0x8701a909, 0x16100309, 0x9711a309, 985b274feedSAvi Kivity 0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a, 986b274feedSAvi Kivity 0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b, 987b274feedSAvi Kivity 0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c, 988b274feedSAvi Kivity 0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d, 989b274feedSAvi Kivity 0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e, 990b274feedSAvi Kivity 0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f, 991b274feedSAvi Kivity 0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10, 992b274feedSAvi Kivity 0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11, 993b274feedSAvi Kivity 0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12, 994b274feedSAvi Kivity 0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13, 995b274feedSAvi Kivity 0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14, 996b274feedSAvi Kivity 0x02001515, 0x8301b515, 0x16100f15, 0x9711af15, 997b274feedSAvi Kivity 0x02001616, 0x8301b616, 0x12101016, 0x9311b016, 998b274feedSAvi Kivity 0x06001717, 0x8701b717, 0x16101117, 0x9711b117, 999b274feedSAvi Kivity 0x06001818, 0x8701b818, 0x16101218, 0x9711b218, 1000b274feedSAvi Kivity 0x02001919, 0x8301b919, 0x12101319, 0x9311b319, 1001b274feedSAvi Kivity 0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a, 1002b274feedSAvi Kivity 0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b, 1003b274feedSAvi Kivity 0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c, 1004b274feedSAvi Kivity 0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d, 1005b274feedSAvi Kivity 0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e, 1006b274feedSAvi Kivity 0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f, 1007b274feedSAvi Kivity 0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20, 1008b274feedSAvi Kivity 0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21, 1009b274feedSAvi Kivity 0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22, 1010b274feedSAvi Kivity 0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23, 1011b274feedSAvi Kivity 0x06002424, 0x8301c424, 0x16101e24, 0x9711be24, 1012b274feedSAvi Kivity 0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25, 1013b274feedSAvi Kivity 0x02002626, 0x8701c626, 0x12102026, 0x9711c026, 1014b274feedSAvi Kivity 0x06002727, 0x8301c727, 0x16102127, 0x9311c127, 1015b274feedSAvi Kivity 0x06002828, 0x8301c828, 0x16102228, 0x9311c228, 1016b274feedSAvi Kivity 0x02002929, 0x8701c929, 0x12102329, 0x9711c329, 1017b274feedSAvi Kivity 0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a, 1018b274feedSAvi Kivity 0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b, 1019b274feedSAvi Kivity 0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c, 1020b274feedSAvi Kivity 0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d, 1021b274feedSAvi Kivity 0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e, 1022b274feedSAvi Kivity 0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f, 1023b274feedSAvi Kivity 0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30, 1024b274feedSAvi Kivity 0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31, 1025b274feedSAvi Kivity 0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32, 1026b274feedSAvi Kivity 0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33, 1027b274feedSAvi Kivity 0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34, 1028b274feedSAvi Kivity 0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35, 1029b274feedSAvi Kivity 0x06003636, 0x8301d636, 0x16103036, 0x9311d036, 1030b274feedSAvi Kivity 0x02003737, 0x8701d737, 0x12103137, 0x9711d137, 1031b274feedSAvi Kivity 0x02003838, 0x8701d838, 0x12103238, 0x9711d238, 1032b274feedSAvi Kivity 0x06003939, 0x8301d939, 0x16103339, 0x9311d339, 1033b274feedSAvi Kivity 0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a, 1034b274feedSAvi Kivity 0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b, 1035b274feedSAvi Kivity 0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c, 1036b274feedSAvi Kivity 0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d, 1037b274feedSAvi Kivity 0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e, 1038b274feedSAvi Kivity 0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f, 1039b274feedSAvi Kivity 0x02004040, 0x8301e040, 0x16103a40, 0x9311da40, 1040b274feedSAvi Kivity 0x06004141, 0x8701e141, 0x12103b41, 0x9711db41, 1041b274feedSAvi Kivity 0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42, 1042b274feedSAvi Kivity 0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43, 1043b274feedSAvi Kivity 0x06004444, 0x8701e444, 0x12103e44, 0x9711de44, 1044b274feedSAvi Kivity 0x02004545, 0x8301e545, 0x16103f45, 0x9311df45, 1045b274feedSAvi Kivity 0x02004646, 0x8301e646, 0x12104046, 0x9311e046, 1046b274feedSAvi Kivity 0x06004747, 0x8701e747, 0x16104147, 0x9711e147, 1047b274feedSAvi Kivity 0x06004848, 0x8701e848, 0x16104248, 0x9711e248, 1048b274feedSAvi Kivity 0x02004949, 0x8301e949, 0x12104349, 0x9311e349, 1049b274feedSAvi Kivity 0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a, 1050b274feedSAvi Kivity 0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b, 1051b274feedSAvi Kivity 0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c, 1052b274feedSAvi Kivity 0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d, 1053b274feedSAvi Kivity 0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e, 1054b274feedSAvi Kivity 0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f, 1055b274feedSAvi Kivity 0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50, 1056b274feedSAvi Kivity 0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51, 1057b274feedSAvi Kivity 0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52, 1058b274feedSAvi Kivity 0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53, 1059b274feedSAvi Kivity 0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54, 1060b274feedSAvi Kivity 0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55, 1061b274feedSAvi Kivity 0x06005656, 0x8701f656, 0x16105056, 0x9711f056, 1062b274feedSAvi Kivity 0x02005757, 0x8301f757, 0x12105157, 0x9311f157, 1063b274feedSAvi Kivity 0x02005858, 0x8301f858, 0x12105258, 0x9311f258, 1064b274feedSAvi Kivity 0x06005959, 0x8701f959, 0x16105359, 0x9711f359, 1065b274feedSAvi Kivity 0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a, 1066b274feedSAvi Kivity 0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b, 1067b274feedSAvi Kivity 0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c, 1068b274feedSAvi Kivity 0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d, 1069b274feedSAvi Kivity 0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e, 1070b274feedSAvi Kivity 0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f, 1071b274feedSAvi Kivity 0x06006060, 0x47010060, 0x16105a60, 0x9711fa60, 1072b274feedSAvi Kivity 0x02006161, 0x03010161, 0x12105b61, 0x9311fb61, 1073b274feedSAvi Kivity 0x02006262, 0x03010262, 0x16105c62, 0x9711fc62, 1074b274feedSAvi Kivity 0x06006363, 0x07010363, 0x12105d63, 0x9311fd63, 1075b274feedSAvi Kivity 0x02006464, 0x03010464, 0x12105e64, 0x9311fe64, 1076b274feedSAvi Kivity 0x06006565, 0x07010565, 0x16105f65, 0x9711ff65, 1077b274feedSAvi Kivity 0x06006666, 0x07010666, 0x16106066, 0x57110066, 1078b274feedSAvi Kivity 0x02006767, 0x03010767, 0x12106167, 0x13110167, 1079b274feedSAvi Kivity 0x02006868, 0x03010868, 0x12106268, 0x13110268, 1080b274feedSAvi Kivity 0x06006969, 0x07010969, 0x16106369, 0x17110369, 1081b274feedSAvi Kivity 0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a, 1082b274feedSAvi Kivity 0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b, 1083b274feedSAvi Kivity 0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c, 1084b274feedSAvi Kivity 0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d, 1085b274feedSAvi Kivity 0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e, 1086b274feedSAvi Kivity 0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f, 1087b274feedSAvi Kivity 0x02007070, 0x03011070, 0x16106a70, 0x17110a70, 1088b274feedSAvi Kivity 0x06007171, 0x07011171, 0x12106b71, 0x13110b71, 1089b274feedSAvi Kivity 0x06007272, 0x07011272, 0x16106c72, 0x17110c72, 1090b274feedSAvi Kivity 0x02007373, 0x03011373, 0x12106d73, 0x13110d73, 1091b274feedSAvi Kivity 0x06007474, 0x07011474, 0x12106e74, 0x13110e74, 1092b274feedSAvi Kivity 0x02007575, 0x03011575, 0x16106f75, 0x17110f75, 1093b274feedSAvi Kivity 0x02007676, 0x03011676, 0x12107076, 0x13111076, 1094b274feedSAvi Kivity 0x06007777, 0x07011777, 0x16107177, 0x17111177, 1095b274feedSAvi Kivity 0x06007878, 0x07011878, 0x16107278, 0x17111278, 1096b274feedSAvi Kivity 0x02007979, 0x03011979, 0x12107379, 0x13111379, 1097b274feedSAvi Kivity 0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a, 1098b274feedSAvi Kivity 0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b, 1099b274feedSAvi Kivity 0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c, 1100b274feedSAvi Kivity 0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d, 1101b274feedSAvi Kivity 0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e, 1102b274feedSAvi Kivity 0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f, 1103b274feedSAvi Kivity 0x82008080, 0x03012080, 0x12107a80, 0x13111a80, 1104b274feedSAvi Kivity 0x86008181, 0x07012181, 0x16107b81, 0x17111b81, 1105b274feedSAvi Kivity 0x86008282, 0x07012282, 0x12107c82, 0x13111c82, 1106b274feedSAvi Kivity 0x82008383, 0x03012383, 0x16107d83, 0x17111d83, 1107b274feedSAvi Kivity 0x86008484, 0x07012484, 0x16107e84, 0x17111e84, 1108b274feedSAvi Kivity 0x82008585, 0x03012585, 0x12107f85, 0x13111f85, 1109b274feedSAvi Kivity 0x82008686, 0x03012686, 0x92108086, 0x13112086, 1110b274feedSAvi Kivity 0x86008787, 0x07012787, 0x96108187, 0x17112187, 1111b274feedSAvi Kivity 0x86008888, 0x07012888, 0x96108288, 0x17112288, 1112b274feedSAvi Kivity 0x82008989, 0x03012989, 0x92108389, 0x13112389, 1113b274feedSAvi Kivity 0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a, 1114b274feedSAvi Kivity 0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b, 1115b274feedSAvi Kivity 0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c, 1116b274feedSAvi Kivity 0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d, 1117b274feedSAvi Kivity 0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e, 1118b274feedSAvi Kivity 0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f, 1119b274feedSAvi Kivity 0x86009090, 0x07013090, 0x92108a90, 0x13112a90, 1120b274feedSAvi Kivity 0x82009191, 0x03013191, 0x96108b91, 0x17112b91, 1121b274feedSAvi Kivity 0x82009292, 0x03013292, 0x92108c92, 0x13112c92, 1122b274feedSAvi Kivity 0x86009393, 0x07013393, 0x96108d93, 0x17112d93, 1123b274feedSAvi Kivity 0x82009494, 0x03013494, 0x96108e94, 0x17112e94, 1124b274feedSAvi Kivity 0x86009595, 0x07013595, 0x92108f95, 0x13112f95, 1125b274feedSAvi Kivity 0x86009696, 0x07013696, 0x96109096, 0x17113096, 1126b274feedSAvi Kivity 0x82009797, 0x03013797, 0x92109197, 0x13113197, 1127b274feedSAvi Kivity 0x82009898, 0x03013898, 0x92109298, 0x13113298, 1128b274feedSAvi Kivity 0x86009999, 0x07013999, 0x96109399, 0x17113399, 1129b274feedSAvi Kivity 0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a, 1130b274feedSAvi Kivity 0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b, 1131b274feedSAvi Kivity 0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c, 1132b274feedSAvi Kivity 0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d, 1133b274feedSAvi Kivity 0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e, 1134b274feedSAvi Kivity 0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f, 1135b274feedSAvi Kivity 0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0, 1136b274feedSAvi Kivity 0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1, 1137b274feedSAvi Kivity 0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2, 1138b274feedSAvi Kivity 0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3, 1139b274feedSAvi Kivity 0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4, 1140b274feedSAvi Kivity 0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5, 1141b274feedSAvi Kivity 0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6, 1142b274feedSAvi Kivity 0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7, 1143b274feedSAvi Kivity 0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8, 1144b274feedSAvi Kivity 0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9, 1145b274feedSAvi Kivity 0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa, 1146b274feedSAvi Kivity 0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab, 1147b274feedSAvi Kivity 0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac, 1148b274feedSAvi Kivity 0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad, 1149b274feedSAvi Kivity 0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae, 1150b274feedSAvi Kivity 0x130049af, 0x130149af, 0x131049af, 0x131149af, 1151b274feedSAvi Kivity 0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0, 1152b274feedSAvi Kivity 0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1, 1153b274feedSAvi Kivity 0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2, 1154b274feedSAvi Kivity 0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3, 1155b274feedSAvi Kivity 0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4, 1156b274feedSAvi Kivity 0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5, 1157b274feedSAvi Kivity 0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6, 1158b274feedSAvi Kivity 0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7, 1159b274feedSAvi Kivity 0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8, 1160b274feedSAvi Kivity 0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9, 1161b274feedSAvi Kivity 0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba, 1162b274feedSAvi Kivity 0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb, 1163b274feedSAvi Kivity 0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc, 1164b274feedSAvi Kivity 0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd, 1165b274feedSAvi Kivity 0x130058be, 0x130158be, 0x131058be, 0x131158be, 1166b274feedSAvi Kivity 0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf, 1167b274feedSAvi Kivity 0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0, 1168b274feedSAvi Kivity 0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1, 1169b274feedSAvi Kivity 0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2, 1170b274feedSAvi Kivity 0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3, 1171b274feedSAvi Kivity 0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4, 1172b274feedSAvi Kivity 0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5, 1173b274feedSAvi Kivity 0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6, 1174b274feedSAvi Kivity 0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7, 1175b274feedSAvi Kivity 0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8, 1176b274feedSAvi Kivity 0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9, 1177b274feedSAvi Kivity 0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca, 1178b274feedSAvi Kivity 0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb, 1179b274feedSAvi Kivity 0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc, 1180b274feedSAvi Kivity 0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd, 1181b274feedSAvi Kivity 0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce, 1182b274feedSAvi Kivity 0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf, 1183b274feedSAvi Kivity 0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0, 1184b274feedSAvi Kivity 0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1, 1185b274feedSAvi Kivity 0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2, 1186b274feedSAvi Kivity 0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3, 1187b274feedSAvi Kivity 0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4, 1188b274feedSAvi Kivity 0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5, 1189b274feedSAvi Kivity 0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6, 1190b274feedSAvi Kivity 0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7, 1191b274feedSAvi Kivity 0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8, 1192b274feedSAvi Kivity 0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9, 1193b274feedSAvi Kivity 0x170074da, 0x170174da, 0x171074da, 0x171174da, 1194b274feedSAvi Kivity 0x130075db, 0x130175db, 0x131075db, 0x131175db, 1195b274feedSAvi Kivity 0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc, 1196b274feedSAvi Kivity 0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd, 1197b274feedSAvi Kivity 0x170078de, 0x170178de, 0x171078de, 0x171178de, 1198b274feedSAvi Kivity 0x130079df, 0x130179df, 0x131079df, 0x131179df, 1199b274feedSAvi Kivity 0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0, 1200b274feedSAvi Kivity 0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1, 1201b274feedSAvi Kivity 0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2, 1202b274feedSAvi Kivity 0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3, 1203b274feedSAvi Kivity 0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4, 1204b274feedSAvi Kivity 0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5, 1205b274feedSAvi Kivity 0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6, 1206b274feedSAvi Kivity 0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7, 1207b274feedSAvi Kivity 0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8, 1208b274feedSAvi Kivity 0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9, 1209b274feedSAvi Kivity 0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea, 1210b274feedSAvi Kivity 0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb, 1211b274feedSAvi Kivity 0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec, 1212b274feedSAvi Kivity 0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed, 1213b274feedSAvi Kivity 0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee, 1214b274feedSAvi Kivity 0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef, 1215b274feedSAvi Kivity 0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0, 1216b274feedSAvi Kivity 0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1, 1217b274feedSAvi Kivity 0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2, 1218b274feedSAvi Kivity 0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3, 1219b274feedSAvi Kivity 0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4, 1220b274feedSAvi Kivity 0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5, 1221b274feedSAvi Kivity 0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6, 1222b274feedSAvi Kivity 0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7, 1223b274feedSAvi Kivity 0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8, 1224b274feedSAvi Kivity 0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9, 1225b274feedSAvi Kivity 0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa, 1226b274feedSAvi Kivity 0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb, 1227b274feedSAvi Kivity 0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc, 1228b274feedSAvi Kivity 0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd, 1229b274feedSAvi Kivity 0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe, 1230b274feedSAvi Kivity 0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff, 1231b274feedSAvi Kivity }; 1232b274feedSAvi Kivity 1233b274feedSAvi Kivity MK_INSN(das, "das"); 1234b274feedSAvi Kivity 123518253fdeSAvi Kivity inregs = (struct regs){ 0 }; 123618253fdeSAvi Kivity 1237b274feedSAvi Kivity for (i = 0; i < 1024; ++i) { 1238b274feedSAvi Kivity unsigned tmp = test_cases[i]; 1239b274feedSAvi Kivity inregs.eax = tmp & 0xff; 1240b274feedSAvi Kivity inregs.eflags = (tmp >> 16) & 0xff; 124118253fdeSAvi Kivity exec_in_big_real_mode(&insn_das); 124218253fdeSAvi Kivity if (!regs_equal(R_AX) 1243b274feedSAvi Kivity || outregs.eax != ((tmp >> 8) & 0xff) 1244b274feedSAvi Kivity || (outregs.eflags & 0xff) != (tmp >> 24)) { 124581050840SAvi Kivity ++nr_fail; 124681050840SAvi Kivity break; 1247b274feedSAvi Kivity } 1248b274feedSAvi Kivity } 12496055ea1fSAvi Kivity report("DAS", ~0, nr_fail == 0); 1250b274feedSAvi Kivity } 1251b274feedSAvi Kivity 12520cbd5b06SMohammed Gamal void test_cwd_cdq() 12530cbd5b06SMohammed Gamal { 12540cbd5b06SMohammed Gamal /* Sign-bit set */ 12550cbd5b06SMohammed Gamal MK_INSN(cwd_1, "mov $0x8000, %ax\n\t" 12560cbd5b06SMohammed Gamal "cwd\n\t"); 12570cbd5b06SMohammed Gamal 12580cbd5b06SMohammed Gamal /* Sign-bit not set */ 12590cbd5b06SMohammed Gamal MK_INSN(cwd_2, "mov $0x1000, %ax\n\t" 12600cbd5b06SMohammed Gamal "cwd\n\t"); 12610cbd5b06SMohammed Gamal 12620cbd5b06SMohammed Gamal /* Sign-bit set */ 12630cbd5b06SMohammed Gamal MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t" 12640cbd5b06SMohammed Gamal "cdq\n\t"); 12650cbd5b06SMohammed Gamal 12660cbd5b06SMohammed Gamal /* Sign-bit not set */ 12670cbd5b06SMohammed Gamal MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t" 12680cbd5b06SMohammed Gamal "cdq\n\t"); 12690cbd5b06SMohammed Gamal 127018253fdeSAvi Kivity inregs = (struct regs){ 0 }; 127118253fdeSAvi Kivity 127218253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwd_1); 12736055ea1fSAvi Kivity report("cwd 1", R_AX | R_DX, 12746055ea1fSAvi Kivity outregs.eax == 0x8000 && outregs.edx == 0xffff); 12750cbd5b06SMohammed Gamal 127618253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwd_2); 12776055ea1fSAvi Kivity report("cwd 2", R_AX | R_DX, 12786055ea1fSAvi Kivity outregs.eax == 0x1000 && outregs.edx == 0); 12790cbd5b06SMohammed Gamal 128018253fdeSAvi Kivity exec_in_big_real_mode(&insn_cdq_1); 12816055ea1fSAvi Kivity report("cdq 1", R_AX | R_DX, 12826055ea1fSAvi Kivity outregs.eax == 0x80000000 && outregs.edx == 0xffffffff); 12830cbd5b06SMohammed Gamal 128418253fdeSAvi Kivity exec_in_big_real_mode(&insn_cdq_2); 12856055ea1fSAvi Kivity report("cdq 2", R_AX | R_DX, 12866055ea1fSAvi Kivity outregs.eax == 0x10000000 && outregs.edx == 0); 12870cbd5b06SMohammed Gamal } 12880cbd5b06SMohammed Gamal 128937f51a4aSWei Yongjun static struct { 129037f51a4aSWei Yongjun void *address; 129137f51a4aSWei Yongjun unsigned short sel; 129237f51a4aSWei Yongjun } __attribute__((packed)) desc = { 129337f51a4aSWei Yongjun (void *)0x1234, 129437f51a4aSWei Yongjun 0x10, 129537f51a4aSWei Yongjun }; 129637f51a4aSWei Yongjun 129737f51a4aSWei Yongjun void test_lds_lss() 129837f51a4aSWei Yongjun { 129937f51a4aSWei Yongjun inregs = (struct regs){ .ebx = (unsigned long)&desc }; 130037f51a4aSWei Yongjun 130137f51a4aSWei Yongjun MK_INSN(lds, "push %ds\n\t" 130237f51a4aSWei Yongjun "lds (%ebx), %eax\n\t" 130337f51a4aSWei Yongjun "mov %ds, %ebx\n\t" 130437f51a4aSWei Yongjun "pop %ds\n\t"); 130537f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lds); 130637f51a4aSWei Yongjun report("lds", R_AX | R_BX, 130737f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 130837f51a4aSWei Yongjun outregs.ebx == desc.sel); 130937f51a4aSWei Yongjun 131037f51a4aSWei Yongjun MK_INSN(les, "push %es\n\t" 131137f51a4aSWei Yongjun "les (%ebx), %eax\n\t" 131237f51a4aSWei Yongjun "mov %es, %ebx\n\t" 131337f51a4aSWei Yongjun "pop %es\n\t"); 131437f51a4aSWei Yongjun exec_in_big_real_mode(&insn_les); 131537f51a4aSWei Yongjun report("les", R_AX | R_BX, 131637f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 131737f51a4aSWei Yongjun outregs.ebx == desc.sel); 131837f51a4aSWei Yongjun 131937f51a4aSWei Yongjun MK_INSN(lfs, "push %fs\n\t" 132037f51a4aSWei Yongjun "lfs (%ebx), %eax\n\t" 132137f51a4aSWei Yongjun "mov %fs, %ebx\n\t" 132237f51a4aSWei Yongjun "pop %fs\n\t"); 132337f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lfs); 132437f51a4aSWei Yongjun report("lfs", R_AX | R_BX, 132537f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 132637f51a4aSWei Yongjun outregs.ebx == desc.sel); 132737f51a4aSWei Yongjun 132837f51a4aSWei Yongjun MK_INSN(lgs, "push %gs\n\t" 132937f51a4aSWei Yongjun "lgs (%ebx), %eax\n\t" 133037f51a4aSWei Yongjun "mov %gs, %ebx\n\t" 133137f51a4aSWei Yongjun "pop %gs\n\t"); 133237f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lgs); 133337f51a4aSWei Yongjun report("lgs", R_AX | R_BX, 133437f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 133537f51a4aSWei Yongjun outregs.ebx == desc.sel); 133637f51a4aSWei Yongjun 133737f51a4aSWei Yongjun MK_INSN(lss, "push %ss\n\t" 133837f51a4aSWei Yongjun "lss (%ebx), %eax\n\t" 133937f51a4aSWei Yongjun "mov %ss, %ebx\n\t" 134037f51a4aSWei Yongjun "pop %ss\n\t"); 134137f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lss); 134237f51a4aSWei Yongjun report("lss", R_AX | R_BX, 134337f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 134437f51a4aSWei Yongjun outregs.ebx == desc.sel); 134537f51a4aSWei Yongjun } 134637f51a4aSWei Yongjun 1347b1c7c575SWei Yongjun void test_jcxz(void) 1348b1c7c575SWei Yongjun { 1349b1c7c575SWei Yongjun MK_INSN(jcxz1, "jcxz 1f\n\t" 1350b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1351b1c7c575SWei Yongjun "1:\n\t"); 1352b1c7c575SWei Yongjun MK_INSN(jcxz2, "mov $0x100, %ecx\n\t" 1353b1c7c575SWei Yongjun "jcxz 1f\n\t" 1354b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1355b1c7c575SWei Yongjun "mov $0, %ecx\n\t" 1356b1c7c575SWei Yongjun "1:\n\t"); 1357b1c7c575SWei Yongjun MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t" 1358b1c7c575SWei Yongjun "jcxz 1f\n\t" 1359b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1360b1c7c575SWei Yongjun "1:\n\t"); 1361b1c7c575SWei Yongjun MK_INSN(jecxz1, "jecxz 1f\n\t" 1362b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1363b1c7c575SWei Yongjun "1:\n\t"); 1364b1c7c575SWei Yongjun MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t" 1365b1c7c575SWei Yongjun "jecxz 1f\n\t" 1366b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1367b1c7c575SWei Yongjun "mov $0, %ecx\n\t" 1368b1c7c575SWei Yongjun "1:\n\t"); 1369b1c7c575SWei Yongjun 1370b1c7c575SWei Yongjun inregs = (struct regs){ 0 }; 1371b1c7c575SWei Yongjun 1372b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jcxz1); 1373b1c7c575SWei Yongjun report("jcxz short 1", 0, 1); 1374b1c7c575SWei Yongjun 1375b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jcxz2); 1376b1c7c575SWei Yongjun report("jcxz short 2", R_AX, outregs.eax == 0x1234); 1377b1c7c575SWei Yongjun 1378b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jcxz3); 1379b1c7c575SWei Yongjun report("jcxz short 3", R_CX, outregs.ecx == 0x10000); 1380b1c7c575SWei Yongjun 1381b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jecxz1); 1382b1c7c575SWei Yongjun report("jecxz short 1", 0, 1); 1383b1c7c575SWei Yongjun 1384b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jecxz2); 1385b1c7c575SWei Yongjun report("jecxz short 2", R_AX, outregs.eax == 0x1234); 1386b1c7c575SWei Yongjun } 1387b1c7c575SWei Yongjun 13888f578e98SAvi Kivity static void test_cpuid(void) 13898f578e98SAvi Kivity { 13908f578e98SAvi Kivity MK_INSN(cpuid, "cpuid"); 13918f578e98SAvi Kivity unsigned function = 0x1234; 13928f578e98SAvi Kivity unsigned eax, ebx, ecx, edx; 13938f578e98SAvi Kivity 13948f578e98SAvi Kivity inregs.eax = eax = function; 139518ba9083SGleb Natapov inregs.ecx = ecx = 0; 1396674d2dbeSPaolo Bonzini asm("cpuid" : "+a"(eax), "=b"(ebx), "+c"(ecx), "=d"(edx)); 13978f578e98SAvi Kivity exec_in_big_real_mode(&insn_cpuid); 13988f578e98SAvi Kivity report("cpuid", R_AX|R_BX|R_CX|R_DX, 13998f578e98SAvi Kivity outregs.eax == eax && outregs.ebx == ebx 14008f578e98SAvi Kivity && outregs.ecx == ecx && outregs.edx == edx); 14018f578e98SAvi Kivity } 14028f578e98SAvi Kivity 1403ed93f43bSAvi Kivity static void test_ss_base_for_esp_ebp(void) 1404ed93f43bSAvi Kivity { 1405ed93f43bSAvi Kivity MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss"); 1406ed93f43bSAvi Kivity MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss"); 1407ed93f43bSAvi Kivity static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 }; 1408ed93f43bSAvi Kivity 1409ed93f43bSAvi Kivity inregs.ebx = 1; 1410ed93f43bSAvi Kivity inregs.ebp = (unsigned)array; 1411ed93f43bSAvi Kivity exec_in_big_real_mode(&insn_ssrel1); 1412ed93f43bSAvi Kivity report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321); 1413ed93f43bSAvi Kivity inregs.ebx = 1; 1414ed93f43bSAvi Kivity inregs.ebp = (unsigned)array; 1415ed93f43bSAvi Kivity inregs.edi = 0; 1416ed93f43bSAvi Kivity exec_in_big_real_mode(&insn_ssrel2); 1417ed93f43bSAvi Kivity report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321); 1418ed93f43bSAvi Kivity } 1419ed93f43bSAvi Kivity 1420c2281fa4SAvi Kivity static void test_sgdt_sidt(void) 1421c2281fa4SAvi Kivity { 1422c2281fa4SAvi Kivity MK_INSN(sgdt, "sgdtw (%eax)"); 1423c2281fa4SAvi Kivity MK_INSN(sidt, "sidtw (%eax)"); 1424c2281fa4SAvi Kivity unsigned x, y; 1425c2281fa4SAvi Kivity 1426c2281fa4SAvi Kivity inregs.eax = (unsigned)&y; 1427c2281fa4SAvi Kivity asm volatile("sgdtw %0" : "=m"(x)); 1428c2281fa4SAvi Kivity exec_in_big_real_mode(&insn_sgdt); 1429c2281fa4SAvi Kivity report("sgdt", 0, x == y); 1430c2281fa4SAvi Kivity 1431c2281fa4SAvi Kivity inregs.eax = (unsigned)&y; 1432c2281fa4SAvi Kivity asm volatile("sidtw %0" : "=m"(x)); 1433c2281fa4SAvi Kivity exec_in_big_real_mode(&insn_sidt); 1434c2281fa4SAvi Kivity report("sidt", 0, x == y); 1435c2281fa4SAvi Kivity } 1436c2281fa4SAvi Kivity 143788b6dac4SPaolo Bonzini static void test_sahf(void) 143888b6dac4SPaolo Bonzini { 143988b6dac4SPaolo Bonzini MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw"); 144088b6dac4SPaolo Bonzini 144188b6dac4SPaolo Bonzini inregs.eax = 0xfd00; 144288b6dac4SPaolo Bonzini exec_in_big_real_mode(&insn_sahf); 144388b6dac4SPaolo Bonzini report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7)); 144488b6dac4SPaolo Bonzini } 144588b6dac4SPaolo Bonzini 14467ae3645aSAvi Kivity static void test_lahf(void) 14477ae3645aSAvi Kivity { 14487ae3645aSAvi Kivity MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf"); 14497ae3645aSAvi Kivity 14507ae3645aSAvi Kivity inregs.eax = 0xc7; 14517ae3645aSAvi Kivity exec_in_big_real_mode(&insn_lahf); 14527ae3645aSAvi Kivity report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax); 14537ae3645aSAvi Kivity } 14547ae3645aSAvi Kivity 1455fd9ea640SAvi Kivity static void test_movzx_movsx(void) 1456fd9ea640SAvi Kivity { 1457fd9ea640SAvi Kivity MK_INSN(movsx, "movsx %al, %ebx"); 1458fd9ea640SAvi Kivity MK_INSN(movzx, "movzx %al, %ebx"); 14593013e079SGleb Natapov MK_INSN(movzsah, "movsx %ah, %ebx"); 14603013e079SGleb Natapov MK_INSN(movzxah, "movzx %ah, %ebx"); 1461fd9ea640SAvi Kivity 1462fd9ea640SAvi Kivity inregs.eax = 0x1234569c; 14633013e079SGleb Natapov inregs.esp = 0xffff; 1464fd9ea640SAvi Kivity exec_in_big_real_mode(&insn_movsx); 1465fd9ea640SAvi Kivity report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax); 1466fd9ea640SAvi Kivity exec_in_big_real_mode(&insn_movzx); 1467fd9ea640SAvi Kivity report("movzx", R_BX, outregs.ebx == (unsigned char)inregs.eax); 14683013e079SGleb Natapov exec_in_big_real_mode(&insn_movzsah); 14693013e079SGleb Natapov report("movsx ah", R_BX, outregs.ebx == (signed char)(inregs.eax>>8)); 14703013e079SGleb Natapov exec_in_big_real_mode(&insn_movzxah); 14713013e079SGleb Natapov report("movzx ah", R_BX, outregs.ebx == (unsigned char)(inregs.eax >> 8)); 1472fd9ea640SAvi Kivity } 1473fd9ea640SAvi Kivity 1474b493b2e8SAvi Kivity static void test_bswap(void) 1475b493b2e8SAvi Kivity { 1476b493b2e8SAvi Kivity MK_INSN(bswap, "bswap %ecx"); 1477b493b2e8SAvi Kivity 1478b493b2e8SAvi Kivity inregs.ecx = 0x12345678; 1479b493b2e8SAvi Kivity exec_in_big_real_mode(&insn_bswap); 1480b493b2e8SAvi Kivity report("bswap", R_CX, outregs.ecx == 0x78563412); 1481b493b2e8SAvi Kivity } 1482b493b2e8SAvi Kivity 14838cd86387SGleb Natapov static void test_aad(void) 14848cd86387SGleb Natapov { 14858cd86387SGleb Natapov MK_INSN(aad, "aad"); 14868cd86387SGleb Natapov 14878cd86387SGleb Natapov inregs.eax = 0x12345678; 14888cd86387SGleb Natapov exec_in_big_real_mode(&insn_aad); 14898cd86387SGleb Natapov report("aad", R_AX, outregs.eax == 0x123400d4); 14908cd86387SGleb Natapov } 14918cd86387SGleb Natapov 14922a9b5718SPaolo Bonzini static void test_aam(void) 14932a9b5718SPaolo Bonzini { 14942a9b5718SPaolo Bonzini MK_INSN(aam, "aam"); 14952a9b5718SPaolo Bonzini 14962a9b5718SPaolo Bonzini inregs.eax = 0x76543210; 14972a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_aam); 14982a9b5718SPaolo Bonzini report("aam", R_AX, outregs.eax == 0x76540106); 14992a9b5718SPaolo Bonzini } 15002a9b5718SPaolo Bonzini 15012a9b5718SPaolo Bonzini static void test_xlat(void) 15022a9b5718SPaolo Bonzini { 15032a9b5718SPaolo Bonzini MK_INSN(xlat, "xlat"); 15042a9b5718SPaolo Bonzini u8 table[256]; 15052a9b5718SPaolo Bonzini int i; 15062a9b5718SPaolo Bonzini 15072a9b5718SPaolo Bonzini for (i = 0; i < 256; i++) { 15082a9b5718SPaolo Bonzini table[i] = i + 1; 15092a9b5718SPaolo Bonzini } 15102a9b5718SPaolo Bonzini 15112a9b5718SPaolo Bonzini inregs.eax = 0x89abcdef; 15122a9b5718SPaolo Bonzini inregs.ebx = (u32)table; 15132a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_xlat); 15142a9b5718SPaolo Bonzini report("xlat", R_AX, outregs.eax == 0x89abcdf0); 15152a9b5718SPaolo Bonzini } 15162a9b5718SPaolo Bonzini 15172a9b5718SPaolo Bonzini static void test_salc(void) 15182a9b5718SPaolo Bonzini { 15192a9b5718SPaolo Bonzini MK_INSN(clc_salc, "clc; .byte 0xd6"); 15202a9b5718SPaolo Bonzini MK_INSN(stc_salc, "stc; .byte 0xd6"); 15212a9b5718SPaolo Bonzini 15222a9b5718SPaolo Bonzini inregs.eax = 0x12345678; 15232a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_clc_salc); 15242a9b5718SPaolo Bonzini report("salc (1)", R_AX, outregs.eax == 0x12345600); 15252a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_stc_salc); 15262a9b5718SPaolo Bonzini report("salc (2)", R_AX, outregs.eax == 0x123456ff); 15272a9b5718SPaolo Bonzini } 15282a9b5718SPaolo Bonzini 15290987db7aSGleb Natapov static void test_fninit(void) 15300987db7aSGleb Natapov { 15310987db7aSGleb Natapov u16 fcw = -1, fsw = -1; 15320987db7aSGleb Natapov MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)"); 15330987db7aSGleb Natapov 15340987db7aSGleb Natapov inregs.eax = (u32)&fsw; 15350987db7aSGleb Natapov inregs.ebx = (u32)&fcw; 15360987db7aSGleb Natapov 15370987db7aSGleb Natapov exec_in_big_real_mode(&insn_fninit); 15380987db7aSGleb Natapov report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f); 15390987db7aSGleb Natapov } 15400987db7aSGleb Natapov 15411a4c03a0SArthur Chunqi Li static void test_nopl(void) 15421a4c03a0SArthur Chunqi Li { 15431a4c03a0SArthur Chunqi Li MK_INSN(nopl1, ".byte 0x90\n\r"); // 1 byte nop 15441a4c03a0SArthur Chunqi Li MK_INSN(nopl2, ".byte 0x66, 0x90\n\r"); // 2 bytes nop 15451a4c03a0SArthur Chunqi Li MK_INSN(nopl3, ".byte 0x0f, 0x1f, 0x00\n\r"); // 3 bytes nop 15461a4c03a0SArthur Chunqi Li MK_INSN(nopl4, ".byte 0x0f, 0x1f, 0x40, 0x00\n\r"); // 4 bytes nop 15471a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl1); 15481a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl2); 15491a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl3); 15501a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl4); 15511a4c03a0SArthur Chunqi Li report("nopl", 0, 1); 15521a4c03a0SArthur Chunqi Li } 15531a4c03a0SArthur Chunqi Li 1554b5105e8bSPaolo Bonzini static u32 perf_baseline; 1555b5105e8bSPaolo Bonzini 15567505ea23SPaolo Bonzini #define PERF_COUNT 1000000 1557b5105e8bSPaolo Bonzini 1558b5105e8bSPaolo Bonzini #define MK_INSN_PERF(name, insn) \ 1559b5105e8bSPaolo Bonzini MK_INSN(name, "rdtsc; mov %eax, %ebx; mov %edx, %esi\n" \ 1560b5105e8bSPaolo Bonzini "1:" insn "\n" \ 15617505ea23SPaolo Bonzini ".byte 0x67; loop 1b\n" \ 1562b5105e8bSPaolo Bonzini "rdtsc"); 1563b5105e8bSPaolo Bonzini 1564b5105e8bSPaolo Bonzini static u32 cycles_in_big_real_mode(struct insn_desc *insn) 1565b5105e8bSPaolo Bonzini { 1566b5105e8bSPaolo Bonzini u64 start, end; 1567b5105e8bSPaolo Bonzini 1568b5105e8bSPaolo Bonzini inregs.ecx = PERF_COUNT; 1569b5105e8bSPaolo Bonzini exec_in_big_real_mode(insn); 1570b5105e8bSPaolo Bonzini start = ((u64)outregs.esi << 32) | outregs.ebx; 1571b5105e8bSPaolo Bonzini end = ((u64)outregs.edx << 32) | outregs.eax; 1572b5105e8bSPaolo Bonzini 1573b5105e8bSPaolo Bonzini return end - start; 1574b5105e8bSPaolo Bonzini } 1575b5105e8bSPaolo Bonzini 1576b5105e8bSPaolo Bonzini static void test_perf_loop(void) 1577b5105e8bSPaolo Bonzini { 1578b5105e8bSPaolo Bonzini /* 1579b5105e8bSPaolo Bonzini * This test runs simple instructions that should roughly take the 1580b5105e8bSPaolo Bonzini * the same time to emulate: PERF_COUNT iterations of "loop" and 3 1581b5105e8bSPaolo Bonzini * setup instructions. Other performance tests can run PERF_COUNT 1582b5105e8bSPaolo Bonzini * iterations of the same instruction and subtract the cycle count 1583b5105e8bSPaolo Bonzini * of this test. 1584b5105e8bSPaolo Bonzini */ 1585b5105e8bSPaolo Bonzini MK_INSN_PERF(perf_loop, ""); 1586b5105e8bSPaolo Bonzini perf_baseline = cycles_in_big_real_mode(&insn_perf_loop); 1587b5105e8bSPaolo Bonzini print_serial_u32(perf_baseline / (PERF_COUNT + 3)); 1588b5105e8bSPaolo Bonzini print_serial(" cycles/emulated jump instruction\n"); 1589b5105e8bSPaolo Bonzini } 1590b5105e8bSPaolo Bonzini 1591b5105e8bSPaolo Bonzini static void test_perf_mov(void) 1592b5105e8bSPaolo Bonzini { 1593b5105e8bSPaolo Bonzini u32 cyc; 1594b5105e8bSPaolo Bonzini 1595b5105e8bSPaolo Bonzini MK_INSN_PERF(perf_move, "mov %esi, %edi"); 1596b5105e8bSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_move); 1597b5105e8bSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 1598b5105e8bSPaolo Bonzini print_serial(" cycles/emulated move instruction\n"); 1599b5105e8bSPaolo Bonzini } 1600b5105e8bSPaolo Bonzini 1601b5105e8bSPaolo Bonzini static void test_perf_arith(void) 1602b5105e8bSPaolo Bonzini { 1603b5105e8bSPaolo Bonzini u32 cyc; 1604b5105e8bSPaolo Bonzini 1605b5105e8bSPaolo Bonzini MK_INSN_PERF(perf_arith, "add $4, %edi"); 1606b5105e8bSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_arith); 1607b5105e8bSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 1608b5105e8bSPaolo Bonzini print_serial(" cycles/emulated arithmetic instruction\n"); 1609b5105e8bSPaolo Bonzini } 1610b5105e8bSPaolo Bonzini 1611b5105e8bSPaolo Bonzini static void test_perf_memory_load(void) 1612b5105e8bSPaolo Bonzini { 1613b5105e8bSPaolo Bonzini u32 cyc, tmp; 1614b5105e8bSPaolo Bonzini 1615b5105e8bSPaolo Bonzini MK_INSN_PERF(perf_memory_load, "cmp $0, (%edi)"); 1616b5105e8bSPaolo Bonzini inregs.edi = (u32)&tmp; 1617b5105e8bSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_memory_load); 1618b5105e8bSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 1619b5105e8bSPaolo Bonzini print_serial(" cycles/emulated memory load instruction\n"); 1620b5105e8bSPaolo Bonzini } 1621b5105e8bSPaolo Bonzini 16229306cb8eSPaolo Bonzini static void test_perf_memory_store(void) 16239306cb8eSPaolo Bonzini { 16249306cb8eSPaolo Bonzini u32 cyc, tmp; 16259306cb8eSPaolo Bonzini 16269306cb8eSPaolo Bonzini MK_INSN_PERF(perf_memory_store, "mov %ax, (%edi)"); 16279306cb8eSPaolo Bonzini inregs.edi = (u32)&tmp; 16289306cb8eSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_memory_store); 16299306cb8eSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 16309306cb8eSPaolo Bonzini print_serial(" cycles/emulated memory store instruction\n"); 16319306cb8eSPaolo Bonzini } 16329306cb8eSPaolo Bonzini 1633b5105e8bSPaolo Bonzini static void test_perf_memory_rmw(void) 1634b5105e8bSPaolo Bonzini { 1635b5105e8bSPaolo Bonzini u32 cyc, tmp; 1636b5105e8bSPaolo Bonzini 1637b5105e8bSPaolo Bonzini MK_INSN_PERF(perf_memory_rmw, "add $1, (%edi)"); 1638b5105e8bSPaolo Bonzini inregs.edi = (u32)&tmp; 1639b5105e8bSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_memory_rmw); 1640b5105e8bSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 1641b5105e8bSPaolo Bonzini print_serial(" cycles/emulated memory RMW instruction\n"); 1642b5105e8bSPaolo Bonzini } 1643b5105e8bSPaolo Bonzini 16440a5701edSNadav Amit void test_dr_mod(void) 16450a5701edSNadav Amit { 16460a5701edSNadav Amit MK_INSN(drmod, "movl %ebx, %dr0\n\t" 16470a5701edSNadav Amit ".byte 0x0f \n\t .byte 0x21 \n\t .byte 0x0\n\t"); 16480a5701edSNadav Amit inregs.eax = 0xdead; 16490a5701edSNadav Amit inregs.ebx = 0xaced; 16500a5701edSNadav Amit exec_in_big_real_mode(&insn_drmod); 16510a5701edSNadav Amit report("mov dr with mod bits", R_AX | R_BX, outregs.eax == 0xaced); 16520a5701edSNadav Amit } 16530a5701edSNadav Amit 165499ee878cSNadav Amit void test_smsw(void) 165599ee878cSNadav Amit { 165699ee878cSNadav Amit MK_INSN(smsw, "movl %cr0, %ebx\n\t" 165799ee878cSNadav Amit "movl %ebx, %ecx\n\t" 165899ee878cSNadav Amit "or $0x40000000, %ebx\n\t" 165999ee878cSNadav Amit "movl %ebx, %cr0\n\t" 166099ee878cSNadav Amit "smswl %eax\n\t" 166199ee878cSNadav Amit "movl %ecx, %cr0\n\t"); 166299ee878cSNadav Amit inregs.eax = 0x12345678; 166399ee878cSNadav Amit exec_in_big_real_mode(&insn_smsw); 166499ee878cSNadav Amit report("smsw", R_AX | R_BX | R_CX, outregs.eax == outregs.ebx); 166599ee878cSNadav Amit } 166699ee878cSNadav Amit 16677bee560dSNadav Amit void test_xadd(void) 16687bee560dSNadav Amit { 16697bee560dSNadav Amit MK_INSN(xadd, "xaddl %eax, %eax\n\t"); 16707bee560dSNadav Amit inregs.eax = 0x12345678; 16717bee560dSNadav Amit exec_in_big_real_mode(&insn_xadd); 16727bee560dSNadav Amit report("xadd", R_AX, outregs.eax == inregs.eax * 2); 16737bee560dSNadav Amit } 16747bee560dSNadav Amit 167599ee878cSNadav Amit 16767d36db35SAvi Kivity void realmode_start(void) 16777d36db35SAvi Kivity { 16787d36db35SAvi Kivity test_null(); 16797d36db35SAvi Kivity 16807d36db35SAvi Kivity test_shld(); 16817d36db35SAvi Kivity test_push_pop(); 16827d36db35SAvi Kivity test_pusha_popa(); 16837d36db35SAvi Kivity test_mov_imm(); 16847d36db35SAvi Kivity test_cmp_imm(); 16857d36db35SAvi Kivity test_add_imm(); 16867d36db35SAvi Kivity test_sub_imm(); 16877d36db35SAvi Kivity test_xor_imm(); 16887d36db35SAvi Kivity test_io(); 16897d36db35SAvi Kivity test_eflags_insn(); 16907d36db35SAvi Kivity test_jcc_short(); 16917d36db35SAvi Kivity test_jcc_near(); 16927d36db35SAvi Kivity /* test_call() uses short jump so call it after testing jcc */ 16937d36db35SAvi Kivity test_call(); 16947d36db35SAvi Kivity /* long jmp test uses call near so test it after testing call */ 16957d36db35SAvi Kivity test_long_jmp(); 16967d36db35SAvi Kivity test_xchg(); 16977d36db35SAvi Kivity test_iret(); 169896b9ca1eSMohammed Gamal test_int(); 1699fa74f8a6SMohammed Gamal test_imul(); 170059317bd1SMohammed Gamal test_mul(); 17010d4c7614SMohammed Gamal test_div(); 17020d4c7614SMohammed Gamal test_idiv(); 1703eacef4e2SWei Yongjun test_loopcc(); 17046e293cf5SWei Yongjun test_cbw(); 17050cbd5b06SMohammed Gamal test_cwd_cdq(); 1706b274feedSAvi Kivity test_das(); 170737f51a4aSWei Yongjun test_lds_lss(); 1708b1c7c575SWei Yongjun test_jcxz(); 17098f578e98SAvi Kivity test_cpuid(); 1710ed93f43bSAvi Kivity test_ss_base_for_esp_ebp(); 1711c2281fa4SAvi Kivity test_sgdt_sidt(); 17127ae3645aSAvi Kivity test_lahf(); 171388b6dac4SPaolo Bonzini test_sahf(); 1714fd9ea640SAvi Kivity test_movzx_movsx(); 1715b493b2e8SAvi Kivity test_bswap(); 17168cd86387SGleb Natapov test_aad(); 17172a9b5718SPaolo Bonzini test_aam(); 17182a9b5718SPaolo Bonzini test_xlat(); 17192a9b5718SPaolo Bonzini test_salc(); 17200987db7aSGleb Natapov test_fninit(); 17210a5701edSNadav Amit test_dr_mod(); 172299ee878cSNadav Amit test_smsw(); 17231a4c03a0SArthur Chunqi Li test_nopl(); 17247bee560dSNadav Amit test_xadd(); 1725b5105e8bSPaolo Bonzini test_perf_loop(); 1726b5105e8bSPaolo Bonzini test_perf_mov(); 1727b5105e8bSPaolo Bonzini test_perf_arith(); 1728b5105e8bSPaolo Bonzini test_perf_memory_load(); 17299306cb8eSPaolo Bonzini test_perf_memory_store(); 1730b5105e8bSPaolo Bonzini test_perf_memory_rmw(); 17317d36db35SAvi Kivity 1732b393fe28SNadav Amit exit(failed); 17337d36db35SAvi Kivity } 17347d36db35SAvi Kivity 17357d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff }; 17367d36db35SAvi Kivity 17377d36db35SAvi Kivity struct __attribute__((packed)) { 17387d36db35SAvi Kivity unsigned short limit; 17397d36db35SAvi Kivity void *base; 17407d36db35SAvi Kivity } r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt }; 17417d36db35SAvi Kivity 17427d36db35SAvi Kivity asm( 17437d36db35SAvi Kivity ".section .init \n\t" 17447d36db35SAvi Kivity 17457d36db35SAvi Kivity ".code32 \n\t" 17467d36db35SAvi Kivity 17477d36db35SAvi Kivity "mb_magic = 0x1BADB002 \n\t" 17487d36db35SAvi Kivity "mb_flags = 0x0 \n\t" 17497d36db35SAvi Kivity 17507d36db35SAvi Kivity "# multiboot header \n\t" 17517d36db35SAvi Kivity ".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t" 17527d36db35SAvi Kivity 17537d36db35SAvi Kivity ".globl start \n\t" 17547d36db35SAvi Kivity ".data \n\t" 17557d36db35SAvi Kivity ". = . + 4096 \n\t" 17567d36db35SAvi Kivity "stacktop: \n\t" 17577d36db35SAvi Kivity 17587d36db35SAvi Kivity ".text \n\t" 17597d36db35SAvi Kivity "start: \n\t" 17607d36db35SAvi Kivity "lgdt r_gdt_descr \n\t" 17617d36db35SAvi Kivity "ljmp $8, $1f; 1: \n\t" 17627d36db35SAvi Kivity ".code16gcc \n\t" 17637d36db35SAvi Kivity "mov $16, %eax \n\t" 17647d36db35SAvi Kivity "mov %ax, %ds \n\t" 17657d36db35SAvi Kivity "mov %ax, %es \n\t" 17667d36db35SAvi Kivity "mov %ax, %fs \n\t" 17677d36db35SAvi Kivity "mov %ax, %gs \n\t" 17687d36db35SAvi Kivity "mov %ax, %ss \n\t" 17697d36db35SAvi Kivity "mov %cr0, %eax \n\t" 17707d36db35SAvi Kivity "btc $0, %eax \n\t" 17717d36db35SAvi Kivity "mov %eax, %cr0 \n\t" 17727d36db35SAvi Kivity "ljmp $0, $realmode_entry \n\t" 17737d36db35SAvi Kivity 17747d36db35SAvi Kivity "realmode_entry: \n\t" 17757d36db35SAvi Kivity 17767d36db35SAvi Kivity "xor %ax, %ax \n\t" 17777d36db35SAvi Kivity "mov %ax, %ds \n\t" 17787d36db35SAvi Kivity "mov %ax, %es \n\t" 17797d36db35SAvi Kivity "mov %ax, %ss \n\t" 17807d36db35SAvi Kivity "mov %ax, %fs \n\t" 17817d36db35SAvi Kivity "mov %ax, %gs \n\t" 17827d36db35SAvi Kivity "mov $stacktop, %esp\n\t" 17837d36db35SAvi Kivity "ljmp $0, $realmode_start \n\t" 17847d36db35SAvi Kivity 17857d36db35SAvi Kivity ".code16gcc \n\t" 17867d36db35SAvi Kivity ); 1787