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 947d36db35SAvi Kivity static void exit(int code) 957d36db35SAvi Kivity { 96f366255fSPaolo Bonzini outb(code, 0xf4); 977d36db35SAvi Kivity } 987d36db35SAvi Kivity 997d36db35SAvi Kivity struct regs { 1007d36db35SAvi Kivity u32 eax, ebx, ecx, edx; 1017d36db35SAvi Kivity u32 esi, edi, esp, ebp; 1027d36db35SAvi Kivity u32 eip, eflags; 1037d36db35SAvi Kivity }; 1047d36db35SAvi Kivity 1057d36db35SAvi Kivity static u64 gdt[] = { 1067d36db35SAvi Kivity 0, 1077d36db35SAvi Kivity 0x00cf9b000000ffffull, // flat 32-bit code segment 1087d36db35SAvi Kivity 0x00cf93000000ffffull, // flat 32-bit data segment 1097d36db35SAvi Kivity }; 1107d36db35SAvi Kivity 1117d36db35SAvi Kivity static struct { 1127d36db35SAvi Kivity u16 limit; 1137d36db35SAvi Kivity void *base; 1147d36db35SAvi Kivity } __attribute__((packed)) gdt_descr = { 1157d36db35SAvi Kivity sizeof(gdt) - 1, 1167d36db35SAvi Kivity gdt, 1177d36db35SAvi Kivity }; 1187d36db35SAvi Kivity 119d4dc402cSAvi Kivity struct insn_desc { 120d4dc402cSAvi Kivity u16 ptr; 121d4dc402cSAvi Kivity u16 len; 122d4dc402cSAvi Kivity }; 123d4dc402cSAvi Kivity 12418253fdeSAvi Kivity static struct regs inregs, outregs; 12518253fdeSAvi Kivity 12618253fdeSAvi Kivity static void exec_in_big_real_mode(struct insn_desc *insn) 1277d36db35SAvi Kivity { 1287d36db35SAvi Kivity unsigned long tmp; 1297d36db35SAvi Kivity static struct regs save; 1307d36db35SAvi Kivity int i; 1317d36db35SAvi Kivity extern u8 test_insn[], test_insn_end[]; 1327d36db35SAvi Kivity 133d4dc402cSAvi Kivity for (i = 0; i < insn->len; ++i) 134d4dc402cSAvi Kivity test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i]; 1357d36db35SAvi Kivity for (; i < test_insn_end - test_insn; ++i) 1367d36db35SAvi Kivity test_insn[i] = 0x90; // nop 1377d36db35SAvi Kivity 13818253fdeSAvi Kivity save = inregs; 1397d36db35SAvi Kivity asm volatile( 1407d36db35SAvi Kivity "lgdtl %[gdt_descr] \n\t" 1417d36db35SAvi Kivity "mov %%cr0, %[tmp] \n\t" 1427d36db35SAvi Kivity "or $1, %[tmp] \n\t" 1437d36db35SAvi Kivity "mov %[tmp], %%cr0 \n\t" 1447d36db35SAvi Kivity "mov %[bigseg], %%gs \n\t" 1457d36db35SAvi Kivity "and $-2, %[tmp] \n\t" 1467d36db35SAvi Kivity "mov %[tmp], %%cr0 \n\t" 1477d36db35SAvi Kivity 14832001692SAvi Kivity "pushw %[save]+36; popfw \n\t" 1497d36db35SAvi Kivity "xchg %%eax, %[save]+0 \n\t" 1507d36db35SAvi Kivity "xchg %%ebx, %[save]+4 \n\t" 1517d36db35SAvi Kivity "xchg %%ecx, %[save]+8 \n\t" 1527d36db35SAvi Kivity "xchg %%edx, %[save]+12 \n\t" 1537d36db35SAvi Kivity "xchg %%esi, %[save]+16 \n\t" 1547d36db35SAvi Kivity "xchg %%edi, %[save]+20 \n\t" 1557d36db35SAvi Kivity "xchg %%esp, %[save]+24 \n\t" 1567d36db35SAvi Kivity "xchg %%ebp, %[save]+28 \n\t" 1577d36db35SAvi Kivity 1587d36db35SAvi Kivity "test_insn: . = . + 32\n\t" 1597d36db35SAvi Kivity "test_insn_end: \n\t" 1607d36db35SAvi Kivity 1617d36db35SAvi Kivity "xchg %%eax, %[save]+0 \n\t" 1627d36db35SAvi Kivity "xchg %%ebx, %[save]+4 \n\t" 1637d36db35SAvi Kivity "xchg %%ecx, %[save]+8 \n\t" 1647d36db35SAvi Kivity "xchg %%edx, %[save]+12 \n\t" 1657d36db35SAvi Kivity "xchg %%esi, %[save]+16 \n\t" 1667d36db35SAvi Kivity "xchg %%edi, %[save]+20 \n\t" 1677d36db35SAvi Kivity "xchg %%esp, %[save]+24 \n\t" 1687d36db35SAvi Kivity "xchg %%ebp, %[save]+28 \n\t" 1697d36db35SAvi Kivity 1707d36db35SAvi Kivity /* Save EFLAGS in outregs*/ 1717d36db35SAvi Kivity "pushfl \n\t" 1727d36db35SAvi Kivity "popl %[save]+36 \n\t" 1737d36db35SAvi Kivity 1745edbb9aeSPaolo Bonzini /* Restore DF for the harness code */ 1755edbb9aeSPaolo Bonzini "cld\n\t" 1767d36db35SAvi Kivity "xor %[tmp], %[tmp] \n\t" 1777d36db35SAvi Kivity "mov %[tmp], %%gs \n\t" 1787d36db35SAvi Kivity : [tmp]"=&r"(tmp), [save]"+m"(save) 1797d36db35SAvi Kivity : [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16) 1807d36db35SAvi Kivity : "cc", "memory" 1817d36db35SAvi Kivity ); 18218253fdeSAvi Kivity outregs = save; 1837d36db35SAvi Kivity } 1847d36db35SAvi Kivity 1857d36db35SAvi Kivity #define R_AX 1 1867d36db35SAvi Kivity #define R_BX 2 1877d36db35SAvi Kivity #define R_CX 4 1887d36db35SAvi Kivity #define R_DX 8 1897d36db35SAvi Kivity #define R_SI 16 1907d36db35SAvi Kivity #define R_DI 32 1917d36db35SAvi Kivity #define R_SP 64 1927d36db35SAvi Kivity #define R_BP 128 1937d36db35SAvi Kivity 19418253fdeSAvi Kivity int regs_equal(int ignore) 1957d36db35SAvi Kivity { 19618253fdeSAvi Kivity const u32 *p1 = &inregs.eax, *p2 = &outregs.eax; // yuck 1977d36db35SAvi Kivity int i; 1987d36db35SAvi Kivity 1997d36db35SAvi Kivity for (i = 0; i < 8; ++i) 2007d36db35SAvi Kivity if (!(ignore & (1 << i)) && p1[i] != p2[i]) 2017d36db35SAvi Kivity return 0; 2027d36db35SAvi Kivity return 1; 2037d36db35SAvi Kivity } 2047d36db35SAvi Kivity 2056055ea1fSAvi Kivity static void report(const char *name, u16 regs_ignore, _Bool ok) 20681050840SAvi Kivity { 2076055ea1fSAvi Kivity if (!regs_equal(regs_ignore)) { 2086055ea1fSAvi Kivity ok = 0; 2096055ea1fSAvi Kivity } 21081050840SAvi Kivity print_serial(ok ? "PASS: " : "FAIL: "); 21181050840SAvi Kivity print_serial(name); 21281050840SAvi Kivity print_serial("\n"); 21381050840SAvi Kivity } 21481050840SAvi Kivity 2157d36db35SAvi Kivity #define MK_INSN(name, str) \ 2167d36db35SAvi Kivity asm ( \ 217d4dc402cSAvi Kivity ".pushsection .data.insn \n\t" \ 218d4dc402cSAvi Kivity "insn_" #name ": \n\t" \ 219d4dc402cSAvi Kivity ".word 1001f, 1002f - 1001f \n\t" \ 220d4dc402cSAvi Kivity ".popsection \n\t" \ 221d4dc402cSAvi Kivity ".pushsection .text.insn, \"ax\" \n\t" \ 222d4dc402cSAvi Kivity "1001: \n\t" \ 223d4dc402cSAvi Kivity "insn_code_" #name ": " str " \n\t" \ 224d4dc402cSAvi Kivity "1002: \n\t" \ 225d4dc402cSAvi Kivity ".popsection" \ 2267d36db35SAvi Kivity ); \ 227d4dc402cSAvi Kivity extern struct insn_desc insn_##name; 2287d36db35SAvi Kivity 2297d36db35SAvi Kivity void test_xchg(void) 2307d36db35SAvi Kivity { 2317d36db35SAvi Kivity MK_INSN(xchg_test1, "xchg %eax,%eax\n\t"); 2327d36db35SAvi Kivity MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t"); 2337d36db35SAvi Kivity MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t"); 2347d36db35SAvi Kivity MK_INSN(xchg_test4, "xchg %eax,%edx\n\t"); 2357d36db35SAvi Kivity MK_INSN(xchg_test5, "xchg %eax,%esi\n\t"); 2367d36db35SAvi Kivity MK_INSN(xchg_test6, "xchg %eax,%edi\n\t"); 2377d36db35SAvi Kivity MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t"); 2387d36db35SAvi Kivity MK_INSN(xchg_test8, "xchg %eax,%esp\n\t"); 2397d36db35SAvi Kivity 24018253fdeSAvi Kivity inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7}; 2417d36db35SAvi Kivity 24218253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test1); 2436055ea1fSAvi Kivity report("xchg 1", 0, 1); 24418253fdeSAvi Kivity 24518253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test2); 2466055ea1fSAvi Kivity report("xchg 2", R_AX | R_BX, 2476055ea1fSAvi Kivity outregs.eax == inregs.ebx && outregs.ebx == inregs.eax); 2487d36db35SAvi Kivity 24918253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test3); 2506055ea1fSAvi Kivity report("xchg 3", R_AX | R_CX, 2516055ea1fSAvi Kivity outregs.eax == inregs.ecx && outregs.ecx == inregs.eax); 2527d36db35SAvi Kivity 25318253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test4); 2546055ea1fSAvi Kivity report("xchg 4", R_AX | R_DX, 2556055ea1fSAvi Kivity outregs.eax == inregs.edx && outregs.edx == inregs.eax); 2567d36db35SAvi Kivity 25718253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test5); 2586055ea1fSAvi Kivity report("xchg 5", R_AX | R_SI, 2596055ea1fSAvi Kivity outregs.eax == inregs.esi && outregs.esi == inregs.eax); 2607d36db35SAvi Kivity 26118253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test6); 2626055ea1fSAvi Kivity report("xchg 6", R_AX | R_DI, 2636055ea1fSAvi Kivity outregs.eax == inregs.edi && outregs.edi == inregs.eax); 2647d36db35SAvi Kivity 26518253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test7); 2666055ea1fSAvi Kivity report("xchg 7", R_AX | R_BP, 2676055ea1fSAvi Kivity outregs.eax == inregs.ebp && outregs.ebp == inregs.eax); 2687d36db35SAvi Kivity 26918253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test8); 2706055ea1fSAvi Kivity report("xchg 8", R_AX | R_SP, 2716055ea1fSAvi Kivity outregs.eax == inregs.esp && outregs.esp == inregs.eax); 2727d36db35SAvi Kivity } 2737d36db35SAvi Kivity 2747d36db35SAvi Kivity void test_shld(void) 2757d36db35SAvi Kivity { 2767d36db35SAvi Kivity MK_INSN(shld_test, "shld $8,%edx,%eax\n\t"); 2777d36db35SAvi Kivity 27818253fdeSAvi Kivity inregs = (struct regs){ .eax = 0xbe, .edx = 0xef000000 }; 27918253fdeSAvi Kivity exec_in_big_real_mode(&insn_shld_test); 2806055ea1fSAvi Kivity report("shld", ~0, outregs.eax == 0xbeef); 2817d36db35SAvi Kivity } 2827d36db35SAvi Kivity 2837d36db35SAvi Kivity void test_mov_imm(void) 2847d36db35SAvi Kivity { 2857d36db35SAvi Kivity MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax"); 2867d36db35SAvi Kivity MK_INSN(mov_r16_imm_1, "mov $1234, %ax"); 2877d36db35SAvi Kivity MK_INSN(mov_r8_imm_1, "mov $0x12, %ah"); 2887d36db35SAvi Kivity MK_INSN(mov_r8_imm_2, "mov $0x34, %al"); 2897d36db35SAvi Kivity MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t"); 2907d36db35SAvi Kivity 29118253fdeSAvi Kivity inregs = (struct regs){ 0 }; 29218253fdeSAvi Kivity 29318253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r16_imm_1); 2946055ea1fSAvi Kivity report("mov 1", R_AX, outregs.eax == 1234); 2957d36db35SAvi Kivity 2967d36db35SAvi Kivity /* test mov $imm, %eax */ 29718253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r32_imm_1); 2986055ea1fSAvi Kivity report("mov 2", R_AX, outregs.eax == 1234567890); 2997d36db35SAvi Kivity 3007d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 30118253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_1); 3026055ea1fSAvi Kivity report("mov 3", R_AX, outregs.eax == 0x1200); 3037d36db35SAvi Kivity 30418253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_2); 3056055ea1fSAvi Kivity report("mov 4", R_AX, outregs.eax == 0x34); 3067d36db35SAvi Kivity 30718253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_3); 3086055ea1fSAvi Kivity report("mov 5", R_AX, outregs.eax == 0x1234); 3097d36db35SAvi Kivity } 3107d36db35SAvi Kivity 3117d36db35SAvi Kivity void test_sub_imm(void) 3127d36db35SAvi Kivity { 3137d36db35SAvi Kivity MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t"); 3147d36db35SAvi Kivity MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t"); 3157d36db35SAvi Kivity MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t"); 3167d36db35SAvi Kivity MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t"); 3177d36db35SAvi Kivity 31818253fdeSAvi Kivity inregs = (struct regs){ 0 }; 31918253fdeSAvi Kivity 32018253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r16_imm_1); 3216055ea1fSAvi Kivity report("sub 1", R_AX, outregs.eax == 1224); 3227d36db35SAvi Kivity 3237d36db35SAvi Kivity /* test mov $imm, %eax */ 32418253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r32_imm_1); 3256055ea1fSAvi Kivity report("sub 2", R_AX, outregs.eax == 1234567880); 3267d36db35SAvi Kivity 3277d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 32818253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r8_imm_1); 3296055ea1fSAvi Kivity report("sub 3", R_AX, outregs.eax == 0x0200); 3307d36db35SAvi Kivity 33118253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r8_imm_2); 3326055ea1fSAvi Kivity report("sub 4", R_AX, outregs.eax == 0x24); 3337d36db35SAvi Kivity } 3347d36db35SAvi Kivity 3357d36db35SAvi Kivity void test_xor_imm(void) 3367d36db35SAvi Kivity { 3377d36db35SAvi Kivity MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t"); 3387d36db35SAvi Kivity MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t"); 3397d36db35SAvi Kivity MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t"); 3407d36db35SAvi Kivity MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t"); 3417d36db35SAvi Kivity 34218253fdeSAvi Kivity inregs = (struct regs){ 0 }; 34318253fdeSAvi Kivity 34418253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r16_imm_1); 3456055ea1fSAvi Kivity report("xor 1", R_AX, outregs.eax == 0); 3467d36db35SAvi Kivity 3477d36db35SAvi Kivity /* test mov $imm, %eax */ 34818253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r32_imm_1); 3496055ea1fSAvi Kivity report("xor 2", R_AX, outregs.eax == 0); 3507d36db35SAvi Kivity 3517d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 35218253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r8_imm_1); 3536055ea1fSAvi Kivity report("xor 3", R_AX, outregs.eax == 0); 3547d36db35SAvi Kivity 35518253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r8_imm_2); 3566055ea1fSAvi Kivity report("xor 4", R_AX, outregs.eax == 0); 3577d36db35SAvi Kivity } 3587d36db35SAvi Kivity 3597d36db35SAvi Kivity void test_cmp_imm(void) 3607d36db35SAvi Kivity { 3617d36db35SAvi Kivity MK_INSN(cmp_test1, "mov $0x34, %al\n\t" 3627d36db35SAvi Kivity "cmp $0x34, %al\n\t"); 3637d36db35SAvi Kivity MK_INSN(cmp_test2, "mov $0x34, %al\n\t" 3647d36db35SAvi Kivity "cmp $0x39, %al\n\t"); 3657d36db35SAvi Kivity MK_INSN(cmp_test3, "mov $0x34, %al\n\t" 3667d36db35SAvi Kivity "cmp $0x24, %al\n\t"); 3677d36db35SAvi Kivity 36818253fdeSAvi Kivity inregs = (struct regs){ 0 }; 36918253fdeSAvi Kivity 3707d36db35SAvi Kivity /* test cmp imm8 with AL */ 3717d36db35SAvi Kivity /* ZF: (bit 6) Zero Flag becomes 1 if an operation results 3727d36db35SAvi Kivity * in a 0 writeback, or 0 register 3737d36db35SAvi Kivity */ 37418253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test1); 3756055ea1fSAvi Kivity report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6)); 3767d36db35SAvi Kivity 37718253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test2); 3786055ea1fSAvi Kivity report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0); 3797d36db35SAvi Kivity 38018253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test3); 3816055ea1fSAvi Kivity report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0); 3827d36db35SAvi Kivity } 3837d36db35SAvi Kivity 3847d36db35SAvi Kivity void test_add_imm(void) 3857d36db35SAvi Kivity { 3867d36db35SAvi Kivity MK_INSN(add_test1, "mov $0x43211234, %eax \n\t" 3877d36db35SAvi Kivity "add $0x12344321, %eax \n\t"); 3887d36db35SAvi Kivity MK_INSN(add_test2, "mov $0x12, %eax \n\t" 3897d36db35SAvi Kivity "add $0x21, %al\n\t"); 3907d36db35SAvi Kivity 39118253fdeSAvi Kivity inregs = (struct regs){ 0 }; 39218253fdeSAvi Kivity 39318253fdeSAvi Kivity exec_in_big_real_mode(&insn_add_test1); 3946055ea1fSAvi Kivity report("add 1", ~0, outregs.eax == 0x55555555); 3957d36db35SAvi Kivity 39618253fdeSAvi Kivity exec_in_big_real_mode(&insn_add_test2); 3976055ea1fSAvi Kivity report("add 2", ~0, outregs.eax == 0x33); 3987d36db35SAvi Kivity } 3997d36db35SAvi Kivity 4007d36db35SAvi Kivity void test_eflags_insn(void) 4017d36db35SAvi Kivity { 4027d36db35SAvi Kivity MK_INSN(clc, "clc"); 403b3261e48SMohammed Gamal MK_INSN(stc, "stc"); 4047d36db35SAvi Kivity MK_INSN(cli, "cli"); 4057d36db35SAvi Kivity MK_INSN(sti, "sti"); 4067d36db35SAvi Kivity MK_INSN(cld, "cld"); 4077d36db35SAvi Kivity MK_INSN(std, "std"); 4087d36db35SAvi Kivity 40918253fdeSAvi Kivity inregs = (struct regs){ 0 }; 41018253fdeSAvi Kivity 41118253fdeSAvi Kivity exec_in_big_real_mode(&insn_clc); 4126055ea1fSAvi Kivity report("clc", ~0, (outregs.eflags & 1) == 0); 4137d36db35SAvi Kivity 41418253fdeSAvi Kivity exec_in_big_real_mode(&insn_stc); 4156055ea1fSAvi Kivity report("stc", ~0, (outregs.eflags & 1) == 1); 416b3261e48SMohammed Gamal 41718253fdeSAvi Kivity exec_in_big_real_mode(&insn_cli); 4186055ea1fSAvi Kivity report("cli", ~0, !(outregs.eflags & (1 << 9))); 4197d36db35SAvi Kivity 42018253fdeSAvi Kivity exec_in_big_real_mode(&insn_sti); 4216055ea1fSAvi Kivity report("sti", ~0, outregs.eflags & (1 << 9)); 4227d36db35SAvi Kivity 42318253fdeSAvi Kivity exec_in_big_real_mode(&insn_cld); 4246055ea1fSAvi Kivity report("cld", ~0, !(outregs.eflags & (1 << 10))); 4257d36db35SAvi Kivity 42618253fdeSAvi Kivity exec_in_big_real_mode(&insn_std); 4276055ea1fSAvi Kivity report("std", ~0, (outregs.eflags & (1 << 10))); 4287d36db35SAvi Kivity } 4297d36db35SAvi Kivity 4307d36db35SAvi Kivity void test_io(void) 4317d36db35SAvi Kivity { 4327d36db35SAvi Kivity MK_INSN(io_test1, "mov $0xff, %al \n\t" 4337d36db35SAvi Kivity "out %al, $0xe0 \n\t" 4347d36db35SAvi Kivity "mov $0x00, %al \n\t" 4357d36db35SAvi Kivity "in $0xe0, %al \n\t"); 4367d36db35SAvi Kivity MK_INSN(io_test2, "mov $0xffff, %ax \n\t" 4377d36db35SAvi Kivity "out %ax, $0xe0 \n\t" 4387d36db35SAvi Kivity "mov $0x0000, %ax \n\t" 4397d36db35SAvi Kivity "in $0xe0, %ax \n\t"); 4407d36db35SAvi Kivity MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t" 4417d36db35SAvi Kivity "out %eax, $0xe0 \n\t" 4427d36db35SAvi Kivity "mov $0x000000, %eax \n\t" 4437d36db35SAvi Kivity "in $0xe0, %eax \n\t"); 4447d36db35SAvi Kivity MK_INSN(io_test4, "mov $0xe0, %dx \n\t" 4457d36db35SAvi Kivity "mov $0xff, %al \n\t" 4467d36db35SAvi Kivity "out %al, %dx \n\t" 4477d36db35SAvi Kivity "mov $0x00, %al \n\t" 4487d36db35SAvi Kivity "in %dx, %al \n\t"); 4497d36db35SAvi Kivity MK_INSN(io_test5, "mov $0xe0, %dx \n\t" 4507d36db35SAvi Kivity "mov $0xffff, %ax \n\t" 4517d36db35SAvi Kivity "out %ax, %dx \n\t" 4527d36db35SAvi Kivity "mov $0x0000, %ax \n\t" 4537d36db35SAvi Kivity "in %dx, %ax \n\t"); 4547d36db35SAvi Kivity MK_INSN(io_test6, "mov $0xe0, %dx \n\t" 4557d36db35SAvi Kivity "mov $0xffffffff, %eax \n\t" 4567d36db35SAvi Kivity "out %eax, %dx \n\t" 4577d36db35SAvi Kivity "mov $0x00000000, %eax \n\t" 4587d36db35SAvi Kivity "in %dx, %eax \n\t"); 4597d36db35SAvi Kivity 46018253fdeSAvi Kivity inregs = (struct regs){ 0 }; 46118253fdeSAvi Kivity 46218253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test1); 4636055ea1fSAvi Kivity report("pio 1", R_AX, outregs.eax == 0xff); 4647d36db35SAvi Kivity 46518253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test2); 4666055ea1fSAvi Kivity report("pio 2", R_AX, outregs.eax == 0xffff); 4677d36db35SAvi Kivity 46818253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test3); 4696055ea1fSAvi Kivity report("pio 3", R_AX, outregs.eax == 0xffffffff); 4707d36db35SAvi Kivity 47118253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test4); 4726055ea1fSAvi Kivity report("pio 4", R_AX|R_DX, outregs.eax == 0xff); 4737d36db35SAvi Kivity 47418253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test5); 4756055ea1fSAvi Kivity report("pio 5", R_AX|R_DX, outregs.eax == 0xffff); 4767d36db35SAvi Kivity 47718253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test6); 4786055ea1fSAvi Kivity report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff); 4797d36db35SAvi Kivity } 4807d36db35SAvi Kivity 481c0b7268dSAvi Kivity asm ("retf: lretw"); 482c0b7268dSAvi Kivity extern void retf(); 483c0b7268dSAvi Kivity 4844f66bc86SBruce Rogers asm ("retf_imm: lretw $10"); 4854f66bc86SBruce Rogers extern void retf_imm(); 4864f66bc86SBruce Rogers 4877d36db35SAvi Kivity void test_call(void) 4887d36db35SAvi Kivity { 4897d36db35SAvi Kivity u32 esp[16]; 490c0b7268dSAvi Kivity u32 addr; 4917d36db35SAvi Kivity 49218253fdeSAvi Kivity inregs = (struct regs){ 0 }; 4937d36db35SAvi Kivity inregs.esp = (u32)esp; 4947d36db35SAvi Kivity 4957d36db35SAvi Kivity MK_INSN(call1, "mov $test_function, %eax \n\t" 4967d36db35SAvi Kivity "call *%eax\n\t"); 4977d36db35SAvi Kivity MK_INSN(call_near1, "jmp 2f\n\t" 4987d36db35SAvi Kivity "1: mov $0x1234, %eax\n\t" 4997d36db35SAvi Kivity "ret\n\t" 5007d36db35SAvi Kivity "2: call 1b\t"); 5017d36db35SAvi Kivity MK_INSN(call_near2, "call 1f\n\t" 5027d36db35SAvi Kivity "jmp 2f\n\t" 5037d36db35SAvi Kivity "1: mov $0x1234, %eax\n\t" 5047d36db35SAvi Kivity "ret\n\t" 5057d36db35SAvi Kivity "2:\t"); 506c0b7268dSAvi Kivity MK_INSN(call_far1, "lcallw *(%ebx)\n\t"); 507556d2680SWei Yongjun MK_INSN(call_far2, "lcallw $0, $retf\n\t"); 508c6061817SAvi Kivity MK_INSN(ret_imm, "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b"); 5094f66bc86SBruce Rogers MK_INSN(retf_imm, "sub $10, %sp; lcallw $0, $retf_imm"); 5107d36db35SAvi Kivity 51118253fdeSAvi Kivity exec_in_big_real_mode(&insn_call1); 5126055ea1fSAvi Kivity report("call 1", R_AX, outregs.eax == 0x1234); 5137d36db35SAvi Kivity 51418253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_near1); 5156055ea1fSAvi Kivity report("call near 1", R_AX, outregs.eax == 0x1234); 5167d36db35SAvi Kivity 51718253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_near2); 5186055ea1fSAvi Kivity report("call near 2", R_AX, outregs.eax == 0x1234); 519c0b7268dSAvi Kivity 520c0b7268dSAvi Kivity addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f); 521c0b7268dSAvi Kivity inregs.ebx = (unsigned)&addr; 52218253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_far1); 5236055ea1fSAvi Kivity report("call far 1", 0, 1); 524c6061817SAvi Kivity 525556d2680SWei Yongjun exec_in_big_real_mode(&insn_call_far2); 526556d2680SWei Yongjun report("call far 2", 0, 1); 527556d2680SWei Yongjun 52818253fdeSAvi Kivity exec_in_big_real_mode(&insn_ret_imm); 5296055ea1fSAvi Kivity report("ret imm 1", 0, 1); 5304f66bc86SBruce Rogers 5314f66bc86SBruce Rogers exec_in_big_real_mode(&insn_retf_imm); 5324f66bc86SBruce Rogers report("retf imm 1", 0, 1); 5337d36db35SAvi Kivity } 5347d36db35SAvi Kivity 5357d36db35SAvi Kivity void test_jcc_short(void) 5367d36db35SAvi Kivity { 5377d36db35SAvi Kivity MK_INSN(jnz_short1, "jnz 1f\n\t" 5387d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5397d36db35SAvi Kivity "1:\n\t"); 5407d36db35SAvi Kivity MK_INSN(jnz_short2, "1:\n\t" 5417d36db35SAvi Kivity "cmp $0x1234, %eax\n\t" 5427d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5437d36db35SAvi Kivity "jnz 1b\n\t"); 5447d36db35SAvi Kivity MK_INSN(jmp_short1, "jmp 1f\n\t" 5457d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5467d36db35SAvi Kivity "1:\n\t"); 5477d36db35SAvi Kivity 54818253fdeSAvi Kivity inregs = (struct regs){ 0 }; 5497d36db35SAvi Kivity 55018253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_short1); 5516055ea1fSAvi Kivity report("jnz short 1", ~0, 1); 55218253fdeSAvi Kivity 55318253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_short2); 5546055ea1fSAvi Kivity report("jnz short 2", R_AX, (outregs.eflags & (1 << 6))); 5557d36db35SAvi Kivity 55618253fdeSAvi Kivity exec_in_big_real_mode(&insn_jmp_short1); 5576055ea1fSAvi Kivity report("jmp short 1", ~0, 1); 5587d36db35SAvi Kivity } 5597d36db35SAvi Kivity 5607d36db35SAvi Kivity void test_jcc_near(void) 5617d36db35SAvi Kivity { 5627d36db35SAvi Kivity /* encode near jmp manually. gas will not do it if offsets < 127 byte */ 5637d36db35SAvi Kivity MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t" 5647d36db35SAvi Kivity "mov $0x1234, %eax\n\t"); 5657d36db35SAvi Kivity MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t" 5667d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5677d36db35SAvi Kivity ".byte 0x0f, 0x85, 0xf0, 0xff\n\t"); 5687d36db35SAvi Kivity MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t" 5697d36db35SAvi Kivity "mov $0x1234, %eax\n\t"); 5707d36db35SAvi Kivity 57118253fdeSAvi Kivity inregs = (struct regs){ 0 }; 5727d36db35SAvi Kivity 57318253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_near1); 5746055ea1fSAvi Kivity report("jnz near 1", 0, 1); 57518253fdeSAvi Kivity 57618253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_near2); 5776055ea1fSAvi Kivity report("jnz near 2", R_AX, outregs.eflags & (1 << 6)); 5787d36db35SAvi Kivity 57918253fdeSAvi Kivity exec_in_big_real_mode(&insn_jmp_near1); 5806055ea1fSAvi Kivity report("jmp near 1", 0, 1); 5817d36db35SAvi Kivity } 5827d36db35SAvi Kivity 5837d36db35SAvi Kivity void test_long_jmp() 5847d36db35SAvi Kivity { 5857d36db35SAvi Kivity u32 esp[16]; 5867d36db35SAvi Kivity 58718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 5884aa22949SAvi Kivity inregs.esp = (u32)(esp+16); 5897d36db35SAvi Kivity MK_INSN(long_jmp, "call 1f\n\t" 5907d36db35SAvi Kivity "jmp 2f\n\t" 5917d36db35SAvi Kivity "1: jmp $0, $test_function\n\t" 5927d36db35SAvi Kivity "2:\n\t"); 59318253fdeSAvi Kivity exec_in_big_real_mode(&insn_long_jmp); 5946055ea1fSAvi Kivity report("jmp far 1", R_AX, outregs.eax == 0x1234); 5957d36db35SAvi Kivity } 596fa74f8a6SMohammed Gamal 5977d36db35SAvi Kivity void test_push_pop() 5987d36db35SAvi Kivity { 5997d36db35SAvi Kivity MK_INSN(push32, "mov $0x12345678, %eax\n\t" 6007d36db35SAvi Kivity "push %eax\n\t" 6017d36db35SAvi Kivity "pop %ebx\n\t"); 6027d36db35SAvi Kivity MK_INSN(push16, "mov $0x1234, %ax\n\t" 6037d36db35SAvi Kivity "push %ax\n\t" 6047d36db35SAvi Kivity "pop %bx\n\t"); 6057d36db35SAvi Kivity 6067d36db35SAvi Kivity MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten 6077d36db35SAvi Kivity "mov $0x123, %ax\n\t" 6087d36db35SAvi Kivity "mov %ax, %es\n\t" 6097d36db35SAvi Kivity "push %es\n\t" 6107d36db35SAvi Kivity "pop %bx \n\t" 6117d36db35SAvi Kivity ); 6127d36db35SAvi Kivity MK_INSN(pop_es, "push %ax\n\t" 6137d36db35SAvi Kivity "pop %es\n\t" 6147d36db35SAvi Kivity "mov %es, %bx\n\t" 6157d36db35SAvi Kivity ); 6167d36db35SAvi Kivity MK_INSN(push_pop_ss, "push %ss\n\t" 6177d36db35SAvi Kivity "pushw %ax\n\t" 6187d36db35SAvi Kivity "popw %ss\n\t" 6197d36db35SAvi Kivity "mov %ss, %bx\n\t" 6207d36db35SAvi Kivity "pop %ss\n\t" 6217d36db35SAvi Kivity ); 6227d36db35SAvi Kivity MK_INSN(push_pop_fs, "push %fs\n\t" 6237d36db35SAvi Kivity "pushl %eax\n\t" 6247d36db35SAvi Kivity "popl %fs\n\t" 6257d36db35SAvi Kivity "mov %fs, %ebx\n\t" 6267d36db35SAvi Kivity "pop %fs\n\t" 6277d36db35SAvi Kivity ); 62809b657b6SAvi Kivity MK_INSN(push_pop_high_esp_bits, 62909b657b6SAvi Kivity "xor $0x12340000, %esp \n\t" 63009b657b6SAvi Kivity "push %ax; \n\t" 63109b657b6SAvi Kivity "xor $0x12340000, %esp \n\t" 63209b657b6SAvi Kivity "pop %bx"); 6337d36db35SAvi Kivity 63418253fdeSAvi Kivity inregs = (struct regs){ 0 }; 63518253fdeSAvi Kivity 63618253fdeSAvi Kivity exec_in_big_real_mode(&insn_push32); 6376055ea1fSAvi Kivity report("push/pop 1", R_AX|R_BX, 6386055ea1fSAvi Kivity outregs.eax == outregs.ebx && outregs.eax == 0x12345678); 6397d36db35SAvi Kivity 64018253fdeSAvi Kivity exec_in_big_real_mode(&insn_push16); 6416055ea1fSAvi Kivity report("push/pop 2", R_AX|R_BX, 6426055ea1fSAvi Kivity outregs.eax == outregs.ebx && outregs.eax == 0x1234); 6437d36db35SAvi Kivity 64418253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_es); 6456055ea1fSAvi Kivity report("push/pop 3", R_AX|R_BX, 6466055ea1fSAvi Kivity outregs.ebx == outregs.eax && outregs.eax == 0x123); 6477d36db35SAvi Kivity 64818253fdeSAvi Kivity exec_in_big_real_mode(&insn_pop_es); 6496055ea1fSAvi Kivity report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax); 6507d36db35SAvi Kivity 65118253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_pop_ss); 6526055ea1fSAvi Kivity report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax); 6537d36db35SAvi Kivity 65418253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_pop_fs); 6556055ea1fSAvi Kivity report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax); 65609b657b6SAvi Kivity 65709b657b6SAvi Kivity inregs.eax = 0x9977; 65809b657b6SAvi Kivity inregs.ebx = 0x7799; 65909b657b6SAvi Kivity exec_in_big_real_mode(&insn_push_pop_high_esp_bits); 66009b657b6SAvi Kivity report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977); 6617d36db35SAvi Kivity } 6627d36db35SAvi Kivity 6637d36db35SAvi Kivity void test_null(void) 6647d36db35SAvi Kivity { 665d4dc402cSAvi Kivity MK_INSN(null, ""); 666d4dc402cSAvi Kivity 66718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 66818253fdeSAvi Kivity 66918253fdeSAvi Kivity exec_in_big_real_mode(&insn_null); 6706055ea1fSAvi Kivity report("null", 0, 1); 6717d36db35SAvi Kivity } 6727d36db35SAvi Kivity 6737d36db35SAvi Kivity struct { 6747d36db35SAvi Kivity char stack[500]; 6757d36db35SAvi Kivity char top[]; 6767d36db35SAvi Kivity } tmp_stack; 6777d36db35SAvi Kivity 6787d36db35SAvi Kivity void test_pusha_popa() 6797d36db35SAvi Kivity { 6807d36db35SAvi Kivity MK_INSN(pusha, "pusha\n\t" 6817d36db35SAvi Kivity "pop %edi\n\t" 6827d36db35SAvi Kivity "pop %esi\n\t" 6837d36db35SAvi Kivity "pop %ebp\n\t" 6847d36db35SAvi Kivity "add $4, %esp\n\t" 6857d36db35SAvi Kivity "pop %ebx\n\t" 6867d36db35SAvi Kivity "pop %edx\n\t" 6877d36db35SAvi Kivity "pop %ecx\n\t" 6887d36db35SAvi Kivity "pop %eax\n\t" 6897d36db35SAvi Kivity ); 6907d36db35SAvi Kivity 6917d36db35SAvi Kivity MK_INSN(popa, "push %eax\n\t" 6927d36db35SAvi Kivity "push %ecx\n\t" 6937d36db35SAvi Kivity "push %edx\n\t" 6947d36db35SAvi Kivity "push %ebx\n\t" 6957d36db35SAvi Kivity "push %esp\n\t" 6967d36db35SAvi Kivity "push %ebp\n\t" 6977d36db35SAvi Kivity "push %esi\n\t" 6987d36db35SAvi Kivity "push %edi\n\t" 6997d36db35SAvi Kivity "popa\n\t" 7007d36db35SAvi Kivity ); 7017d36db35SAvi Kivity 70218253fdeSAvi Kivity inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top }; 7037d36db35SAvi Kivity 70418253fdeSAvi Kivity exec_in_big_real_mode(&insn_pusha); 7056055ea1fSAvi Kivity report("pusha/popa 1", 0, 1); 70618253fdeSAvi Kivity 70718253fdeSAvi Kivity exec_in_big_real_mode(&insn_popa); 7086055ea1fSAvi Kivity report("pusha/popa 1", 0, 1); 7097d36db35SAvi Kivity } 7107d36db35SAvi Kivity 7117d36db35SAvi Kivity void test_iret() 7127d36db35SAvi Kivity { 7137d36db35SAvi Kivity MK_INSN(iret32, "pushf\n\t" 7147d36db35SAvi Kivity "pushl %cs\n\t" 7157d36db35SAvi Kivity "call 1f\n\t" /* a near call will push eip onto the stack */ 7167d36db35SAvi Kivity "jmp 2f\n\t" 7177d36db35SAvi Kivity "1: iret\n\t" 7187d36db35SAvi Kivity "2:\n\t" 7197d36db35SAvi Kivity ); 7207d36db35SAvi Kivity 7217d36db35SAvi Kivity MK_INSN(iret16, "pushfw\n\t" 7227d36db35SAvi Kivity "pushw %cs\n\t" 7237d36db35SAvi Kivity "callw 1f\n\t" 7247d36db35SAvi Kivity "jmp 2f\n\t" 7257d36db35SAvi Kivity "1: iretw\n\t" 7267d36db35SAvi Kivity "2:\n\t"); 7277d36db35SAvi Kivity 7287d36db35SAvi Kivity MK_INSN(iret_flags32, "pushfl\n\t" 7297d36db35SAvi Kivity "popl %eax\n\t" 7307d36db35SAvi Kivity "andl $~0x2, %eax\n\t" 7317d36db35SAvi Kivity "orl $0xffc08028, %eax\n\t" 7327d36db35SAvi Kivity "pushl %eax\n\t" 7337d36db35SAvi Kivity "pushl %cs\n\t" 7347d36db35SAvi Kivity "call 1f\n\t" 7357d36db35SAvi Kivity "jmp 2f\n\t" 7367d36db35SAvi Kivity "1: iret\n\t" 7377d36db35SAvi Kivity "2:\n\t"); 7387d36db35SAvi Kivity 7397d36db35SAvi Kivity MK_INSN(iret_flags16, "pushfw\n\t" 7407d36db35SAvi Kivity "popw %ax\n\t" 7417d36db35SAvi Kivity "and $~0x2, %ax\n\t" 7427d36db35SAvi Kivity "or $0x8028, %ax\n\t" 7437d36db35SAvi Kivity "pushw %ax\n\t" 7447d36db35SAvi Kivity "pushw %cs\n\t" 7457d36db35SAvi Kivity "callw 1f\n\t" 7467d36db35SAvi Kivity "jmp 2f\n\t" 7477d36db35SAvi Kivity "1: iretw\n\t" 7487d36db35SAvi Kivity "2:\n\t"); 7497d36db35SAvi Kivity 75018253fdeSAvi Kivity inregs = (struct regs){ 0 }; 7517d36db35SAvi Kivity 75218253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret32); 7536055ea1fSAvi Kivity report("iret 1", 0, 1); 7547d36db35SAvi Kivity 75518253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret16); 7566055ea1fSAvi Kivity report("iret 2", 0, 1); 7577d36db35SAvi Kivity 75818253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret_flags32); 7596055ea1fSAvi Kivity report("iret 3", R_AX, 1); 76018253fdeSAvi Kivity 76118253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret_flags16); 7626055ea1fSAvi Kivity report("iret 4", R_AX, 1); 7637d36db35SAvi Kivity } 7647d36db35SAvi Kivity 76596b9ca1eSMohammed Gamal void test_int() 76696b9ca1eSMohammed Gamal { 76718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 76896b9ca1eSMohammed Gamal 76996b9ca1eSMohammed Gamal *(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */ 77096b9ca1eSMohammed Gamal *(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */ 77196b9ca1eSMohammed Gamal 77296b9ca1eSMohammed Gamal MK_INSN(int11, "int $0x11\n\t"); 77396b9ca1eSMohammed Gamal 77418253fdeSAvi Kivity exec_in_big_real_mode(&insn_int11); 7756055ea1fSAvi Kivity report("int 1", 0, 1); 77696b9ca1eSMohammed Gamal } 77796b9ca1eSMohammed Gamal 778fa74f8a6SMohammed Gamal void test_imul() 779fa74f8a6SMohammed Gamal { 780fa74f8a6SMohammed Gamal MK_INSN(imul8_1, "mov $2, %al\n\t" 781fa74f8a6SMohammed Gamal "mov $-4, %cx\n\t" 782fa74f8a6SMohammed Gamal "imul %cl\n\t"); 783fa74f8a6SMohammed Gamal 784fa74f8a6SMohammed Gamal MK_INSN(imul16_1, "mov $2, %ax\n\t" 785fa74f8a6SMohammed Gamal "mov $-4, %cx\n\t" 786fa74f8a6SMohammed Gamal "imul %cx\n\t"); 787fa74f8a6SMohammed Gamal 788fa74f8a6SMohammed Gamal MK_INSN(imul32_1, "mov $2, %eax\n\t" 789fa74f8a6SMohammed Gamal "mov $-4, %ecx\n\t" 790fa74f8a6SMohammed Gamal "imul %ecx\n\t"); 791fa74f8a6SMohammed Gamal 792fa74f8a6SMohammed Gamal MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t" 793fa74f8a6SMohammed Gamal "mov $4, %cx\n\t" 794fa74f8a6SMohammed Gamal "imul %cl\n\t"); 795fa74f8a6SMohammed Gamal 796fa74f8a6SMohammed Gamal MK_INSN(imul16_2, "mov $2, %ax\n\t" 797fa74f8a6SMohammed Gamal "mov $4, %cx\n\t" 798fa74f8a6SMohammed Gamal "imul %cx\n\t"); 799fa74f8a6SMohammed Gamal 800fa74f8a6SMohammed Gamal MK_INSN(imul32_2, "mov $2, %eax\n\t" 801fa74f8a6SMohammed Gamal "mov $4, %ecx\n\t" 802fa74f8a6SMohammed Gamal "imul %ecx\n\t"); 803fa74f8a6SMohammed Gamal 80418253fdeSAvi Kivity inregs = (struct regs){ 0 }; 80518253fdeSAvi Kivity 80618253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul8_1); 8076055ea1fSAvi Kivity report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8); 808fa74f8a6SMohammed Gamal 80918253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul16_1); 8106055ea1fSAvi Kivity report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8); 811fa74f8a6SMohammed Gamal 81218253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul32_1); 8136055ea1fSAvi Kivity report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8); 814fa74f8a6SMohammed Gamal 81518253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul8_2); 8166055ea1fSAvi Kivity report("imul 4", R_AX | R_CX | R_DX, 8176055ea1fSAvi Kivity (outregs.eax & 0xffff) == 8 81881050840SAvi Kivity && (outregs.eax & 0xffff0000) == 0x12340000); 819fa74f8a6SMohammed Gamal 82018253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul16_2); 8216055ea1fSAvi Kivity report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8); 822fa74f8a6SMohammed Gamal 82318253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul32_2); 8246055ea1fSAvi Kivity report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8); 825fa74f8a6SMohammed Gamal } 826fa74f8a6SMohammed Gamal 82759317bd1SMohammed Gamal void test_mul() 82859317bd1SMohammed Gamal { 82959317bd1SMohammed Gamal MK_INSN(mul8, "mov $2, %al\n\t" 83059317bd1SMohammed Gamal "mov $4, %cx\n\t" 83159317bd1SMohammed Gamal "imul %cl\n\t"); 83259317bd1SMohammed Gamal 83359317bd1SMohammed Gamal MK_INSN(mul16, "mov $2, %ax\n\t" 83459317bd1SMohammed Gamal "mov $4, %cx\n\t" 83559317bd1SMohammed Gamal "imul %cx\n\t"); 83659317bd1SMohammed Gamal 83759317bd1SMohammed Gamal MK_INSN(mul32, "mov $2, %eax\n\t" 83859317bd1SMohammed Gamal "mov $4, %ecx\n\t" 83959317bd1SMohammed Gamal "imul %ecx\n\t"); 84059317bd1SMohammed Gamal 84118253fdeSAvi Kivity inregs = (struct regs){ 0 }; 84218253fdeSAvi Kivity 84318253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul8); 8446055ea1fSAvi Kivity report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8); 84559317bd1SMohammed Gamal 84618253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul16); 8476055ea1fSAvi Kivity report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8); 84859317bd1SMohammed Gamal 84918253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul32); 8506055ea1fSAvi Kivity report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8); 85159317bd1SMohammed Gamal } 85259317bd1SMohammed Gamal 8530d4c7614SMohammed Gamal void test_div() 8540d4c7614SMohammed Gamal { 8550d4c7614SMohammed Gamal MK_INSN(div8, "mov $257, %ax\n\t" 8560d4c7614SMohammed Gamal "mov $2, %cl\n\t" 8570d4c7614SMohammed Gamal "div %cl\n\t"); 8580d4c7614SMohammed Gamal 8590d4c7614SMohammed Gamal MK_INSN(div16, "mov $512, %ax\n\t" 8600d4c7614SMohammed Gamal "mov $5, %cx\n\t" 8610d4c7614SMohammed Gamal "div %cx\n\t"); 8620d4c7614SMohammed Gamal 8630d4c7614SMohammed Gamal MK_INSN(div32, "mov $512, %eax\n\t" 8640d4c7614SMohammed Gamal "mov $5, %ecx\n\t" 8650d4c7614SMohammed Gamal "div %ecx\n\t"); 8660d4c7614SMohammed Gamal 86718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 86818253fdeSAvi Kivity 86918253fdeSAvi Kivity exec_in_big_real_mode(&insn_div8); 8706055ea1fSAvi Kivity report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384); 8710d4c7614SMohammed Gamal 87218253fdeSAvi Kivity exec_in_big_real_mode(&insn_div16); 8736055ea1fSAvi Kivity report("div 2", R_AX | R_CX | R_DX, 8746055ea1fSAvi Kivity outregs.eax == 102 && outregs.edx == 2); 8750d4c7614SMohammed Gamal 87618253fdeSAvi Kivity exec_in_big_real_mode(&insn_div32); 8776055ea1fSAvi Kivity report("div 3", R_AX | R_CX | R_DX, 8786055ea1fSAvi Kivity outregs.eax == 102 && outregs.edx == 2); 8790d4c7614SMohammed Gamal } 8800d4c7614SMohammed Gamal 8810d4c7614SMohammed Gamal void test_idiv() 8820d4c7614SMohammed Gamal { 8830d4c7614SMohammed Gamal MK_INSN(idiv8, "mov $256, %ax\n\t" 8840d4c7614SMohammed Gamal "mov $-2, %cl\n\t" 8850d4c7614SMohammed Gamal "idiv %cl\n\t"); 8860d4c7614SMohammed Gamal 8870d4c7614SMohammed Gamal MK_INSN(idiv16, "mov $512, %ax\n\t" 8880d4c7614SMohammed Gamal "mov $-2, %cx\n\t" 8890d4c7614SMohammed Gamal "idiv %cx\n\t"); 8900d4c7614SMohammed Gamal 8910d4c7614SMohammed Gamal MK_INSN(idiv32, "mov $512, %eax\n\t" 8920d4c7614SMohammed Gamal "mov $-2, %ecx\n\t" 8930d4c7614SMohammed Gamal "idiv %ecx\n\t"); 8940d4c7614SMohammed Gamal 89518253fdeSAvi Kivity inregs = (struct regs){ 0 }; 89618253fdeSAvi Kivity 89718253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv8); 8986055ea1fSAvi Kivity report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128); 8990d4c7614SMohammed Gamal 90018253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv16); 9016055ea1fSAvi Kivity report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256); 9020d4c7614SMohammed Gamal 90318253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv32); 9046055ea1fSAvi Kivity report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256); 9050d4c7614SMohammed Gamal } 9060d4c7614SMohammed Gamal 9076e293cf5SWei Yongjun void test_cbw(void) 9086e293cf5SWei Yongjun { 9096e293cf5SWei Yongjun MK_INSN(cbw, "mov $0xFE, %eax \n\t" 9106e293cf5SWei Yongjun "cbw\n\t"); 9116e293cf5SWei Yongjun MK_INSN(cwde, "mov $0xFFFE, %eax \n\t" 9126e293cf5SWei Yongjun "cwde\n\t"); 9136e293cf5SWei Yongjun 91418253fdeSAvi Kivity inregs = (struct regs){ 0 }; 91518253fdeSAvi Kivity 91618253fdeSAvi Kivity exec_in_big_real_mode(&insn_cbw); 9176055ea1fSAvi Kivity report("cbq 1", ~0, outregs.eax == 0xFFFE); 9186e293cf5SWei Yongjun 91918253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwde); 9206055ea1fSAvi Kivity report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE); 9216e293cf5SWei Yongjun } 9226e293cf5SWei Yongjun 923eacef4e2SWei Yongjun void test_loopcc(void) 924eacef4e2SWei Yongjun { 925eacef4e2SWei Yongjun MK_INSN(loop, "mov $10, %ecx\n\t" 926eacef4e2SWei Yongjun "1: inc %eax\n\t" 927eacef4e2SWei Yongjun "loop 1b\n\t"); 928eacef4e2SWei Yongjun 929eacef4e2SWei Yongjun MK_INSN(loope, "mov $10, %ecx\n\t" 930eacef4e2SWei Yongjun "mov $1, %eax\n\t" 931eacef4e2SWei Yongjun "1: dec %eax\n\t" 932eacef4e2SWei Yongjun "loope 1b\n\t"); 933eacef4e2SWei Yongjun 934eacef4e2SWei Yongjun MK_INSN(loopne, "mov $10, %ecx\n\t" 935eacef4e2SWei Yongjun "mov $5, %eax\n\t" 936eacef4e2SWei Yongjun "1: dec %eax\n\t" 937eacef4e2SWei Yongjun "loopne 1b\n\t"); 938eacef4e2SWei Yongjun 93918253fdeSAvi Kivity inregs = (struct regs){ 0 }; 940eacef4e2SWei Yongjun 94118253fdeSAvi Kivity exec_in_big_real_mode(&insn_loop); 9426055ea1fSAvi Kivity report("LOOPcc short 1", R_AX, outregs.eax == 10); 94318253fdeSAvi Kivity 94418253fdeSAvi Kivity exec_in_big_real_mode(&insn_loope); 9456055ea1fSAvi Kivity report("LOOPcc short 2", R_AX | R_CX, 9466055ea1fSAvi Kivity outregs.eax == -1 && outregs.ecx == 8); 947eacef4e2SWei Yongjun 94818253fdeSAvi Kivity exec_in_big_real_mode(&insn_loopne); 9496055ea1fSAvi Kivity report("LOOPcc short 3", R_AX | R_CX, 9506055ea1fSAvi Kivity outregs.eax == 0 && outregs.ecx == 5); 951eacef4e2SWei Yongjun } 952eacef4e2SWei Yongjun 953b274feedSAvi Kivity static void test_das(void) 954b274feedSAvi Kivity { 955b274feedSAvi Kivity short i; 95681050840SAvi Kivity u16 nr_fail = 0; 957b274feedSAvi Kivity static unsigned test_cases[1024] = { 958b274feedSAvi Kivity 0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00, 959b274feedSAvi Kivity 0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01, 960b274feedSAvi Kivity 0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02, 961b274feedSAvi Kivity 0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03, 962b274feedSAvi Kivity 0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04, 963b274feedSAvi Kivity 0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05, 964b274feedSAvi Kivity 0x06000606, 0x8701a606, 0x56100006, 0x9711a006, 965b274feedSAvi Kivity 0x02000707, 0x8301a707, 0x12100107, 0x9311a107, 966b274feedSAvi Kivity 0x02000808, 0x8301a808, 0x12100208, 0x9311a208, 967b274feedSAvi Kivity 0x06000909, 0x8701a909, 0x16100309, 0x9711a309, 968b274feedSAvi Kivity 0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a, 969b274feedSAvi Kivity 0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b, 970b274feedSAvi Kivity 0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c, 971b274feedSAvi Kivity 0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d, 972b274feedSAvi Kivity 0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e, 973b274feedSAvi Kivity 0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f, 974b274feedSAvi Kivity 0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10, 975b274feedSAvi Kivity 0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11, 976b274feedSAvi Kivity 0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12, 977b274feedSAvi Kivity 0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13, 978b274feedSAvi Kivity 0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14, 979b274feedSAvi Kivity 0x02001515, 0x8301b515, 0x16100f15, 0x9711af15, 980b274feedSAvi Kivity 0x02001616, 0x8301b616, 0x12101016, 0x9311b016, 981b274feedSAvi Kivity 0x06001717, 0x8701b717, 0x16101117, 0x9711b117, 982b274feedSAvi Kivity 0x06001818, 0x8701b818, 0x16101218, 0x9711b218, 983b274feedSAvi Kivity 0x02001919, 0x8301b919, 0x12101319, 0x9311b319, 984b274feedSAvi Kivity 0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a, 985b274feedSAvi Kivity 0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b, 986b274feedSAvi Kivity 0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c, 987b274feedSAvi Kivity 0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d, 988b274feedSAvi Kivity 0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e, 989b274feedSAvi Kivity 0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f, 990b274feedSAvi Kivity 0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20, 991b274feedSAvi Kivity 0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21, 992b274feedSAvi Kivity 0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22, 993b274feedSAvi Kivity 0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23, 994b274feedSAvi Kivity 0x06002424, 0x8301c424, 0x16101e24, 0x9711be24, 995b274feedSAvi Kivity 0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25, 996b274feedSAvi Kivity 0x02002626, 0x8701c626, 0x12102026, 0x9711c026, 997b274feedSAvi Kivity 0x06002727, 0x8301c727, 0x16102127, 0x9311c127, 998b274feedSAvi Kivity 0x06002828, 0x8301c828, 0x16102228, 0x9311c228, 999b274feedSAvi Kivity 0x02002929, 0x8701c929, 0x12102329, 0x9711c329, 1000b274feedSAvi Kivity 0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a, 1001b274feedSAvi Kivity 0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b, 1002b274feedSAvi Kivity 0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c, 1003b274feedSAvi Kivity 0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d, 1004b274feedSAvi Kivity 0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e, 1005b274feedSAvi Kivity 0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f, 1006b274feedSAvi Kivity 0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30, 1007b274feedSAvi Kivity 0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31, 1008b274feedSAvi Kivity 0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32, 1009b274feedSAvi Kivity 0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33, 1010b274feedSAvi Kivity 0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34, 1011b274feedSAvi Kivity 0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35, 1012b274feedSAvi Kivity 0x06003636, 0x8301d636, 0x16103036, 0x9311d036, 1013b274feedSAvi Kivity 0x02003737, 0x8701d737, 0x12103137, 0x9711d137, 1014b274feedSAvi Kivity 0x02003838, 0x8701d838, 0x12103238, 0x9711d238, 1015b274feedSAvi Kivity 0x06003939, 0x8301d939, 0x16103339, 0x9311d339, 1016b274feedSAvi Kivity 0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a, 1017b274feedSAvi Kivity 0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b, 1018b274feedSAvi Kivity 0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c, 1019b274feedSAvi Kivity 0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d, 1020b274feedSAvi Kivity 0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e, 1021b274feedSAvi Kivity 0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f, 1022b274feedSAvi Kivity 0x02004040, 0x8301e040, 0x16103a40, 0x9311da40, 1023b274feedSAvi Kivity 0x06004141, 0x8701e141, 0x12103b41, 0x9711db41, 1024b274feedSAvi Kivity 0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42, 1025b274feedSAvi Kivity 0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43, 1026b274feedSAvi Kivity 0x06004444, 0x8701e444, 0x12103e44, 0x9711de44, 1027b274feedSAvi Kivity 0x02004545, 0x8301e545, 0x16103f45, 0x9311df45, 1028b274feedSAvi Kivity 0x02004646, 0x8301e646, 0x12104046, 0x9311e046, 1029b274feedSAvi Kivity 0x06004747, 0x8701e747, 0x16104147, 0x9711e147, 1030b274feedSAvi Kivity 0x06004848, 0x8701e848, 0x16104248, 0x9711e248, 1031b274feedSAvi Kivity 0x02004949, 0x8301e949, 0x12104349, 0x9311e349, 1032b274feedSAvi Kivity 0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a, 1033b274feedSAvi Kivity 0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b, 1034b274feedSAvi Kivity 0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c, 1035b274feedSAvi Kivity 0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d, 1036b274feedSAvi Kivity 0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e, 1037b274feedSAvi Kivity 0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f, 1038b274feedSAvi Kivity 0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50, 1039b274feedSAvi Kivity 0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51, 1040b274feedSAvi Kivity 0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52, 1041b274feedSAvi Kivity 0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53, 1042b274feedSAvi Kivity 0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54, 1043b274feedSAvi Kivity 0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55, 1044b274feedSAvi Kivity 0x06005656, 0x8701f656, 0x16105056, 0x9711f056, 1045b274feedSAvi Kivity 0x02005757, 0x8301f757, 0x12105157, 0x9311f157, 1046b274feedSAvi Kivity 0x02005858, 0x8301f858, 0x12105258, 0x9311f258, 1047b274feedSAvi Kivity 0x06005959, 0x8701f959, 0x16105359, 0x9711f359, 1048b274feedSAvi Kivity 0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a, 1049b274feedSAvi Kivity 0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b, 1050b274feedSAvi Kivity 0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c, 1051b274feedSAvi Kivity 0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d, 1052b274feedSAvi Kivity 0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e, 1053b274feedSAvi Kivity 0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f, 1054b274feedSAvi Kivity 0x06006060, 0x47010060, 0x16105a60, 0x9711fa60, 1055b274feedSAvi Kivity 0x02006161, 0x03010161, 0x12105b61, 0x9311fb61, 1056b274feedSAvi Kivity 0x02006262, 0x03010262, 0x16105c62, 0x9711fc62, 1057b274feedSAvi Kivity 0x06006363, 0x07010363, 0x12105d63, 0x9311fd63, 1058b274feedSAvi Kivity 0x02006464, 0x03010464, 0x12105e64, 0x9311fe64, 1059b274feedSAvi Kivity 0x06006565, 0x07010565, 0x16105f65, 0x9711ff65, 1060b274feedSAvi Kivity 0x06006666, 0x07010666, 0x16106066, 0x57110066, 1061b274feedSAvi Kivity 0x02006767, 0x03010767, 0x12106167, 0x13110167, 1062b274feedSAvi Kivity 0x02006868, 0x03010868, 0x12106268, 0x13110268, 1063b274feedSAvi Kivity 0x06006969, 0x07010969, 0x16106369, 0x17110369, 1064b274feedSAvi Kivity 0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a, 1065b274feedSAvi Kivity 0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b, 1066b274feedSAvi Kivity 0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c, 1067b274feedSAvi Kivity 0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d, 1068b274feedSAvi Kivity 0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e, 1069b274feedSAvi Kivity 0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f, 1070b274feedSAvi Kivity 0x02007070, 0x03011070, 0x16106a70, 0x17110a70, 1071b274feedSAvi Kivity 0x06007171, 0x07011171, 0x12106b71, 0x13110b71, 1072b274feedSAvi Kivity 0x06007272, 0x07011272, 0x16106c72, 0x17110c72, 1073b274feedSAvi Kivity 0x02007373, 0x03011373, 0x12106d73, 0x13110d73, 1074b274feedSAvi Kivity 0x06007474, 0x07011474, 0x12106e74, 0x13110e74, 1075b274feedSAvi Kivity 0x02007575, 0x03011575, 0x16106f75, 0x17110f75, 1076b274feedSAvi Kivity 0x02007676, 0x03011676, 0x12107076, 0x13111076, 1077b274feedSAvi Kivity 0x06007777, 0x07011777, 0x16107177, 0x17111177, 1078b274feedSAvi Kivity 0x06007878, 0x07011878, 0x16107278, 0x17111278, 1079b274feedSAvi Kivity 0x02007979, 0x03011979, 0x12107379, 0x13111379, 1080b274feedSAvi Kivity 0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a, 1081b274feedSAvi Kivity 0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b, 1082b274feedSAvi Kivity 0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c, 1083b274feedSAvi Kivity 0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d, 1084b274feedSAvi Kivity 0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e, 1085b274feedSAvi Kivity 0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f, 1086b274feedSAvi Kivity 0x82008080, 0x03012080, 0x12107a80, 0x13111a80, 1087b274feedSAvi Kivity 0x86008181, 0x07012181, 0x16107b81, 0x17111b81, 1088b274feedSAvi Kivity 0x86008282, 0x07012282, 0x12107c82, 0x13111c82, 1089b274feedSAvi Kivity 0x82008383, 0x03012383, 0x16107d83, 0x17111d83, 1090b274feedSAvi Kivity 0x86008484, 0x07012484, 0x16107e84, 0x17111e84, 1091b274feedSAvi Kivity 0x82008585, 0x03012585, 0x12107f85, 0x13111f85, 1092b274feedSAvi Kivity 0x82008686, 0x03012686, 0x92108086, 0x13112086, 1093b274feedSAvi Kivity 0x86008787, 0x07012787, 0x96108187, 0x17112187, 1094b274feedSAvi Kivity 0x86008888, 0x07012888, 0x96108288, 0x17112288, 1095b274feedSAvi Kivity 0x82008989, 0x03012989, 0x92108389, 0x13112389, 1096b274feedSAvi Kivity 0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a, 1097b274feedSAvi Kivity 0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b, 1098b274feedSAvi Kivity 0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c, 1099b274feedSAvi Kivity 0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d, 1100b274feedSAvi Kivity 0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e, 1101b274feedSAvi Kivity 0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f, 1102b274feedSAvi Kivity 0x86009090, 0x07013090, 0x92108a90, 0x13112a90, 1103b274feedSAvi Kivity 0x82009191, 0x03013191, 0x96108b91, 0x17112b91, 1104b274feedSAvi Kivity 0x82009292, 0x03013292, 0x92108c92, 0x13112c92, 1105b274feedSAvi Kivity 0x86009393, 0x07013393, 0x96108d93, 0x17112d93, 1106b274feedSAvi Kivity 0x82009494, 0x03013494, 0x96108e94, 0x17112e94, 1107b274feedSAvi Kivity 0x86009595, 0x07013595, 0x92108f95, 0x13112f95, 1108b274feedSAvi Kivity 0x86009696, 0x07013696, 0x96109096, 0x17113096, 1109b274feedSAvi Kivity 0x82009797, 0x03013797, 0x92109197, 0x13113197, 1110b274feedSAvi Kivity 0x82009898, 0x03013898, 0x92109298, 0x13113298, 1111b274feedSAvi Kivity 0x86009999, 0x07013999, 0x96109399, 0x17113399, 1112b274feedSAvi Kivity 0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a, 1113b274feedSAvi Kivity 0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b, 1114b274feedSAvi Kivity 0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c, 1115b274feedSAvi Kivity 0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d, 1116b274feedSAvi Kivity 0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e, 1117b274feedSAvi Kivity 0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f, 1118b274feedSAvi Kivity 0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0, 1119b274feedSAvi Kivity 0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1, 1120b274feedSAvi Kivity 0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2, 1121b274feedSAvi Kivity 0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3, 1122b274feedSAvi Kivity 0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4, 1123b274feedSAvi Kivity 0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5, 1124b274feedSAvi Kivity 0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6, 1125b274feedSAvi Kivity 0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7, 1126b274feedSAvi Kivity 0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8, 1127b274feedSAvi Kivity 0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9, 1128b274feedSAvi Kivity 0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa, 1129b274feedSAvi Kivity 0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab, 1130b274feedSAvi Kivity 0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac, 1131b274feedSAvi Kivity 0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad, 1132b274feedSAvi Kivity 0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae, 1133b274feedSAvi Kivity 0x130049af, 0x130149af, 0x131049af, 0x131149af, 1134b274feedSAvi Kivity 0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0, 1135b274feedSAvi Kivity 0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1, 1136b274feedSAvi Kivity 0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2, 1137b274feedSAvi Kivity 0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3, 1138b274feedSAvi Kivity 0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4, 1139b274feedSAvi Kivity 0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5, 1140b274feedSAvi Kivity 0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6, 1141b274feedSAvi Kivity 0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7, 1142b274feedSAvi Kivity 0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8, 1143b274feedSAvi Kivity 0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9, 1144b274feedSAvi Kivity 0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba, 1145b274feedSAvi Kivity 0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb, 1146b274feedSAvi Kivity 0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc, 1147b274feedSAvi Kivity 0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd, 1148b274feedSAvi Kivity 0x130058be, 0x130158be, 0x131058be, 0x131158be, 1149b274feedSAvi Kivity 0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf, 1150b274feedSAvi Kivity 0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0, 1151b274feedSAvi Kivity 0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1, 1152b274feedSAvi Kivity 0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2, 1153b274feedSAvi Kivity 0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3, 1154b274feedSAvi Kivity 0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4, 1155b274feedSAvi Kivity 0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5, 1156b274feedSAvi Kivity 0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6, 1157b274feedSAvi Kivity 0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7, 1158b274feedSAvi Kivity 0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8, 1159b274feedSAvi Kivity 0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9, 1160b274feedSAvi Kivity 0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca, 1161b274feedSAvi Kivity 0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb, 1162b274feedSAvi Kivity 0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc, 1163b274feedSAvi Kivity 0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd, 1164b274feedSAvi Kivity 0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce, 1165b274feedSAvi Kivity 0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf, 1166b274feedSAvi Kivity 0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0, 1167b274feedSAvi Kivity 0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1, 1168b274feedSAvi Kivity 0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2, 1169b274feedSAvi Kivity 0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3, 1170b274feedSAvi Kivity 0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4, 1171b274feedSAvi Kivity 0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5, 1172b274feedSAvi Kivity 0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6, 1173b274feedSAvi Kivity 0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7, 1174b274feedSAvi Kivity 0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8, 1175b274feedSAvi Kivity 0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9, 1176b274feedSAvi Kivity 0x170074da, 0x170174da, 0x171074da, 0x171174da, 1177b274feedSAvi Kivity 0x130075db, 0x130175db, 0x131075db, 0x131175db, 1178b274feedSAvi Kivity 0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc, 1179b274feedSAvi Kivity 0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd, 1180b274feedSAvi Kivity 0x170078de, 0x170178de, 0x171078de, 0x171178de, 1181b274feedSAvi Kivity 0x130079df, 0x130179df, 0x131079df, 0x131179df, 1182b274feedSAvi Kivity 0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0, 1183b274feedSAvi Kivity 0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1, 1184b274feedSAvi Kivity 0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2, 1185b274feedSAvi Kivity 0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3, 1186b274feedSAvi Kivity 0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4, 1187b274feedSAvi Kivity 0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5, 1188b274feedSAvi Kivity 0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6, 1189b274feedSAvi Kivity 0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7, 1190b274feedSAvi Kivity 0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8, 1191b274feedSAvi Kivity 0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9, 1192b274feedSAvi Kivity 0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea, 1193b274feedSAvi Kivity 0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb, 1194b274feedSAvi Kivity 0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec, 1195b274feedSAvi Kivity 0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed, 1196b274feedSAvi Kivity 0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee, 1197b274feedSAvi Kivity 0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef, 1198b274feedSAvi Kivity 0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0, 1199b274feedSAvi Kivity 0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1, 1200b274feedSAvi Kivity 0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2, 1201b274feedSAvi Kivity 0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3, 1202b274feedSAvi Kivity 0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4, 1203b274feedSAvi Kivity 0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5, 1204b274feedSAvi Kivity 0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6, 1205b274feedSAvi Kivity 0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7, 1206b274feedSAvi Kivity 0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8, 1207b274feedSAvi Kivity 0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9, 1208b274feedSAvi Kivity 0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa, 1209b274feedSAvi Kivity 0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb, 1210b274feedSAvi Kivity 0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc, 1211b274feedSAvi Kivity 0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd, 1212b274feedSAvi Kivity 0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe, 1213b274feedSAvi Kivity 0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff, 1214b274feedSAvi Kivity }; 1215b274feedSAvi Kivity 1216b274feedSAvi Kivity MK_INSN(das, "das"); 1217b274feedSAvi Kivity 121818253fdeSAvi Kivity inregs = (struct regs){ 0 }; 121918253fdeSAvi Kivity 1220b274feedSAvi Kivity for (i = 0; i < 1024; ++i) { 1221b274feedSAvi Kivity unsigned tmp = test_cases[i]; 1222b274feedSAvi Kivity inregs.eax = tmp & 0xff; 1223b274feedSAvi Kivity inregs.eflags = (tmp >> 16) & 0xff; 122418253fdeSAvi Kivity exec_in_big_real_mode(&insn_das); 122518253fdeSAvi Kivity if (!regs_equal(R_AX) 1226b274feedSAvi Kivity || outregs.eax != ((tmp >> 8) & 0xff) 1227b274feedSAvi Kivity || (outregs.eflags & 0xff) != (tmp >> 24)) { 122881050840SAvi Kivity ++nr_fail; 122981050840SAvi Kivity break; 1230b274feedSAvi Kivity } 1231b274feedSAvi Kivity } 12326055ea1fSAvi Kivity report("DAS", ~0, nr_fail == 0); 1233b274feedSAvi Kivity } 1234b274feedSAvi Kivity 12350cbd5b06SMohammed Gamal void test_cwd_cdq() 12360cbd5b06SMohammed Gamal { 12370cbd5b06SMohammed Gamal /* Sign-bit set */ 12380cbd5b06SMohammed Gamal MK_INSN(cwd_1, "mov $0x8000, %ax\n\t" 12390cbd5b06SMohammed Gamal "cwd\n\t"); 12400cbd5b06SMohammed Gamal 12410cbd5b06SMohammed Gamal /* Sign-bit not set */ 12420cbd5b06SMohammed Gamal MK_INSN(cwd_2, "mov $0x1000, %ax\n\t" 12430cbd5b06SMohammed Gamal "cwd\n\t"); 12440cbd5b06SMohammed Gamal 12450cbd5b06SMohammed Gamal /* Sign-bit set */ 12460cbd5b06SMohammed Gamal MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t" 12470cbd5b06SMohammed Gamal "cdq\n\t"); 12480cbd5b06SMohammed Gamal 12490cbd5b06SMohammed Gamal /* Sign-bit not set */ 12500cbd5b06SMohammed Gamal MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t" 12510cbd5b06SMohammed Gamal "cdq\n\t"); 12520cbd5b06SMohammed Gamal 125318253fdeSAvi Kivity inregs = (struct regs){ 0 }; 125418253fdeSAvi Kivity 125518253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwd_1); 12566055ea1fSAvi Kivity report("cwd 1", R_AX | R_DX, 12576055ea1fSAvi Kivity outregs.eax == 0x8000 && outregs.edx == 0xffff); 12580cbd5b06SMohammed Gamal 125918253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwd_2); 12606055ea1fSAvi Kivity report("cwd 2", R_AX | R_DX, 12616055ea1fSAvi Kivity outregs.eax == 0x1000 && outregs.edx == 0); 12620cbd5b06SMohammed Gamal 126318253fdeSAvi Kivity exec_in_big_real_mode(&insn_cdq_1); 12646055ea1fSAvi Kivity report("cdq 1", R_AX | R_DX, 12656055ea1fSAvi Kivity outregs.eax == 0x80000000 && outregs.edx == 0xffffffff); 12660cbd5b06SMohammed Gamal 126718253fdeSAvi Kivity exec_in_big_real_mode(&insn_cdq_2); 12686055ea1fSAvi Kivity report("cdq 2", R_AX | R_DX, 12696055ea1fSAvi Kivity outregs.eax == 0x10000000 && outregs.edx == 0); 12700cbd5b06SMohammed Gamal } 12710cbd5b06SMohammed Gamal 127237f51a4aSWei Yongjun static struct { 127337f51a4aSWei Yongjun void *address; 127437f51a4aSWei Yongjun unsigned short sel; 127537f51a4aSWei Yongjun } __attribute__((packed)) desc = { 127637f51a4aSWei Yongjun (void *)0x1234, 127737f51a4aSWei Yongjun 0x10, 127837f51a4aSWei Yongjun }; 127937f51a4aSWei Yongjun 128037f51a4aSWei Yongjun void test_lds_lss() 128137f51a4aSWei Yongjun { 128237f51a4aSWei Yongjun inregs = (struct regs){ .ebx = (unsigned long)&desc }; 128337f51a4aSWei Yongjun 128437f51a4aSWei Yongjun MK_INSN(lds, "push %ds\n\t" 128537f51a4aSWei Yongjun "lds (%ebx), %eax\n\t" 128637f51a4aSWei Yongjun "mov %ds, %ebx\n\t" 128737f51a4aSWei Yongjun "pop %ds\n\t"); 128837f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lds); 128937f51a4aSWei Yongjun report("lds", R_AX | R_BX, 129037f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 129137f51a4aSWei Yongjun outregs.ebx == desc.sel); 129237f51a4aSWei Yongjun 129337f51a4aSWei Yongjun MK_INSN(les, "push %es\n\t" 129437f51a4aSWei Yongjun "les (%ebx), %eax\n\t" 129537f51a4aSWei Yongjun "mov %es, %ebx\n\t" 129637f51a4aSWei Yongjun "pop %es\n\t"); 129737f51a4aSWei Yongjun exec_in_big_real_mode(&insn_les); 129837f51a4aSWei Yongjun report("les", R_AX | R_BX, 129937f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 130037f51a4aSWei Yongjun outregs.ebx == desc.sel); 130137f51a4aSWei Yongjun 130237f51a4aSWei Yongjun MK_INSN(lfs, "push %fs\n\t" 130337f51a4aSWei Yongjun "lfs (%ebx), %eax\n\t" 130437f51a4aSWei Yongjun "mov %fs, %ebx\n\t" 130537f51a4aSWei Yongjun "pop %fs\n\t"); 130637f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lfs); 130737f51a4aSWei Yongjun report("lfs", R_AX | R_BX, 130837f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 130937f51a4aSWei Yongjun outregs.ebx == desc.sel); 131037f51a4aSWei Yongjun 131137f51a4aSWei Yongjun MK_INSN(lgs, "push %gs\n\t" 131237f51a4aSWei Yongjun "lgs (%ebx), %eax\n\t" 131337f51a4aSWei Yongjun "mov %gs, %ebx\n\t" 131437f51a4aSWei Yongjun "pop %gs\n\t"); 131537f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lgs); 131637f51a4aSWei Yongjun report("lgs", R_AX | R_BX, 131737f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 131837f51a4aSWei Yongjun outregs.ebx == desc.sel); 131937f51a4aSWei Yongjun 132037f51a4aSWei Yongjun MK_INSN(lss, "push %ss\n\t" 132137f51a4aSWei Yongjun "lss (%ebx), %eax\n\t" 132237f51a4aSWei Yongjun "mov %ss, %ebx\n\t" 132337f51a4aSWei Yongjun "pop %ss\n\t"); 132437f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lss); 132537f51a4aSWei Yongjun report("lss", R_AX | R_BX, 132637f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 132737f51a4aSWei Yongjun outregs.ebx == desc.sel); 132837f51a4aSWei Yongjun } 132937f51a4aSWei Yongjun 1330b1c7c575SWei Yongjun void test_jcxz(void) 1331b1c7c575SWei Yongjun { 1332b1c7c575SWei Yongjun MK_INSN(jcxz1, "jcxz 1f\n\t" 1333b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1334b1c7c575SWei Yongjun "1:\n\t"); 1335b1c7c575SWei Yongjun MK_INSN(jcxz2, "mov $0x100, %ecx\n\t" 1336b1c7c575SWei Yongjun "jcxz 1f\n\t" 1337b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1338b1c7c575SWei Yongjun "mov $0, %ecx\n\t" 1339b1c7c575SWei Yongjun "1:\n\t"); 1340b1c7c575SWei Yongjun MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t" 1341b1c7c575SWei Yongjun "jcxz 1f\n\t" 1342b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1343b1c7c575SWei Yongjun "1:\n\t"); 1344b1c7c575SWei Yongjun MK_INSN(jecxz1, "jecxz 1f\n\t" 1345b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1346b1c7c575SWei Yongjun "1:\n\t"); 1347b1c7c575SWei Yongjun MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t" 1348b1c7c575SWei Yongjun "jecxz 1f\n\t" 1349b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1350b1c7c575SWei Yongjun "mov $0, %ecx\n\t" 1351b1c7c575SWei Yongjun "1:\n\t"); 1352b1c7c575SWei Yongjun 1353b1c7c575SWei Yongjun inregs = (struct regs){ 0 }; 1354b1c7c575SWei Yongjun 1355b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jcxz1); 1356b1c7c575SWei Yongjun report("jcxz short 1", 0, 1); 1357b1c7c575SWei Yongjun 1358b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jcxz2); 1359b1c7c575SWei Yongjun report("jcxz short 2", R_AX, outregs.eax == 0x1234); 1360b1c7c575SWei Yongjun 1361b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jcxz3); 1362b1c7c575SWei Yongjun report("jcxz short 3", R_CX, outregs.ecx == 0x10000); 1363b1c7c575SWei Yongjun 1364b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jecxz1); 1365b1c7c575SWei Yongjun report("jecxz short 1", 0, 1); 1366b1c7c575SWei Yongjun 1367b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jecxz2); 1368b1c7c575SWei Yongjun report("jecxz short 2", R_AX, outregs.eax == 0x1234); 1369b1c7c575SWei Yongjun } 1370b1c7c575SWei Yongjun 13718f578e98SAvi Kivity static void test_cpuid(void) 13728f578e98SAvi Kivity { 13738f578e98SAvi Kivity MK_INSN(cpuid, "cpuid"); 13748f578e98SAvi Kivity unsigned function = 0x1234; 13758f578e98SAvi Kivity unsigned eax, ebx, ecx, edx; 13768f578e98SAvi Kivity 13778f578e98SAvi Kivity inregs.eax = eax = function; 1378*18ba9083SGleb Natapov inregs.ecx = ecx = 0; 13798f578e98SAvi Kivity asm("cpuid" : "+a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)); 13808f578e98SAvi Kivity exec_in_big_real_mode(&insn_cpuid); 13818f578e98SAvi Kivity report("cpuid", R_AX|R_BX|R_CX|R_DX, 13828f578e98SAvi Kivity outregs.eax == eax && outregs.ebx == ebx 13838f578e98SAvi Kivity && outregs.ecx == ecx && outregs.edx == edx); 13848f578e98SAvi Kivity } 13858f578e98SAvi Kivity 1386ed93f43bSAvi Kivity static void test_ss_base_for_esp_ebp(void) 1387ed93f43bSAvi Kivity { 1388ed93f43bSAvi Kivity MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss"); 1389ed93f43bSAvi Kivity MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss"); 1390ed93f43bSAvi Kivity static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 }; 1391ed93f43bSAvi Kivity 1392ed93f43bSAvi Kivity inregs.ebx = 1; 1393ed93f43bSAvi Kivity inregs.ebp = (unsigned)array; 1394ed93f43bSAvi Kivity exec_in_big_real_mode(&insn_ssrel1); 1395ed93f43bSAvi Kivity report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321); 1396ed93f43bSAvi Kivity inregs.ebx = 1; 1397ed93f43bSAvi Kivity inregs.ebp = (unsigned)array; 1398ed93f43bSAvi Kivity inregs.edi = 0; 1399ed93f43bSAvi Kivity exec_in_big_real_mode(&insn_ssrel2); 1400ed93f43bSAvi Kivity report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321); 1401ed93f43bSAvi Kivity } 1402ed93f43bSAvi Kivity 1403c2281fa4SAvi Kivity static void test_sgdt_sidt(void) 1404c2281fa4SAvi Kivity { 1405c2281fa4SAvi Kivity MK_INSN(sgdt, "sgdtw (%eax)"); 1406c2281fa4SAvi Kivity MK_INSN(sidt, "sidtw (%eax)"); 1407c2281fa4SAvi Kivity unsigned x, y; 1408c2281fa4SAvi Kivity 1409c2281fa4SAvi Kivity inregs.eax = (unsigned)&y; 1410c2281fa4SAvi Kivity asm volatile("sgdtw %0" : "=m"(x)); 1411c2281fa4SAvi Kivity exec_in_big_real_mode(&insn_sgdt); 1412c2281fa4SAvi Kivity report("sgdt", 0, x == y); 1413c2281fa4SAvi Kivity 1414c2281fa4SAvi Kivity inregs.eax = (unsigned)&y; 1415c2281fa4SAvi Kivity asm volatile("sidtw %0" : "=m"(x)); 1416c2281fa4SAvi Kivity exec_in_big_real_mode(&insn_sidt); 1417c2281fa4SAvi Kivity report("sidt", 0, x == y); 1418c2281fa4SAvi Kivity } 1419c2281fa4SAvi Kivity 142088b6dac4SPaolo Bonzini static void test_sahf(void) 142188b6dac4SPaolo Bonzini { 142288b6dac4SPaolo Bonzini MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw"); 142388b6dac4SPaolo Bonzini 142488b6dac4SPaolo Bonzini inregs.eax = 0xfd00; 142588b6dac4SPaolo Bonzini exec_in_big_real_mode(&insn_sahf); 142688b6dac4SPaolo Bonzini report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7)); 142788b6dac4SPaolo Bonzini } 142888b6dac4SPaolo Bonzini 14297ae3645aSAvi Kivity static void test_lahf(void) 14307ae3645aSAvi Kivity { 14317ae3645aSAvi Kivity MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf"); 14327ae3645aSAvi Kivity 14337ae3645aSAvi Kivity inregs.eax = 0xc7; 14347ae3645aSAvi Kivity exec_in_big_real_mode(&insn_lahf); 14357ae3645aSAvi Kivity report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax); 14367ae3645aSAvi Kivity } 14377ae3645aSAvi Kivity 1438fd9ea640SAvi Kivity static void test_movzx_movsx(void) 1439fd9ea640SAvi Kivity { 1440fd9ea640SAvi Kivity MK_INSN(movsx, "movsx %al, %ebx"); 1441fd9ea640SAvi Kivity MK_INSN(movzx, "movzx %al, %ebx"); 14423013e079SGleb Natapov MK_INSN(movzsah, "movsx %ah, %ebx"); 14433013e079SGleb Natapov MK_INSN(movzxah, "movzx %ah, %ebx"); 1444fd9ea640SAvi Kivity 1445fd9ea640SAvi Kivity inregs.eax = 0x1234569c; 14463013e079SGleb Natapov inregs.esp = 0xffff; 1447fd9ea640SAvi Kivity exec_in_big_real_mode(&insn_movsx); 1448fd9ea640SAvi Kivity report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax); 1449fd9ea640SAvi Kivity exec_in_big_real_mode(&insn_movzx); 1450fd9ea640SAvi Kivity report("movzx", R_BX, outregs.ebx == (unsigned char)inregs.eax); 14513013e079SGleb Natapov exec_in_big_real_mode(&insn_movzsah); 14523013e079SGleb Natapov report("movsx ah", R_BX, outregs.ebx == (signed char)(inregs.eax>>8)); 14533013e079SGleb Natapov exec_in_big_real_mode(&insn_movzxah); 14543013e079SGleb Natapov report("movzx ah", R_BX, outregs.ebx == (unsigned char)(inregs.eax >> 8)); 1455fd9ea640SAvi Kivity } 1456fd9ea640SAvi Kivity 1457b493b2e8SAvi Kivity static void test_bswap(void) 1458b493b2e8SAvi Kivity { 1459b493b2e8SAvi Kivity MK_INSN(bswap, "bswap %ecx"); 1460b493b2e8SAvi Kivity 1461b493b2e8SAvi Kivity inregs.ecx = 0x12345678; 1462b493b2e8SAvi Kivity exec_in_big_real_mode(&insn_bswap); 1463b493b2e8SAvi Kivity report("bswap", R_CX, outregs.ecx == 0x78563412); 1464b493b2e8SAvi Kivity } 1465b493b2e8SAvi Kivity 14668cd86387SGleb Natapov static void test_aad(void) 14678cd86387SGleb Natapov { 14688cd86387SGleb Natapov MK_INSN(aad, "aad"); 14698cd86387SGleb Natapov 14708cd86387SGleb Natapov inregs.eax = 0x12345678; 14718cd86387SGleb Natapov exec_in_big_real_mode(&insn_aad); 14728cd86387SGleb Natapov report("aad", R_AX, outregs.eax == 0x123400d4); 14738cd86387SGleb Natapov } 14748cd86387SGleb Natapov 14752a9b5718SPaolo Bonzini static void test_aam(void) 14762a9b5718SPaolo Bonzini { 14772a9b5718SPaolo Bonzini MK_INSN(aam, "aam"); 14782a9b5718SPaolo Bonzini 14792a9b5718SPaolo Bonzini inregs.eax = 0x76543210; 14802a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_aam); 14812a9b5718SPaolo Bonzini report("aam", R_AX, outregs.eax == 0x76540106); 14822a9b5718SPaolo Bonzini } 14832a9b5718SPaolo Bonzini 14842a9b5718SPaolo Bonzini static void test_xlat(void) 14852a9b5718SPaolo Bonzini { 14862a9b5718SPaolo Bonzini MK_INSN(xlat, "xlat"); 14872a9b5718SPaolo Bonzini u8 table[256]; 14882a9b5718SPaolo Bonzini int i; 14892a9b5718SPaolo Bonzini 14902a9b5718SPaolo Bonzini for (i = 0; i < 256; i++) { 14912a9b5718SPaolo Bonzini table[i] = i + 1; 14922a9b5718SPaolo Bonzini } 14932a9b5718SPaolo Bonzini 14942a9b5718SPaolo Bonzini inregs.eax = 0x89abcdef; 14952a9b5718SPaolo Bonzini inregs.ebx = (u32)table; 14962a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_xlat); 14972a9b5718SPaolo Bonzini report("xlat", R_AX, outregs.eax == 0x89abcdf0); 14982a9b5718SPaolo Bonzini } 14992a9b5718SPaolo Bonzini 15002a9b5718SPaolo Bonzini static void test_salc(void) 15012a9b5718SPaolo Bonzini { 15022a9b5718SPaolo Bonzini MK_INSN(clc_salc, "clc; .byte 0xd6"); 15032a9b5718SPaolo Bonzini MK_INSN(stc_salc, "stc; .byte 0xd6"); 15042a9b5718SPaolo Bonzini 15052a9b5718SPaolo Bonzini inregs.eax = 0x12345678; 15062a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_clc_salc); 15072a9b5718SPaolo Bonzini report("salc (1)", R_AX, outregs.eax == 0x12345600); 15082a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_stc_salc); 15092a9b5718SPaolo Bonzini report("salc (2)", R_AX, outregs.eax == 0x123456ff); 15102a9b5718SPaolo Bonzini } 15112a9b5718SPaolo Bonzini 15120987db7aSGleb Natapov static void test_fninit(void) 15130987db7aSGleb Natapov { 15140987db7aSGleb Natapov u16 fcw = -1, fsw = -1; 15150987db7aSGleb Natapov MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)"); 15160987db7aSGleb Natapov 15170987db7aSGleb Natapov inregs.eax = (u32)&fsw; 15180987db7aSGleb Natapov inregs.ebx = (u32)&fcw; 15190987db7aSGleb Natapov 15200987db7aSGleb Natapov exec_in_big_real_mode(&insn_fninit); 15210987db7aSGleb Natapov report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f); 15220987db7aSGleb Natapov } 15230987db7aSGleb Natapov 15241a4c03a0SArthur Chunqi Li static void test_nopl(void) 15251a4c03a0SArthur Chunqi Li { 15261a4c03a0SArthur Chunqi Li MK_INSN(nopl1, ".byte 0x90\n\r"); // 1 byte nop 15271a4c03a0SArthur Chunqi Li MK_INSN(nopl2, ".byte 0x66, 0x90\n\r"); // 2 bytes nop 15281a4c03a0SArthur Chunqi Li MK_INSN(nopl3, ".byte 0x0f, 0x1f, 0x00\n\r"); // 3 bytes nop 15291a4c03a0SArthur Chunqi Li MK_INSN(nopl4, ".byte 0x0f, 0x1f, 0x40, 0x00\n\r"); // 4 bytes nop 15301a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl1); 15311a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl2); 15321a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl3); 15331a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl4); 15341a4c03a0SArthur Chunqi Li report("nopl", 0, 1); 15351a4c03a0SArthur Chunqi Li } 15361a4c03a0SArthur Chunqi Li 15377d36db35SAvi Kivity void realmode_start(void) 15387d36db35SAvi Kivity { 15397d36db35SAvi Kivity test_null(); 15407d36db35SAvi Kivity 15417d36db35SAvi Kivity test_shld(); 15427d36db35SAvi Kivity test_push_pop(); 15437d36db35SAvi Kivity test_pusha_popa(); 15447d36db35SAvi Kivity test_mov_imm(); 15457d36db35SAvi Kivity test_cmp_imm(); 15467d36db35SAvi Kivity test_add_imm(); 15477d36db35SAvi Kivity test_sub_imm(); 15487d36db35SAvi Kivity test_xor_imm(); 15497d36db35SAvi Kivity test_io(); 15507d36db35SAvi Kivity test_eflags_insn(); 15517d36db35SAvi Kivity test_jcc_short(); 15527d36db35SAvi Kivity test_jcc_near(); 15537d36db35SAvi Kivity /* test_call() uses short jump so call it after testing jcc */ 15547d36db35SAvi Kivity test_call(); 15557d36db35SAvi Kivity /* long jmp test uses call near so test it after testing call */ 15567d36db35SAvi Kivity test_long_jmp(); 15577d36db35SAvi Kivity test_xchg(); 15587d36db35SAvi Kivity test_iret(); 155996b9ca1eSMohammed Gamal test_int(); 1560fa74f8a6SMohammed Gamal test_imul(); 156159317bd1SMohammed Gamal test_mul(); 15620d4c7614SMohammed Gamal test_div(); 15630d4c7614SMohammed Gamal test_idiv(); 1564eacef4e2SWei Yongjun test_loopcc(); 15656e293cf5SWei Yongjun test_cbw(); 15660cbd5b06SMohammed Gamal test_cwd_cdq(); 1567b274feedSAvi Kivity test_das(); 156837f51a4aSWei Yongjun test_lds_lss(); 1569b1c7c575SWei Yongjun test_jcxz(); 15708f578e98SAvi Kivity test_cpuid(); 1571ed93f43bSAvi Kivity test_ss_base_for_esp_ebp(); 1572c2281fa4SAvi Kivity test_sgdt_sidt(); 15737ae3645aSAvi Kivity test_lahf(); 157488b6dac4SPaolo Bonzini test_sahf(); 1575fd9ea640SAvi Kivity test_movzx_movsx(); 1576b493b2e8SAvi Kivity test_bswap(); 15778cd86387SGleb Natapov test_aad(); 15782a9b5718SPaolo Bonzini test_aam(); 15792a9b5718SPaolo Bonzini test_xlat(); 15802a9b5718SPaolo Bonzini test_salc(); 15810987db7aSGleb Natapov test_fninit(); 15821a4c03a0SArthur Chunqi Li test_nopl(); 15837d36db35SAvi Kivity 15847d36db35SAvi Kivity exit(0); 15857d36db35SAvi Kivity } 15867d36db35SAvi Kivity 15877d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff }; 15887d36db35SAvi Kivity 15897d36db35SAvi Kivity struct __attribute__((packed)) { 15907d36db35SAvi Kivity unsigned short limit; 15917d36db35SAvi Kivity void *base; 15927d36db35SAvi Kivity } r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt }; 15937d36db35SAvi Kivity 15947d36db35SAvi Kivity asm( 15957d36db35SAvi Kivity ".section .init \n\t" 15967d36db35SAvi Kivity 15977d36db35SAvi Kivity ".code32 \n\t" 15987d36db35SAvi Kivity 15997d36db35SAvi Kivity "mb_magic = 0x1BADB002 \n\t" 16007d36db35SAvi Kivity "mb_flags = 0x0 \n\t" 16017d36db35SAvi Kivity 16027d36db35SAvi Kivity "# multiboot header \n\t" 16037d36db35SAvi Kivity ".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t" 16047d36db35SAvi Kivity 16057d36db35SAvi Kivity ".globl start \n\t" 16067d36db35SAvi Kivity ".data \n\t" 16077d36db35SAvi Kivity ". = . + 4096 \n\t" 16087d36db35SAvi Kivity "stacktop: \n\t" 16097d36db35SAvi Kivity 16107d36db35SAvi Kivity ".text \n\t" 16117d36db35SAvi Kivity "start: \n\t" 16127d36db35SAvi Kivity "lgdt r_gdt_descr \n\t" 16137d36db35SAvi Kivity "ljmp $8, $1f; 1: \n\t" 16147d36db35SAvi Kivity ".code16gcc \n\t" 16157d36db35SAvi Kivity "mov $16, %eax \n\t" 16167d36db35SAvi Kivity "mov %ax, %ds \n\t" 16177d36db35SAvi Kivity "mov %ax, %es \n\t" 16187d36db35SAvi Kivity "mov %ax, %fs \n\t" 16197d36db35SAvi Kivity "mov %ax, %gs \n\t" 16207d36db35SAvi Kivity "mov %ax, %ss \n\t" 16217d36db35SAvi Kivity "mov %cr0, %eax \n\t" 16227d36db35SAvi Kivity "btc $0, %eax \n\t" 16237d36db35SAvi Kivity "mov %eax, %cr0 \n\t" 16247d36db35SAvi Kivity "ljmp $0, $realmode_entry \n\t" 16257d36db35SAvi Kivity 16267d36db35SAvi Kivity "realmode_entry: \n\t" 16277d36db35SAvi Kivity 16287d36db35SAvi Kivity "xor %ax, %ax \n\t" 16297d36db35SAvi Kivity "mov %ax, %ds \n\t" 16307d36db35SAvi Kivity "mov %ax, %es \n\t" 16317d36db35SAvi Kivity "mov %ax, %ss \n\t" 16327d36db35SAvi Kivity "mov %ax, %fs \n\t" 16337d36db35SAvi Kivity "mov %ax, %gs \n\t" 16347d36db35SAvi Kivity "mov $stacktop, %esp\n\t" 16357d36db35SAvi Kivity "ljmp $0, $realmode_start \n\t" 16367d36db35SAvi Kivity 16377d36db35SAvi Kivity ".code16gcc \n\t" 16387d36db35SAvi Kivity ); 1639