17d36db35SAvi Kivity asm(".code16gcc"); 27d36db35SAvi Kivity 37d36db35SAvi Kivity typedef unsigned char u8; 47d36db35SAvi Kivity typedef unsigned short u16; 57d36db35SAvi Kivity typedef unsigned u32; 67d36db35SAvi Kivity typedef unsigned long long u64; 77d36db35SAvi Kivity 87d36db35SAvi Kivity void test_function(void); 97d36db35SAvi Kivity 107d36db35SAvi Kivity asm( 117d36db35SAvi Kivity "test_function: \n\t" 127d36db35SAvi Kivity "mov $0x1234, %eax \n\t" 137d36db35SAvi Kivity "ret" 147d36db35SAvi Kivity ); 157d36db35SAvi Kivity 167d36db35SAvi Kivity static int strlen(const char *str) 177d36db35SAvi Kivity { 187d36db35SAvi Kivity int n; 197d36db35SAvi Kivity 207d36db35SAvi Kivity for (n = 0; *str; ++str) 217d36db35SAvi Kivity ++n; 227d36db35SAvi Kivity return n; 237d36db35SAvi Kivity } 247d36db35SAvi Kivity 257d36db35SAvi Kivity static void print_serial(const char *buf) 267d36db35SAvi Kivity { 277d36db35SAvi Kivity unsigned long len = strlen(buf); 287d36db35SAvi Kivity 297d36db35SAvi Kivity asm volatile ("cld; addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1)); 307d36db35SAvi Kivity } 317d36db35SAvi Kivity 327d36db35SAvi Kivity static void exit(int code) 337d36db35SAvi Kivity { 347d36db35SAvi Kivity asm volatile("out %0, %1" : : "a"(code), "d"((short)0xf4)); 357d36db35SAvi Kivity } 367d36db35SAvi Kivity 377d36db35SAvi Kivity struct regs { 387d36db35SAvi Kivity u32 eax, ebx, ecx, edx; 397d36db35SAvi Kivity u32 esi, edi, esp, ebp; 407d36db35SAvi Kivity u32 eip, eflags; 417d36db35SAvi Kivity }; 427d36db35SAvi Kivity 437d36db35SAvi Kivity static u64 gdt[] = { 447d36db35SAvi Kivity 0, 457d36db35SAvi Kivity 0x00cf9b000000ffffull, // flat 32-bit code segment 467d36db35SAvi Kivity 0x00cf93000000ffffull, // flat 32-bit data segment 477d36db35SAvi Kivity }; 487d36db35SAvi Kivity 497d36db35SAvi Kivity static struct { 507d36db35SAvi Kivity u16 limit; 517d36db35SAvi Kivity void *base; 527d36db35SAvi Kivity } __attribute__((packed)) gdt_descr = { 537d36db35SAvi Kivity sizeof(gdt) - 1, 547d36db35SAvi Kivity gdt, 557d36db35SAvi Kivity }; 567d36db35SAvi Kivity 57*d4dc402cSAvi Kivity struct insn_desc { 58*d4dc402cSAvi Kivity u16 ptr; 59*d4dc402cSAvi Kivity u16 len; 60*d4dc402cSAvi Kivity }; 61*d4dc402cSAvi Kivity 627d36db35SAvi Kivity static void exec_in_big_real_mode(const struct regs *inregs, 637d36db35SAvi Kivity struct regs *outregs, 64*d4dc402cSAvi Kivity struct insn_desc *insn) 657d36db35SAvi Kivity { 667d36db35SAvi Kivity unsigned long tmp; 677d36db35SAvi Kivity static struct regs save; 687d36db35SAvi Kivity int i; 697d36db35SAvi Kivity extern u8 test_insn[], test_insn_end[]; 707d36db35SAvi Kivity 71*d4dc402cSAvi Kivity for (i = 0; i < insn->len; ++i) 72*d4dc402cSAvi Kivity test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i]; 737d36db35SAvi Kivity for (; i < test_insn_end - test_insn; ++i) 747d36db35SAvi Kivity test_insn[i] = 0x90; // nop 757d36db35SAvi Kivity 767d36db35SAvi Kivity save = *inregs; 777d36db35SAvi Kivity asm volatile( 787d36db35SAvi Kivity "lgdtl %[gdt_descr] \n\t" 797d36db35SAvi Kivity "mov %%cr0, %[tmp] \n\t" 807d36db35SAvi Kivity "or $1, %[tmp] \n\t" 817d36db35SAvi Kivity "mov %[tmp], %%cr0 \n\t" 827d36db35SAvi Kivity "mov %[bigseg], %%gs \n\t" 837d36db35SAvi Kivity "and $-2, %[tmp] \n\t" 847d36db35SAvi Kivity "mov %[tmp], %%cr0 \n\t" 857d36db35SAvi Kivity 8632001692SAvi Kivity "pushw %[save]+36; popfw \n\t" 877d36db35SAvi Kivity "xchg %%eax, %[save]+0 \n\t" 887d36db35SAvi Kivity "xchg %%ebx, %[save]+4 \n\t" 897d36db35SAvi Kivity "xchg %%ecx, %[save]+8 \n\t" 907d36db35SAvi Kivity "xchg %%edx, %[save]+12 \n\t" 917d36db35SAvi Kivity "xchg %%esi, %[save]+16 \n\t" 927d36db35SAvi Kivity "xchg %%edi, %[save]+20 \n\t" 937d36db35SAvi Kivity "xchg %%esp, %[save]+24 \n\t" 947d36db35SAvi Kivity "xchg %%ebp, %[save]+28 \n\t" 957d36db35SAvi Kivity 967d36db35SAvi Kivity "test_insn: . = . + 32\n\t" 977d36db35SAvi Kivity "test_insn_end: \n\t" 987d36db35SAvi Kivity 997d36db35SAvi Kivity "xchg %%eax, %[save]+0 \n\t" 1007d36db35SAvi Kivity "xchg %%ebx, %[save]+4 \n\t" 1017d36db35SAvi Kivity "xchg %%ecx, %[save]+8 \n\t" 1027d36db35SAvi Kivity "xchg %%edx, %[save]+12 \n\t" 1037d36db35SAvi Kivity "xchg %%esi, %[save]+16 \n\t" 1047d36db35SAvi Kivity "xchg %%edi, %[save]+20 \n\t" 1057d36db35SAvi Kivity "xchg %%esp, %[save]+24 \n\t" 1067d36db35SAvi Kivity "xchg %%ebp, %[save]+28 \n\t" 1077d36db35SAvi Kivity 1087d36db35SAvi Kivity /* Save EFLAGS in outregs*/ 1097d36db35SAvi Kivity "pushfl \n\t" 1107d36db35SAvi Kivity "popl %[save]+36 \n\t" 1117d36db35SAvi Kivity 1127d36db35SAvi Kivity "xor %[tmp], %[tmp] \n\t" 1137d36db35SAvi Kivity "mov %[tmp], %%gs \n\t" 1147d36db35SAvi Kivity : [tmp]"=&r"(tmp), [save]"+m"(save) 1157d36db35SAvi Kivity : [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16) 1167d36db35SAvi Kivity : "cc", "memory" 1177d36db35SAvi Kivity ); 1187d36db35SAvi Kivity *outregs = save; 1197d36db35SAvi Kivity } 1207d36db35SAvi Kivity 1217d36db35SAvi Kivity #define R_AX 1 1227d36db35SAvi Kivity #define R_BX 2 1237d36db35SAvi Kivity #define R_CX 4 1247d36db35SAvi Kivity #define R_DX 8 1257d36db35SAvi Kivity #define R_SI 16 1267d36db35SAvi Kivity #define R_DI 32 1277d36db35SAvi Kivity #define R_SP 64 1287d36db35SAvi Kivity #define R_BP 128 1297d36db35SAvi Kivity 1307d36db35SAvi Kivity int regs_equal(const struct regs *r1, const struct regs *r2, int ignore) 1317d36db35SAvi Kivity { 1327d36db35SAvi Kivity const u32 *p1 = &r1->eax, *p2 = &r2->eax; // yuck 1337d36db35SAvi Kivity int i; 1347d36db35SAvi Kivity 1357d36db35SAvi Kivity for (i = 0; i < 8; ++i) 1367d36db35SAvi Kivity if (!(ignore & (1 << i)) && p1[i] != p2[i]) 1377d36db35SAvi Kivity return 0; 1387d36db35SAvi Kivity return 1; 1397d36db35SAvi Kivity } 1407d36db35SAvi Kivity 1417d36db35SAvi Kivity #define MK_INSN(name, str) \ 1427d36db35SAvi Kivity asm ( \ 143*d4dc402cSAvi Kivity ".pushsection .data.insn \n\t" \ 144*d4dc402cSAvi Kivity "insn_" #name ": \n\t" \ 145*d4dc402cSAvi Kivity ".word 1001f, 1002f - 1001f \n\t" \ 146*d4dc402cSAvi Kivity ".popsection \n\t" \ 147*d4dc402cSAvi Kivity ".pushsection .text.insn, \"ax\" \n\t" \ 148*d4dc402cSAvi Kivity "1001: \n\t" \ 149*d4dc402cSAvi Kivity "insn_code_" #name ": " str " \n\t" \ 150*d4dc402cSAvi Kivity "1002: \n\t" \ 151*d4dc402cSAvi Kivity ".popsection" \ 1527d36db35SAvi Kivity ); \ 153*d4dc402cSAvi Kivity extern struct insn_desc insn_##name; 1547d36db35SAvi Kivity 1557d36db35SAvi Kivity void test_xchg(void) 1567d36db35SAvi Kivity { 1577d36db35SAvi Kivity struct regs inregs = { .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7}, outregs; 1587d36db35SAvi Kivity 1597d36db35SAvi Kivity MK_INSN(xchg_test1, "xchg %eax,%eax\n\t"); 1607d36db35SAvi Kivity MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t"); 1617d36db35SAvi Kivity MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t"); 1627d36db35SAvi Kivity MK_INSN(xchg_test4, "xchg %eax,%edx\n\t"); 1637d36db35SAvi Kivity MK_INSN(xchg_test5, "xchg %eax,%esi\n\t"); 1647d36db35SAvi Kivity MK_INSN(xchg_test6, "xchg %eax,%edi\n\t"); 1657d36db35SAvi Kivity MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t"); 1667d36db35SAvi Kivity MK_INSN(xchg_test8, "xchg %eax,%esp\n\t"); 1677d36db35SAvi Kivity 168*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_xchg_test1); 1697d36db35SAvi Kivity 1707d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, 0)) 1717d36db35SAvi Kivity print_serial("xchg test 1: FAIL\n"); 1727d36db35SAvi Kivity else 1737d36db35SAvi Kivity print_serial("xchg test 1: PASS\n"); 1747d36db35SAvi Kivity 175*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_xchg_test2); 1767d36db35SAvi Kivity 1777d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX | R_BX) || 1787d36db35SAvi Kivity outregs.eax != inregs.ebx || 1797d36db35SAvi Kivity outregs.ebx != inregs.eax) 1807d36db35SAvi Kivity print_serial("xchg test 2: FAIL\n"); 1817d36db35SAvi Kivity else 1827d36db35SAvi Kivity print_serial("xchg test 2: PASS\n"); 1837d36db35SAvi Kivity 184*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_xchg_test3); 1857d36db35SAvi Kivity 1867d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX | R_CX) || 1877d36db35SAvi Kivity outregs.eax != inregs.ecx || 1887d36db35SAvi Kivity outregs.ecx != inregs.eax) 1897d36db35SAvi Kivity print_serial("xchg test 3: FAIL\n"); 1907d36db35SAvi Kivity else 1917d36db35SAvi Kivity print_serial("xchg test 3: PASS\n"); 1927d36db35SAvi Kivity 193*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_xchg_test4); 1947d36db35SAvi Kivity 1957d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX | R_DX) || 1967d36db35SAvi Kivity outregs.eax != inregs.edx || 1977d36db35SAvi Kivity outregs.edx != inregs.eax) 1987d36db35SAvi Kivity print_serial("xchg test 4: FAIL\n"); 1997d36db35SAvi Kivity else 2007d36db35SAvi Kivity print_serial("xchg test 4: PASS\n"); 2017d36db35SAvi Kivity 202*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_xchg_test5); 2037d36db35SAvi Kivity 2047d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX | R_SI) || 2057d36db35SAvi Kivity outregs.eax != inregs.esi || 2067d36db35SAvi Kivity outregs.esi != inregs.eax) 2077d36db35SAvi Kivity print_serial("xchg test 5: FAIL\n"); 2087d36db35SAvi Kivity else 2097d36db35SAvi Kivity print_serial("xchg test 5: PASS\n"); 2107d36db35SAvi Kivity 211*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_xchg_test6); 2127d36db35SAvi Kivity 2137d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX | R_DI) || 2147d36db35SAvi Kivity outregs.eax != inregs.edi || 2157d36db35SAvi Kivity outregs.edi != inregs.eax) 2167d36db35SAvi Kivity print_serial("xchg test 6: FAIL\n"); 2177d36db35SAvi Kivity else 2187d36db35SAvi Kivity print_serial("xchg test 6: PASS\n"); 2197d36db35SAvi Kivity 220*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_xchg_test7); 2217d36db35SAvi Kivity 2227d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX | R_BP) || 2237d36db35SAvi Kivity outregs.eax != inregs.ebp || 2247d36db35SAvi Kivity outregs.ebp != inregs.eax) 2257d36db35SAvi Kivity print_serial("xchg test 7: FAIL\n"); 2267d36db35SAvi Kivity else 2277d36db35SAvi Kivity print_serial("xchg test 7: PASS\n"); 2287d36db35SAvi Kivity 229*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_xchg_test8); 2307d36db35SAvi Kivity 2317d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX | R_SP) || 2327d36db35SAvi Kivity outregs.eax != inregs.esp || 2337d36db35SAvi Kivity outregs.esp != inregs.eax) 2347d36db35SAvi Kivity print_serial("xchg test 8: FAIL\n"); 2357d36db35SAvi Kivity else 2367d36db35SAvi Kivity print_serial("xchg test 8: PASS\n"); 2377d36db35SAvi Kivity } 2387d36db35SAvi Kivity 2397d36db35SAvi Kivity void test_shld(void) 2407d36db35SAvi Kivity { 2417d36db35SAvi Kivity struct regs inregs = { .eax = 0xbe, .edx = 0xef000000 }, outregs; 2427d36db35SAvi Kivity MK_INSN(shld_test, "shld $8,%edx,%eax\n\t"); 2437d36db35SAvi Kivity 244*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_shld_test); 2457d36db35SAvi Kivity if (outregs.eax != 0xbeef) 2467d36db35SAvi Kivity print_serial("shld: FAIL\n"); 2477d36db35SAvi Kivity else 2487d36db35SAvi Kivity print_serial("shld: PASS\n"); 2497d36db35SAvi Kivity } 2507d36db35SAvi Kivity 2517d36db35SAvi Kivity void test_mov_imm(void) 2527d36db35SAvi Kivity { 2537d36db35SAvi Kivity struct regs inregs = { 0 }, outregs; 2547d36db35SAvi Kivity MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax"); 2557d36db35SAvi Kivity MK_INSN(mov_r16_imm_1, "mov $1234, %ax"); 2567d36db35SAvi Kivity MK_INSN(mov_r8_imm_1, "mov $0x12, %ah"); 2577d36db35SAvi Kivity MK_INSN(mov_r8_imm_2, "mov $0x34, %al"); 2587d36db35SAvi Kivity MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t"); 2597d36db35SAvi Kivity 260*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_mov_r16_imm_1); 2617d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 1234) 2627d36db35SAvi Kivity print_serial("mov test 1: FAIL\n"); 2637d36db35SAvi Kivity else 2647d36db35SAvi Kivity print_serial("mov test 1: PASS\n"); 2657d36db35SAvi Kivity 2667d36db35SAvi Kivity /* test mov $imm, %eax */ 267*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_mov_r32_imm_1); 2687d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 1234567890) 2697d36db35SAvi Kivity print_serial("mov test 2: FAIL\n"); 2707d36db35SAvi Kivity else 2717d36db35SAvi Kivity print_serial("mov test 2: PASS\n"); 2727d36db35SAvi Kivity 2737d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 274*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_mov_r8_imm_1); 2757d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1200) 2767d36db35SAvi Kivity print_serial("mov test 3: FAIL\n"); 2777d36db35SAvi Kivity else 2787d36db35SAvi Kivity print_serial("mov test 3: PASS\n"); 2797d36db35SAvi Kivity 280*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_mov_r8_imm_2); 2817d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x34) 2827d36db35SAvi Kivity print_serial("mov test 4: FAIL\n"); 2837d36db35SAvi Kivity else 2847d36db35SAvi Kivity print_serial("mov test 4: PASS\n"); 2857d36db35SAvi Kivity 286*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_mov_r8_imm_3); 2877d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234) 2887d36db35SAvi Kivity print_serial("mov test 5: FAIL\n"); 2897d36db35SAvi Kivity else 2907d36db35SAvi Kivity print_serial("mov test 5: PASS\n"); 2917d36db35SAvi Kivity } 2927d36db35SAvi Kivity 2937d36db35SAvi Kivity void test_sub_imm(void) 2947d36db35SAvi Kivity { 2957d36db35SAvi Kivity struct regs inregs = { 0 }, outregs; 2967d36db35SAvi Kivity MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t"); 2977d36db35SAvi Kivity MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t"); 2987d36db35SAvi Kivity MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t"); 2997d36db35SAvi Kivity MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t"); 3007d36db35SAvi Kivity 301*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_sub_r16_imm_1); 3027d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 1224) 3037d36db35SAvi Kivity print_serial("sub test 1: FAIL\n"); 3047d36db35SAvi Kivity else 3057d36db35SAvi Kivity print_serial("sub test 1: PASS\n"); 3067d36db35SAvi Kivity 3077d36db35SAvi Kivity /* test mov $imm, %eax */ 308*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_sub_r32_imm_1); 3097d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 1234567880) 3107d36db35SAvi Kivity print_serial("sub test 2: FAIL\n"); 3117d36db35SAvi Kivity else 3127d36db35SAvi Kivity print_serial("sub test 2: PASS\n"); 3137d36db35SAvi Kivity 3147d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 315*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_sub_r8_imm_1); 3167d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x0200) 3177d36db35SAvi Kivity print_serial("sub test 3: FAIL\n"); 3187d36db35SAvi Kivity else 3197d36db35SAvi Kivity print_serial("sub test 3: PASS\n"); 3207d36db35SAvi Kivity 321*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_sub_r8_imm_2); 3227d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x24) 3237d36db35SAvi Kivity print_serial("sub test 4: FAIL\n"); 3247d36db35SAvi Kivity else 3257d36db35SAvi Kivity print_serial("sub test 4: PASS\n"); 3267d36db35SAvi Kivity } 3277d36db35SAvi Kivity 3287d36db35SAvi Kivity 3297d36db35SAvi Kivity void test_xor_imm(void) 3307d36db35SAvi Kivity { 3317d36db35SAvi Kivity struct regs inregs = { 0 }, outregs; 3327d36db35SAvi Kivity MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t"); 3337d36db35SAvi Kivity MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t"); 3347d36db35SAvi Kivity MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t"); 3357d36db35SAvi Kivity MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t"); 3367d36db35SAvi Kivity 337*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_xor_r16_imm_1); 3387d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0) 3397d36db35SAvi Kivity print_serial("xor test 1: FAIL\n"); 3407d36db35SAvi Kivity else 3417d36db35SAvi Kivity print_serial("xor test 1: PASS\n"); 3427d36db35SAvi Kivity 3437d36db35SAvi Kivity /* test mov $imm, %eax */ 344*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_xor_r32_imm_1); 3457d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0) 3467d36db35SAvi Kivity print_serial("xor test 2: FAIL\n"); 3477d36db35SAvi Kivity else 3487d36db35SAvi Kivity print_serial("xor test 2: PASS\n"); 3497d36db35SAvi Kivity 3507d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 351*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_xor_r8_imm_1); 3527d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0) 3537d36db35SAvi Kivity print_serial("xor test 3: FAIL\n"); 3547d36db35SAvi Kivity else 3557d36db35SAvi Kivity print_serial("xor test 3: PASS\n"); 3567d36db35SAvi Kivity 357*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_xor_r8_imm_2); 3587d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0) 3597d36db35SAvi Kivity print_serial("xor test 4: FAIL\n"); 3607d36db35SAvi Kivity else 3617d36db35SAvi Kivity print_serial("xor test 4: PASS\n"); 3627d36db35SAvi Kivity } 3637d36db35SAvi Kivity 3647d36db35SAvi Kivity void test_cmp_imm(void) 3657d36db35SAvi Kivity { 3667d36db35SAvi Kivity struct regs inregs = { 0 }, outregs; 3677d36db35SAvi Kivity MK_INSN(cmp_test1, "mov $0x34, %al\n\t" 3687d36db35SAvi Kivity "cmp $0x34, %al\n\t"); 3697d36db35SAvi Kivity MK_INSN(cmp_test2, "mov $0x34, %al\n\t" 3707d36db35SAvi Kivity "cmp $0x39, %al\n\t"); 3717d36db35SAvi Kivity MK_INSN(cmp_test3, "mov $0x34, %al\n\t" 3727d36db35SAvi Kivity "cmp $0x24, %al\n\t"); 3737d36db35SAvi Kivity 3747d36db35SAvi Kivity /* test cmp imm8 with AL */ 3757d36db35SAvi Kivity /* ZF: (bit 6) Zero Flag becomes 1 if an operation results 3767d36db35SAvi Kivity * in a 0 writeback, or 0 register 3777d36db35SAvi Kivity */ 378*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_cmp_test1); 3797d36db35SAvi Kivity if ((outregs.eflags & (1<<6)) != (1<<6)) 3807d36db35SAvi Kivity print_serial("cmp test 1: FAIL\n"); 3817d36db35SAvi Kivity else 3827d36db35SAvi Kivity print_serial("cmp test 1: PASS\n"); 3837d36db35SAvi Kivity 384*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_cmp_test2); 3857d36db35SAvi Kivity if ((outregs.eflags & (1<<6)) != 0) 3867d36db35SAvi Kivity print_serial("cmp test 2: FAIL\n"); 3877d36db35SAvi Kivity else 3887d36db35SAvi Kivity print_serial("cmp test 2: PASS\n"); 3897d36db35SAvi Kivity 390*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_cmp_test3); 3917d36db35SAvi Kivity if ((outregs.eflags & (1<<6)) != 0) 3927d36db35SAvi Kivity print_serial("cmp test 3: FAIL\n"); 3937d36db35SAvi Kivity else 3947d36db35SAvi Kivity print_serial("cmp test 3: PASS\n"); 3957d36db35SAvi Kivity } 3967d36db35SAvi Kivity 3977d36db35SAvi Kivity void test_add_imm(void) 3987d36db35SAvi Kivity { 3997d36db35SAvi Kivity struct regs inregs = { 0 }, outregs; 4007d36db35SAvi Kivity MK_INSN(add_test1, "mov $0x43211234, %eax \n\t" 4017d36db35SAvi Kivity "add $0x12344321, %eax \n\t"); 4027d36db35SAvi Kivity MK_INSN(add_test2, "mov $0x12, %eax \n\t" 4037d36db35SAvi Kivity "add $0x21, %al\n\t"); 4047d36db35SAvi Kivity 405*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_add_test1); 4067d36db35SAvi Kivity if (outregs.eax != 0x55555555) 4077d36db35SAvi Kivity print_serial("add test 1: FAIL\n"); 4087d36db35SAvi Kivity else 4097d36db35SAvi Kivity print_serial("add test 1: PASS\n"); 4107d36db35SAvi Kivity 411*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_add_test2); 4127d36db35SAvi Kivity if (outregs.eax != 0x33) 4137d36db35SAvi Kivity print_serial("add test 2: FAIL\n"); 4147d36db35SAvi Kivity else 4157d36db35SAvi Kivity print_serial("add test 2: PASS\n"); 4167d36db35SAvi Kivity } 4177d36db35SAvi Kivity 4187d36db35SAvi Kivity void test_eflags_insn(void) 4197d36db35SAvi Kivity { 4207d36db35SAvi Kivity struct regs inregs = { 0 }, outregs; 4217d36db35SAvi Kivity MK_INSN(clc, "clc"); 422b3261e48SMohammed Gamal MK_INSN(stc, "stc"); 4237d36db35SAvi Kivity MK_INSN(cli, "cli"); 4247d36db35SAvi Kivity MK_INSN(sti, "sti"); 4257d36db35SAvi Kivity MK_INSN(cld, "cld"); 4267d36db35SAvi Kivity MK_INSN(std, "std"); 4277d36db35SAvi Kivity 428*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_clc); 4297d36db35SAvi Kivity if (outregs.eflags & 1) 4307d36db35SAvi Kivity print_serial("clc test: FAIL\n"); 4317d36db35SAvi Kivity else 4327d36db35SAvi Kivity print_serial("clc test: PASS\n"); 4337d36db35SAvi Kivity 434*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_stc); 435b3261e48SMohammed Gamal if (!(outregs.eflags & 1)) 436b3261e48SMohammed Gamal print_serial("stc test: FAIL\n"); 437b3261e48SMohammed Gamal else 438b3261e48SMohammed Gamal print_serial("stc test: PASS\n"); 439b3261e48SMohammed Gamal 440*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_cli); 4417d36db35SAvi Kivity if (outregs.eflags & (1 << 9)) 4427d36db35SAvi Kivity print_serial("cli test: FAIL\n"); 4437d36db35SAvi Kivity else 4447d36db35SAvi Kivity print_serial("cli test: PASS\n"); 4457d36db35SAvi Kivity 446*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_sti); 4477d36db35SAvi Kivity if (!(outregs.eflags & (1 << 9))) 4487d36db35SAvi Kivity print_serial("sti test: FAIL\n"); 4497d36db35SAvi Kivity else 4507d36db35SAvi Kivity print_serial("sti test: PASS\n"); 4517d36db35SAvi Kivity 452*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_cld); 4537d36db35SAvi Kivity if (outregs.eflags & (1 << 10)) 4547d36db35SAvi Kivity print_serial("cld test: FAIL\n"); 4557d36db35SAvi Kivity else 4567d36db35SAvi Kivity print_serial("cld test: PASS\n"); 4577d36db35SAvi Kivity 458*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_std); 4597d36db35SAvi Kivity if (!(outregs.eflags & (1 << 10))) 4607d36db35SAvi Kivity print_serial("std test: FAIL\n"); 4617d36db35SAvi Kivity else 4627d36db35SAvi Kivity print_serial("std test: PASS\n"); 4637d36db35SAvi Kivity } 4647d36db35SAvi Kivity 4657d36db35SAvi Kivity void test_io(void) 4667d36db35SAvi Kivity { 4677d36db35SAvi Kivity struct regs inregs = { 0 }, outregs; 4687d36db35SAvi Kivity MK_INSN(io_test1, "mov $0xff, %al \n\t" 4697d36db35SAvi Kivity "out %al, $0xe0 \n\t" 4707d36db35SAvi Kivity "mov $0x00, %al \n\t" 4717d36db35SAvi Kivity "in $0xe0, %al \n\t"); 4727d36db35SAvi Kivity MK_INSN(io_test2, "mov $0xffff, %ax \n\t" 4737d36db35SAvi Kivity "out %ax, $0xe0 \n\t" 4747d36db35SAvi Kivity "mov $0x0000, %ax \n\t" 4757d36db35SAvi Kivity "in $0xe0, %ax \n\t"); 4767d36db35SAvi Kivity MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t" 4777d36db35SAvi Kivity "out %eax, $0xe0 \n\t" 4787d36db35SAvi Kivity "mov $0x000000, %eax \n\t" 4797d36db35SAvi Kivity "in $0xe0, %eax \n\t"); 4807d36db35SAvi Kivity MK_INSN(io_test4, "mov $0xe0, %dx \n\t" 4817d36db35SAvi Kivity "mov $0xff, %al \n\t" 4827d36db35SAvi Kivity "out %al, %dx \n\t" 4837d36db35SAvi Kivity "mov $0x00, %al \n\t" 4847d36db35SAvi Kivity "in %dx, %al \n\t"); 4857d36db35SAvi Kivity MK_INSN(io_test5, "mov $0xe0, %dx \n\t" 4867d36db35SAvi Kivity "mov $0xffff, %ax \n\t" 4877d36db35SAvi Kivity "out %ax, %dx \n\t" 4887d36db35SAvi Kivity "mov $0x0000, %ax \n\t" 4897d36db35SAvi Kivity "in %dx, %ax \n\t"); 4907d36db35SAvi Kivity MK_INSN(io_test6, "mov $0xe0, %dx \n\t" 4917d36db35SAvi Kivity "mov $0xffffffff, %eax \n\t" 4927d36db35SAvi Kivity "out %eax, %dx \n\t" 4937d36db35SAvi Kivity "mov $0x00000000, %eax \n\t" 4947d36db35SAvi Kivity "in %dx, %eax \n\t"); 4957d36db35SAvi Kivity 496*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_io_test1); 4977d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0xff) 4987d36db35SAvi Kivity print_serial("I/O test 1: FAIL\n"); 4997d36db35SAvi Kivity else 5007d36db35SAvi Kivity print_serial("I/O test 1: PASS\n"); 5017d36db35SAvi Kivity 502*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_io_test2); 5037d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0xffff) 5047d36db35SAvi Kivity print_serial("I/O test 2: FAIL\n"); 5057d36db35SAvi Kivity else 5067d36db35SAvi Kivity print_serial("I/O test 2: PASS\n"); 5077d36db35SAvi Kivity 508*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_io_test3); 5097d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0xffffffff) 5107d36db35SAvi Kivity print_serial("I/O test 3: FAIL\n"); 5117d36db35SAvi Kivity else 5127d36db35SAvi Kivity print_serial("I/O test 3: PASS\n"); 5137d36db35SAvi Kivity 514*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_io_test4); 5157d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX|R_DX) || outregs.eax != 0xff) 5167d36db35SAvi Kivity print_serial("I/O test 4: FAIL\n"); 5177d36db35SAvi Kivity else 5187d36db35SAvi Kivity print_serial("I/O test 4: PASS\n"); 5197d36db35SAvi Kivity 520*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_io_test5); 5217d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX|R_DX) || outregs.eax != 0xffff) 5227d36db35SAvi Kivity print_serial("I/O test 5: FAIL\n"); 5237d36db35SAvi Kivity else 5247d36db35SAvi Kivity print_serial("I/O test 5: PASS\n"); 5257d36db35SAvi Kivity 526*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_io_test6); 5277d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX|R_DX) || outregs.eax != 0xffffffff) 5287d36db35SAvi Kivity print_serial("I/O test 6: FAIL\n"); 5297d36db35SAvi Kivity else 5307d36db35SAvi Kivity print_serial("I/O test 6: PASS\n"); 5317d36db35SAvi Kivity } 5327d36db35SAvi Kivity 533c0b7268dSAvi Kivity asm ("retf: lretw"); 534c0b7268dSAvi Kivity extern void retf(); 535c0b7268dSAvi Kivity 5367d36db35SAvi Kivity void test_call(void) 5377d36db35SAvi Kivity { 5387d36db35SAvi Kivity struct regs inregs = { 0 }, outregs; 5397d36db35SAvi Kivity u32 esp[16]; 540c0b7268dSAvi Kivity u32 addr; 5417d36db35SAvi Kivity 5427d36db35SAvi Kivity inregs.esp = (u32)esp; 5437d36db35SAvi Kivity 5447d36db35SAvi Kivity MK_INSN(call1, "mov $test_function, %eax \n\t" 5457d36db35SAvi Kivity "call *%eax\n\t"); 5467d36db35SAvi Kivity MK_INSN(call_near1, "jmp 2f\n\t" 5477d36db35SAvi Kivity "1: mov $0x1234, %eax\n\t" 5487d36db35SAvi Kivity "ret\n\t" 5497d36db35SAvi Kivity "2: call 1b\t"); 5507d36db35SAvi Kivity MK_INSN(call_near2, "call 1f\n\t" 5517d36db35SAvi Kivity "jmp 2f\n\t" 5527d36db35SAvi Kivity "1: mov $0x1234, %eax\n\t" 5537d36db35SAvi Kivity "ret\n\t" 5547d36db35SAvi Kivity "2:\t"); 555c0b7268dSAvi Kivity MK_INSN(call_far1, "lcallw *(%ebx)\n\t"); 556c6061817SAvi Kivity MK_INSN(ret_imm, "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b"); 5577d36db35SAvi Kivity 558*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_call1); 5597d36db35SAvi Kivity if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234) 5607d36db35SAvi Kivity print_serial("Call Test 1: FAIL\n"); 5617d36db35SAvi Kivity else 5627d36db35SAvi Kivity print_serial("Call Test 1: PASS\n"); 5637d36db35SAvi Kivity 564*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_call_near1); 5657d36db35SAvi Kivity if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234) 5667d36db35SAvi Kivity print_serial("Call near Test 1: FAIL\n"); 5677d36db35SAvi Kivity else 5687d36db35SAvi Kivity print_serial("Call near Test 1: PASS\n"); 5697d36db35SAvi Kivity 570*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_call_near2); 5717d36db35SAvi Kivity if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234) 5727d36db35SAvi Kivity print_serial("Call near Test 2: FAIL\n"); 5737d36db35SAvi Kivity else 5747d36db35SAvi Kivity print_serial("Call near Test 2: PASS\n"); 575c0b7268dSAvi Kivity 576c0b7268dSAvi Kivity addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f); 577c0b7268dSAvi Kivity inregs.ebx = (unsigned)&addr; 578*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_call_far1); 579c0b7268dSAvi Kivity if (!regs_equal(&inregs, &outregs, 0)) 580c0b7268dSAvi Kivity print_serial("Call far Test 1: FAIL\n"); 581c0b7268dSAvi Kivity else 582c0b7268dSAvi Kivity print_serial("Call far Test 1: PASS\n"); 583c6061817SAvi Kivity 584*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_ret_imm); 585c6061817SAvi Kivity if (!regs_equal(&inregs, &outregs, 0)) 586c6061817SAvi Kivity print_serial("ret imm Test 1: FAIL\n"); 587c6061817SAvi Kivity else 588c6061817SAvi Kivity print_serial("ret imm Test 1: PASS\n"); 5897d36db35SAvi Kivity } 5907d36db35SAvi Kivity 5917d36db35SAvi Kivity void test_jcc_short(void) 5927d36db35SAvi Kivity { 5937d36db35SAvi Kivity struct regs inregs = { 0 }, outregs; 5947d36db35SAvi Kivity MK_INSN(jnz_short1, "jnz 1f\n\t" 5957d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5967d36db35SAvi Kivity "1:\n\t"); 5977d36db35SAvi Kivity MK_INSN(jnz_short2, "1:\n\t" 5987d36db35SAvi Kivity "cmp $0x1234, %eax\n\t" 5997d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 6007d36db35SAvi Kivity "jnz 1b\n\t"); 6017d36db35SAvi Kivity MK_INSN(jmp_short1, "jmp 1f\n\t" 6027d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 6037d36db35SAvi Kivity "1:\n\t"); 6047d36db35SAvi Kivity 605*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_jnz_short1); 6067d36db35SAvi Kivity if(!regs_equal(&inregs, &outregs, 0)) 6077d36db35SAvi Kivity print_serial("JNZ short Test 1: FAIL\n"); 6087d36db35SAvi Kivity else 6097d36db35SAvi Kivity print_serial("JNZ short Test 1: PASS\n"); 6107d36db35SAvi Kivity 611*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_jnz_short2); 6127d36db35SAvi Kivity if(!regs_equal(&inregs, &outregs, R_AX) || !(outregs.eflags & (1 << 6))) 6137d36db35SAvi Kivity print_serial("JNZ short Test 2: FAIL\n"); 6147d36db35SAvi Kivity else 6157d36db35SAvi Kivity print_serial("JNZ short Test 2: PASS\n"); 6167d36db35SAvi Kivity 617*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_jmp_short1); 6187d36db35SAvi Kivity if(!regs_equal(&inregs, &outregs, 0)) 6197d36db35SAvi Kivity print_serial("JMP short Test 1: FAIL\n"); 6207d36db35SAvi Kivity else 6217d36db35SAvi Kivity print_serial("JMP short Test 1: PASS\n"); 6227d36db35SAvi Kivity } 6237d36db35SAvi Kivity 6247d36db35SAvi Kivity void test_jcc_near(void) 6257d36db35SAvi Kivity { 6267d36db35SAvi Kivity struct regs inregs = { 0 }, outregs; 6277d36db35SAvi Kivity /* encode near jmp manually. gas will not do it if offsets < 127 byte */ 6287d36db35SAvi Kivity MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t" 6297d36db35SAvi Kivity "mov $0x1234, %eax\n\t"); 6307d36db35SAvi Kivity MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t" 6317d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 6327d36db35SAvi Kivity ".byte 0x0f, 0x85, 0xf0, 0xff\n\t"); 6337d36db35SAvi Kivity MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t" 6347d36db35SAvi Kivity "mov $0x1234, %eax\n\t"); 6357d36db35SAvi Kivity 636*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_jnz_near1); 6377d36db35SAvi Kivity if(!regs_equal(&inregs, &outregs, 0)) 6387d36db35SAvi Kivity print_serial("JNZ near Test 1: FAIL\n"); 6397d36db35SAvi Kivity else 6407d36db35SAvi Kivity print_serial("JNZ near Test 1: PASS\n"); 6417d36db35SAvi Kivity 642*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_jnz_near2); 6437d36db35SAvi Kivity if(!regs_equal(&inregs, &outregs, R_AX) || !(outregs.eflags & (1 << 6))) 6447d36db35SAvi Kivity print_serial("JNZ near Test 2: FAIL\n"); 6457d36db35SAvi Kivity else 6467d36db35SAvi Kivity print_serial("JNZ near Test 2: PASS\n"); 6477d36db35SAvi Kivity 648*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_jmp_near1); 6497d36db35SAvi Kivity if(!regs_equal(&inregs, &outregs, 0)) 6507d36db35SAvi Kivity print_serial("JMP near Test 1: FAIL\n"); 6517d36db35SAvi Kivity else 6527d36db35SAvi Kivity print_serial("JMP near Test 1: PASS\n"); 6537d36db35SAvi Kivity } 6547d36db35SAvi Kivity 6557d36db35SAvi Kivity void test_long_jmp() 6567d36db35SAvi Kivity { 6577d36db35SAvi Kivity struct regs inregs = { 0 }, outregs; 6587d36db35SAvi Kivity u32 esp[16]; 6597d36db35SAvi Kivity 6607d36db35SAvi Kivity inregs.esp = (u32)esp; 6617d36db35SAvi Kivity MK_INSN(long_jmp, "call 1f\n\t" 6627d36db35SAvi Kivity "jmp 2f\n\t" 6637d36db35SAvi Kivity "1: jmp $0, $test_function\n\t" 6647d36db35SAvi Kivity "2:\n\t"); 665*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_long_jmp); 6667d36db35SAvi Kivity if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234) 6677d36db35SAvi Kivity print_serial("Long JMP Test: FAIL\n"); 6687d36db35SAvi Kivity else 6697d36db35SAvi Kivity print_serial("Long JMP Test: PASS\n"); 6707d36db35SAvi Kivity } 671fa74f8a6SMohammed Gamal 6727d36db35SAvi Kivity void test_push_pop() 6737d36db35SAvi Kivity { 6747d36db35SAvi Kivity struct regs inregs = { 0 }, outregs; 6757d36db35SAvi Kivity MK_INSN(push32, "mov $0x12345678, %eax\n\t" 6767d36db35SAvi Kivity "push %eax\n\t" 6777d36db35SAvi Kivity "pop %ebx\n\t"); 6787d36db35SAvi Kivity MK_INSN(push16, "mov $0x1234, %ax\n\t" 6797d36db35SAvi Kivity "push %ax\n\t" 6807d36db35SAvi Kivity "pop %bx\n\t"); 6817d36db35SAvi Kivity 6827d36db35SAvi Kivity MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten 6837d36db35SAvi Kivity "mov $0x123, %ax\n\t" 6847d36db35SAvi Kivity "mov %ax, %es\n\t" 6857d36db35SAvi Kivity "push %es\n\t" 6867d36db35SAvi Kivity "pop %bx \n\t" 6877d36db35SAvi Kivity ); 6887d36db35SAvi Kivity MK_INSN(pop_es, "push %ax\n\t" 6897d36db35SAvi Kivity "pop %es\n\t" 6907d36db35SAvi Kivity "mov %es, %bx\n\t" 6917d36db35SAvi Kivity ); 6927d36db35SAvi Kivity MK_INSN(push_pop_ss, "push %ss\n\t" 6937d36db35SAvi Kivity "pushw %ax\n\t" 6947d36db35SAvi Kivity "popw %ss\n\t" 6957d36db35SAvi Kivity "mov %ss, %bx\n\t" 6967d36db35SAvi Kivity "pop %ss\n\t" 6977d36db35SAvi Kivity ); 6987d36db35SAvi Kivity MK_INSN(push_pop_fs, "push %fs\n\t" 6997d36db35SAvi Kivity "pushl %eax\n\t" 7007d36db35SAvi Kivity "popl %fs\n\t" 7017d36db35SAvi Kivity "mov %fs, %ebx\n\t" 7027d36db35SAvi Kivity "pop %fs\n\t" 7037d36db35SAvi Kivity ); 7047d36db35SAvi Kivity 705*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_push32); 7067d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.eax != outregs.ebx || outregs.eax != 0x12345678) 7077d36db35SAvi Kivity print_serial("Push/Pop Test 1: FAIL\n"); 7087d36db35SAvi Kivity else 7097d36db35SAvi Kivity print_serial("Push/Pop Test 1: PASS\n"); 7107d36db35SAvi Kivity 711*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_push16); 7127d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.eax != outregs.ebx || outregs.eax != 0x1234) 7137d36db35SAvi Kivity print_serial("Push/Pop Test 2: FAIL\n"); 7147d36db35SAvi Kivity else 7157d36db35SAvi Kivity print_serial("Push/Pop Test 2: PASS\n"); 7167d36db35SAvi Kivity 717*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_push_es); 7187d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.ebx != outregs.eax || outregs.eax != 0x123) 7197d36db35SAvi Kivity print_serial("Push/Pop Test 3: FAIL\n"); 7207d36db35SAvi Kivity else 7217d36db35SAvi Kivity print_serial("Push/Pop Test 3: PASS\n"); 7227d36db35SAvi Kivity 723*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_pop_es); 7247d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.ebx != outregs.eax) 7257d36db35SAvi Kivity print_serial("Push/Pop Test 4: FAIL\n"); 7267d36db35SAvi Kivity else 7277d36db35SAvi Kivity print_serial("Push/Pop Test 4: PASS\n"); 7287d36db35SAvi Kivity 729*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_push_pop_ss); 7307d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.ebx != outregs.eax) 7317d36db35SAvi Kivity print_serial("Push/Pop Test 5: FAIL\n"); 7327d36db35SAvi Kivity else 7337d36db35SAvi Kivity print_serial("Push/Pop Test 5: PASS\n"); 7347d36db35SAvi Kivity 735*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_push_pop_fs); 7367d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.ebx != outregs.eax) 7377d36db35SAvi Kivity print_serial("Push/Pop Test 6: FAIL\n"); 7387d36db35SAvi Kivity else 7397d36db35SAvi Kivity print_serial("Push/Pop Test 6: PASS\n"); 7407d36db35SAvi Kivity } 7417d36db35SAvi Kivity 7427d36db35SAvi Kivity void test_null(void) 7437d36db35SAvi Kivity { 7447d36db35SAvi Kivity struct regs inregs = { 0 }, outregs; 745*d4dc402cSAvi Kivity MK_INSN(null, ""); 746*d4dc402cSAvi Kivity 747*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_null); 7487d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, 0)) 7497d36db35SAvi Kivity print_serial("null test: FAIL\n"); 7507d36db35SAvi Kivity else 7517d36db35SAvi Kivity print_serial("null test: PASS\n"); 7527d36db35SAvi Kivity } 7537d36db35SAvi Kivity 7547d36db35SAvi Kivity struct { 7557d36db35SAvi Kivity char stack[500]; 7567d36db35SAvi Kivity char top[]; 7577d36db35SAvi Kivity } tmp_stack; 7587d36db35SAvi Kivity 7597d36db35SAvi Kivity void test_pusha_popa() 7607d36db35SAvi Kivity { 7617d36db35SAvi Kivity struct regs inregs = { .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top }, outregs; 7627d36db35SAvi Kivity 7637d36db35SAvi Kivity MK_INSN(pusha, "pusha\n\t" 7647d36db35SAvi Kivity "pop %edi\n\t" 7657d36db35SAvi Kivity "pop %esi\n\t" 7667d36db35SAvi Kivity "pop %ebp\n\t" 7677d36db35SAvi Kivity "add $4, %esp\n\t" 7687d36db35SAvi Kivity "pop %ebx\n\t" 7697d36db35SAvi Kivity "pop %edx\n\t" 7707d36db35SAvi Kivity "pop %ecx\n\t" 7717d36db35SAvi Kivity "pop %eax\n\t" 7727d36db35SAvi Kivity ); 7737d36db35SAvi Kivity 7747d36db35SAvi Kivity MK_INSN(popa, "push %eax\n\t" 7757d36db35SAvi Kivity "push %ecx\n\t" 7767d36db35SAvi Kivity "push %edx\n\t" 7777d36db35SAvi Kivity "push %ebx\n\t" 7787d36db35SAvi Kivity "push %esp\n\t" 7797d36db35SAvi Kivity "push %ebp\n\t" 7807d36db35SAvi Kivity "push %esi\n\t" 7817d36db35SAvi Kivity "push %edi\n\t" 7827d36db35SAvi Kivity "popa\n\t" 7837d36db35SAvi Kivity ); 7847d36db35SAvi Kivity 785*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_pusha); 7867d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, 0)) 7877d36db35SAvi Kivity print_serial("Pusha/Popa Test1: FAIL\n"); 7887d36db35SAvi Kivity else 7897d36db35SAvi Kivity print_serial("Pusha/Popa Test1: PASS\n"); 7907d36db35SAvi Kivity 791*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_popa); 7927d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, 0)) 7937d36db35SAvi Kivity print_serial("Pusha/Popa Test2: FAIL\n"); 7947d36db35SAvi Kivity else 7957d36db35SAvi Kivity print_serial("Pusha/Popa Test2: PASS\n"); 7967d36db35SAvi Kivity } 7977d36db35SAvi Kivity 7987d36db35SAvi Kivity void test_iret() 7997d36db35SAvi Kivity { 8007d36db35SAvi Kivity struct regs inregs = { 0 }, outregs; 8017d36db35SAvi Kivity 8027d36db35SAvi Kivity MK_INSN(iret32, "pushf\n\t" 8037d36db35SAvi Kivity "pushl %cs\n\t" 8047d36db35SAvi Kivity "call 1f\n\t" /* a near call will push eip onto the stack */ 8057d36db35SAvi Kivity "jmp 2f\n\t" 8067d36db35SAvi Kivity "1: iret\n\t" 8077d36db35SAvi Kivity "2:\n\t" 8087d36db35SAvi Kivity ); 8097d36db35SAvi Kivity 8107d36db35SAvi Kivity MK_INSN(iret16, "pushfw\n\t" 8117d36db35SAvi Kivity "pushw %cs\n\t" 8127d36db35SAvi Kivity "callw 1f\n\t" 8137d36db35SAvi Kivity "jmp 2f\n\t" 8147d36db35SAvi Kivity "1: iretw\n\t" 8157d36db35SAvi Kivity "2:\n\t"); 8167d36db35SAvi Kivity 8177d36db35SAvi Kivity MK_INSN(iret_flags32, "pushfl\n\t" 8187d36db35SAvi Kivity "popl %eax\n\t" 8197d36db35SAvi Kivity "andl $~0x2, %eax\n\t" 8207d36db35SAvi Kivity "orl $0xffc08028, %eax\n\t" 8217d36db35SAvi Kivity "pushl %eax\n\t" 8227d36db35SAvi Kivity "pushl %cs\n\t" 8237d36db35SAvi Kivity "call 1f\n\t" 8247d36db35SAvi Kivity "jmp 2f\n\t" 8257d36db35SAvi Kivity "1: iret\n\t" 8267d36db35SAvi Kivity "2:\n\t"); 8277d36db35SAvi Kivity 8287d36db35SAvi Kivity MK_INSN(iret_flags16, "pushfw\n\t" 8297d36db35SAvi Kivity "popw %ax\n\t" 8307d36db35SAvi Kivity "and $~0x2, %ax\n\t" 8317d36db35SAvi Kivity "or $0x8028, %ax\n\t" 8327d36db35SAvi Kivity "pushw %ax\n\t" 8337d36db35SAvi Kivity "pushw %cs\n\t" 8347d36db35SAvi Kivity "callw 1f\n\t" 8357d36db35SAvi Kivity "jmp 2f\n\t" 8367d36db35SAvi Kivity "1: iretw\n\t" 8377d36db35SAvi Kivity "2:\n\t"); 8387d36db35SAvi Kivity 839*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_iret32); 8407d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, 0)) 8417d36db35SAvi Kivity print_serial("iret Test 1: FAIL\n"); 8427d36db35SAvi Kivity else 8437d36db35SAvi Kivity print_serial("iret Test 1: PASS\n"); 8447d36db35SAvi Kivity 845*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_iret16); 8467d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, 0)) 8477d36db35SAvi Kivity print_serial("iret Test 2: FAIL\n"); 8487d36db35SAvi Kivity else 8497d36db35SAvi Kivity print_serial("iret Test 2: PASS\n"); 8507d36db35SAvi Kivity 851*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_iret_flags32); 8527d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX)) 8537d36db35SAvi Kivity print_serial("iret Test 3: FAIL\n"); 8547d36db35SAvi Kivity else 8557d36db35SAvi Kivity print_serial("iret Test 3: PASS\n"); 8567d36db35SAvi Kivity 857*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_iret_flags16); 8587d36db35SAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX)) 8597d36db35SAvi Kivity print_serial("iret Test 4: FAIL\n"); 8607d36db35SAvi Kivity else 8617d36db35SAvi Kivity print_serial("iret Test 4: PASS\n"); 8627d36db35SAvi Kivity } 8637d36db35SAvi Kivity 86496b9ca1eSMohammed Gamal void test_int() 86596b9ca1eSMohammed Gamal { 86696b9ca1eSMohammed Gamal struct regs inregs = { 0 }, outregs; 86796b9ca1eSMohammed Gamal 86896b9ca1eSMohammed Gamal *(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */ 86996b9ca1eSMohammed Gamal *(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */ 87096b9ca1eSMohammed Gamal 87196b9ca1eSMohammed Gamal MK_INSN(int11, "int $0x11\n\t"); 87296b9ca1eSMohammed Gamal 873*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_int11); 87496b9ca1eSMohammed Gamal if (!regs_equal(&inregs, &outregs, 0)) 87596b9ca1eSMohammed Gamal print_serial("int Test 1: FAIL\n"); 87696b9ca1eSMohammed Gamal else 87796b9ca1eSMohammed Gamal print_serial("int Test 1: PASS\n"); 87896b9ca1eSMohammed Gamal } 87996b9ca1eSMohammed Gamal 880fa74f8a6SMohammed Gamal void test_imul() 881fa74f8a6SMohammed Gamal { 882fa74f8a6SMohammed Gamal struct regs inregs = { 0 }, outregs; 883fa74f8a6SMohammed Gamal 884fa74f8a6SMohammed Gamal MK_INSN(imul8_1, "mov $2, %al\n\t" 885fa74f8a6SMohammed Gamal "mov $-4, %cx\n\t" 886fa74f8a6SMohammed Gamal "imul %cl\n\t"); 887fa74f8a6SMohammed Gamal 888fa74f8a6SMohammed Gamal MK_INSN(imul16_1, "mov $2, %ax\n\t" 889fa74f8a6SMohammed Gamal "mov $-4, %cx\n\t" 890fa74f8a6SMohammed Gamal "imul %cx\n\t"); 891fa74f8a6SMohammed Gamal 892fa74f8a6SMohammed Gamal MK_INSN(imul32_1, "mov $2, %eax\n\t" 893fa74f8a6SMohammed Gamal "mov $-4, %ecx\n\t" 894fa74f8a6SMohammed Gamal "imul %ecx\n\t"); 895fa74f8a6SMohammed Gamal 896fa74f8a6SMohammed Gamal MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t" 897fa74f8a6SMohammed Gamal "mov $4, %cx\n\t" 898fa74f8a6SMohammed Gamal "imul %cl\n\t"); 899fa74f8a6SMohammed Gamal 900fa74f8a6SMohammed Gamal MK_INSN(imul16_2, "mov $2, %ax\n\t" 901fa74f8a6SMohammed Gamal "mov $4, %cx\n\t" 902fa74f8a6SMohammed Gamal "imul %cx\n\t"); 903fa74f8a6SMohammed Gamal 904fa74f8a6SMohammed Gamal MK_INSN(imul32_2, "mov $2, %eax\n\t" 905fa74f8a6SMohammed Gamal "mov $4, %ecx\n\t" 906fa74f8a6SMohammed Gamal "imul %ecx\n\t"); 907fa74f8a6SMohammed Gamal 908*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_imul8_1); 909fa74f8a6SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || (outregs.eax & 0xff) != (u8)-8) 910fa74f8a6SMohammed Gamal print_serial("imul Test 1: FAIL\n"); 911fa74f8a6SMohammed Gamal else 912fa74f8a6SMohammed Gamal print_serial("imul Test 1: PASS\n"); 913fa74f8a6SMohammed Gamal 914*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_imul16_1); 915fa74f8a6SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u16)-8) 916fa74f8a6SMohammed Gamal print_serial("imul Test 2: FAIL\n"); 917fa74f8a6SMohammed Gamal else 918fa74f8a6SMohammed Gamal print_serial("imul Test 2: PASS\n"); 919fa74f8a6SMohammed Gamal 920*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_imul32_1); 921fa74f8a6SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u32)-8) 922fa74f8a6SMohammed Gamal print_serial("imul Test 3: FAIL\n"); 923fa74f8a6SMohammed Gamal else 924fa74f8a6SMohammed Gamal print_serial("imul Test 3: PASS\n"); 925fa74f8a6SMohammed Gamal 926*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_imul8_2); 927fa74f8a6SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || (outregs.eax & 0xffff) != 8 || 928fa74f8a6SMohammed Gamal (outregs.eax & 0xffff0000) != 0x12340000) 929fa74f8a6SMohammed Gamal print_serial("imul Test 4: FAIL\n"); 930fa74f8a6SMohammed Gamal else 931fa74f8a6SMohammed Gamal print_serial("imul Test 4: PASS\n"); 932fa74f8a6SMohammed Gamal 933*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_imul16_2); 934fa74f8a6SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 8) 935fa74f8a6SMohammed Gamal print_serial("imul Test 5: FAIL\n"); 936fa74f8a6SMohammed Gamal else 937fa74f8a6SMohammed Gamal print_serial("imul Test 5: PASS\n"); 938fa74f8a6SMohammed Gamal 939*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_imul32_2); 940fa74f8a6SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 8) 941fa74f8a6SMohammed Gamal print_serial("imul Test 6: FAIL\n"); 942fa74f8a6SMohammed Gamal else 943fa74f8a6SMohammed Gamal print_serial("imul Test 6: PASS\n"); 944fa74f8a6SMohammed Gamal } 945fa74f8a6SMohammed Gamal 94659317bd1SMohammed Gamal void test_mul() 94759317bd1SMohammed Gamal { 94859317bd1SMohammed Gamal struct regs inregs = { 0 }, outregs; 94959317bd1SMohammed Gamal 95059317bd1SMohammed Gamal MK_INSN(mul8, "mov $2, %al\n\t" 95159317bd1SMohammed Gamal "mov $4, %cx\n\t" 95259317bd1SMohammed Gamal "imul %cl\n\t"); 95359317bd1SMohammed Gamal 95459317bd1SMohammed Gamal MK_INSN(mul16, "mov $2, %ax\n\t" 95559317bd1SMohammed Gamal "mov $4, %cx\n\t" 95659317bd1SMohammed Gamal "imul %cx\n\t"); 95759317bd1SMohammed Gamal 95859317bd1SMohammed Gamal MK_INSN(mul32, "mov $2, %eax\n\t" 95959317bd1SMohammed Gamal "mov $4, %ecx\n\t" 96059317bd1SMohammed Gamal "imul %ecx\n\t"); 96159317bd1SMohammed Gamal 962*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_mul8); 96359317bd1SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || (outregs.eax & 0xff) != 8) 96459317bd1SMohammed Gamal print_serial("mul Test 1: FAIL\n"); 96559317bd1SMohammed Gamal else 96659317bd1SMohammed Gamal print_serial("mul Test 1: PASS\n"); 96759317bd1SMohammed Gamal 968*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_mul16); 96959317bd1SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 8) 97059317bd1SMohammed Gamal print_serial("mul Test 2: FAIL\n"); 97159317bd1SMohammed Gamal else 97259317bd1SMohammed Gamal print_serial("mul Test 2: PASS\n"); 97359317bd1SMohammed Gamal 974*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_mul32); 97559317bd1SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 8) 97659317bd1SMohammed Gamal print_serial("mul Test 3: FAIL\n"); 97759317bd1SMohammed Gamal else 97859317bd1SMohammed Gamal print_serial("mul Test 3: PASS\n"); 97959317bd1SMohammed Gamal } 98059317bd1SMohammed Gamal 9810d4c7614SMohammed Gamal void test_div() 9820d4c7614SMohammed Gamal { 9830d4c7614SMohammed Gamal struct regs inregs = { 0 }, outregs; 9840d4c7614SMohammed Gamal 9850d4c7614SMohammed Gamal MK_INSN(div8, "mov $257, %ax\n\t" 9860d4c7614SMohammed Gamal "mov $2, %cl\n\t" 9870d4c7614SMohammed Gamal "div %cl\n\t"); 9880d4c7614SMohammed Gamal 9890d4c7614SMohammed Gamal MK_INSN(div16, "mov $512, %ax\n\t" 9900d4c7614SMohammed Gamal "mov $5, %cx\n\t" 9910d4c7614SMohammed Gamal "div %cx\n\t"); 9920d4c7614SMohammed Gamal 9930d4c7614SMohammed Gamal MK_INSN(div32, "mov $512, %eax\n\t" 9940d4c7614SMohammed Gamal "mov $5, %ecx\n\t" 9950d4c7614SMohammed Gamal "div %ecx\n\t"); 9960d4c7614SMohammed Gamal 997*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_div8); 9980d4c7614SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 384) 9990d4c7614SMohammed Gamal print_serial("div Test 1: FAIL\n"); 10000d4c7614SMohammed Gamal else 10010d4c7614SMohammed Gamal print_serial("div Test 1: PASS\n"); 10020d4c7614SMohammed Gamal 1003*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_div16); 10040d4c7614SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 102 || 10050d4c7614SMohammed Gamal outregs.edx != 2) 10060d4c7614SMohammed Gamal print_serial("div Test 2: FAIL\n"); 10070d4c7614SMohammed Gamal else 10080d4c7614SMohammed Gamal print_serial("div Test 2: PASS\n"); 10090d4c7614SMohammed Gamal 1010*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_div32); 10110d4c7614SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 102 || 10120d4c7614SMohammed Gamal outregs.edx != 2) 10130d4c7614SMohammed Gamal print_serial("div Test 3: FAIL\n"); 10140d4c7614SMohammed Gamal else 10150d4c7614SMohammed Gamal print_serial("div Test 3: PASS\n"); 10160d4c7614SMohammed Gamal } 10170d4c7614SMohammed Gamal 10180d4c7614SMohammed Gamal void test_idiv() 10190d4c7614SMohammed Gamal { 10200d4c7614SMohammed Gamal struct regs inregs = { 0 }, outregs; 10210d4c7614SMohammed Gamal 10220d4c7614SMohammed Gamal MK_INSN(idiv8, "mov $256, %ax\n\t" 10230d4c7614SMohammed Gamal "mov $-2, %cl\n\t" 10240d4c7614SMohammed Gamal "idiv %cl\n\t"); 10250d4c7614SMohammed Gamal 10260d4c7614SMohammed Gamal MK_INSN(idiv16, "mov $512, %ax\n\t" 10270d4c7614SMohammed Gamal "mov $-2, %cx\n\t" 10280d4c7614SMohammed Gamal "idiv %cx\n\t"); 10290d4c7614SMohammed Gamal 10300d4c7614SMohammed Gamal MK_INSN(idiv32, "mov $512, %eax\n\t" 10310d4c7614SMohammed Gamal "mov $-2, %ecx\n\t" 10320d4c7614SMohammed Gamal "idiv %ecx\n\t"); 10330d4c7614SMohammed Gamal 1034*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_idiv8); 10350d4c7614SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u8)-128) 10360d4c7614SMohammed Gamal print_serial("idiv Test 1: FAIL\n"); 10370d4c7614SMohammed Gamal else 10380d4c7614SMohammed Gamal print_serial("idiv Test 1: PASS\n"); 10390d4c7614SMohammed Gamal 1040*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_idiv16); 10410d4c7614SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u16)-256) 10420d4c7614SMohammed Gamal print_serial("idiv Test 2: FAIL\n"); 10430d4c7614SMohammed Gamal else 10440d4c7614SMohammed Gamal print_serial("idiv Test 2: PASS\n"); 10450d4c7614SMohammed Gamal 1046*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_idiv32); 10470d4c7614SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u32)-256) 10480d4c7614SMohammed Gamal print_serial("idiv Test 3: FAIL\n"); 10490d4c7614SMohammed Gamal else 10500d4c7614SMohammed Gamal print_serial("idiv Test 3: PASS\n"); 10510d4c7614SMohammed Gamal } 10520d4c7614SMohammed Gamal 10536e293cf5SWei Yongjun void test_cbw(void) 10546e293cf5SWei Yongjun { 10556e293cf5SWei Yongjun struct regs inregs = { 0 }, outregs; 10566e293cf5SWei Yongjun 10576e293cf5SWei Yongjun MK_INSN(cbw, "mov $0xFE, %eax \n\t" 10586e293cf5SWei Yongjun "cbw\n\t"); 10596e293cf5SWei Yongjun MK_INSN(cwde, "mov $0xFFFE, %eax \n\t" 10606e293cf5SWei Yongjun "cwde\n\t"); 10616e293cf5SWei Yongjun 1062*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_cbw); 10636e293cf5SWei Yongjun if (outregs.eax != 0xFFFE) 10646e293cf5SWei Yongjun print_serial("cbw test1: FAIL\n"); 10656e293cf5SWei Yongjun else 10666e293cf5SWei Yongjun print_serial("cbw test 1: PASS\n"); 10676e293cf5SWei Yongjun 1068*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_cwde); 10696e293cf5SWei Yongjun if (outregs.eax != 0xFFFFFFFE) 10706e293cf5SWei Yongjun print_serial("cwde test1: FAIL\n"); 10716e293cf5SWei Yongjun else 10726e293cf5SWei Yongjun print_serial("cwde test 1: PASS\n"); 10736e293cf5SWei Yongjun } 10746e293cf5SWei Yongjun 1075eacef4e2SWei Yongjun void test_loopcc(void) 1076eacef4e2SWei Yongjun { 1077eacef4e2SWei Yongjun struct regs inregs = { 0 }, outregs; 1078eacef4e2SWei Yongjun 1079eacef4e2SWei Yongjun MK_INSN(loop, "mov $10, %ecx\n\t" 1080eacef4e2SWei Yongjun "1: inc %eax\n\t" 1081eacef4e2SWei Yongjun "loop 1b\n\t"); 1082eacef4e2SWei Yongjun 1083eacef4e2SWei Yongjun MK_INSN(loope, "mov $10, %ecx\n\t" 1084eacef4e2SWei Yongjun "mov $1, %eax\n\t" 1085eacef4e2SWei Yongjun "1: dec %eax\n\t" 1086eacef4e2SWei Yongjun "loope 1b\n\t"); 1087eacef4e2SWei Yongjun 1088eacef4e2SWei Yongjun MK_INSN(loopne, "mov $10, %ecx\n\t" 1089eacef4e2SWei Yongjun "mov $5, %eax\n\t" 1090eacef4e2SWei Yongjun "1: dec %eax\n\t" 1091eacef4e2SWei Yongjun "loopne 1b\n\t"); 1092eacef4e2SWei Yongjun 1093*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_loop); 1094eacef4e2SWei Yongjun if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 10) 1095eacef4e2SWei Yongjun print_serial("LOOPcc short Test 1: FAIL\n"); 1096eacef4e2SWei Yongjun else 1097eacef4e2SWei Yongjun print_serial("LOOPcc short Test 1: PASS\n"); 1098eacef4e2SWei Yongjun 1099*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_loope); 1100eacef4e2SWei Yongjun if(!regs_equal(&inregs, &outregs, R_AX | R_CX) || 1101eacef4e2SWei Yongjun outregs.eax != -1 || outregs.ecx != 8) 1102eacef4e2SWei Yongjun print_serial("LOOPcc short Test 2: FAIL\n"); 1103eacef4e2SWei Yongjun else 1104eacef4e2SWei Yongjun print_serial("LOOPcc short Test 2: PASS\n"); 1105eacef4e2SWei Yongjun 1106*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_loopne); 1107eacef4e2SWei Yongjun if(!regs_equal(&inregs, &outregs, R_AX | R_CX) || 1108eacef4e2SWei Yongjun outregs.eax != 0 || outregs.ecx != 5) 1109eacef4e2SWei Yongjun print_serial("LOOPcc short Test 3: FAIL\n"); 1110eacef4e2SWei Yongjun else 1111eacef4e2SWei Yongjun print_serial("LOOPcc short Test 3: PASS\n"); 1112eacef4e2SWei Yongjun } 1113eacef4e2SWei Yongjun 1114b274feedSAvi Kivity static void test_das(void) 1115b274feedSAvi Kivity { 1116b274feedSAvi Kivity struct regs inregs = { 0 }, outregs = { 0 }; 1117b274feedSAvi Kivity short i; 1118b274feedSAvi Kivity static unsigned test_cases[1024] = { 1119b274feedSAvi Kivity 0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00, 1120b274feedSAvi Kivity 0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01, 1121b274feedSAvi Kivity 0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02, 1122b274feedSAvi Kivity 0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03, 1123b274feedSAvi Kivity 0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04, 1124b274feedSAvi Kivity 0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05, 1125b274feedSAvi Kivity 0x06000606, 0x8701a606, 0x56100006, 0x9711a006, 1126b274feedSAvi Kivity 0x02000707, 0x8301a707, 0x12100107, 0x9311a107, 1127b274feedSAvi Kivity 0x02000808, 0x8301a808, 0x12100208, 0x9311a208, 1128b274feedSAvi Kivity 0x06000909, 0x8701a909, 0x16100309, 0x9711a309, 1129b274feedSAvi Kivity 0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a, 1130b274feedSAvi Kivity 0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b, 1131b274feedSAvi Kivity 0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c, 1132b274feedSAvi Kivity 0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d, 1133b274feedSAvi Kivity 0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e, 1134b274feedSAvi Kivity 0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f, 1135b274feedSAvi Kivity 0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10, 1136b274feedSAvi Kivity 0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11, 1137b274feedSAvi Kivity 0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12, 1138b274feedSAvi Kivity 0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13, 1139b274feedSAvi Kivity 0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14, 1140b274feedSAvi Kivity 0x02001515, 0x8301b515, 0x16100f15, 0x9711af15, 1141b274feedSAvi Kivity 0x02001616, 0x8301b616, 0x12101016, 0x9311b016, 1142b274feedSAvi Kivity 0x06001717, 0x8701b717, 0x16101117, 0x9711b117, 1143b274feedSAvi Kivity 0x06001818, 0x8701b818, 0x16101218, 0x9711b218, 1144b274feedSAvi Kivity 0x02001919, 0x8301b919, 0x12101319, 0x9311b319, 1145b274feedSAvi Kivity 0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a, 1146b274feedSAvi Kivity 0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b, 1147b274feedSAvi Kivity 0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c, 1148b274feedSAvi Kivity 0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d, 1149b274feedSAvi Kivity 0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e, 1150b274feedSAvi Kivity 0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f, 1151b274feedSAvi Kivity 0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20, 1152b274feedSAvi Kivity 0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21, 1153b274feedSAvi Kivity 0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22, 1154b274feedSAvi Kivity 0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23, 1155b274feedSAvi Kivity 0x06002424, 0x8301c424, 0x16101e24, 0x9711be24, 1156b274feedSAvi Kivity 0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25, 1157b274feedSAvi Kivity 0x02002626, 0x8701c626, 0x12102026, 0x9711c026, 1158b274feedSAvi Kivity 0x06002727, 0x8301c727, 0x16102127, 0x9311c127, 1159b274feedSAvi Kivity 0x06002828, 0x8301c828, 0x16102228, 0x9311c228, 1160b274feedSAvi Kivity 0x02002929, 0x8701c929, 0x12102329, 0x9711c329, 1161b274feedSAvi Kivity 0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a, 1162b274feedSAvi Kivity 0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b, 1163b274feedSAvi Kivity 0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c, 1164b274feedSAvi Kivity 0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d, 1165b274feedSAvi Kivity 0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e, 1166b274feedSAvi Kivity 0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f, 1167b274feedSAvi Kivity 0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30, 1168b274feedSAvi Kivity 0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31, 1169b274feedSAvi Kivity 0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32, 1170b274feedSAvi Kivity 0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33, 1171b274feedSAvi Kivity 0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34, 1172b274feedSAvi Kivity 0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35, 1173b274feedSAvi Kivity 0x06003636, 0x8301d636, 0x16103036, 0x9311d036, 1174b274feedSAvi Kivity 0x02003737, 0x8701d737, 0x12103137, 0x9711d137, 1175b274feedSAvi Kivity 0x02003838, 0x8701d838, 0x12103238, 0x9711d238, 1176b274feedSAvi Kivity 0x06003939, 0x8301d939, 0x16103339, 0x9311d339, 1177b274feedSAvi Kivity 0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a, 1178b274feedSAvi Kivity 0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b, 1179b274feedSAvi Kivity 0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c, 1180b274feedSAvi Kivity 0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d, 1181b274feedSAvi Kivity 0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e, 1182b274feedSAvi Kivity 0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f, 1183b274feedSAvi Kivity 0x02004040, 0x8301e040, 0x16103a40, 0x9311da40, 1184b274feedSAvi Kivity 0x06004141, 0x8701e141, 0x12103b41, 0x9711db41, 1185b274feedSAvi Kivity 0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42, 1186b274feedSAvi Kivity 0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43, 1187b274feedSAvi Kivity 0x06004444, 0x8701e444, 0x12103e44, 0x9711de44, 1188b274feedSAvi Kivity 0x02004545, 0x8301e545, 0x16103f45, 0x9311df45, 1189b274feedSAvi Kivity 0x02004646, 0x8301e646, 0x12104046, 0x9311e046, 1190b274feedSAvi Kivity 0x06004747, 0x8701e747, 0x16104147, 0x9711e147, 1191b274feedSAvi Kivity 0x06004848, 0x8701e848, 0x16104248, 0x9711e248, 1192b274feedSAvi Kivity 0x02004949, 0x8301e949, 0x12104349, 0x9311e349, 1193b274feedSAvi Kivity 0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a, 1194b274feedSAvi Kivity 0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b, 1195b274feedSAvi Kivity 0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c, 1196b274feedSAvi Kivity 0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d, 1197b274feedSAvi Kivity 0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e, 1198b274feedSAvi Kivity 0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f, 1199b274feedSAvi Kivity 0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50, 1200b274feedSAvi Kivity 0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51, 1201b274feedSAvi Kivity 0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52, 1202b274feedSAvi Kivity 0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53, 1203b274feedSAvi Kivity 0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54, 1204b274feedSAvi Kivity 0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55, 1205b274feedSAvi Kivity 0x06005656, 0x8701f656, 0x16105056, 0x9711f056, 1206b274feedSAvi Kivity 0x02005757, 0x8301f757, 0x12105157, 0x9311f157, 1207b274feedSAvi Kivity 0x02005858, 0x8301f858, 0x12105258, 0x9311f258, 1208b274feedSAvi Kivity 0x06005959, 0x8701f959, 0x16105359, 0x9711f359, 1209b274feedSAvi Kivity 0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a, 1210b274feedSAvi Kivity 0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b, 1211b274feedSAvi Kivity 0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c, 1212b274feedSAvi Kivity 0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d, 1213b274feedSAvi Kivity 0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e, 1214b274feedSAvi Kivity 0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f, 1215b274feedSAvi Kivity 0x06006060, 0x47010060, 0x16105a60, 0x9711fa60, 1216b274feedSAvi Kivity 0x02006161, 0x03010161, 0x12105b61, 0x9311fb61, 1217b274feedSAvi Kivity 0x02006262, 0x03010262, 0x16105c62, 0x9711fc62, 1218b274feedSAvi Kivity 0x06006363, 0x07010363, 0x12105d63, 0x9311fd63, 1219b274feedSAvi Kivity 0x02006464, 0x03010464, 0x12105e64, 0x9311fe64, 1220b274feedSAvi Kivity 0x06006565, 0x07010565, 0x16105f65, 0x9711ff65, 1221b274feedSAvi Kivity 0x06006666, 0x07010666, 0x16106066, 0x57110066, 1222b274feedSAvi Kivity 0x02006767, 0x03010767, 0x12106167, 0x13110167, 1223b274feedSAvi Kivity 0x02006868, 0x03010868, 0x12106268, 0x13110268, 1224b274feedSAvi Kivity 0x06006969, 0x07010969, 0x16106369, 0x17110369, 1225b274feedSAvi Kivity 0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a, 1226b274feedSAvi Kivity 0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b, 1227b274feedSAvi Kivity 0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c, 1228b274feedSAvi Kivity 0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d, 1229b274feedSAvi Kivity 0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e, 1230b274feedSAvi Kivity 0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f, 1231b274feedSAvi Kivity 0x02007070, 0x03011070, 0x16106a70, 0x17110a70, 1232b274feedSAvi Kivity 0x06007171, 0x07011171, 0x12106b71, 0x13110b71, 1233b274feedSAvi Kivity 0x06007272, 0x07011272, 0x16106c72, 0x17110c72, 1234b274feedSAvi Kivity 0x02007373, 0x03011373, 0x12106d73, 0x13110d73, 1235b274feedSAvi Kivity 0x06007474, 0x07011474, 0x12106e74, 0x13110e74, 1236b274feedSAvi Kivity 0x02007575, 0x03011575, 0x16106f75, 0x17110f75, 1237b274feedSAvi Kivity 0x02007676, 0x03011676, 0x12107076, 0x13111076, 1238b274feedSAvi Kivity 0x06007777, 0x07011777, 0x16107177, 0x17111177, 1239b274feedSAvi Kivity 0x06007878, 0x07011878, 0x16107278, 0x17111278, 1240b274feedSAvi Kivity 0x02007979, 0x03011979, 0x12107379, 0x13111379, 1241b274feedSAvi Kivity 0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a, 1242b274feedSAvi Kivity 0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b, 1243b274feedSAvi Kivity 0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c, 1244b274feedSAvi Kivity 0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d, 1245b274feedSAvi Kivity 0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e, 1246b274feedSAvi Kivity 0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f, 1247b274feedSAvi Kivity 0x82008080, 0x03012080, 0x12107a80, 0x13111a80, 1248b274feedSAvi Kivity 0x86008181, 0x07012181, 0x16107b81, 0x17111b81, 1249b274feedSAvi Kivity 0x86008282, 0x07012282, 0x12107c82, 0x13111c82, 1250b274feedSAvi Kivity 0x82008383, 0x03012383, 0x16107d83, 0x17111d83, 1251b274feedSAvi Kivity 0x86008484, 0x07012484, 0x16107e84, 0x17111e84, 1252b274feedSAvi Kivity 0x82008585, 0x03012585, 0x12107f85, 0x13111f85, 1253b274feedSAvi Kivity 0x82008686, 0x03012686, 0x92108086, 0x13112086, 1254b274feedSAvi Kivity 0x86008787, 0x07012787, 0x96108187, 0x17112187, 1255b274feedSAvi Kivity 0x86008888, 0x07012888, 0x96108288, 0x17112288, 1256b274feedSAvi Kivity 0x82008989, 0x03012989, 0x92108389, 0x13112389, 1257b274feedSAvi Kivity 0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a, 1258b274feedSAvi Kivity 0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b, 1259b274feedSAvi Kivity 0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c, 1260b274feedSAvi Kivity 0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d, 1261b274feedSAvi Kivity 0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e, 1262b274feedSAvi Kivity 0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f, 1263b274feedSAvi Kivity 0x86009090, 0x07013090, 0x92108a90, 0x13112a90, 1264b274feedSAvi Kivity 0x82009191, 0x03013191, 0x96108b91, 0x17112b91, 1265b274feedSAvi Kivity 0x82009292, 0x03013292, 0x92108c92, 0x13112c92, 1266b274feedSAvi Kivity 0x86009393, 0x07013393, 0x96108d93, 0x17112d93, 1267b274feedSAvi Kivity 0x82009494, 0x03013494, 0x96108e94, 0x17112e94, 1268b274feedSAvi Kivity 0x86009595, 0x07013595, 0x92108f95, 0x13112f95, 1269b274feedSAvi Kivity 0x86009696, 0x07013696, 0x96109096, 0x17113096, 1270b274feedSAvi Kivity 0x82009797, 0x03013797, 0x92109197, 0x13113197, 1271b274feedSAvi Kivity 0x82009898, 0x03013898, 0x92109298, 0x13113298, 1272b274feedSAvi Kivity 0x86009999, 0x07013999, 0x96109399, 0x17113399, 1273b274feedSAvi Kivity 0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a, 1274b274feedSAvi Kivity 0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b, 1275b274feedSAvi Kivity 0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c, 1276b274feedSAvi Kivity 0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d, 1277b274feedSAvi Kivity 0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e, 1278b274feedSAvi Kivity 0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f, 1279b274feedSAvi Kivity 0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0, 1280b274feedSAvi Kivity 0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1, 1281b274feedSAvi Kivity 0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2, 1282b274feedSAvi Kivity 0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3, 1283b274feedSAvi Kivity 0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4, 1284b274feedSAvi Kivity 0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5, 1285b274feedSAvi Kivity 0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6, 1286b274feedSAvi Kivity 0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7, 1287b274feedSAvi Kivity 0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8, 1288b274feedSAvi Kivity 0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9, 1289b274feedSAvi Kivity 0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa, 1290b274feedSAvi Kivity 0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab, 1291b274feedSAvi Kivity 0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac, 1292b274feedSAvi Kivity 0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad, 1293b274feedSAvi Kivity 0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae, 1294b274feedSAvi Kivity 0x130049af, 0x130149af, 0x131049af, 0x131149af, 1295b274feedSAvi Kivity 0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0, 1296b274feedSAvi Kivity 0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1, 1297b274feedSAvi Kivity 0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2, 1298b274feedSAvi Kivity 0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3, 1299b274feedSAvi Kivity 0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4, 1300b274feedSAvi Kivity 0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5, 1301b274feedSAvi Kivity 0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6, 1302b274feedSAvi Kivity 0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7, 1303b274feedSAvi Kivity 0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8, 1304b274feedSAvi Kivity 0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9, 1305b274feedSAvi Kivity 0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba, 1306b274feedSAvi Kivity 0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb, 1307b274feedSAvi Kivity 0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc, 1308b274feedSAvi Kivity 0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd, 1309b274feedSAvi Kivity 0x130058be, 0x130158be, 0x131058be, 0x131158be, 1310b274feedSAvi Kivity 0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf, 1311b274feedSAvi Kivity 0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0, 1312b274feedSAvi Kivity 0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1, 1313b274feedSAvi Kivity 0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2, 1314b274feedSAvi Kivity 0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3, 1315b274feedSAvi Kivity 0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4, 1316b274feedSAvi Kivity 0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5, 1317b274feedSAvi Kivity 0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6, 1318b274feedSAvi Kivity 0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7, 1319b274feedSAvi Kivity 0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8, 1320b274feedSAvi Kivity 0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9, 1321b274feedSAvi Kivity 0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca, 1322b274feedSAvi Kivity 0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb, 1323b274feedSAvi Kivity 0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc, 1324b274feedSAvi Kivity 0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd, 1325b274feedSAvi Kivity 0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce, 1326b274feedSAvi Kivity 0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf, 1327b274feedSAvi Kivity 0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0, 1328b274feedSAvi Kivity 0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1, 1329b274feedSAvi Kivity 0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2, 1330b274feedSAvi Kivity 0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3, 1331b274feedSAvi Kivity 0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4, 1332b274feedSAvi Kivity 0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5, 1333b274feedSAvi Kivity 0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6, 1334b274feedSAvi Kivity 0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7, 1335b274feedSAvi Kivity 0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8, 1336b274feedSAvi Kivity 0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9, 1337b274feedSAvi Kivity 0x170074da, 0x170174da, 0x171074da, 0x171174da, 1338b274feedSAvi Kivity 0x130075db, 0x130175db, 0x131075db, 0x131175db, 1339b274feedSAvi Kivity 0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc, 1340b274feedSAvi Kivity 0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd, 1341b274feedSAvi Kivity 0x170078de, 0x170178de, 0x171078de, 0x171178de, 1342b274feedSAvi Kivity 0x130079df, 0x130179df, 0x131079df, 0x131179df, 1343b274feedSAvi Kivity 0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0, 1344b274feedSAvi Kivity 0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1, 1345b274feedSAvi Kivity 0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2, 1346b274feedSAvi Kivity 0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3, 1347b274feedSAvi Kivity 0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4, 1348b274feedSAvi Kivity 0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5, 1349b274feedSAvi Kivity 0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6, 1350b274feedSAvi Kivity 0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7, 1351b274feedSAvi Kivity 0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8, 1352b274feedSAvi Kivity 0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9, 1353b274feedSAvi Kivity 0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea, 1354b274feedSAvi Kivity 0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb, 1355b274feedSAvi Kivity 0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec, 1356b274feedSAvi Kivity 0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed, 1357b274feedSAvi Kivity 0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee, 1358b274feedSAvi Kivity 0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef, 1359b274feedSAvi Kivity 0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0, 1360b274feedSAvi Kivity 0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1, 1361b274feedSAvi Kivity 0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2, 1362b274feedSAvi Kivity 0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3, 1363b274feedSAvi Kivity 0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4, 1364b274feedSAvi Kivity 0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5, 1365b274feedSAvi Kivity 0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6, 1366b274feedSAvi Kivity 0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7, 1367b274feedSAvi Kivity 0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8, 1368b274feedSAvi Kivity 0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9, 1369b274feedSAvi Kivity 0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa, 1370b274feedSAvi Kivity 0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb, 1371b274feedSAvi Kivity 0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc, 1372b274feedSAvi Kivity 0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd, 1373b274feedSAvi Kivity 0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe, 1374b274feedSAvi Kivity 0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff, 1375b274feedSAvi Kivity }; 1376b274feedSAvi Kivity 1377b274feedSAvi Kivity MK_INSN(das, "das"); 1378b274feedSAvi Kivity 1379b274feedSAvi Kivity for (i = 0; i < 1024; ++i) { 1380b274feedSAvi Kivity unsigned tmp = test_cases[i]; 1381b274feedSAvi Kivity inregs.eax = tmp & 0xff; 1382b274feedSAvi Kivity inregs.eflags = (tmp >> 16) & 0xff; 1383*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_das); 1384b274feedSAvi Kivity if (!regs_equal(&inregs, &outregs, R_AX) 1385b274feedSAvi Kivity || outregs.eax != ((tmp >> 8) & 0xff) 1386b274feedSAvi Kivity || (outregs.eflags & 0xff) != (tmp >> 24)) { 1387b274feedSAvi Kivity print_serial("DAS Test: FAIL\n"); 1388b274feedSAvi Kivity return; 1389b274feedSAvi Kivity } 1390b274feedSAvi Kivity } 1391b274feedSAvi Kivity print_serial("DAS Test: PASS\n"); 1392b274feedSAvi Kivity } 1393b274feedSAvi Kivity 13940cbd5b06SMohammed Gamal void test_cwd_cdq() 13950cbd5b06SMohammed Gamal { 13960cbd5b06SMohammed Gamal struct regs inregs = { 0 }, outregs; 13970cbd5b06SMohammed Gamal 13980cbd5b06SMohammed Gamal /* Sign-bit set */ 13990cbd5b06SMohammed Gamal MK_INSN(cwd_1, "mov $0x8000, %ax\n\t" 14000cbd5b06SMohammed Gamal "cwd\n\t"); 14010cbd5b06SMohammed Gamal 14020cbd5b06SMohammed Gamal /* Sign-bit not set */ 14030cbd5b06SMohammed Gamal MK_INSN(cwd_2, "mov $0x1000, %ax\n\t" 14040cbd5b06SMohammed Gamal "cwd\n\t"); 14050cbd5b06SMohammed Gamal 14060cbd5b06SMohammed Gamal /* Sign-bit set */ 14070cbd5b06SMohammed Gamal MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t" 14080cbd5b06SMohammed Gamal "cdq\n\t"); 14090cbd5b06SMohammed Gamal 14100cbd5b06SMohammed Gamal /* Sign-bit not set */ 14110cbd5b06SMohammed Gamal MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t" 14120cbd5b06SMohammed Gamal "cdq\n\t"); 14130cbd5b06SMohammed Gamal 1414*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_cwd_1); 14150cbd5b06SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_DX) || outregs.eax != 0x8000 || outregs.edx != 0xffff) 14160cbd5b06SMohammed Gamal print_serial("cwd Test 1: FAIL\n"); 14170cbd5b06SMohammed Gamal else 14180cbd5b06SMohammed Gamal print_serial("cwd Test 1: PASS\n"); 14190cbd5b06SMohammed Gamal 1420*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_cwd_2); 14210cbd5b06SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_DX) || outregs.eax != 0x1000 || outregs.edx != 0) 14220cbd5b06SMohammed Gamal print_serial("cwd Test 2: FAIL\n"); 14230cbd5b06SMohammed Gamal else 14240cbd5b06SMohammed Gamal print_serial("cwd Test 2: PASS\n"); 14250cbd5b06SMohammed Gamal 1426*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_cdq_1); 14270cbd5b06SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_DX) || outregs.eax != 0x80000000 || outregs.edx != 0xffffffff) 14280cbd5b06SMohammed Gamal print_serial("cdq Test 1: FAIL\n"); 14290cbd5b06SMohammed Gamal else 14300cbd5b06SMohammed Gamal print_serial("cdq Test 1: PASS\n"); 14310cbd5b06SMohammed Gamal 1432*d4dc402cSAvi Kivity exec_in_big_real_mode(&inregs, &outregs, &insn_cdq_2); 14330cbd5b06SMohammed Gamal if (!regs_equal(&inregs, &outregs, R_AX | R_DX) || outregs.eax != 0x10000000 || outregs.edx != 0) 14340cbd5b06SMohammed Gamal print_serial("cdq Test 2: FAIL\n"); 14350cbd5b06SMohammed Gamal else 14360cbd5b06SMohammed Gamal print_serial("cdq Test 2: PASS\n"); 14370cbd5b06SMohammed Gamal } 14380cbd5b06SMohammed Gamal 14397d36db35SAvi Kivity void realmode_start(void) 14407d36db35SAvi Kivity { 14417d36db35SAvi Kivity test_null(); 14427d36db35SAvi Kivity 14437d36db35SAvi Kivity test_shld(); 14447d36db35SAvi Kivity test_push_pop(); 14457d36db35SAvi Kivity test_pusha_popa(); 14467d36db35SAvi Kivity test_mov_imm(); 14477d36db35SAvi Kivity test_cmp_imm(); 14487d36db35SAvi Kivity test_add_imm(); 14497d36db35SAvi Kivity test_sub_imm(); 14507d36db35SAvi Kivity test_xor_imm(); 14517d36db35SAvi Kivity test_io(); 14527d36db35SAvi Kivity test_eflags_insn(); 14537d36db35SAvi Kivity test_jcc_short(); 14547d36db35SAvi Kivity test_jcc_near(); 14557d36db35SAvi Kivity /* test_call() uses short jump so call it after testing jcc */ 14567d36db35SAvi Kivity test_call(); 14577d36db35SAvi Kivity /* long jmp test uses call near so test it after testing call */ 14587d36db35SAvi Kivity test_long_jmp(); 14597d36db35SAvi Kivity test_xchg(); 14607d36db35SAvi Kivity test_iret(); 146196b9ca1eSMohammed Gamal test_int(); 1462fa74f8a6SMohammed Gamal test_imul(); 146359317bd1SMohammed Gamal test_mul(); 14640d4c7614SMohammed Gamal test_div(); 14650d4c7614SMohammed Gamal test_idiv(); 1466eacef4e2SWei Yongjun test_loopcc(); 14676e293cf5SWei Yongjun test_cbw(); 14680cbd5b06SMohammed Gamal test_cwd_cdq(); 1469b274feedSAvi Kivity test_das(); 14707d36db35SAvi Kivity 14717d36db35SAvi Kivity exit(0); 14727d36db35SAvi Kivity } 14737d36db35SAvi Kivity 14747d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff }; 14757d36db35SAvi Kivity 14767d36db35SAvi Kivity struct __attribute__((packed)) { 14777d36db35SAvi Kivity unsigned short limit; 14787d36db35SAvi Kivity void *base; 14797d36db35SAvi Kivity } r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt }; 14807d36db35SAvi Kivity 14817d36db35SAvi Kivity asm( 14827d36db35SAvi Kivity ".section .init \n\t" 14837d36db35SAvi Kivity 14847d36db35SAvi Kivity ".code32 \n\t" 14857d36db35SAvi Kivity 14867d36db35SAvi Kivity "mb_magic = 0x1BADB002 \n\t" 14877d36db35SAvi Kivity "mb_flags = 0x0 \n\t" 14887d36db35SAvi Kivity 14897d36db35SAvi Kivity "# multiboot header \n\t" 14907d36db35SAvi Kivity ".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t" 14917d36db35SAvi Kivity 14927d36db35SAvi Kivity ".globl start \n\t" 14937d36db35SAvi Kivity ".data \n\t" 14947d36db35SAvi Kivity ". = . + 4096 \n\t" 14957d36db35SAvi Kivity "stacktop: \n\t" 14967d36db35SAvi Kivity 14977d36db35SAvi Kivity ".text \n\t" 14987d36db35SAvi Kivity "start: \n\t" 14997d36db35SAvi Kivity "lgdt r_gdt_descr \n\t" 15007d36db35SAvi Kivity "ljmp $8, $1f; 1: \n\t" 15017d36db35SAvi Kivity ".code16gcc \n\t" 15027d36db35SAvi Kivity "mov $16, %eax \n\t" 15037d36db35SAvi Kivity "mov %ax, %ds \n\t" 15047d36db35SAvi Kivity "mov %ax, %es \n\t" 15057d36db35SAvi Kivity "mov %ax, %fs \n\t" 15067d36db35SAvi Kivity "mov %ax, %gs \n\t" 15077d36db35SAvi Kivity "mov %ax, %ss \n\t" 15087d36db35SAvi Kivity "mov %cr0, %eax \n\t" 15097d36db35SAvi Kivity "btc $0, %eax \n\t" 15107d36db35SAvi Kivity "mov %eax, %cr0 \n\t" 15117d36db35SAvi Kivity "ljmp $0, $realmode_entry \n\t" 15127d36db35SAvi Kivity 15137d36db35SAvi Kivity "realmode_entry: \n\t" 15147d36db35SAvi Kivity 15157d36db35SAvi Kivity "xor %ax, %ax \n\t" 15167d36db35SAvi Kivity "mov %ax, %ds \n\t" 15177d36db35SAvi Kivity "mov %ax, %es \n\t" 15187d36db35SAvi Kivity "mov %ax, %ss \n\t" 15197d36db35SAvi Kivity "mov %ax, %fs \n\t" 15207d36db35SAvi Kivity "mov %ax, %gs \n\t" 15217d36db35SAvi Kivity "mov $stacktop, %esp\n\t" 15227d36db35SAvi Kivity "ljmp $0, $realmode_start \n\t" 15237d36db35SAvi Kivity 15247d36db35SAvi Kivity ".code16gcc \n\t" 15257d36db35SAvi Kivity ); 1526