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"); 440*556d2680SWei Yongjun MK_INSN(call_far2, "lcallw $0, $retf\n\t"); 441c6061817SAvi Kivity MK_INSN(ret_imm, "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b"); 4427d36db35SAvi Kivity 44318253fdeSAvi Kivity exec_in_big_real_mode(&insn_call1); 4446055ea1fSAvi Kivity report("call 1", R_AX, outregs.eax == 0x1234); 4457d36db35SAvi Kivity 44618253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_near1); 4476055ea1fSAvi Kivity report("call near 1", R_AX, outregs.eax == 0x1234); 4487d36db35SAvi Kivity 44918253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_near2); 4506055ea1fSAvi Kivity report("call near 2", R_AX, outregs.eax == 0x1234); 451c0b7268dSAvi Kivity 452c0b7268dSAvi Kivity addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f); 453c0b7268dSAvi Kivity inregs.ebx = (unsigned)&addr; 45418253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_far1); 4556055ea1fSAvi Kivity report("call far 1", 0, 1); 456c6061817SAvi Kivity 457*556d2680SWei Yongjun exec_in_big_real_mode(&insn_call_far2); 458*556d2680SWei Yongjun report("call far 2", 0, 1); 459*556d2680SWei Yongjun 46018253fdeSAvi Kivity exec_in_big_real_mode(&insn_ret_imm); 4616055ea1fSAvi Kivity report("ret imm 1", 0, 1); 4627d36db35SAvi Kivity } 4637d36db35SAvi Kivity 4647d36db35SAvi Kivity void test_jcc_short(void) 4657d36db35SAvi Kivity { 4667d36db35SAvi Kivity MK_INSN(jnz_short1, "jnz 1f\n\t" 4677d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 4687d36db35SAvi Kivity "1:\n\t"); 4697d36db35SAvi Kivity MK_INSN(jnz_short2, "1:\n\t" 4707d36db35SAvi Kivity "cmp $0x1234, %eax\n\t" 4717d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 4727d36db35SAvi Kivity "jnz 1b\n\t"); 4737d36db35SAvi Kivity MK_INSN(jmp_short1, "jmp 1f\n\t" 4747d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 4757d36db35SAvi Kivity "1:\n\t"); 4767d36db35SAvi Kivity 47718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 4787d36db35SAvi Kivity 47918253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_short1); 4806055ea1fSAvi Kivity report("jnz short 1", ~0, 1); 48118253fdeSAvi Kivity 48218253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_short2); 4836055ea1fSAvi Kivity report("jnz short 2", R_AX, (outregs.eflags & (1 << 6))); 4847d36db35SAvi Kivity 48518253fdeSAvi Kivity exec_in_big_real_mode(&insn_jmp_short1); 4866055ea1fSAvi Kivity report("jmp short 1", ~0, 1); 4877d36db35SAvi Kivity } 4887d36db35SAvi Kivity 4897d36db35SAvi Kivity void test_jcc_near(void) 4907d36db35SAvi Kivity { 4917d36db35SAvi Kivity /* encode near jmp manually. gas will not do it if offsets < 127 byte */ 4927d36db35SAvi Kivity MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t" 4937d36db35SAvi Kivity "mov $0x1234, %eax\n\t"); 4947d36db35SAvi Kivity MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t" 4957d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 4967d36db35SAvi Kivity ".byte 0x0f, 0x85, 0xf0, 0xff\n\t"); 4977d36db35SAvi Kivity MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t" 4987d36db35SAvi Kivity "mov $0x1234, %eax\n\t"); 4997d36db35SAvi Kivity 50018253fdeSAvi Kivity inregs = (struct regs){ 0 }; 5017d36db35SAvi Kivity 50218253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_near1); 5036055ea1fSAvi Kivity report("jnz near 1", 0, 1); 50418253fdeSAvi Kivity 50518253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_near2); 5066055ea1fSAvi Kivity report("jnz near 2", R_AX, outregs.eflags & (1 << 6)); 5077d36db35SAvi Kivity 50818253fdeSAvi Kivity exec_in_big_real_mode(&insn_jmp_near1); 5096055ea1fSAvi Kivity report("jmp near 1", 0, 1); 5107d36db35SAvi Kivity } 5117d36db35SAvi Kivity 5127d36db35SAvi Kivity void test_long_jmp() 5137d36db35SAvi Kivity { 5147d36db35SAvi Kivity u32 esp[16]; 5157d36db35SAvi Kivity 51618253fdeSAvi Kivity inregs = (struct regs){ 0 }; 5174aa22949SAvi Kivity inregs.esp = (u32)(esp+16); 5187d36db35SAvi Kivity MK_INSN(long_jmp, "call 1f\n\t" 5197d36db35SAvi Kivity "jmp 2f\n\t" 5207d36db35SAvi Kivity "1: jmp $0, $test_function\n\t" 5217d36db35SAvi Kivity "2:\n\t"); 52218253fdeSAvi Kivity exec_in_big_real_mode(&insn_long_jmp); 5236055ea1fSAvi Kivity report("jmp far 1", R_AX, outregs.eax == 0x1234); 5247d36db35SAvi Kivity } 525fa74f8a6SMohammed Gamal 5267d36db35SAvi Kivity void test_push_pop() 5277d36db35SAvi Kivity { 5287d36db35SAvi Kivity MK_INSN(push32, "mov $0x12345678, %eax\n\t" 5297d36db35SAvi Kivity "push %eax\n\t" 5307d36db35SAvi Kivity "pop %ebx\n\t"); 5317d36db35SAvi Kivity MK_INSN(push16, "mov $0x1234, %ax\n\t" 5327d36db35SAvi Kivity "push %ax\n\t" 5337d36db35SAvi Kivity "pop %bx\n\t"); 5347d36db35SAvi Kivity 5357d36db35SAvi Kivity MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten 5367d36db35SAvi Kivity "mov $0x123, %ax\n\t" 5377d36db35SAvi Kivity "mov %ax, %es\n\t" 5387d36db35SAvi Kivity "push %es\n\t" 5397d36db35SAvi Kivity "pop %bx \n\t" 5407d36db35SAvi Kivity ); 5417d36db35SAvi Kivity MK_INSN(pop_es, "push %ax\n\t" 5427d36db35SAvi Kivity "pop %es\n\t" 5437d36db35SAvi Kivity "mov %es, %bx\n\t" 5447d36db35SAvi Kivity ); 5457d36db35SAvi Kivity MK_INSN(push_pop_ss, "push %ss\n\t" 5467d36db35SAvi Kivity "pushw %ax\n\t" 5477d36db35SAvi Kivity "popw %ss\n\t" 5487d36db35SAvi Kivity "mov %ss, %bx\n\t" 5497d36db35SAvi Kivity "pop %ss\n\t" 5507d36db35SAvi Kivity ); 5517d36db35SAvi Kivity MK_INSN(push_pop_fs, "push %fs\n\t" 5527d36db35SAvi Kivity "pushl %eax\n\t" 5537d36db35SAvi Kivity "popl %fs\n\t" 5547d36db35SAvi Kivity "mov %fs, %ebx\n\t" 5557d36db35SAvi Kivity "pop %fs\n\t" 5567d36db35SAvi Kivity ); 5577d36db35SAvi Kivity 55818253fdeSAvi Kivity inregs = (struct regs){ 0 }; 55918253fdeSAvi Kivity 56018253fdeSAvi Kivity exec_in_big_real_mode(&insn_push32); 5616055ea1fSAvi Kivity report("push/pop 1", R_AX|R_BX, 5626055ea1fSAvi Kivity outregs.eax == outregs.ebx && outregs.eax == 0x12345678); 5637d36db35SAvi Kivity 56418253fdeSAvi Kivity exec_in_big_real_mode(&insn_push16); 5656055ea1fSAvi Kivity report("push/pop 2", R_AX|R_BX, 5666055ea1fSAvi Kivity outregs.eax == outregs.ebx && outregs.eax == 0x1234); 5677d36db35SAvi Kivity 56818253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_es); 5696055ea1fSAvi Kivity report("push/pop 3", R_AX|R_BX, 5706055ea1fSAvi Kivity outregs.ebx == outregs.eax && outregs.eax == 0x123); 5717d36db35SAvi Kivity 57218253fdeSAvi Kivity exec_in_big_real_mode(&insn_pop_es); 5736055ea1fSAvi Kivity report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax); 5747d36db35SAvi Kivity 57518253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_pop_ss); 5766055ea1fSAvi Kivity report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax); 5777d36db35SAvi Kivity 57818253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_pop_fs); 5796055ea1fSAvi Kivity report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax); 5807d36db35SAvi Kivity } 5817d36db35SAvi Kivity 5827d36db35SAvi Kivity void test_null(void) 5837d36db35SAvi Kivity { 584d4dc402cSAvi Kivity MK_INSN(null, ""); 585d4dc402cSAvi Kivity 58618253fdeSAvi Kivity inregs = (struct regs){ 0 }; 58718253fdeSAvi Kivity 58818253fdeSAvi Kivity exec_in_big_real_mode(&insn_null); 5896055ea1fSAvi Kivity report("null", 0, 1); 5907d36db35SAvi Kivity } 5917d36db35SAvi Kivity 5927d36db35SAvi Kivity struct { 5937d36db35SAvi Kivity char stack[500]; 5947d36db35SAvi Kivity char top[]; 5957d36db35SAvi Kivity } tmp_stack; 5967d36db35SAvi Kivity 5977d36db35SAvi Kivity void test_pusha_popa() 5987d36db35SAvi Kivity { 5997d36db35SAvi Kivity MK_INSN(pusha, "pusha\n\t" 6007d36db35SAvi Kivity "pop %edi\n\t" 6017d36db35SAvi Kivity "pop %esi\n\t" 6027d36db35SAvi Kivity "pop %ebp\n\t" 6037d36db35SAvi Kivity "add $4, %esp\n\t" 6047d36db35SAvi Kivity "pop %ebx\n\t" 6057d36db35SAvi Kivity "pop %edx\n\t" 6067d36db35SAvi Kivity "pop %ecx\n\t" 6077d36db35SAvi Kivity "pop %eax\n\t" 6087d36db35SAvi Kivity ); 6097d36db35SAvi Kivity 6107d36db35SAvi Kivity MK_INSN(popa, "push %eax\n\t" 6117d36db35SAvi Kivity "push %ecx\n\t" 6127d36db35SAvi Kivity "push %edx\n\t" 6137d36db35SAvi Kivity "push %ebx\n\t" 6147d36db35SAvi Kivity "push %esp\n\t" 6157d36db35SAvi Kivity "push %ebp\n\t" 6167d36db35SAvi Kivity "push %esi\n\t" 6177d36db35SAvi Kivity "push %edi\n\t" 6187d36db35SAvi Kivity "popa\n\t" 6197d36db35SAvi Kivity ); 6207d36db35SAvi Kivity 62118253fdeSAvi Kivity inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top }; 6227d36db35SAvi Kivity 62318253fdeSAvi Kivity exec_in_big_real_mode(&insn_pusha); 6246055ea1fSAvi Kivity report("pusha/popa 1", 0, 1); 62518253fdeSAvi Kivity 62618253fdeSAvi Kivity exec_in_big_real_mode(&insn_popa); 6276055ea1fSAvi Kivity report("pusha/popa 1", 0, 1); 6287d36db35SAvi Kivity } 6297d36db35SAvi Kivity 6307d36db35SAvi Kivity void test_iret() 6317d36db35SAvi Kivity { 6327d36db35SAvi Kivity MK_INSN(iret32, "pushf\n\t" 6337d36db35SAvi Kivity "pushl %cs\n\t" 6347d36db35SAvi Kivity "call 1f\n\t" /* a near call will push eip onto the stack */ 6357d36db35SAvi Kivity "jmp 2f\n\t" 6367d36db35SAvi Kivity "1: iret\n\t" 6377d36db35SAvi Kivity "2:\n\t" 6387d36db35SAvi Kivity ); 6397d36db35SAvi Kivity 6407d36db35SAvi Kivity MK_INSN(iret16, "pushfw\n\t" 6417d36db35SAvi Kivity "pushw %cs\n\t" 6427d36db35SAvi Kivity "callw 1f\n\t" 6437d36db35SAvi Kivity "jmp 2f\n\t" 6447d36db35SAvi Kivity "1: iretw\n\t" 6457d36db35SAvi Kivity "2:\n\t"); 6467d36db35SAvi Kivity 6477d36db35SAvi Kivity MK_INSN(iret_flags32, "pushfl\n\t" 6487d36db35SAvi Kivity "popl %eax\n\t" 6497d36db35SAvi Kivity "andl $~0x2, %eax\n\t" 6507d36db35SAvi Kivity "orl $0xffc08028, %eax\n\t" 6517d36db35SAvi Kivity "pushl %eax\n\t" 6527d36db35SAvi Kivity "pushl %cs\n\t" 6537d36db35SAvi Kivity "call 1f\n\t" 6547d36db35SAvi Kivity "jmp 2f\n\t" 6557d36db35SAvi Kivity "1: iret\n\t" 6567d36db35SAvi Kivity "2:\n\t"); 6577d36db35SAvi Kivity 6587d36db35SAvi Kivity MK_INSN(iret_flags16, "pushfw\n\t" 6597d36db35SAvi Kivity "popw %ax\n\t" 6607d36db35SAvi Kivity "and $~0x2, %ax\n\t" 6617d36db35SAvi Kivity "or $0x8028, %ax\n\t" 6627d36db35SAvi Kivity "pushw %ax\n\t" 6637d36db35SAvi Kivity "pushw %cs\n\t" 6647d36db35SAvi Kivity "callw 1f\n\t" 6657d36db35SAvi Kivity "jmp 2f\n\t" 6667d36db35SAvi Kivity "1: iretw\n\t" 6677d36db35SAvi Kivity "2:\n\t"); 6687d36db35SAvi Kivity 66918253fdeSAvi Kivity inregs = (struct regs){ 0 }; 6707d36db35SAvi Kivity 67118253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret32); 6726055ea1fSAvi Kivity report("iret 1", 0, 1); 6737d36db35SAvi Kivity 67418253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret16); 6756055ea1fSAvi Kivity report("iret 2", 0, 1); 6767d36db35SAvi Kivity 67718253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret_flags32); 6786055ea1fSAvi Kivity report("iret 3", R_AX, 1); 67918253fdeSAvi Kivity 68018253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret_flags16); 6816055ea1fSAvi Kivity report("iret 4", R_AX, 1); 6827d36db35SAvi Kivity } 6837d36db35SAvi Kivity 68496b9ca1eSMohammed Gamal void test_int() 68596b9ca1eSMohammed Gamal { 68618253fdeSAvi Kivity inregs = (struct regs){ 0 }; 68796b9ca1eSMohammed Gamal 68896b9ca1eSMohammed Gamal *(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */ 68996b9ca1eSMohammed Gamal *(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */ 69096b9ca1eSMohammed Gamal 69196b9ca1eSMohammed Gamal MK_INSN(int11, "int $0x11\n\t"); 69296b9ca1eSMohammed Gamal 69318253fdeSAvi Kivity exec_in_big_real_mode(&insn_int11); 6946055ea1fSAvi Kivity report("int 1", 0, 1); 69596b9ca1eSMohammed Gamal } 69696b9ca1eSMohammed Gamal 697fa74f8a6SMohammed Gamal void test_imul() 698fa74f8a6SMohammed Gamal { 699fa74f8a6SMohammed Gamal MK_INSN(imul8_1, "mov $2, %al\n\t" 700fa74f8a6SMohammed Gamal "mov $-4, %cx\n\t" 701fa74f8a6SMohammed Gamal "imul %cl\n\t"); 702fa74f8a6SMohammed Gamal 703fa74f8a6SMohammed Gamal MK_INSN(imul16_1, "mov $2, %ax\n\t" 704fa74f8a6SMohammed Gamal "mov $-4, %cx\n\t" 705fa74f8a6SMohammed Gamal "imul %cx\n\t"); 706fa74f8a6SMohammed Gamal 707fa74f8a6SMohammed Gamal MK_INSN(imul32_1, "mov $2, %eax\n\t" 708fa74f8a6SMohammed Gamal "mov $-4, %ecx\n\t" 709fa74f8a6SMohammed Gamal "imul %ecx\n\t"); 710fa74f8a6SMohammed Gamal 711fa74f8a6SMohammed Gamal MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t" 712fa74f8a6SMohammed Gamal "mov $4, %cx\n\t" 713fa74f8a6SMohammed Gamal "imul %cl\n\t"); 714fa74f8a6SMohammed Gamal 715fa74f8a6SMohammed Gamal MK_INSN(imul16_2, "mov $2, %ax\n\t" 716fa74f8a6SMohammed Gamal "mov $4, %cx\n\t" 717fa74f8a6SMohammed Gamal "imul %cx\n\t"); 718fa74f8a6SMohammed Gamal 719fa74f8a6SMohammed Gamal MK_INSN(imul32_2, "mov $2, %eax\n\t" 720fa74f8a6SMohammed Gamal "mov $4, %ecx\n\t" 721fa74f8a6SMohammed Gamal "imul %ecx\n\t"); 722fa74f8a6SMohammed Gamal 72318253fdeSAvi Kivity inregs = (struct regs){ 0 }; 72418253fdeSAvi Kivity 72518253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul8_1); 7266055ea1fSAvi Kivity report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8); 727fa74f8a6SMohammed Gamal 72818253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul16_1); 7296055ea1fSAvi Kivity report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8); 730fa74f8a6SMohammed Gamal 73118253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul32_1); 7326055ea1fSAvi Kivity report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8); 733fa74f8a6SMohammed Gamal 73418253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul8_2); 7356055ea1fSAvi Kivity report("imul 4", R_AX | R_CX | R_DX, 7366055ea1fSAvi Kivity (outregs.eax & 0xffff) == 8 73781050840SAvi Kivity && (outregs.eax & 0xffff0000) == 0x12340000); 738fa74f8a6SMohammed Gamal 73918253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul16_2); 7406055ea1fSAvi Kivity report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8); 741fa74f8a6SMohammed Gamal 74218253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul32_2); 7436055ea1fSAvi Kivity report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8); 744fa74f8a6SMohammed Gamal } 745fa74f8a6SMohammed Gamal 74659317bd1SMohammed Gamal void test_mul() 74759317bd1SMohammed Gamal { 74859317bd1SMohammed Gamal MK_INSN(mul8, "mov $2, %al\n\t" 74959317bd1SMohammed Gamal "mov $4, %cx\n\t" 75059317bd1SMohammed Gamal "imul %cl\n\t"); 75159317bd1SMohammed Gamal 75259317bd1SMohammed Gamal MK_INSN(mul16, "mov $2, %ax\n\t" 75359317bd1SMohammed Gamal "mov $4, %cx\n\t" 75459317bd1SMohammed Gamal "imul %cx\n\t"); 75559317bd1SMohammed Gamal 75659317bd1SMohammed Gamal MK_INSN(mul32, "mov $2, %eax\n\t" 75759317bd1SMohammed Gamal "mov $4, %ecx\n\t" 75859317bd1SMohammed Gamal "imul %ecx\n\t"); 75959317bd1SMohammed Gamal 76018253fdeSAvi Kivity inregs = (struct regs){ 0 }; 76118253fdeSAvi Kivity 76218253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul8); 7636055ea1fSAvi Kivity report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8); 76459317bd1SMohammed Gamal 76518253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul16); 7666055ea1fSAvi Kivity report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8); 76759317bd1SMohammed Gamal 76818253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul32); 7696055ea1fSAvi Kivity report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8); 77059317bd1SMohammed Gamal } 77159317bd1SMohammed Gamal 7720d4c7614SMohammed Gamal void test_div() 7730d4c7614SMohammed Gamal { 7740d4c7614SMohammed Gamal MK_INSN(div8, "mov $257, %ax\n\t" 7750d4c7614SMohammed Gamal "mov $2, %cl\n\t" 7760d4c7614SMohammed Gamal "div %cl\n\t"); 7770d4c7614SMohammed Gamal 7780d4c7614SMohammed Gamal MK_INSN(div16, "mov $512, %ax\n\t" 7790d4c7614SMohammed Gamal "mov $5, %cx\n\t" 7800d4c7614SMohammed Gamal "div %cx\n\t"); 7810d4c7614SMohammed Gamal 7820d4c7614SMohammed Gamal MK_INSN(div32, "mov $512, %eax\n\t" 7830d4c7614SMohammed Gamal "mov $5, %ecx\n\t" 7840d4c7614SMohammed Gamal "div %ecx\n\t"); 7850d4c7614SMohammed Gamal 78618253fdeSAvi Kivity inregs = (struct regs){ 0 }; 78718253fdeSAvi Kivity 78818253fdeSAvi Kivity exec_in_big_real_mode(&insn_div8); 7896055ea1fSAvi Kivity report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384); 7900d4c7614SMohammed Gamal 79118253fdeSAvi Kivity exec_in_big_real_mode(&insn_div16); 7926055ea1fSAvi Kivity report("div 2", R_AX | R_CX | R_DX, 7936055ea1fSAvi Kivity outregs.eax == 102 && outregs.edx == 2); 7940d4c7614SMohammed Gamal 79518253fdeSAvi Kivity exec_in_big_real_mode(&insn_div32); 7966055ea1fSAvi Kivity report("div 3", R_AX | R_CX | R_DX, 7976055ea1fSAvi Kivity outregs.eax == 102 && outregs.edx == 2); 7980d4c7614SMohammed Gamal } 7990d4c7614SMohammed Gamal 8000d4c7614SMohammed Gamal void test_idiv() 8010d4c7614SMohammed Gamal { 8020d4c7614SMohammed Gamal MK_INSN(idiv8, "mov $256, %ax\n\t" 8030d4c7614SMohammed Gamal "mov $-2, %cl\n\t" 8040d4c7614SMohammed Gamal "idiv %cl\n\t"); 8050d4c7614SMohammed Gamal 8060d4c7614SMohammed Gamal MK_INSN(idiv16, "mov $512, %ax\n\t" 8070d4c7614SMohammed Gamal "mov $-2, %cx\n\t" 8080d4c7614SMohammed Gamal "idiv %cx\n\t"); 8090d4c7614SMohammed Gamal 8100d4c7614SMohammed Gamal MK_INSN(idiv32, "mov $512, %eax\n\t" 8110d4c7614SMohammed Gamal "mov $-2, %ecx\n\t" 8120d4c7614SMohammed Gamal "idiv %ecx\n\t"); 8130d4c7614SMohammed Gamal 81418253fdeSAvi Kivity inregs = (struct regs){ 0 }; 81518253fdeSAvi Kivity 81618253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv8); 8176055ea1fSAvi Kivity report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128); 8180d4c7614SMohammed Gamal 81918253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv16); 8206055ea1fSAvi Kivity report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256); 8210d4c7614SMohammed Gamal 82218253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv32); 8236055ea1fSAvi Kivity report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256); 8240d4c7614SMohammed Gamal } 8250d4c7614SMohammed Gamal 8266e293cf5SWei Yongjun void test_cbw(void) 8276e293cf5SWei Yongjun { 8286e293cf5SWei Yongjun MK_INSN(cbw, "mov $0xFE, %eax \n\t" 8296e293cf5SWei Yongjun "cbw\n\t"); 8306e293cf5SWei Yongjun MK_INSN(cwde, "mov $0xFFFE, %eax \n\t" 8316e293cf5SWei Yongjun "cwde\n\t"); 8326e293cf5SWei Yongjun 83318253fdeSAvi Kivity inregs = (struct regs){ 0 }; 83418253fdeSAvi Kivity 83518253fdeSAvi Kivity exec_in_big_real_mode(&insn_cbw); 8366055ea1fSAvi Kivity report("cbq 1", ~0, outregs.eax == 0xFFFE); 8376e293cf5SWei Yongjun 83818253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwde); 8396055ea1fSAvi Kivity report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE); 8406e293cf5SWei Yongjun } 8416e293cf5SWei Yongjun 842eacef4e2SWei Yongjun void test_loopcc(void) 843eacef4e2SWei Yongjun { 844eacef4e2SWei Yongjun MK_INSN(loop, "mov $10, %ecx\n\t" 845eacef4e2SWei Yongjun "1: inc %eax\n\t" 846eacef4e2SWei Yongjun "loop 1b\n\t"); 847eacef4e2SWei Yongjun 848eacef4e2SWei Yongjun MK_INSN(loope, "mov $10, %ecx\n\t" 849eacef4e2SWei Yongjun "mov $1, %eax\n\t" 850eacef4e2SWei Yongjun "1: dec %eax\n\t" 851eacef4e2SWei Yongjun "loope 1b\n\t"); 852eacef4e2SWei Yongjun 853eacef4e2SWei Yongjun MK_INSN(loopne, "mov $10, %ecx\n\t" 854eacef4e2SWei Yongjun "mov $5, %eax\n\t" 855eacef4e2SWei Yongjun "1: dec %eax\n\t" 856eacef4e2SWei Yongjun "loopne 1b\n\t"); 857eacef4e2SWei Yongjun 85818253fdeSAvi Kivity inregs = (struct regs){ 0 }; 859eacef4e2SWei Yongjun 86018253fdeSAvi Kivity exec_in_big_real_mode(&insn_loop); 8616055ea1fSAvi Kivity report("LOOPcc short 1", R_AX, outregs.eax == 10); 86218253fdeSAvi Kivity 86318253fdeSAvi Kivity exec_in_big_real_mode(&insn_loope); 8646055ea1fSAvi Kivity report("LOOPcc short 2", R_AX | R_CX, 8656055ea1fSAvi Kivity outregs.eax == -1 && outregs.ecx == 8); 866eacef4e2SWei Yongjun 86718253fdeSAvi Kivity exec_in_big_real_mode(&insn_loopne); 8686055ea1fSAvi Kivity report("LOOPcc short 3", R_AX | R_CX, 8696055ea1fSAvi Kivity outregs.eax == 0 && outregs.ecx == 5); 870eacef4e2SWei Yongjun } 871eacef4e2SWei Yongjun 872b274feedSAvi Kivity static void test_das(void) 873b274feedSAvi Kivity { 874b274feedSAvi Kivity short i; 87581050840SAvi Kivity u16 nr_fail = 0; 876b274feedSAvi Kivity static unsigned test_cases[1024] = { 877b274feedSAvi Kivity 0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00, 878b274feedSAvi Kivity 0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01, 879b274feedSAvi Kivity 0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02, 880b274feedSAvi Kivity 0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03, 881b274feedSAvi Kivity 0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04, 882b274feedSAvi Kivity 0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05, 883b274feedSAvi Kivity 0x06000606, 0x8701a606, 0x56100006, 0x9711a006, 884b274feedSAvi Kivity 0x02000707, 0x8301a707, 0x12100107, 0x9311a107, 885b274feedSAvi Kivity 0x02000808, 0x8301a808, 0x12100208, 0x9311a208, 886b274feedSAvi Kivity 0x06000909, 0x8701a909, 0x16100309, 0x9711a309, 887b274feedSAvi Kivity 0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a, 888b274feedSAvi Kivity 0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b, 889b274feedSAvi Kivity 0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c, 890b274feedSAvi Kivity 0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d, 891b274feedSAvi Kivity 0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e, 892b274feedSAvi Kivity 0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f, 893b274feedSAvi Kivity 0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10, 894b274feedSAvi Kivity 0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11, 895b274feedSAvi Kivity 0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12, 896b274feedSAvi Kivity 0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13, 897b274feedSAvi Kivity 0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14, 898b274feedSAvi Kivity 0x02001515, 0x8301b515, 0x16100f15, 0x9711af15, 899b274feedSAvi Kivity 0x02001616, 0x8301b616, 0x12101016, 0x9311b016, 900b274feedSAvi Kivity 0x06001717, 0x8701b717, 0x16101117, 0x9711b117, 901b274feedSAvi Kivity 0x06001818, 0x8701b818, 0x16101218, 0x9711b218, 902b274feedSAvi Kivity 0x02001919, 0x8301b919, 0x12101319, 0x9311b319, 903b274feedSAvi Kivity 0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a, 904b274feedSAvi Kivity 0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b, 905b274feedSAvi Kivity 0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c, 906b274feedSAvi Kivity 0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d, 907b274feedSAvi Kivity 0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e, 908b274feedSAvi Kivity 0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f, 909b274feedSAvi Kivity 0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20, 910b274feedSAvi Kivity 0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21, 911b274feedSAvi Kivity 0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22, 912b274feedSAvi Kivity 0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23, 913b274feedSAvi Kivity 0x06002424, 0x8301c424, 0x16101e24, 0x9711be24, 914b274feedSAvi Kivity 0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25, 915b274feedSAvi Kivity 0x02002626, 0x8701c626, 0x12102026, 0x9711c026, 916b274feedSAvi Kivity 0x06002727, 0x8301c727, 0x16102127, 0x9311c127, 917b274feedSAvi Kivity 0x06002828, 0x8301c828, 0x16102228, 0x9311c228, 918b274feedSAvi Kivity 0x02002929, 0x8701c929, 0x12102329, 0x9711c329, 919b274feedSAvi Kivity 0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a, 920b274feedSAvi Kivity 0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b, 921b274feedSAvi Kivity 0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c, 922b274feedSAvi Kivity 0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d, 923b274feedSAvi Kivity 0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e, 924b274feedSAvi Kivity 0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f, 925b274feedSAvi Kivity 0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30, 926b274feedSAvi Kivity 0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31, 927b274feedSAvi Kivity 0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32, 928b274feedSAvi Kivity 0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33, 929b274feedSAvi Kivity 0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34, 930b274feedSAvi Kivity 0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35, 931b274feedSAvi Kivity 0x06003636, 0x8301d636, 0x16103036, 0x9311d036, 932b274feedSAvi Kivity 0x02003737, 0x8701d737, 0x12103137, 0x9711d137, 933b274feedSAvi Kivity 0x02003838, 0x8701d838, 0x12103238, 0x9711d238, 934b274feedSAvi Kivity 0x06003939, 0x8301d939, 0x16103339, 0x9311d339, 935b274feedSAvi Kivity 0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a, 936b274feedSAvi Kivity 0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b, 937b274feedSAvi Kivity 0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c, 938b274feedSAvi Kivity 0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d, 939b274feedSAvi Kivity 0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e, 940b274feedSAvi Kivity 0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f, 941b274feedSAvi Kivity 0x02004040, 0x8301e040, 0x16103a40, 0x9311da40, 942b274feedSAvi Kivity 0x06004141, 0x8701e141, 0x12103b41, 0x9711db41, 943b274feedSAvi Kivity 0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42, 944b274feedSAvi Kivity 0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43, 945b274feedSAvi Kivity 0x06004444, 0x8701e444, 0x12103e44, 0x9711de44, 946b274feedSAvi Kivity 0x02004545, 0x8301e545, 0x16103f45, 0x9311df45, 947b274feedSAvi Kivity 0x02004646, 0x8301e646, 0x12104046, 0x9311e046, 948b274feedSAvi Kivity 0x06004747, 0x8701e747, 0x16104147, 0x9711e147, 949b274feedSAvi Kivity 0x06004848, 0x8701e848, 0x16104248, 0x9711e248, 950b274feedSAvi Kivity 0x02004949, 0x8301e949, 0x12104349, 0x9311e349, 951b274feedSAvi Kivity 0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a, 952b274feedSAvi Kivity 0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b, 953b274feedSAvi Kivity 0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c, 954b274feedSAvi Kivity 0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d, 955b274feedSAvi Kivity 0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e, 956b274feedSAvi Kivity 0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f, 957b274feedSAvi Kivity 0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50, 958b274feedSAvi Kivity 0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51, 959b274feedSAvi Kivity 0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52, 960b274feedSAvi Kivity 0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53, 961b274feedSAvi Kivity 0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54, 962b274feedSAvi Kivity 0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55, 963b274feedSAvi Kivity 0x06005656, 0x8701f656, 0x16105056, 0x9711f056, 964b274feedSAvi Kivity 0x02005757, 0x8301f757, 0x12105157, 0x9311f157, 965b274feedSAvi Kivity 0x02005858, 0x8301f858, 0x12105258, 0x9311f258, 966b274feedSAvi Kivity 0x06005959, 0x8701f959, 0x16105359, 0x9711f359, 967b274feedSAvi Kivity 0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a, 968b274feedSAvi Kivity 0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b, 969b274feedSAvi Kivity 0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c, 970b274feedSAvi Kivity 0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d, 971b274feedSAvi Kivity 0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e, 972b274feedSAvi Kivity 0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f, 973b274feedSAvi Kivity 0x06006060, 0x47010060, 0x16105a60, 0x9711fa60, 974b274feedSAvi Kivity 0x02006161, 0x03010161, 0x12105b61, 0x9311fb61, 975b274feedSAvi Kivity 0x02006262, 0x03010262, 0x16105c62, 0x9711fc62, 976b274feedSAvi Kivity 0x06006363, 0x07010363, 0x12105d63, 0x9311fd63, 977b274feedSAvi Kivity 0x02006464, 0x03010464, 0x12105e64, 0x9311fe64, 978b274feedSAvi Kivity 0x06006565, 0x07010565, 0x16105f65, 0x9711ff65, 979b274feedSAvi Kivity 0x06006666, 0x07010666, 0x16106066, 0x57110066, 980b274feedSAvi Kivity 0x02006767, 0x03010767, 0x12106167, 0x13110167, 981b274feedSAvi Kivity 0x02006868, 0x03010868, 0x12106268, 0x13110268, 982b274feedSAvi Kivity 0x06006969, 0x07010969, 0x16106369, 0x17110369, 983b274feedSAvi Kivity 0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a, 984b274feedSAvi Kivity 0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b, 985b274feedSAvi Kivity 0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c, 986b274feedSAvi Kivity 0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d, 987b274feedSAvi Kivity 0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e, 988b274feedSAvi Kivity 0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f, 989b274feedSAvi Kivity 0x02007070, 0x03011070, 0x16106a70, 0x17110a70, 990b274feedSAvi Kivity 0x06007171, 0x07011171, 0x12106b71, 0x13110b71, 991b274feedSAvi Kivity 0x06007272, 0x07011272, 0x16106c72, 0x17110c72, 992b274feedSAvi Kivity 0x02007373, 0x03011373, 0x12106d73, 0x13110d73, 993b274feedSAvi Kivity 0x06007474, 0x07011474, 0x12106e74, 0x13110e74, 994b274feedSAvi Kivity 0x02007575, 0x03011575, 0x16106f75, 0x17110f75, 995b274feedSAvi Kivity 0x02007676, 0x03011676, 0x12107076, 0x13111076, 996b274feedSAvi Kivity 0x06007777, 0x07011777, 0x16107177, 0x17111177, 997b274feedSAvi Kivity 0x06007878, 0x07011878, 0x16107278, 0x17111278, 998b274feedSAvi Kivity 0x02007979, 0x03011979, 0x12107379, 0x13111379, 999b274feedSAvi Kivity 0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a, 1000b274feedSAvi Kivity 0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b, 1001b274feedSAvi Kivity 0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c, 1002b274feedSAvi Kivity 0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d, 1003b274feedSAvi Kivity 0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e, 1004b274feedSAvi Kivity 0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f, 1005b274feedSAvi Kivity 0x82008080, 0x03012080, 0x12107a80, 0x13111a80, 1006b274feedSAvi Kivity 0x86008181, 0x07012181, 0x16107b81, 0x17111b81, 1007b274feedSAvi Kivity 0x86008282, 0x07012282, 0x12107c82, 0x13111c82, 1008b274feedSAvi Kivity 0x82008383, 0x03012383, 0x16107d83, 0x17111d83, 1009b274feedSAvi Kivity 0x86008484, 0x07012484, 0x16107e84, 0x17111e84, 1010b274feedSAvi Kivity 0x82008585, 0x03012585, 0x12107f85, 0x13111f85, 1011b274feedSAvi Kivity 0x82008686, 0x03012686, 0x92108086, 0x13112086, 1012b274feedSAvi Kivity 0x86008787, 0x07012787, 0x96108187, 0x17112187, 1013b274feedSAvi Kivity 0x86008888, 0x07012888, 0x96108288, 0x17112288, 1014b274feedSAvi Kivity 0x82008989, 0x03012989, 0x92108389, 0x13112389, 1015b274feedSAvi Kivity 0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a, 1016b274feedSAvi Kivity 0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b, 1017b274feedSAvi Kivity 0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c, 1018b274feedSAvi Kivity 0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d, 1019b274feedSAvi Kivity 0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e, 1020b274feedSAvi Kivity 0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f, 1021b274feedSAvi Kivity 0x86009090, 0x07013090, 0x92108a90, 0x13112a90, 1022b274feedSAvi Kivity 0x82009191, 0x03013191, 0x96108b91, 0x17112b91, 1023b274feedSAvi Kivity 0x82009292, 0x03013292, 0x92108c92, 0x13112c92, 1024b274feedSAvi Kivity 0x86009393, 0x07013393, 0x96108d93, 0x17112d93, 1025b274feedSAvi Kivity 0x82009494, 0x03013494, 0x96108e94, 0x17112e94, 1026b274feedSAvi Kivity 0x86009595, 0x07013595, 0x92108f95, 0x13112f95, 1027b274feedSAvi Kivity 0x86009696, 0x07013696, 0x96109096, 0x17113096, 1028b274feedSAvi Kivity 0x82009797, 0x03013797, 0x92109197, 0x13113197, 1029b274feedSAvi Kivity 0x82009898, 0x03013898, 0x92109298, 0x13113298, 1030b274feedSAvi Kivity 0x86009999, 0x07013999, 0x96109399, 0x17113399, 1031b274feedSAvi Kivity 0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a, 1032b274feedSAvi Kivity 0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b, 1033b274feedSAvi Kivity 0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c, 1034b274feedSAvi Kivity 0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d, 1035b274feedSAvi Kivity 0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e, 1036b274feedSAvi Kivity 0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f, 1037b274feedSAvi Kivity 0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0, 1038b274feedSAvi Kivity 0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1, 1039b274feedSAvi Kivity 0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2, 1040b274feedSAvi Kivity 0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3, 1041b274feedSAvi Kivity 0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4, 1042b274feedSAvi Kivity 0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5, 1043b274feedSAvi Kivity 0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6, 1044b274feedSAvi Kivity 0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7, 1045b274feedSAvi Kivity 0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8, 1046b274feedSAvi Kivity 0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9, 1047b274feedSAvi Kivity 0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa, 1048b274feedSAvi Kivity 0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab, 1049b274feedSAvi Kivity 0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac, 1050b274feedSAvi Kivity 0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad, 1051b274feedSAvi Kivity 0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae, 1052b274feedSAvi Kivity 0x130049af, 0x130149af, 0x131049af, 0x131149af, 1053b274feedSAvi Kivity 0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0, 1054b274feedSAvi Kivity 0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1, 1055b274feedSAvi Kivity 0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2, 1056b274feedSAvi Kivity 0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3, 1057b274feedSAvi Kivity 0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4, 1058b274feedSAvi Kivity 0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5, 1059b274feedSAvi Kivity 0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6, 1060b274feedSAvi Kivity 0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7, 1061b274feedSAvi Kivity 0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8, 1062b274feedSAvi Kivity 0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9, 1063b274feedSAvi Kivity 0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba, 1064b274feedSAvi Kivity 0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb, 1065b274feedSAvi Kivity 0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc, 1066b274feedSAvi Kivity 0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd, 1067b274feedSAvi Kivity 0x130058be, 0x130158be, 0x131058be, 0x131158be, 1068b274feedSAvi Kivity 0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf, 1069b274feedSAvi Kivity 0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0, 1070b274feedSAvi Kivity 0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1, 1071b274feedSAvi Kivity 0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2, 1072b274feedSAvi Kivity 0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3, 1073b274feedSAvi Kivity 0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4, 1074b274feedSAvi Kivity 0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5, 1075b274feedSAvi Kivity 0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6, 1076b274feedSAvi Kivity 0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7, 1077b274feedSAvi Kivity 0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8, 1078b274feedSAvi Kivity 0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9, 1079b274feedSAvi Kivity 0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca, 1080b274feedSAvi Kivity 0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb, 1081b274feedSAvi Kivity 0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc, 1082b274feedSAvi Kivity 0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd, 1083b274feedSAvi Kivity 0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce, 1084b274feedSAvi Kivity 0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf, 1085b274feedSAvi Kivity 0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0, 1086b274feedSAvi Kivity 0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1, 1087b274feedSAvi Kivity 0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2, 1088b274feedSAvi Kivity 0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3, 1089b274feedSAvi Kivity 0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4, 1090b274feedSAvi Kivity 0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5, 1091b274feedSAvi Kivity 0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6, 1092b274feedSAvi Kivity 0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7, 1093b274feedSAvi Kivity 0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8, 1094b274feedSAvi Kivity 0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9, 1095b274feedSAvi Kivity 0x170074da, 0x170174da, 0x171074da, 0x171174da, 1096b274feedSAvi Kivity 0x130075db, 0x130175db, 0x131075db, 0x131175db, 1097b274feedSAvi Kivity 0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc, 1098b274feedSAvi Kivity 0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd, 1099b274feedSAvi Kivity 0x170078de, 0x170178de, 0x171078de, 0x171178de, 1100b274feedSAvi Kivity 0x130079df, 0x130179df, 0x131079df, 0x131179df, 1101b274feedSAvi Kivity 0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0, 1102b274feedSAvi Kivity 0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1, 1103b274feedSAvi Kivity 0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2, 1104b274feedSAvi Kivity 0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3, 1105b274feedSAvi Kivity 0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4, 1106b274feedSAvi Kivity 0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5, 1107b274feedSAvi Kivity 0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6, 1108b274feedSAvi Kivity 0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7, 1109b274feedSAvi Kivity 0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8, 1110b274feedSAvi Kivity 0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9, 1111b274feedSAvi Kivity 0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea, 1112b274feedSAvi Kivity 0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb, 1113b274feedSAvi Kivity 0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec, 1114b274feedSAvi Kivity 0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed, 1115b274feedSAvi Kivity 0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee, 1116b274feedSAvi Kivity 0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef, 1117b274feedSAvi Kivity 0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0, 1118b274feedSAvi Kivity 0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1, 1119b274feedSAvi Kivity 0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2, 1120b274feedSAvi Kivity 0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3, 1121b274feedSAvi Kivity 0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4, 1122b274feedSAvi Kivity 0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5, 1123b274feedSAvi Kivity 0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6, 1124b274feedSAvi Kivity 0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7, 1125b274feedSAvi Kivity 0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8, 1126b274feedSAvi Kivity 0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9, 1127b274feedSAvi Kivity 0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa, 1128b274feedSAvi Kivity 0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb, 1129b274feedSAvi Kivity 0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc, 1130b274feedSAvi Kivity 0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd, 1131b274feedSAvi Kivity 0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe, 1132b274feedSAvi Kivity 0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff, 1133b274feedSAvi Kivity }; 1134b274feedSAvi Kivity 1135b274feedSAvi Kivity MK_INSN(das, "das"); 1136b274feedSAvi Kivity 113718253fdeSAvi Kivity inregs = (struct regs){ 0 }; 113818253fdeSAvi Kivity 1139b274feedSAvi Kivity for (i = 0; i < 1024; ++i) { 1140b274feedSAvi Kivity unsigned tmp = test_cases[i]; 1141b274feedSAvi Kivity inregs.eax = tmp & 0xff; 1142b274feedSAvi Kivity inregs.eflags = (tmp >> 16) & 0xff; 114318253fdeSAvi Kivity exec_in_big_real_mode(&insn_das); 114418253fdeSAvi Kivity if (!regs_equal(R_AX) 1145b274feedSAvi Kivity || outregs.eax != ((tmp >> 8) & 0xff) 1146b274feedSAvi Kivity || (outregs.eflags & 0xff) != (tmp >> 24)) { 114781050840SAvi Kivity ++nr_fail; 114881050840SAvi Kivity break; 1149b274feedSAvi Kivity } 1150b274feedSAvi Kivity } 11516055ea1fSAvi Kivity report("DAS", ~0, nr_fail == 0); 1152b274feedSAvi Kivity } 1153b274feedSAvi Kivity 11540cbd5b06SMohammed Gamal void test_cwd_cdq() 11550cbd5b06SMohammed Gamal { 11560cbd5b06SMohammed Gamal /* Sign-bit set */ 11570cbd5b06SMohammed Gamal MK_INSN(cwd_1, "mov $0x8000, %ax\n\t" 11580cbd5b06SMohammed Gamal "cwd\n\t"); 11590cbd5b06SMohammed Gamal 11600cbd5b06SMohammed Gamal /* Sign-bit not set */ 11610cbd5b06SMohammed Gamal MK_INSN(cwd_2, "mov $0x1000, %ax\n\t" 11620cbd5b06SMohammed Gamal "cwd\n\t"); 11630cbd5b06SMohammed Gamal 11640cbd5b06SMohammed Gamal /* Sign-bit set */ 11650cbd5b06SMohammed Gamal MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t" 11660cbd5b06SMohammed Gamal "cdq\n\t"); 11670cbd5b06SMohammed Gamal 11680cbd5b06SMohammed Gamal /* Sign-bit not set */ 11690cbd5b06SMohammed Gamal MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t" 11700cbd5b06SMohammed Gamal "cdq\n\t"); 11710cbd5b06SMohammed Gamal 117218253fdeSAvi Kivity inregs = (struct regs){ 0 }; 117318253fdeSAvi Kivity 117418253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwd_1); 11756055ea1fSAvi Kivity report("cwd 1", R_AX | R_DX, 11766055ea1fSAvi Kivity outregs.eax == 0x8000 && outregs.edx == 0xffff); 11770cbd5b06SMohammed Gamal 117818253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwd_2); 11796055ea1fSAvi Kivity report("cwd 2", R_AX | R_DX, 11806055ea1fSAvi Kivity outregs.eax == 0x1000 && outregs.edx == 0); 11810cbd5b06SMohammed Gamal 118218253fdeSAvi Kivity exec_in_big_real_mode(&insn_cdq_1); 11836055ea1fSAvi Kivity report("cdq 1", R_AX | R_DX, 11846055ea1fSAvi Kivity outregs.eax == 0x80000000 && outregs.edx == 0xffffffff); 11850cbd5b06SMohammed Gamal 118618253fdeSAvi Kivity exec_in_big_real_mode(&insn_cdq_2); 11876055ea1fSAvi Kivity report("cdq 2", R_AX | R_DX, 11886055ea1fSAvi Kivity outregs.eax == 0x10000000 && outregs.edx == 0); 11890cbd5b06SMohammed Gamal } 11900cbd5b06SMohammed Gamal 119137f51a4aSWei Yongjun static struct { 119237f51a4aSWei Yongjun void *address; 119337f51a4aSWei Yongjun unsigned short sel; 119437f51a4aSWei Yongjun } __attribute__((packed)) desc = { 119537f51a4aSWei Yongjun (void *)0x1234, 119637f51a4aSWei Yongjun 0x10, 119737f51a4aSWei Yongjun }; 119837f51a4aSWei Yongjun 119937f51a4aSWei Yongjun void test_lds_lss() 120037f51a4aSWei Yongjun { 120137f51a4aSWei Yongjun inregs = (struct regs){ .ebx = (unsigned long)&desc }; 120237f51a4aSWei Yongjun 120337f51a4aSWei Yongjun MK_INSN(lds, "push %ds\n\t" 120437f51a4aSWei Yongjun "lds (%ebx), %eax\n\t" 120537f51a4aSWei Yongjun "mov %ds, %ebx\n\t" 120637f51a4aSWei Yongjun "pop %ds\n\t"); 120737f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lds); 120837f51a4aSWei Yongjun report("lds", R_AX | R_BX, 120937f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 121037f51a4aSWei Yongjun outregs.ebx == desc.sel); 121137f51a4aSWei Yongjun 121237f51a4aSWei Yongjun MK_INSN(les, "push %es\n\t" 121337f51a4aSWei Yongjun "les (%ebx), %eax\n\t" 121437f51a4aSWei Yongjun "mov %es, %ebx\n\t" 121537f51a4aSWei Yongjun "pop %es\n\t"); 121637f51a4aSWei Yongjun exec_in_big_real_mode(&insn_les); 121737f51a4aSWei Yongjun report("les", R_AX | R_BX, 121837f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 121937f51a4aSWei Yongjun outregs.ebx == desc.sel); 122037f51a4aSWei Yongjun 122137f51a4aSWei Yongjun MK_INSN(lfs, "push %fs\n\t" 122237f51a4aSWei Yongjun "lfs (%ebx), %eax\n\t" 122337f51a4aSWei Yongjun "mov %fs, %ebx\n\t" 122437f51a4aSWei Yongjun "pop %fs\n\t"); 122537f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lfs); 122637f51a4aSWei Yongjun report("lfs", R_AX | R_BX, 122737f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 122837f51a4aSWei Yongjun outregs.ebx == desc.sel); 122937f51a4aSWei Yongjun 123037f51a4aSWei Yongjun MK_INSN(lgs, "push %gs\n\t" 123137f51a4aSWei Yongjun "lgs (%ebx), %eax\n\t" 123237f51a4aSWei Yongjun "mov %gs, %ebx\n\t" 123337f51a4aSWei Yongjun "pop %gs\n\t"); 123437f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lgs); 123537f51a4aSWei Yongjun report("lgs", R_AX | R_BX, 123637f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 123737f51a4aSWei Yongjun outregs.ebx == desc.sel); 123837f51a4aSWei Yongjun 123937f51a4aSWei Yongjun MK_INSN(lss, "push %ss\n\t" 124037f51a4aSWei Yongjun "lss (%ebx), %eax\n\t" 124137f51a4aSWei Yongjun "mov %ss, %ebx\n\t" 124237f51a4aSWei Yongjun "pop %ss\n\t"); 124337f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lss); 124437f51a4aSWei Yongjun report("lss", R_AX | R_BX, 124537f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 124637f51a4aSWei Yongjun outregs.ebx == desc.sel); 124737f51a4aSWei Yongjun } 124837f51a4aSWei Yongjun 1249b1c7c575SWei Yongjun void test_jcxz(void) 1250b1c7c575SWei Yongjun { 1251b1c7c575SWei Yongjun MK_INSN(jcxz1, "jcxz 1f\n\t" 1252b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1253b1c7c575SWei Yongjun "1:\n\t"); 1254b1c7c575SWei Yongjun MK_INSN(jcxz2, "mov $0x100, %ecx\n\t" 1255b1c7c575SWei Yongjun "jcxz 1f\n\t" 1256b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1257b1c7c575SWei Yongjun "mov $0, %ecx\n\t" 1258b1c7c575SWei Yongjun "1:\n\t"); 1259b1c7c575SWei Yongjun MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t" 1260b1c7c575SWei Yongjun "jcxz 1f\n\t" 1261b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1262b1c7c575SWei Yongjun "1:\n\t"); 1263b1c7c575SWei Yongjun MK_INSN(jecxz1, "jecxz 1f\n\t" 1264b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1265b1c7c575SWei Yongjun "1:\n\t"); 1266b1c7c575SWei Yongjun MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t" 1267b1c7c575SWei Yongjun "jecxz 1f\n\t" 1268b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1269b1c7c575SWei Yongjun "mov $0, %ecx\n\t" 1270b1c7c575SWei Yongjun "1:\n\t"); 1271b1c7c575SWei Yongjun 1272b1c7c575SWei Yongjun inregs = (struct regs){ 0 }; 1273b1c7c575SWei Yongjun 1274b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jcxz1); 1275b1c7c575SWei Yongjun report("jcxz short 1", 0, 1); 1276b1c7c575SWei Yongjun 1277b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jcxz2); 1278b1c7c575SWei Yongjun report("jcxz short 2", R_AX, outregs.eax == 0x1234); 1279b1c7c575SWei Yongjun 1280b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jcxz3); 1281b1c7c575SWei Yongjun report("jcxz short 3", R_CX, outregs.ecx == 0x10000); 1282b1c7c575SWei Yongjun 1283b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jecxz1); 1284b1c7c575SWei Yongjun report("jecxz short 1", 0, 1); 1285b1c7c575SWei Yongjun 1286b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jecxz2); 1287b1c7c575SWei Yongjun report("jecxz short 2", R_AX, outregs.eax == 0x1234); 1288b1c7c575SWei Yongjun } 1289b1c7c575SWei Yongjun 12907d36db35SAvi Kivity void realmode_start(void) 12917d36db35SAvi Kivity { 12927d36db35SAvi Kivity test_null(); 12937d36db35SAvi Kivity 12947d36db35SAvi Kivity test_shld(); 12957d36db35SAvi Kivity test_push_pop(); 12967d36db35SAvi Kivity test_pusha_popa(); 12977d36db35SAvi Kivity test_mov_imm(); 12987d36db35SAvi Kivity test_cmp_imm(); 12997d36db35SAvi Kivity test_add_imm(); 13007d36db35SAvi Kivity test_sub_imm(); 13017d36db35SAvi Kivity test_xor_imm(); 13027d36db35SAvi Kivity test_io(); 13037d36db35SAvi Kivity test_eflags_insn(); 13047d36db35SAvi Kivity test_jcc_short(); 13057d36db35SAvi Kivity test_jcc_near(); 13067d36db35SAvi Kivity /* test_call() uses short jump so call it after testing jcc */ 13077d36db35SAvi Kivity test_call(); 13087d36db35SAvi Kivity /* long jmp test uses call near so test it after testing call */ 13097d36db35SAvi Kivity test_long_jmp(); 13107d36db35SAvi Kivity test_xchg(); 13117d36db35SAvi Kivity test_iret(); 131296b9ca1eSMohammed Gamal test_int(); 1313fa74f8a6SMohammed Gamal test_imul(); 131459317bd1SMohammed Gamal test_mul(); 13150d4c7614SMohammed Gamal test_div(); 13160d4c7614SMohammed Gamal test_idiv(); 1317eacef4e2SWei Yongjun test_loopcc(); 13186e293cf5SWei Yongjun test_cbw(); 13190cbd5b06SMohammed Gamal test_cwd_cdq(); 1320b274feedSAvi Kivity test_das(); 132137f51a4aSWei Yongjun test_lds_lss(); 1322b1c7c575SWei Yongjun test_jcxz(); 13237d36db35SAvi Kivity 13247d36db35SAvi Kivity exit(0); 13257d36db35SAvi Kivity } 13267d36db35SAvi Kivity 13277d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff }; 13287d36db35SAvi Kivity 13297d36db35SAvi Kivity struct __attribute__((packed)) { 13307d36db35SAvi Kivity unsigned short limit; 13317d36db35SAvi Kivity void *base; 13327d36db35SAvi Kivity } r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt }; 13337d36db35SAvi Kivity 13347d36db35SAvi Kivity asm( 13357d36db35SAvi Kivity ".section .init \n\t" 13367d36db35SAvi Kivity 13377d36db35SAvi Kivity ".code32 \n\t" 13387d36db35SAvi Kivity 13397d36db35SAvi Kivity "mb_magic = 0x1BADB002 \n\t" 13407d36db35SAvi Kivity "mb_flags = 0x0 \n\t" 13417d36db35SAvi Kivity 13427d36db35SAvi Kivity "# multiboot header \n\t" 13437d36db35SAvi Kivity ".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t" 13447d36db35SAvi Kivity 13457d36db35SAvi Kivity ".globl start \n\t" 13467d36db35SAvi Kivity ".data \n\t" 13477d36db35SAvi Kivity ". = . + 4096 \n\t" 13487d36db35SAvi Kivity "stacktop: \n\t" 13497d36db35SAvi Kivity 13507d36db35SAvi Kivity ".text \n\t" 13517d36db35SAvi Kivity "start: \n\t" 13527d36db35SAvi Kivity "lgdt r_gdt_descr \n\t" 13537d36db35SAvi Kivity "ljmp $8, $1f; 1: \n\t" 13547d36db35SAvi Kivity ".code16gcc \n\t" 13557d36db35SAvi Kivity "mov $16, %eax \n\t" 13567d36db35SAvi Kivity "mov %ax, %ds \n\t" 13577d36db35SAvi Kivity "mov %ax, %es \n\t" 13587d36db35SAvi Kivity "mov %ax, %fs \n\t" 13597d36db35SAvi Kivity "mov %ax, %gs \n\t" 13607d36db35SAvi Kivity "mov %ax, %ss \n\t" 13617d36db35SAvi Kivity "mov %cr0, %eax \n\t" 13627d36db35SAvi Kivity "btc $0, %eax \n\t" 13637d36db35SAvi Kivity "mov %eax, %cr0 \n\t" 13647d36db35SAvi Kivity "ljmp $0, $realmode_entry \n\t" 13657d36db35SAvi Kivity 13667d36db35SAvi Kivity "realmode_entry: \n\t" 13677d36db35SAvi Kivity 13687d36db35SAvi Kivity "xor %ax, %ax \n\t" 13697d36db35SAvi Kivity "mov %ax, %ds \n\t" 13707d36db35SAvi Kivity "mov %ax, %es \n\t" 13717d36db35SAvi Kivity "mov %ax, %ss \n\t" 13727d36db35SAvi Kivity "mov %ax, %fs \n\t" 13737d36db35SAvi Kivity "mov %ax, %gs \n\t" 13747d36db35SAvi Kivity "mov $stacktop, %esp\n\t" 13757d36db35SAvi Kivity "ljmp $0, $realmode_start \n\t" 13767d36db35SAvi Kivity 13777d36db35SAvi Kivity ".code16gcc \n\t" 13787d36db35SAvi Kivity ); 1379