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 57d4dc402cSAvi Kivity struct insn_desc { 58d4dc402cSAvi Kivity u16 ptr; 59d4dc402cSAvi Kivity u16 len; 60d4dc402cSAvi Kivity }; 61d4dc402cSAvi Kivity 6218253fdeSAvi Kivity static struct regs inregs, outregs; 6318253fdeSAvi Kivity 6418253fdeSAvi Kivity static void exec_in_big_real_mode(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 71d4dc402cSAvi Kivity for (i = 0; i < insn->len; ++i) 72d4dc402cSAvi 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 7618253fdeSAvi 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 ); 11818253fdeSAvi 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 13018253fdeSAvi Kivity int regs_equal(int ignore) 1317d36db35SAvi Kivity { 13218253fdeSAvi Kivity const u32 *p1 = &inregs.eax, *p2 = &outregs.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 1416055ea1fSAvi Kivity static void report(const char *name, u16 regs_ignore, _Bool ok) 14281050840SAvi Kivity { 1436055ea1fSAvi Kivity if (!regs_equal(regs_ignore)) { 1446055ea1fSAvi Kivity ok = 0; 1456055ea1fSAvi Kivity } 14681050840SAvi Kivity print_serial(ok ? "PASS: " : "FAIL: "); 14781050840SAvi Kivity print_serial(name); 14881050840SAvi Kivity print_serial("\n"); 14981050840SAvi Kivity } 15081050840SAvi Kivity 1517d36db35SAvi Kivity #define MK_INSN(name, str) \ 1527d36db35SAvi Kivity asm ( \ 153d4dc402cSAvi Kivity ".pushsection .data.insn \n\t" \ 154d4dc402cSAvi Kivity "insn_" #name ": \n\t" \ 155d4dc402cSAvi Kivity ".word 1001f, 1002f - 1001f \n\t" \ 156d4dc402cSAvi Kivity ".popsection \n\t" \ 157d4dc402cSAvi Kivity ".pushsection .text.insn, \"ax\" \n\t" \ 158d4dc402cSAvi Kivity "1001: \n\t" \ 159d4dc402cSAvi Kivity "insn_code_" #name ": " str " \n\t" \ 160d4dc402cSAvi Kivity "1002: \n\t" \ 161d4dc402cSAvi Kivity ".popsection" \ 1627d36db35SAvi Kivity ); \ 163d4dc402cSAvi Kivity extern struct insn_desc insn_##name; 1647d36db35SAvi Kivity 1657d36db35SAvi Kivity void test_xchg(void) 1667d36db35SAvi Kivity { 1677d36db35SAvi Kivity MK_INSN(xchg_test1, "xchg %eax,%eax\n\t"); 1687d36db35SAvi Kivity MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t"); 1697d36db35SAvi Kivity MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t"); 1707d36db35SAvi Kivity MK_INSN(xchg_test4, "xchg %eax,%edx\n\t"); 1717d36db35SAvi Kivity MK_INSN(xchg_test5, "xchg %eax,%esi\n\t"); 1727d36db35SAvi Kivity MK_INSN(xchg_test6, "xchg %eax,%edi\n\t"); 1737d36db35SAvi Kivity MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t"); 1747d36db35SAvi Kivity MK_INSN(xchg_test8, "xchg %eax,%esp\n\t"); 1757d36db35SAvi Kivity 17618253fdeSAvi Kivity inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7}; 1777d36db35SAvi Kivity 17818253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test1); 1796055ea1fSAvi Kivity report("xchg 1", 0, 1); 18018253fdeSAvi Kivity 18118253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test2); 1826055ea1fSAvi Kivity report("xchg 2", R_AX | R_BX, 1836055ea1fSAvi Kivity outregs.eax == inregs.ebx && outregs.ebx == inregs.eax); 1847d36db35SAvi Kivity 18518253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test3); 1866055ea1fSAvi Kivity report("xchg 3", R_AX | R_CX, 1876055ea1fSAvi Kivity outregs.eax == inregs.ecx && outregs.ecx == inregs.eax); 1887d36db35SAvi Kivity 18918253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test4); 1906055ea1fSAvi Kivity report("xchg 4", R_AX | R_DX, 1916055ea1fSAvi Kivity outregs.eax == inregs.edx && outregs.edx == inregs.eax); 1927d36db35SAvi Kivity 19318253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test5); 1946055ea1fSAvi Kivity report("xchg 5", R_AX | R_SI, 1956055ea1fSAvi Kivity outregs.eax == inregs.esi && outregs.esi == inregs.eax); 1967d36db35SAvi Kivity 19718253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test6); 1986055ea1fSAvi Kivity report("xchg 6", R_AX | R_DI, 1996055ea1fSAvi Kivity outregs.eax == inregs.edi && outregs.edi == inregs.eax); 2007d36db35SAvi Kivity 20118253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test7); 2026055ea1fSAvi Kivity report("xchg 7", R_AX | R_BP, 2036055ea1fSAvi Kivity outregs.eax == inregs.ebp && outregs.ebp == inregs.eax); 2047d36db35SAvi Kivity 20518253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test8); 2066055ea1fSAvi Kivity report("xchg 8", R_AX | R_SP, 2076055ea1fSAvi Kivity outregs.eax == inregs.esp && outregs.esp == inregs.eax); 2087d36db35SAvi Kivity } 2097d36db35SAvi Kivity 2107d36db35SAvi Kivity void test_shld(void) 2117d36db35SAvi Kivity { 2127d36db35SAvi Kivity MK_INSN(shld_test, "shld $8,%edx,%eax\n\t"); 2137d36db35SAvi Kivity 21418253fdeSAvi Kivity inregs = (struct regs){ .eax = 0xbe, .edx = 0xef000000 }; 21518253fdeSAvi Kivity exec_in_big_real_mode(&insn_shld_test); 2166055ea1fSAvi Kivity report("shld", ~0, outregs.eax == 0xbeef); 2177d36db35SAvi Kivity } 2187d36db35SAvi Kivity 2197d36db35SAvi Kivity void test_mov_imm(void) 2207d36db35SAvi Kivity { 2217d36db35SAvi Kivity MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax"); 2227d36db35SAvi Kivity MK_INSN(mov_r16_imm_1, "mov $1234, %ax"); 2237d36db35SAvi Kivity MK_INSN(mov_r8_imm_1, "mov $0x12, %ah"); 2247d36db35SAvi Kivity MK_INSN(mov_r8_imm_2, "mov $0x34, %al"); 2257d36db35SAvi Kivity MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t"); 2267d36db35SAvi Kivity 22718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 22818253fdeSAvi Kivity 22918253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r16_imm_1); 2306055ea1fSAvi Kivity report("mov 1", R_AX, outregs.eax == 1234); 2317d36db35SAvi Kivity 2327d36db35SAvi Kivity /* test mov $imm, %eax */ 23318253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r32_imm_1); 2346055ea1fSAvi Kivity report("mov 2", R_AX, outregs.eax == 1234567890); 2357d36db35SAvi Kivity 2367d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 23718253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_1); 2386055ea1fSAvi Kivity report("mov 3", R_AX, outregs.eax == 0x1200); 2397d36db35SAvi Kivity 24018253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_2); 2416055ea1fSAvi Kivity report("mov 4", R_AX, outregs.eax == 0x34); 2427d36db35SAvi Kivity 24318253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_3); 2446055ea1fSAvi Kivity report("mov 5", R_AX, outregs.eax == 0x1234); 2457d36db35SAvi Kivity } 2467d36db35SAvi Kivity 2477d36db35SAvi Kivity void test_sub_imm(void) 2487d36db35SAvi Kivity { 2497d36db35SAvi Kivity MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t"); 2507d36db35SAvi Kivity MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t"); 2517d36db35SAvi Kivity MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t"); 2527d36db35SAvi Kivity MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t"); 2537d36db35SAvi Kivity 25418253fdeSAvi Kivity inregs = (struct regs){ 0 }; 25518253fdeSAvi Kivity 25618253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r16_imm_1); 2576055ea1fSAvi Kivity report("sub 1", R_AX, outregs.eax == 1224); 2587d36db35SAvi Kivity 2597d36db35SAvi Kivity /* test mov $imm, %eax */ 26018253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r32_imm_1); 2616055ea1fSAvi Kivity report("sub 2", R_AX, outregs.eax == 1234567880); 2627d36db35SAvi Kivity 2637d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 26418253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r8_imm_1); 2656055ea1fSAvi Kivity report("sub 3", R_AX, outregs.eax == 0x0200); 2667d36db35SAvi Kivity 26718253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r8_imm_2); 2686055ea1fSAvi Kivity report("sub 4", R_AX, outregs.eax == 0x24); 2697d36db35SAvi Kivity } 2707d36db35SAvi Kivity 2717d36db35SAvi Kivity void test_xor_imm(void) 2727d36db35SAvi Kivity { 2737d36db35SAvi Kivity MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t"); 2747d36db35SAvi Kivity MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t"); 2757d36db35SAvi Kivity MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t"); 2767d36db35SAvi Kivity MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t"); 2777d36db35SAvi Kivity 27818253fdeSAvi Kivity inregs = (struct regs){ 0 }; 27918253fdeSAvi Kivity 28018253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r16_imm_1); 2816055ea1fSAvi Kivity report("xor 1", R_AX, outregs.eax == 0); 2827d36db35SAvi Kivity 2837d36db35SAvi Kivity /* test mov $imm, %eax */ 28418253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r32_imm_1); 2856055ea1fSAvi Kivity report("xor 2", R_AX, outregs.eax == 0); 2867d36db35SAvi Kivity 2877d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 28818253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r8_imm_1); 2896055ea1fSAvi Kivity report("xor 3", R_AX, outregs.eax == 0); 2907d36db35SAvi Kivity 29118253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r8_imm_2); 2926055ea1fSAvi Kivity report("xor 4", R_AX, outregs.eax == 0); 2937d36db35SAvi Kivity } 2947d36db35SAvi Kivity 2957d36db35SAvi Kivity void test_cmp_imm(void) 2967d36db35SAvi Kivity { 2977d36db35SAvi Kivity MK_INSN(cmp_test1, "mov $0x34, %al\n\t" 2987d36db35SAvi Kivity "cmp $0x34, %al\n\t"); 2997d36db35SAvi Kivity MK_INSN(cmp_test2, "mov $0x34, %al\n\t" 3007d36db35SAvi Kivity "cmp $0x39, %al\n\t"); 3017d36db35SAvi Kivity MK_INSN(cmp_test3, "mov $0x34, %al\n\t" 3027d36db35SAvi Kivity "cmp $0x24, %al\n\t"); 3037d36db35SAvi Kivity 30418253fdeSAvi Kivity inregs = (struct regs){ 0 }; 30518253fdeSAvi Kivity 3067d36db35SAvi Kivity /* test cmp imm8 with AL */ 3077d36db35SAvi Kivity /* ZF: (bit 6) Zero Flag becomes 1 if an operation results 3087d36db35SAvi Kivity * in a 0 writeback, or 0 register 3097d36db35SAvi Kivity */ 31018253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test1); 3116055ea1fSAvi Kivity report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6)); 3127d36db35SAvi Kivity 31318253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test2); 3146055ea1fSAvi Kivity report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0); 3157d36db35SAvi Kivity 31618253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test3); 3176055ea1fSAvi Kivity report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0); 3187d36db35SAvi Kivity } 3197d36db35SAvi Kivity 3207d36db35SAvi Kivity void test_add_imm(void) 3217d36db35SAvi Kivity { 3227d36db35SAvi Kivity MK_INSN(add_test1, "mov $0x43211234, %eax \n\t" 3237d36db35SAvi Kivity "add $0x12344321, %eax \n\t"); 3247d36db35SAvi Kivity MK_INSN(add_test2, "mov $0x12, %eax \n\t" 3257d36db35SAvi Kivity "add $0x21, %al\n\t"); 3267d36db35SAvi Kivity 32718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 32818253fdeSAvi Kivity 32918253fdeSAvi Kivity exec_in_big_real_mode(&insn_add_test1); 3306055ea1fSAvi Kivity report("add 1", ~0, outregs.eax == 0x55555555); 3317d36db35SAvi Kivity 33218253fdeSAvi Kivity exec_in_big_real_mode(&insn_add_test2); 3336055ea1fSAvi Kivity report("add 2", ~0, outregs.eax == 0x33); 3347d36db35SAvi Kivity } 3357d36db35SAvi Kivity 3367d36db35SAvi Kivity void test_eflags_insn(void) 3377d36db35SAvi Kivity { 3387d36db35SAvi Kivity MK_INSN(clc, "clc"); 339b3261e48SMohammed Gamal MK_INSN(stc, "stc"); 3407d36db35SAvi Kivity MK_INSN(cli, "cli"); 3417d36db35SAvi Kivity MK_INSN(sti, "sti"); 3427d36db35SAvi Kivity MK_INSN(cld, "cld"); 3437d36db35SAvi Kivity MK_INSN(std, "std"); 3447d36db35SAvi Kivity 34518253fdeSAvi Kivity inregs = (struct regs){ 0 }; 34618253fdeSAvi Kivity 34718253fdeSAvi Kivity exec_in_big_real_mode(&insn_clc); 3486055ea1fSAvi Kivity report("clc", ~0, (outregs.eflags & 1) == 0); 3497d36db35SAvi Kivity 35018253fdeSAvi Kivity exec_in_big_real_mode(&insn_stc); 3516055ea1fSAvi Kivity report("stc", ~0, (outregs.eflags & 1) == 1); 352b3261e48SMohammed Gamal 35318253fdeSAvi Kivity exec_in_big_real_mode(&insn_cli); 3546055ea1fSAvi Kivity report("cli", ~0, !(outregs.eflags & (1 << 9))); 3557d36db35SAvi Kivity 35618253fdeSAvi Kivity exec_in_big_real_mode(&insn_sti); 3576055ea1fSAvi Kivity report("sti", ~0, outregs.eflags & (1 << 9)); 3587d36db35SAvi Kivity 35918253fdeSAvi Kivity exec_in_big_real_mode(&insn_cld); 3606055ea1fSAvi Kivity report("cld", ~0, !(outregs.eflags & (1 << 10))); 3617d36db35SAvi Kivity 36218253fdeSAvi Kivity exec_in_big_real_mode(&insn_std); 3636055ea1fSAvi Kivity report("std", ~0, (outregs.eflags & (1 << 10))); 3647d36db35SAvi Kivity } 3657d36db35SAvi Kivity 3667d36db35SAvi Kivity void test_io(void) 3677d36db35SAvi Kivity { 3687d36db35SAvi Kivity MK_INSN(io_test1, "mov $0xff, %al \n\t" 3697d36db35SAvi Kivity "out %al, $0xe0 \n\t" 3707d36db35SAvi Kivity "mov $0x00, %al \n\t" 3717d36db35SAvi Kivity "in $0xe0, %al \n\t"); 3727d36db35SAvi Kivity MK_INSN(io_test2, "mov $0xffff, %ax \n\t" 3737d36db35SAvi Kivity "out %ax, $0xe0 \n\t" 3747d36db35SAvi Kivity "mov $0x0000, %ax \n\t" 3757d36db35SAvi Kivity "in $0xe0, %ax \n\t"); 3767d36db35SAvi Kivity MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t" 3777d36db35SAvi Kivity "out %eax, $0xe0 \n\t" 3787d36db35SAvi Kivity "mov $0x000000, %eax \n\t" 3797d36db35SAvi Kivity "in $0xe0, %eax \n\t"); 3807d36db35SAvi Kivity MK_INSN(io_test4, "mov $0xe0, %dx \n\t" 3817d36db35SAvi Kivity "mov $0xff, %al \n\t" 3827d36db35SAvi Kivity "out %al, %dx \n\t" 3837d36db35SAvi Kivity "mov $0x00, %al \n\t" 3847d36db35SAvi Kivity "in %dx, %al \n\t"); 3857d36db35SAvi Kivity MK_INSN(io_test5, "mov $0xe0, %dx \n\t" 3867d36db35SAvi Kivity "mov $0xffff, %ax \n\t" 3877d36db35SAvi Kivity "out %ax, %dx \n\t" 3887d36db35SAvi Kivity "mov $0x0000, %ax \n\t" 3897d36db35SAvi Kivity "in %dx, %ax \n\t"); 3907d36db35SAvi Kivity MK_INSN(io_test6, "mov $0xe0, %dx \n\t" 3917d36db35SAvi Kivity "mov $0xffffffff, %eax \n\t" 3927d36db35SAvi Kivity "out %eax, %dx \n\t" 3937d36db35SAvi Kivity "mov $0x00000000, %eax \n\t" 3947d36db35SAvi Kivity "in %dx, %eax \n\t"); 3957d36db35SAvi Kivity 39618253fdeSAvi Kivity inregs = (struct regs){ 0 }; 39718253fdeSAvi Kivity 39818253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test1); 3996055ea1fSAvi Kivity report("pio 1", R_AX, outregs.eax == 0xff); 4007d36db35SAvi Kivity 40118253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test2); 4026055ea1fSAvi Kivity report("pio 2", R_AX, outregs.eax == 0xffff); 4037d36db35SAvi Kivity 40418253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test3); 4056055ea1fSAvi Kivity report("pio 3", R_AX, outregs.eax == 0xffffffff); 4067d36db35SAvi Kivity 40718253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test4); 4086055ea1fSAvi Kivity report("pio 4", R_AX|R_DX, outregs.eax == 0xff); 4097d36db35SAvi Kivity 41018253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test5); 4116055ea1fSAvi Kivity report("pio 5", R_AX|R_DX, outregs.eax == 0xffff); 4127d36db35SAvi Kivity 41318253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test6); 4146055ea1fSAvi Kivity report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff); 4157d36db35SAvi Kivity } 4167d36db35SAvi Kivity 417c0b7268dSAvi Kivity asm ("retf: lretw"); 418c0b7268dSAvi Kivity extern void retf(); 419c0b7268dSAvi Kivity 4207d36db35SAvi Kivity void test_call(void) 4217d36db35SAvi Kivity { 4227d36db35SAvi Kivity u32 esp[16]; 423c0b7268dSAvi Kivity u32 addr; 4247d36db35SAvi Kivity 42518253fdeSAvi Kivity inregs = (struct regs){ 0 }; 4267d36db35SAvi Kivity inregs.esp = (u32)esp; 4277d36db35SAvi Kivity 4287d36db35SAvi Kivity MK_INSN(call1, "mov $test_function, %eax \n\t" 4297d36db35SAvi Kivity "call *%eax\n\t"); 4307d36db35SAvi Kivity MK_INSN(call_near1, "jmp 2f\n\t" 4317d36db35SAvi Kivity "1: mov $0x1234, %eax\n\t" 4327d36db35SAvi Kivity "ret\n\t" 4337d36db35SAvi Kivity "2: call 1b\t"); 4347d36db35SAvi Kivity MK_INSN(call_near2, "call 1f\n\t" 4357d36db35SAvi Kivity "jmp 2f\n\t" 4367d36db35SAvi Kivity "1: mov $0x1234, %eax\n\t" 4377d36db35SAvi Kivity "ret\n\t" 4387d36db35SAvi Kivity "2:\t"); 439c0b7268dSAvi Kivity MK_INSN(call_far1, "lcallw *(%ebx)\n\t"); 440c6061817SAvi Kivity MK_INSN(ret_imm, "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b"); 4417d36db35SAvi Kivity 44218253fdeSAvi Kivity exec_in_big_real_mode(&insn_call1); 4436055ea1fSAvi Kivity report("call 1", R_AX, outregs.eax == 0x1234); 4447d36db35SAvi Kivity 44518253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_near1); 4466055ea1fSAvi Kivity report("call near 1", R_AX, outregs.eax == 0x1234); 4477d36db35SAvi Kivity 44818253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_near2); 4496055ea1fSAvi Kivity report("call near 2", R_AX, outregs.eax == 0x1234); 450c0b7268dSAvi Kivity 451c0b7268dSAvi Kivity addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f); 452c0b7268dSAvi Kivity inregs.ebx = (unsigned)&addr; 45318253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_far1); 4546055ea1fSAvi Kivity report("call far 1", 0, 1); 455c6061817SAvi Kivity 45618253fdeSAvi Kivity exec_in_big_real_mode(&insn_ret_imm); 4576055ea1fSAvi Kivity report("ret imm 1", 0, 1); 4587d36db35SAvi Kivity } 4597d36db35SAvi Kivity 4607d36db35SAvi Kivity void test_jcc_short(void) 4617d36db35SAvi Kivity { 4627d36db35SAvi Kivity MK_INSN(jnz_short1, "jnz 1f\n\t" 4637d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 4647d36db35SAvi Kivity "1:\n\t"); 4657d36db35SAvi Kivity MK_INSN(jnz_short2, "1:\n\t" 4667d36db35SAvi Kivity "cmp $0x1234, %eax\n\t" 4677d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 4687d36db35SAvi Kivity "jnz 1b\n\t"); 4697d36db35SAvi Kivity MK_INSN(jmp_short1, "jmp 1f\n\t" 4707d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 4717d36db35SAvi Kivity "1:\n\t"); 4727d36db35SAvi Kivity 47318253fdeSAvi Kivity inregs = (struct regs){ 0 }; 4747d36db35SAvi Kivity 47518253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_short1); 4766055ea1fSAvi Kivity report("jnz short 1", ~0, 1); 47718253fdeSAvi Kivity 47818253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_short2); 4796055ea1fSAvi Kivity report("jnz short 2", R_AX, (outregs.eflags & (1 << 6))); 4807d36db35SAvi Kivity 48118253fdeSAvi Kivity exec_in_big_real_mode(&insn_jmp_short1); 4826055ea1fSAvi Kivity report("jmp short 1", ~0, 1); 4837d36db35SAvi Kivity } 4847d36db35SAvi Kivity 4857d36db35SAvi Kivity void test_jcc_near(void) 4867d36db35SAvi Kivity { 4877d36db35SAvi Kivity /* encode near jmp manually. gas will not do it if offsets < 127 byte */ 4887d36db35SAvi Kivity MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t" 4897d36db35SAvi Kivity "mov $0x1234, %eax\n\t"); 4907d36db35SAvi Kivity MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t" 4917d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 4927d36db35SAvi Kivity ".byte 0x0f, 0x85, 0xf0, 0xff\n\t"); 4937d36db35SAvi Kivity MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t" 4947d36db35SAvi Kivity "mov $0x1234, %eax\n\t"); 4957d36db35SAvi Kivity 49618253fdeSAvi Kivity inregs = (struct regs){ 0 }; 4977d36db35SAvi Kivity 49818253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_near1); 4996055ea1fSAvi Kivity report("jnz near 1", 0, 1); 50018253fdeSAvi Kivity 50118253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_near2); 5026055ea1fSAvi Kivity report("jnz near 2", R_AX, outregs.eflags & (1 << 6)); 5037d36db35SAvi Kivity 50418253fdeSAvi Kivity exec_in_big_real_mode(&insn_jmp_near1); 5056055ea1fSAvi Kivity report("jmp near 1", 0, 1); 5067d36db35SAvi Kivity } 5077d36db35SAvi Kivity 5087d36db35SAvi Kivity void test_long_jmp() 5097d36db35SAvi Kivity { 5107d36db35SAvi Kivity u32 esp[16]; 5117d36db35SAvi Kivity 51218253fdeSAvi Kivity inregs = (struct regs){ 0 }; 5134aa22949SAvi Kivity inregs.esp = (u32)(esp+16); 5147d36db35SAvi Kivity MK_INSN(long_jmp, "call 1f\n\t" 5157d36db35SAvi Kivity "jmp 2f\n\t" 5167d36db35SAvi Kivity "1: jmp $0, $test_function\n\t" 5177d36db35SAvi Kivity "2:\n\t"); 51818253fdeSAvi Kivity exec_in_big_real_mode(&insn_long_jmp); 5196055ea1fSAvi Kivity report("jmp far 1", R_AX, outregs.eax == 0x1234); 5207d36db35SAvi Kivity } 521fa74f8a6SMohammed Gamal 5227d36db35SAvi Kivity void test_push_pop() 5237d36db35SAvi Kivity { 5247d36db35SAvi Kivity MK_INSN(push32, "mov $0x12345678, %eax\n\t" 5257d36db35SAvi Kivity "push %eax\n\t" 5267d36db35SAvi Kivity "pop %ebx\n\t"); 5277d36db35SAvi Kivity MK_INSN(push16, "mov $0x1234, %ax\n\t" 5287d36db35SAvi Kivity "push %ax\n\t" 5297d36db35SAvi Kivity "pop %bx\n\t"); 5307d36db35SAvi Kivity 5317d36db35SAvi Kivity MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten 5327d36db35SAvi Kivity "mov $0x123, %ax\n\t" 5337d36db35SAvi Kivity "mov %ax, %es\n\t" 5347d36db35SAvi Kivity "push %es\n\t" 5357d36db35SAvi Kivity "pop %bx \n\t" 5367d36db35SAvi Kivity ); 5377d36db35SAvi Kivity MK_INSN(pop_es, "push %ax\n\t" 5387d36db35SAvi Kivity "pop %es\n\t" 5397d36db35SAvi Kivity "mov %es, %bx\n\t" 5407d36db35SAvi Kivity ); 5417d36db35SAvi Kivity MK_INSN(push_pop_ss, "push %ss\n\t" 5427d36db35SAvi Kivity "pushw %ax\n\t" 5437d36db35SAvi Kivity "popw %ss\n\t" 5447d36db35SAvi Kivity "mov %ss, %bx\n\t" 5457d36db35SAvi Kivity "pop %ss\n\t" 5467d36db35SAvi Kivity ); 5477d36db35SAvi Kivity MK_INSN(push_pop_fs, "push %fs\n\t" 5487d36db35SAvi Kivity "pushl %eax\n\t" 5497d36db35SAvi Kivity "popl %fs\n\t" 5507d36db35SAvi Kivity "mov %fs, %ebx\n\t" 5517d36db35SAvi Kivity "pop %fs\n\t" 5527d36db35SAvi Kivity ); 5537d36db35SAvi Kivity 55418253fdeSAvi Kivity inregs = (struct regs){ 0 }; 55518253fdeSAvi Kivity 55618253fdeSAvi Kivity exec_in_big_real_mode(&insn_push32); 5576055ea1fSAvi Kivity report("push/pop 1", R_AX|R_BX, 5586055ea1fSAvi Kivity outregs.eax == outregs.ebx && outregs.eax == 0x12345678); 5597d36db35SAvi Kivity 56018253fdeSAvi Kivity exec_in_big_real_mode(&insn_push16); 5616055ea1fSAvi Kivity report("push/pop 2", R_AX|R_BX, 5626055ea1fSAvi Kivity outregs.eax == outregs.ebx && outregs.eax == 0x1234); 5637d36db35SAvi Kivity 56418253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_es); 5656055ea1fSAvi Kivity report("push/pop 3", R_AX|R_BX, 5666055ea1fSAvi Kivity outregs.ebx == outregs.eax && outregs.eax == 0x123); 5677d36db35SAvi Kivity 56818253fdeSAvi Kivity exec_in_big_real_mode(&insn_pop_es); 5696055ea1fSAvi Kivity report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax); 5707d36db35SAvi Kivity 57118253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_pop_ss); 5726055ea1fSAvi Kivity report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax); 5737d36db35SAvi Kivity 57418253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_pop_fs); 5756055ea1fSAvi Kivity report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax); 5767d36db35SAvi Kivity } 5777d36db35SAvi Kivity 5787d36db35SAvi Kivity void test_null(void) 5797d36db35SAvi Kivity { 580d4dc402cSAvi Kivity MK_INSN(null, ""); 581d4dc402cSAvi Kivity 58218253fdeSAvi Kivity inregs = (struct regs){ 0 }; 58318253fdeSAvi Kivity 58418253fdeSAvi Kivity exec_in_big_real_mode(&insn_null); 5856055ea1fSAvi Kivity report("null", 0, 1); 5867d36db35SAvi Kivity } 5877d36db35SAvi Kivity 5887d36db35SAvi Kivity struct { 5897d36db35SAvi Kivity char stack[500]; 5907d36db35SAvi Kivity char top[]; 5917d36db35SAvi Kivity } tmp_stack; 5927d36db35SAvi Kivity 5937d36db35SAvi Kivity void test_pusha_popa() 5947d36db35SAvi Kivity { 5957d36db35SAvi Kivity MK_INSN(pusha, "pusha\n\t" 5967d36db35SAvi Kivity "pop %edi\n\t" 5977d36db35SAvi Kivity "pop %esi\n\t" 5987d36db35SAvi Kivity "pop %ebp\n\t" 5997d36db35SAvi Kivity "add $4, %esp\n\t" 6007d36db35SAvi Kivity "pop %ebx\n\t" 6017d36db35SAvi Kivity "pop %edx\n\t" 6027d36db35SAvi Kivity "pop %ecx\n\t" 6037d36db35SAvi Kivity "pop %eax\n\t" 6047d36db35SAvi Kivity ); 6057d36db35SAvi Kivity 6067d36db35SAvi Kivity MK_INSN(popa, "push %eax\n\t" 6077d36db35SAvi Kivity "push %ecx\n\t" 6087d36db35SAvi Kivity "push %edx\n\t" 6097d36db35SAvi Kivity "push %ebx\n\t" 6107d36db35SAvi Kivity "push %esp\n\t" 6117d36db35SAvi Kivity "push %ebp\n\t" 6127d36db35SAvi Kivity "push %esi\n\t" 6137d36db35SAvi Kivity "push %edi\n\t" 6147d36db35SAvi Kivity "popa\n\t" 6157d36db35SAvi Kivity ); 6167d36db35SAvi Kivity 61718253fdeSAvi Kivity inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top }; 6187d36db35SAvi Kivity 61918253fdeSAvi Kivity exec_in_big_real_mode(&insn_pusha); 6206055ea1fSAvi Kivity report("pusha/popa 1", 0, 1); 62118253fdeSAvi Kivity 62218253fdeSAvi Kivity exec_in_big_real_mode(&insn_popa); 6236055ea1fSAvi Kivity report("pusha/popa 1", 0, 1); 6247d36db35SAvi Kivity } 6257d36db35SAvi Kivity 6267d36db35SAvi Kivity void test_iret() 6277d36db35SAvi Kivity { 6287d36db35SAvi Kivity MK_INSN(iret32, "pushf\n\t" 6297d36db35SAvi Kivity "pushl %cs\n\t" 6307d36db35SAvi Kivity "call 1f\n\t" /* a near call will push eip onto the stack */ 6317d36db35SAvi Kivity "jmp 2f\n\t" 6327d36db35SAvi Kivity "1: iret\n\t" 6337d36db35SAvi Kivity "2:\n\t" 6347d36db35SAvi Kivity ); 6357d36db35SAvi Kivity 6367d36db35SAvi Kivity MK_INSN(iret16, "pushfw\n\t" 6377d36db35SAvi Kivity "pushw %cs\n\t" 6387d36db35SAvi Kivity "callw 1f\n\t" 6397d36db35SAvi Kivity "jmp 2f\n\t" 6407d36db35SAvi Kivity "1: iretw\n\t" 6417d36db35SAvi Kivity "2:\n\t"); 6427d36db35SAvi Kivity 6437d36db35SAvi Kivity MK_INSN(iret_flags32, "pushfl\n\t" 6447d36db35SAvi Kivity "popl %eax\n\t" 6457d36db35SAvi Kivity "andl $~0x2, %eax\n\t" 6467d36db35SAvi Kivity "orl $0xffc08028, %eax\n\t" 6477d36db35SAvi Kivity "pushl %eax\n\t" 6487d36db35SAvi Kivity "pushl %cs\n\t" 6497d36db35SAvi Kivity "call 1f\n\t" 6507d36db35SAvi Kivity "jmp 2f\n\t" 6517d36db35SAvi Kivity "1: iret\n\t" 6527d36db35SAvi Kivity "2:\n\t"); 6537d36db35SAvi Kivity 6547d36db35SAvi Kivity MK_INSN(iret_flags16, "pushfw\n\t" 6557d36db35SAvi Kivity "popw %ax\n\t" 6567d36db35SAvi Kivity "and $~0x2, %ax\n\t" 6577d36db35SAvi Kivity "or $0x8028, %ax\n\t" 6587d36db35SAvi Kivity "pushw %ax\n\t" 6597d36db35SAvi Kivity "pushw %cs\n\t" 6607d36db35SAvi Kivity "callw 1f\n\t" 6617d36db35SAvi Kivity "jmp 2f\n\t" 6627d36db35SAvi Kivity "1: iretw\n\t" 6637d36db35SAvi Kivity "2:\n\t"); 6647d36db35SAvi Kivity 66518253fdeSAvi Kivity inregs = (struct regs){ 0 }; 6667d36db35SAvi Kivity 66718253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret32); 6686055ea1fSAvi Kivity report("iret 1", 0, 1); 6697d36db35SAvi Kivity 67018253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret16); 6716055ea1fSAvi Kivity report("iret 2", 0, 1); 6727d36db35SAvi Kivity 67318253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret_flags32); 6746055ea1fSAvi Kivity report("iret 3", R_AX, 1); 67518253fdeSAvi Kivity 67618253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret_flags16); 6776055ea1fSAvi Kivity report("iret 4", R_AX, 1); 6787d36db35SAvi Kivity } 6797d36db35SAvi Kivity 68096b9ca1eSMohammed Gamal void test_int() 68196b9ca1eSMohammed Gamal { 68218253fdeSAvi Kivity inregs = (struct regs){ 0 }; 68396b9ca1eSMohammed Gamal 68496b9ca1eSMohammed Gamal *(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */ 68596b9ca1eSMohammed Gamal *(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */ 68696b9ca1eSMohammed Gamal 68796b9ca1eSMohammed Gamal MK_INSN(int11, "int $0x11\n\t"); 68896b9ca1eSMohammed Gamal 68918253fdeSAvi Kivity exec_in_big_real_mode(&insn_int11); 6906055ea1fSAvi Kivity report("int 1", 0, 1); 69196b9ca1eSMohammed Gamal } 69296b9ca1eSMohammed Gamal 693fa74f8a6SMohammed Gamal void test_imul() 694fa74f8a6SMohammed Gamal { 695fa74f8a6SMohammed Gamal MK_INSN(imul8_1, "mov $2, %al\n\t" 696fa74f8a6SMohammed Gamal "mov $-4, %cx\n\t" 697fa74f8a6SMohammed Gamal "imul %cl\n\t"); 698fa74f8a6SMohammed Gamal 699fa74f8a6SMohammed Gamal MK_INSN(imul16_1, "mov $2, %ax\n\t" 700fa74f8a6SMohammed Gamal "mov $-4, %cx\n\t" 701fa74f8a6SMohammed Gamal "imul %cx\n\t"); 702fa74f8a6SMohammed Gamal 703fa74f8a6SMohammed Gamal MK_INSN(imul32_1, "mov $2, %eax\n\t" 704fa74f8a6SMohammed Gamal "mov $-4, %ecx\n\t" 705fa74f8a6SMohammed Gamal "imul %ecx\n\t"); 706fa74f8a6SMohammed Gamal 707fa74f8a6SMohammed Gamal MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t" 708fa74f8a6SMohammed Gamal "mov $4, %cx\n\t" 709fa74f8a6SMohammed Gamal "imul %cl\n\t"); 710fa74f8a6SMohammed Gamal 711fa74f8a6SMohammed Gamal MK_INSN(imul16_2, "mov $2, %ax\n\t" 712fa74f8a6SMohammed Gamal "mov $4, %cx\n\t" 713fa74f8a6SMohammed Gamal "imul %cx\n\t"); 714fa74f8a6SMohammed Gamal 715fa74f8a6SMohammed Gamal MK_INSN(imul32_2, "mov $2, %eax\n\t" 716fa74f8a6SMohammed Gamal "mov $4, %ecx\n\t" 717fa74f8a6SMohammed Gamal "imul %ecx\n\t"); 718fa74f8a6SMohammed Gamal 71918253fdeSAvi Kivity inregs = (struct regs){ 0 }; 72018253fdeSAvi Kivity 72118253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul8_1); 7226055ea1fSAvi Kivity report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8); 723fa74f8a6SMohammed Gamal 72418253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul16_1); 7256055ea1fSAvi Kivity report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8); 726fa74f8a6SMohammed Gamal 72718253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul32_1); 7286055ea1fSAvi Kivity report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8); 729fa74f8a6SMohammed Gamal 73018253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul8_2); 7316055ea1fSAvi Kivity report("imul 4", R_AX | R_CX | R_DX, 7326055ea1fSAvi Kivity (outregs.eax & 0xffff) == 8 73381050840SAvi Kivity && (outregs.eax & 0xffff0000) == 0x12340000); 734fa74f8a6SMohammed Gamal 73518253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul16_2); 7366055ea1fSAvi Kivity report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8); 737fa74f8a6SMohammed Gamal 73818253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul32_2); 7396055ea1fSAvi Kivity report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8); 740fa74f8a6SMohammed Gamal } 741fa74f8a6SMohammed Gamal 74259317bd1SMohammed Gamal void test_mul() 74359317bd1SMohammed Gamal { 74459317bd1SMohammed Gamal MK_INSN(mul8, "mov $2, %al\n\t" 74559317bd1SMohammed Gamal "mov $4, %cx\n\t" 74659317bd1SMohammed Gamal "imul %cl\n\t"); 74759317bd1SMohammed Gamal 74859317bd1SMohammed Gamal MK_INSN(mul16, "mov $2, %ax\n\t" 74959317bd1SMohammed Gamal "mov $4, %cx\n\t" 75059317bd1SMohammed Gamal "imul %cx\n\t"); 75159317bd1SMohammed Gamal 75259317bd1SMohammed Gamal MK_INSN(mul32, "mov $2, %eax\n\t" 75359317bd1SMohammed Gamal "mov $4, %ecx\n\t" 75459317bd1SMohammed Gamal "imul %ecx\n\t"); 75559317bd1SMohammed Gamal 75618253fdeSAvi Kivity inregs = (struct regs){ 0 }; 75718253fdeSAvi Kivity 75818253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul8); 7596055ea1fSAvi Kivity report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8); 76059317bd1SMohammed Gamal 76118253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul16); 7626055ea1fSAvi Kivity report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8); 76359317bd1SMohammed Gamal 76418253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul32); 7656055ea1fSAvi Kivity report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8); 76659317bd1SMohammed Gamal } 76759317bd1SMohammed Gamal 7680d4c7614SMohammed Gamal void test_div() 7690d4c7614SMohammed Gamal { 7700d4c7614SMohammed Gamal MK_INSN(div8, "mov $257, %ax\n\t" 7710d4c7614SMohammed Gamal "mov $2, %cl\n\t" 7720d4c7614SMohammed Gamal "div %cl\n\t"); 7730d4c7614SMohammed Gamal 7740d4c7614SMohammed Gamal MK_INSN(div16, "mov $512, %ax\n\t" 7750d4c7614SMohammed Gamal "mov $5, %cx\n\t" 7760d4c7614SMohammed Gamal "div %cx\n\t"); 7770d4c7614SMohammed Gamal 7780d4c7614SMohammed Gamal MK_INSN(div32, "mov $512, %eax\n\t" 7790d4c7614SMohammed Gamal "mov $5, %ecx\n\t" 7800d4c7614SMohammed Gamal "div %ecx\n\t"); 7810d4c7614SMohammed Gamal 78218253fdeSAvi Kivity inregs = (struct regs){ 0 }; 78318253fdeSAvi Kivity 78418253fdeSAvi Kivity exec_in_big_real_mode(&insn_div8); 7856055ea1fSAvi Kivity report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384); 7860d4c7614SMohammed Gamal 78718253fdeSAvi Kivity exec_in_big_real_mode(&insn_div16); 7886055ea1fSAvi Kivity report("div 2", R_AX | R_CX | R_DX, 7896055ea1fSAvi Kivity outregs.eax == 102 && outregs.edx == 2); 7900d4c7614SMohammed Gamal 79118253fdeSAvi Kivity exec_in_big_real_mode(&insn_div32); 7926055ea1fSAvi Kivity report("div 3", R_AX | R_CX | R_DX, 7936055ea1fSAvi Kivity outregs.eax == 102 && outregs.edx == 2); 7940d4c7614SMohammed Gamal } 7950d4c7614SMohammed Gamal 7960d4c7614SMohammed Gamal void test_idiv() 7970d4c7614SMohammed Gamal { 7980d4c7614SMohammed Gamal MK_INSN(idiv8, "mov $256, %ax\n\t" 7990d4c7614SMohammed Gamal "mov $-2, %cl\n\t" 8000d4c7614SMohammed Gamal "idiv %cl\n\t"); 8010d4c7614SMohammed Gamal 8020d4c7614SMohammed Gamal MK_INSN(idiv16, "mov $512, %ax\n\t" 8030d4c7614SMohammed Gamal "mov $-2, %cx\n\t" 8040d4c7614SMohammed Gamal "idiv %cx\n\t"); 8050d4c7614SMohammed Gamal 8060d4c7614SMohammed Gamal MK_INSN(idiv32, "mov $512, %eax\n\t" 8070d4c7614SMohammed Gamal "mov $-2, %ecx\n\t" 8080d4c7614SMohammed Gamal "idiv %ecx\n\t"); 8090d4c7614SMohammed Gamal 81018253fdeSAvi Kivity inregs = (struct regs){ 0 }; 81118253fdeSAvi Kivity 81218253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv8); 8136055ea1fSAvi Kivity report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128); 8140d4c7614SMohammed Gamal 81518253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv16); 8166055ea1fSAvi Kivity report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256); 8170d4c7614SMohammed Gamal 81818253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv32); 8196055ea1fSAvi Kivity report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256); 8200d4c7614SMohammed Gamal } 8210d4c7614SMohammed Gamal 8226e293cf5SWei Yongjun void test_cbw(void) 8236e293cf5SWei Yongjun { 8246e293cf5SWei Yongjun MK_INSN(cbw, "mov $0xFE, %eax \n\t" 8256e293cf5SWei Yongjun "cbw\n\t"); 8266e293cf5SWei Yongjun MK_INSN(cwde, "mov $0xFFFE, %eax \n\t" 8276e293cf5SWei Yongjun "cwde\n\t"); 8286e293cf5SWei Yongjun 82918253fdeSAvi Kivity inregs = (struct regs){ 0 }; 83018253fdeSAvi Kivity 83118253fdeSAvi Kivity exec_in_big_real_mode(&insn_cbw); 8326055ea1fSAvi Kivity report("cbq 1", ~0, outregs.eax == 0xFFFE); 8336e293cf5SWei Yongjun 83418253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwde); 8356055ea1fSAvi Kivity report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE); 8366e293cf5SWei Yongjun } 8376e293cf5SWei Yongjun 838eacef4e2SWei Yongjun void test_loopcc(void) 839eacef4e2SWei Yongjun { 840eacef4e2SWei Yongjun MK_INSN(loop, "mov $10, %ecx\n\t" 841eacef4e2SWei Yongjun "1: inc %eax\n\t" 842eacef4e2SWei Yongjun "loop 1b\n\t"); 843eacef4e2SWei Yongjun 844eacef4e2SWei Yongjun MK_INSN(loope, "mov $10, %ecx\n\t" 845eacef4e2SWei Yongjun "mov $1, %eax\n\t" 846eacef4e2SWei Yongjun "1: dec %eax\n\t" 847eacef4e2SWei Yongjun "loope 1b\n\t"); 848eacef4e2SWei Yongjun 849eacef4e2SWei Yongjun MK_INSN(loopne, "mov $10, %ecx\n\t" 850eacef4e2SWei Yongjun "mov $5, %eax\n\t" 851eacef4e2SWei Yongjun "1: dec %eax\n\t" 852eacef4e2SWei Yongjun "loopne 1b\n\t"); 853eacef4e2SWei Yongjun 85418253fdeSAvi Kivity inregs = (struct regs){ 0 }; 855eacef4e2SWei Yongjun 85618253fdeSAvi Kivity exec_in_big_real_mode(&insn_loop); 8576055ea1fSAvi Kivity report("LOOPcc short 1", R_AX, outregs.eax == 10); 85818253fdeSAvi Kivity 85918253fdeSAvi Kivity exec_in_big_real_mode(&insn_loope); 8606055ea1fSAvi Kivity report("LOOPcc short 2", R_AX | R_CX, 8616055ea1fSAvi Kivity outregs.eax == -1 && outregs.ecx == 8); 862eacef4e2SWei Yongjun 86318253fdeSAvi Kivity exec_in_big_real_mode(&insn_loopne); 8646055ea1fSAvi Kivity report("LOOPcc short 3", R_AX | R_CX, 8656055ea1fSAvi Kivity outregs.eax == 0 && outregs.ecx == 5); 866eacef4e2SWei Yongjun } 867eacef4e2SWei Yongjun 868b274feedSAvi Kivity static void test_das(void) 869b274feedSAvi Kivity { 870b274feedSAvi Kivity short i; 87181050840SAvi Kivity u16 nr_fail = 0; 872b274feedSAvi Kivity static unsigned test_cases[1024] = { 873b274feedSAvi Kivity 0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00, 874b274feedSAvi Kivity 0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01, 875b274feedSAvi Kivity 0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02, 876b274feedSAvi Kivity 0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03, 877b274feedSAvi Kivity 0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04, 878b274feedSAvi Kivity 0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05, 879b274feedSAvi Kivity 0x06000606, 0x8701a606, 0x56100006, 0x9711a006, 880b274feedSAvi Kivity 0x02000707, 0x8301a707, 0x12100107, 0x9311a107, 881b274feedSAvi Kivity 0x02000808, 0x8301a808, 0x12100208, 0x9311a208, 882b274feedSAvi Kivity 0x06000909, 0x8701a909, 0x16100309, 0x9711a309, 883b274feedSAvi Kivity 0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a, 884b274feedSAvi Kivity 0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b, 885b274feedSAvi Kivity 0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c, 886b274feedSAvi Kivity 0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d, 887b274feedSAvi Kivity 0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e, 888b274feedSAvi Kivity 0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f, 889b274feedSAvi Kivity 0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10, 890b274feedSAvi Kivity 0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11, 891b274feedSAvi Kivity 0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12, 892b274feedSAvi Kivity 0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13, 893b274feedSAvi Kivity 0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14, 894b274feedSAvi Kivity 0x02001515, 0x8301b515, 0x16100f15, 0x9711af15, 895b274feedSAvi Kivity 0x02001616, 0x8301b616, 0x12101016, 0x9311b016, 896b274feedSAvi Kivity 0x06001717, 0x8701b717, 0x16101117, 0x9711b117, 897b274feedSAvi Kivity 0x06001818, 0x8701b818, 0x16101218, 0x9711b218, 898b274feedSAvi Kivity 0x02001919, 0x8301b919, 0x12101319, 0x9311b319, 899b274feedSAvi Kivity 0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a, 900b274feedSAvi Kivity 0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b, 901b274feedSAvi Kivity 0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c, 902b274feedSAvi Kivity 0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d, 903b274feedSAvi Kivity 0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e, 904b274feedSAvi Kivity 0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f, 905b274feedSAvi Kivity 0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20, 906b274feedSAvi Kivity 0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21, 907b274feedSAvi Kivity 0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22, 908b274feedSAvi Kivity 0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23, 909b274feedSAvi Kivity 0x06002424, 0x8301c424, 0x16101e24, 0x9711be24, 910b274feedSAvi Kivity 0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25, 911b274feedSAvi Kivity 0x02002626, 0x8701c626, 0x12102026, 0x9711c026, 912b274feedSAvi Kivity 0x06002727, 0x8301c727, 0x16102127, 0x9311c127, 913b274feedSAvi Kivity 0x06002828, 0x8301c828, 0x16102228, 0x9311c228, 914b274feedSAvi Kivity 0x02002929, 0x8701c929, 0x12102329, 0x9711c329, 915b274feedSAvi Kivity 0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a, 916b274feedSAvi Kivity 0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b, 917b274feedSAvi Kivity 0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c, 918b274feedSAvi Kivity 0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d, 919b274feedSAvi Kivity 0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e, 920b274feedSAvi Kivity 0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f, 921b274feedSAvi Kivity 0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30, 922b274feedSAvi Kivity 0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31, 923b274feedSAvi Kivity 0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32, 924b274feedSAvi Kivity 0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33, 925b274feedSAvi Kivity 0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34, 926b274feedSAvi Kivity 0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35, 927b274feedSAvi Kivity 0x06003636, 0x8301d636, 0x16103036, 0x9311d036, 928b274feedSAvi Kivity 0x02003737, 0x8701d737, 0x12103137, 0x9711d137, 929b274feedSAvi Kivity 0x02003838, 0x8701d838, 0x12103238, 0x9711d238, 930b274feedSAvi Kivity 0x06003939, 0x8301d939, 0x16103339, 0x9311d339, 931b274feedSAvi Kivity 0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a, 932b274feedSAvi Kivity 0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b, 933b274feedSAvi Kivity 0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c, 934b274feedSAvi Kivity 0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d, 935b274feedSAvi Kivity 0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e, 936b274feedSAvi Kivity 0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f, 937b274feedSAvi Kivity 0x02004040, 0x8301e040, 0x16103a40, 0x9311da40, 938b274feedSAvi Kivity 0x06004141, 0x8701e141, 0x12103b41, 0x9711db41, 939b274feedSAvi Kivity 0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42, 940b274feedSAvi Kivity 0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43, 941b274feedSAvi Kivity 0x06004444, 0x8701e444, 0x12103e44, 0x9711de44, 942b274feedSAvi Kivity 0x02004545, 0x8301e545, 0x16103f45, 0x9311df45, 943b274feedSAvi Kivity 0x02004646, 0x8301e646, 0x12104046, 0x9311e046, 944b274feedSAvi Kivity 0x06004747, 0x8701e747, 0x16104147, 0x9711e147, 945b274feedSAvi Kivity 0x06004848, 0x8701e848, 0x16104248, 0x9711e248, 946b274feedSAvi Kivity 0x02004949, 0x8301e949, 0x12104349, 0x9311e349, 947b274feedSAvi Kivity 0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a, 948b274feedSAvi Kivity 0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b, 949b274feedSAvi Kivity 0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c, 950b274feedSAvi Kivity 0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d, 951b274feedSAvi Kivity 0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e, 952b274feedSAvi Kivity 0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f, 953b274feedSAvi Kivity 0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50, 954b274feedSAvi Kivity 0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51, 955b274feedSAvi Kivity 0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52, 956b274feedSAvi Kivity 0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53, 957b274feedSAvi Kivity 0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54, 958b274feedSAvi Kivity 0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55, 959b274feedSAvi Kivity 0x06005656, 0x8701f656, 0x16105056, 0x9711f056, 960b274feedSAvi Kivity 0x02005757, 0x8301f757, 0x12105157, 0x9311f157, 961b274feedSAvi Kivity 0x02005858, 0x8301f858, 0x12105258, 0x9311f258, 962b274feedSAvi Kivity 0x06005959, 0x8701f959, 0x16105359, 0x9711f359, 963b274feedSAvi Kivity 0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a, 964b274feedSAvi Kivity 0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b, 965b274feedSAvi Kivity 0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c, 966b274feedSAvi Kivity 0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d, 967b274feedSAvi Kivity 0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e, 968b274feedSAvi Kivity 0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f, 969b274feedSAvi Kivity 0x06006060, 0x47010060, 0x16105a60, 0x9711fa60, 970b274feedSAvi Kivity 0x02006161, 0x03010161, 0x12105b61, 0x9311fb61, 971b274feedSAvi Kivity 0x02006262, 0x03010262, 0x16105c62, 0x9711fc62, 972b274feedSAvi Kivity 0x06006363, 0x07010363, 0x12105d63, 0x9311fd63, 973b274feedSAvi Kivity 0x02006464, 0x03010464, 0x12105e64, 0x9311fe64, 974b274feedSAvi Kivity 0x06006565, 0x07010565, 0x16105f65, 0x9711ff65, 975b274feedSAvi Kivity 0x06006666, 0x07010666, 0x16106066, 0x57110066, 976b274feedSAvi Kivity 0x02006767, 0x03010767, 0x12106167, 0x13110167, 977b274feedSAvi Kivity 0x02006868, 0x03010868, 0x12106268, 0x13110268, 978b274feedSAvi Kivity 0x06006969, 0x07010969, 0x16106369, 0x17110369, 979b274feedSAvi Kivity 0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a, 980b274feedSAvi Kivity 0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b, 981b274feedSAvi Kivity 0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c, 982b274feedSAvi Kivity 0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d, 983b274feedSAvi Kivity 0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e, 984b274feedSAvi Kivity 0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f, 985b274feedSAvi Kivity 0x02007070, 0x03011070, 0x16106a70, 0x17110a70, 986b274feedSAvi Kivity 0x06007171, 0x07011171, 0x12106b71, 0x13110b71, 987b274feedSAvi Kivity 0x06007272, 0x07011272, 0x16106c72, 0x17110c72, 988b274feedSAvi Kivity 0x02007373, 0x03011373, 0x12106d73, 0x13110d73, 989b274feedSAvi Kivity 0x06007474, 0x07011474, 0x12106e74, 0x13110e74, 990b274feedSAvi Kivity 0x02007575, 0x03011575, 0x16106f75, 0x17110f75, 991b274feedSAvi Kivity 0x02007676, 0x03011676, 0x12107076, 0x13111076, 992b274feedSAvi Kivity 0x06007777, 0x07011777, 0x16107177, 0x17111177, 993b274feedSAvi Kivity 0x06007878, 0x07011878, 0x16107278, 0x17111278, 994b274feedSAvi Kivity 0x02007979, 0x03011979, 0x12107379, 0x13111379, 995b274feedSAvi Kivity 0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a, 996b274feedSAvi Kivity 0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b, 997b274feedSAvi Kivity 0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c, 998b274feedSAvi Kivity 0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d, 999b274feedSAvi Kivity 0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e, 1000b274feedSAvi Kivity 0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f, 1001b274feedSAvi Kivity 0x82008080, 0x03012080, 0x12107a80, 0x13111a80, 1002b274feedSAvi Kivity 0x86008181, 0x07012181, 0x16107b81, 0x17111b81, 1003b274feedSAvi Kivity 0x86008282, 0x07012282, 0x12107c82, 0x13111c82, 1004b274feedSAvi Kivity 0x82008383, 0x03012383, 0x16107d83, 0x17111d83, 1005b274feedSAvi Kivity 0x86008484, 0x07012484, 0x16107e84, 0x17111e84, 1006b274feedSAvi Kivity 0x82008585, 0x03012585, 0x12107f85, 0x13111f85, 1007b274feedSAvi Kivity 0x82008686, 0x03012686, 0x92108086, 0x13112086, 1008b274feedSAvi Kivity 0x86008787, 0x07012787, 0x96108187, 0x17112187, 1009b274feedSAvi Kivity 0x86008888, 0x07012888, 0x96108288, 0x17112288, 1010b274feedSAvi Kivity 0x82008989, 0x03012989, 0x92108389, 0x13112389, 1011b274feedSAvi Kivity 0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a, 1012b274feedSAvi Kivity 0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b, 1013b274feedSAvi Kivity 0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c, 1014b274feedSAvi Kivity 0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d, 1015b274feedSAvi Kivity 0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e, 1016b274feedSAvi Kivity 0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f, 1017b274feedSAvi Kivity 0x86009090, 0x07013090, 0x92108a90, 0x13112a90, 1018b274feedSAvi Kivity 0x82009191, 0x03013191, 0x96108b91, 0x17112b91, 1019b274feedSAvi Kivity 0x82009292, 0x03013292, 0x92108c92, 0x13112c92, 1020b274feedSAvi Kivity 0x86009393, 0x07013393, 0x96108d93, 0x17112d93, 1021b274feedSAvi Kivity 0x82009494, 0x03013494, 0x96108e94, 0x17112e94, 1022b274feedSAvi Kivity 0x86009595, 0x07013595, 0x92108f95, 0x13112f95, 1023b274feedSAvi Kivity 0x86009696, 0x07013696, 0x96109096, 0x17113096, 1024b274feedSAvi Kivity 0x82009797, 0x03013797, 0x92109197, 0x13113197, 1025b274feedSAvi Kivity 0x82009898, 0x03013898, 0x92109298, 0x13113298, 1026b274feedSAvi Kivity 0x86009999, 0x07013999, 0x96109399, 0x17113399, 1027b274feedSAvi Kivity 0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a, 1028b274feedSAvi Kivity 0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b, 1029b274feedSAvi Kivity 0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c, 1030b274feedSAvi Kivity 0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d, 1031b274feedSAvi Kivity 0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e, 1032b274feedSAvi Kivity 0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f, 1033b274feedSAvi Kivity 0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0, 1034b274feedSAvi Kivity 0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1, 1035b274feedSAvi Kivity 0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2, 1036b274feedSAvi Kivity 0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3, 1037b274feedSAvi Kivity 0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4, 1038b274feedSAvi Kivity 0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5, 1039b274feedSAvi Kivity 0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6, 1040b274feedSAvi Kivity 0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7, 1041b274feedSAvi Kivity 0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8, 1042b274feedSAvi Kivity 0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9, 1043b274feedSAvi Kivity 0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa, 1044b274feedSAvi Kivity 0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab, 1045b274feedSAvi Kivity 0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac, 1046b274feedSAvi Kivity 0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad, 1047b274feedSAvi Kivity 0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae, 1048b274feedSAvi Kivity 0x130049af, 0x130149af, 0x131049af, 0x131149af, 1049b274feedSAvi Kivity 0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0, 1050b274feedSAvi Kivity 0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1, 1051b274feedSAvi Kivity 0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2, 1052b274feedSAvi Kivity 0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3, 1053b274feedSAvi Kivity 0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4, 1054b274feedSAvi Kivity 0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5, 1055b274feedSAvi Kivity 0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6, 1056b274feedSAvi Kivity 0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7, 1057b274feedSAvi Kivity 0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8, 1058b274feedSAvi Kivity 0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9, 1059b274feedSAvi Kivity 0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba, 1060b274feedSAvi Kivity 0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb, 1061b274feedSAvi Kivity 0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc, 1062b274feedSAvi Kivity 0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd, 1063b274feedSAvi Kivity 0x130058be, 0x130158be, 0x131058be, 0x131158be, 1064b274feedSAvi Kivity 0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf, 1065b274feedSAvi Kivity 0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0, 1066b274feedSAvi Kivity 0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1, 1067b274feedSAvi Kivity 0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2, 1068b274feedSAvi Kivity 0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3, 1069b274feedSAvi Kivity 0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4, 1070b274feedSAvi Kivity 0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5, 1071b274feedSAvi Kivity 0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6, 1072b274feedSAvi Kivity 0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7, 1073b274feedSAvi Kivity 0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8, 1074b274feedSAvi Kivity 0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9, 1075b274feedSAvi Kivity 0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca, 1076b274feedSAvi Kivity 0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb, 1077b274feedSAvi Kivity 0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc, 1078b274feedSAvi Kivity 0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd, 1079b274feedSAvi Kivity 0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce, 1080b274feedSAvi Kivity 0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf, 1081b274feedSAvi Kivity 0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0, 1082b274feedSAvi Kivity 0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1, 1083b274feedSAvi Kivity 0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2, 1084b274feedSAvi Kivity 0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3, 1085b274feedSAvi Kivity 0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4, 1086b274feedSAvi Kivity 0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5, 1087b274feedSAvi Kivity 0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6, 1088b274feedSAvi Kivity 0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7, 1089b274feedSAvi Kivity 0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8, 1090b274feedSAvi Kivity 0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9, 1091b274feedSAvi Kivity 0x170074da, 0x170174da, 0x171074da, 0x171174da, 1092b274feedSAvi Kivity 0x130075db, 0x130175db, 0x131075db, 0x131175db, 1093b274feedSAvi Kivity 0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc, 1094b274feedSAvi Kivity 0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd, 1095b274feedSAvi Kivity 0x170078de, 0x170178de, 0x171078de, 0x171178de, 1096b274feedSAvi Kivity 0x130079df, 0x130179df, 0x131079df, 0x131179df, 1097b274feedSAvi Kivity 0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0, 1098b274feedSAvi Kivity 0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1, 1099b274feedSAvi Kivity 0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2, 1100b274feedSAvi Kivity 0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3, 1101b274feedSAvi Kivity 0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4, 1102b274feedSAvi Kivity 0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5, 1103b274feedSAvi Kivity 0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6, 1104b274feedSAvi Kivity 0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7, 1105b274feedSAvi Kivity 0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8, 1106b274feedSAvi Kivity 0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9, 1107b274feedSAvi Kivity 0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea, 1108b274feedSAvi Kivity 0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb, 1109b274feedSAvi Kivity 0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec, 1110b274feedSAvi Kivity 0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed, 1111b274feedSAvi Kivity 0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee, 1112b274feedSAvi Kivity 0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef, 1113b274feedSAvi Kivity 0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0, 1114b274feedSAvi Kivity 0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1, 1115b274feedSAvi Kivity 0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2, 1116b274feedSAvi Kivity 0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3, 1117b274feedSAvi Kivity 0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4, 1118b274feedSAvi Kivity 0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5, 1119b274feedSAvi Kivity 0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6, 1120b274feedSAvi Kivity 0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7, 1121b274feedSAvi Kivity 0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8, 1122b274feedSAvi Kivity 0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9, 1123b274feedSAvi Kivity 0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa, 1124b274feedSAvi Kivity 0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb, 1125b274feedSAvi Kivity 0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc, 1126b274feedSAvi Kivity 0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd, 1127b274feedSAvi Kivity 0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe, 1128b274feedSAvi Kivity 0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff, 1129b274feedSAvi Kivity }; 1130b274feedSAvi Kivity 1131b274feedSAvi Kivity MK_INSN(das, "das"); 1132b274feedSAvi Kivity 113318253fdeSAvi Kivity inregs = (struct regs){ 0 }; 113418253fdeSAvi Kivity 1135b274feedSAvi Kivity for (i = 0; i < 1024; ++i) { 1136b274feedSAvi Kivity unsigned tmp = test_cases[i]; 1137b274feedSAvi Kivity inregs.eax = tmp & 0xff; 1138b274feedSAvi Kivity inregs.eflags = (tmp >> 16) & 0xff; 113918253fdeSAvi Kivity exec_in_big_real_mode(&insn_das); 114018253fdeSAvi Kivity if (!regs_equal(R_AX) 1141b274feedSAvi Kivity || outregs.eax != ((tmp >> 8) & 0xff) 1142b274feedSAvi Kivity || (outregs.eflags & 0xff) != (tmp >> 24)) { 114381050840SAvi Kivity ++nr_fail; 114481050840SAvi Kivity break; 1145b274feedSAvi Kivity } 1146b274feedSAvi Kivity } 11476055ea1fSAvi Kivity report("DAS", ~0, nr_fail == 0); 1148b274feedSAvi Kivity } 1149b274feedSAvi Kivity 11500cbd5b06SMohammed Gamal void test_cwd_cdq() 11510cbd5b06SMohammed Gamal { 11520cbd5b06SMohammed Gamal /* Sign-bit set */ 11530cbd5b06SMohammed Gamal MK_INSN(cwd_1, "mov $0x8000, %ax\n\t" 11540cbd5b06SMohammed Gamal "cwd\n\t"); 11550cbd5b06SMohammed Gamal 11560cbd5b06SMohammed Gamal /* Sign-bit not set */ 11570cbd5b06SMohammed Gamal MK_INSN(cwd_2, "mov $0x1000, %ax\n\t" 11580cbd5b06SMohammed Gamal "cwd\n\t"); 11590cbd5b06SMohammed Gamal 11600cbd5b06SMohammed Gamal /* Sign-bit set */ 11610cbd5b06SMohammed Gamal MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t" 11620cbd5b06SMohammed Gamal "cdq\n\t"); 11630cbd5b06SMohammed Gamal 11640cbd5b06SMohammed Gamal /* Sign-bit not set */ 11650cbd5b06SMohammed Gamal MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t" 11660cbd5b06SMohammed Gamal "cdq\n\t"); 11670cbd5b06SMohammed Gamal 116818253fdeSAvi Kivity inregs = (struct regs){ 0 }; 116918253fdeSAvi Kivity 117018253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwd_1); 11716055ea1fSAvi Kivity report("cwd 1", R_AX | R_DX, 11726055ea1fSAvi Kivity outregs.eax == 0x8000 && outregs.edx == 0xffff); 11730cbd5b06SMohammed Gamal 117418253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwd_2); 11756055ea1fSAvi Kivity report("cwd 2", R_AX | R_DX, 11766055ea1fSAvi Kivity outregs.eax == 0x1000 && outregs.edx == 0); 11770cbd5b06SMohammed Gamal 117818253fdeSAvi Kivity exec_in_big_real_mode(&insn_cdq_1); 11796055ea1fSAvi Kivity report("cdq 1", R_AX | R_DX, 11806055ea1fSAvi Kivity outregs.eax == 0x80000000 && outregs.edx == 0xffffffff); 11810cbd5b06SMohammed Gamal 118218253fdeSAvi Kivity exec_in_big_real_mode(&insn_cdq_2); 11836055ea1fSAvi Kivity report("cdq 2", R_AX | R_DX, 11846055ea1fSAvi Kivity outregs.eax == 0x10000000 && outregs.edx == 0); 11850cbd5b06SMohammed Gamal } 11860cbd5b06SMohammed Gamal 1187*37f51a4aSWei Yongjun static struct { 1188*37f51a4aSWei Yongjun void *address; 1189*37f51a4aSWei Yongjun unsigned short sel; 1190*37f51a4aSWei Yongjun } __attribute__((packed)) desc = { 1191*37f51a4aSWei Yongjun (void *)0x1234, 1192*37f51a4aSWei Yongjun 0x10, 1193*37f51a4aSWei Yongjun }; 1194*37f51a4aSWei Yongjun 1195*37f51a4aSWei Yongjun void test_lds_lss() 1196*37f51a4aSWei Yongjun { 1197*37f51a4aSWei Yongjun inregs = (struct regs){ .ebx = (unsigned long)&desc }; 1198*37f51a4aSWei Yongjun 1199*37f51a4aSWei Yongjun MK_INSN(lds, "push %ds\n\t" 1200*37f51a4aSWei Yongjun "lds (%ebx), %eax\n\t" 1201*37f51a4aSWei Yongjun "mov %ds, %ebx\n\t" 1202*37f51a4aSWei Yongjun "pop %ds\n\t"); 1203*37f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lds); 1204*37f51a4aSWei Yongjun report("lds", R_AX | R_BX, 1205*37f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 1206*37f51a4aSWei Yongjun outregs.ebx == desc.sel); 1207*37f51a4aSWei Yongjun 1208*37f51a4aSWei Yongjun MK_INSN(les, "push %es\n\t" 1209*37f51a4aSWei Yongjun "les (%ebx), %eax\n\t" 1210*37f51a4aSWei Yongjun "mov %es, %ebx\n\t" 1211*37f51a4aSWei Yongjun "pop %es\n\t"); 1212*37f51a4aSWei Yongjun exec_in_big_real_mode(&insn_les); 1213*37f51a4aSWei Yongjun report("les", R_AX | R_BX, 1214*37f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 1215*37f51a4aSWei Yongjun outregs.ebx == desc.sel); 1216*37f51a4aSWei Yongjun 1217*37f51a4aSWei Yongjun MK_INSN(lfs, "push %fs\n\t" 1218*37f51a4aSWei Yongjun "lfs (%ebx), %eax\n\t" 1219*37f51a4aSWei Yongjun "mov %fs, %ebx\n\t" 1220*37f51a4aSWei Yongjun "pop %fs\n\t"); 1221*37f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lfs); 1222*37f51a4aSWei Yongjun report("lfs", R_AX | R_BX, 1223*37f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 1224*37f51a4aSWei Yongjun outregs.ebx == desc.sel); 1225*37f51a4aSWei Yongjun 1226*37f51a4aSWei Yongjun MK_INSN(lgs, "push %gs\n\t" 1227*37f51a4aSWei Yongjun "lgs (%ebx), %eax\n\t" 1228*37f51a4aSWei Yongjun "mov %gs, %ebx\n\t" 1229*37f51a4aSWei Yongjun "pop %gs\n\t"); 1230*37f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lgs); 1231*37f51a4aSWei Yongjun report("lgs", R_AX | R_BX, 1232*37f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 1233*37f51a4aSWei Yongjun outregs.ebx == desc.sel); 1234*37f51a4aSWei Yongjun 1235*37f51a4aSWei Yongjun MK_INSN(lss, "push %ss\n\t" 1236*37f51a4aSWei Yongjun "lss (%ebx), %eax\n\t" 1237*37f51a4aSWei Yongjun "mov %ss, %ebx\n\t" 1238*37f51a4aSWei Yongjun "pop %ss\n\t"); 1239*37f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lss); 1240*37f51a4aSWei Yongjun report("lss", R_AX | R_BX, 1241*37f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 1242*37f51a4aSWei Yongjun outregs.ebx == desc.sel); 1243*37f51a4aSWei Yongjun } 1244*37f51a4aSWei Yongjun 12457d36db35SAvi Kivity void realmode_start(void) 12467d36db35SAvi Kivity { 12477d36db35SAvi Kivity test_null(); 12487d36db35SAvi Kivity 12497d36db35SAvi Kivity test_shld(); 12507d36db35SAvi Kivity test_push_pop(); 12517d36db35SAvi Kivity test_pusha_popa(); 12527d36db35SAvi Kivity test_mov_imm(); 12537d36db35SAvi Kivity test_cmp_imm(); 12547d36db35SAvi Kivity test_add_imm(); 12557d36db35SAvi Kivity test_sub_imm(); 12567d36db35SAvi Kivity test_xor_imm(); 12577d36db35SAvi Kivity test_io(); 12587d36db35SAvi Kivity test_eflags_insn(); 12597d36db35SAvi Kivity test_jcc_short(); 12607d36db35SAvi Kivity test_jcc_near(); 12617d36db35SAvi Kivity /* test_call() uses short jump so call it after testing jcc */ 12627d36db35SAvi Kivity test_call(); 12637d36db35SAvi Kivity /* long jmp test uses call near so test it after testing call */ 12647d36db35SAvi Kivity test_long_jmp(); 12657d36db35SAvi Kivity test_xchg(); 12667d36db35SAvi Kivity test_iret(); 126796b9ca1eSMohammed Gamal test_int(); 1268fa74f8a6SMohammed Gamal test_imul(); 126959317bd1SMohammed Gamal test_mul(); 12700d4c7614SMohammed Gamal test_div(); 12710d4c7614SMohammed Gamal test_idiv(); 1272eacef4e2SWei Yongjun test_loopcc(); 12736e293cf5SWei Yongjun test_cbw(); 12740cbd5b06SMohammed Gamal test_cwd_cdq(); 1275b274feedSAvi Kivity test_das(); 1276*37f51a4aSWei Yongjun test_lds_lss(); 12777d36db35SAvi Kivity 12787d36db35SAvi Kivity exit(0); 12797d36db35SAvi Kivity } 12807d36db35SAvi Kivity 12817d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff }; 12827d36db35SAvi Kivity 12837d36db35SAvi Kivity struct __attribute__((packed)) { 12847d36db35SAvi Kivity unsigned short limit; 12857d36db35SAvi Kivity void *base; 12867d36db35SAvi Kivity } r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt }; 12877d36db35SAvi Kivity 12887d36db35SAvi Kivity asm( 12897d36db35SAvi Kivity ".section .init \n\t" 12907d36db35SAvi Kivity 12917d36db35SAvi Kivity ".code32 \n\t" 12927d36db35SAvi Kivity 12937d36db35SAvi Kivity "mb_magic = 0x1BADB002 \n\t" 12947d36db35SAvi Kivity "mb_flags = 0x0 \n\t" 12957d36db35SAvi Kivity 12967d36db35SAvi Kivity "# multiboot header \n\t" 12977d36db35SAvi Kivity ".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t" 12987d36db35SAvi Kivity 12997d36db35SAvi Kivity ".globl start \n\t" 13007d36db35SAvi Kivity ".data \n\t" 13017d36db35SAvi Kivity ". = . + 4096 \n\t" 13027d36db35SAvi Kivity "stacktop: \n\t" 13037d36db35SAvi Kivity 13047d36db35SAvi Kivity ".text \n\t" 13057d36db35SAvi Kivity "start: \n\t" 13067d36db35SAvi Kivity "lgdt r_gdt_descr \n\t" 13077d36db35SAvi Kivity "ljmp $8, $1f; 1: \n\t" 13087d36db35SAvi Kivity ".code16gcc \n\t" 13097d36db35SAvi Kivity "mov $16, %eax \n\t" 13107d36db35SAvi Kivity "mov %ax, %ds \n\t" 13117d36db35SAvi Kivity "mov %ax, %es \n\t" 13127d36db35SAvi Kivity "mov %ax, %fs \n\t" 13137d36db35SAvi Kivity "mov %ax, %gs \n\t" 13147d36db35SAvi Kivity "mov %ax, %ss \n\t" 13157d36db35SAvi Kivity "mov %cr0, %eax \n\t" 13167d36db35SAvi Kivity "btc $0, %eax \n\t" 13177d36db35SAvi Kivity "mov %eax, %cr0 \n\t" 13187d36db35SAvi Kivity "ljmp $0, $realmode_entry \n\t" 13197d36db35SAvi Kivity 13207d36db35SAvi Kivity "realmode_entry: \n\t" 13217d36db35SAvi Kivity 13227d36db35SAvi Kivity "xor %ax, %ax \n\t" 13237d36db35SAvi Kivity "mov %ax, %ds \n\t" 13247d36db35SAvi Kivity "mov %ax, %es \n\t" 13257d36db35SAvi Kivity "mov %ax, %ss \n\t" 13267d36db35SAvi Kivity "mov %ax, %fs \n\t" 13277d36db35SAvi Kivity "mov %ax, %gs \n\t" 13287d36db35SAvi Kivity "mov $stacktop, %esp\n\t" 13297d36db35SAvi Kivity "ljmp $0, $realmode_start \n\t" 13307d36db35SAvi Kivity 13317d36db35SAvi Kivity ".code16gcc \n\t" 13327d36db35SAvi Kivity ); 1333