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 62*18253fdeSAvi Kivity static struct regs inregs, outregs; 63*18253fdeSAvi Kivity 64*18253fdeSAvi 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 76*18253fdeSAvi 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 ); 118*18253fdeSAvi 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 130*18253fdeSAvi Kivity int regs_equal(int ignore) 1317d36db35SAvi Kivity { 132*18253fdeSAvi 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 14181050840SAvi Kivity static void report(const char *name, _Bool ok) 14281050840SAvi Kivity { 14381050840SAvi Kivity print_serial(ok ? "PASS: " : "FAIL: "); 14481050840SAvi Kivity print_serial(name); 14581050840SAvi Kivity print_serial("\n"); 14681050840SAvi Kivity } 14781050840SAvi Kivity 1487d36db35SAvi Kivity #define MK_INSN(name, str) \ 1497d36db35SAvi Kivity asm ( \ 150d4dc402cSAvi Kivity ".pushsection .data.insn \n\t" \ 151d4dc402cSAvi Kivity "insn_" #name ": \n\t" \ 152d4dc402cSAvi Kivity ".word 1001f, 1002f - 1001f \n\t" \ 153d4dc402cSAvi Kivity ".popsection \n\t" \ 154d4dc402cSAvi Kivity ".pushsection .text.insn, \"ax\" \n\t" \ 155d4dc402cSAvi Kivity "1001: \n\t" \ 156d4dc402cSAvi Kivity "insn_code_" #name ": " str " \n\t" \ 157d4dc402cSAvi Kivity "1002: \n\t" \ 158d4dc402cSAvi Kivity ".popsection" \ 1597d36db35SAvi Kivity ); \ 160d4dc402cSAvi Kivity extern struct insn_desc insn_##name; 1617d36db35SAvi Kivity 1627d36db35SAvi Kivity void test_xchg(void) 1637d36db35SAvi Kivity { 1647d36db35SAvi Kivity MK_INSN(xchg_test1, "xchg %eax,%eax\n\t"); 1657d36db35SAvi Kivity MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t"); 1667d36db35SAvi Kivity MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t"); 1677d36db35SAvi Kivity MK_INSN(xchg_test4, "xchg %eax,%edx\n\t"); 1687d36db35SAvi Kivity MK_INSN(xchg_test5, "xchg %eax,%esi\n\t"); 1697d36db35SAvi Kivity MK_INSN(xchg_test6, "xchg %eax,%edi\n\t"); 1707d36db35SAvi Kivity MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t"); 1717d36db35SAvi Kivity MK_INSN(xchg_test8, "xchg %eax,%esp\n\t"); 1727d36db35SAvi Kivity 173*18253fdeSAvi Kivity inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7}; 1747d36db35SAvi Kivity 175*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test1); 176*18253fdeSAvi Kivity report("xchg 1", regs_equal(0)); 177*18253fdeSAvi Kivity 178*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test2); 17981050840SAvi Kivity report("xchg 2", 180*18253fdeSAvi Kivity regs_equal(R_AX | R_BX) 18181050840SAvi Kivity && outregs.eax == inregs.ebx && outregs.ebx == inregs.eax); 1827d36db35SAvi Kivity 183*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test3); 18481050840SAvi Kivity report("xchg 3", 185*18253fdeSAvi Kivity regs_equal(R_AX | R_CX) 18681050840SAvi Kivity && outregs.eax == inregs.ecx && outregs.ecx == inregs.eax); 1877d36db35SAvi Kivity 188*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test4); 18981050840SAvi Kivity report("xchg 4", 190*18253fdeSAvi Kivity regs_equal(R_AX | R_DX) 19181050840SAvi Kivity && outregs.eax == inregs.edx && outregs.edx == inregs.eax); 1927d36db35SAvi Kivity 193*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test5); 194*18253fdeSAvi Kivity report("xchg 5", regs_equal(R_AX | R_SI) 19581050840SAvi Kivity && outregs.eax == inregs.esi && outregs.esi == inregs.eax); 1967d36db35SAvi Kivity 197*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test6); 198*18253fdeSAvi Kivity report("xchg 6", regs_equal(R_AX | R_DI) 19981050840SAvi Kivity && outregs.eax == inregs.edi && outregs.edi == inregs.eax); 2007d36db35SAvi Kivity 201*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test7); 202*18253fdeSAvi Kivity report("xchg 7", regs_equal(R_AX | R_BP) 20381050840SAvi Kivity && outregs.eax == inregs.ebp && outregs.ebp == inregs.eax); 2047d36db35SAvi Kivity 205*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test8); 206*18253fdeSAvi Kivity report("xchg 8", regs_equal(R_AX | R_SP) 20781050840SAvi 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 214*18253fdeSAvi Kivity inregs = (struct regs){ .eax = 0xbe, .edx = 0xef000000 }; 215*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_shld_test); 21681050840SAvi Kivity report("shld", 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 227*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 228*18253fdeSAvi Kivity 229*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r16_imm_1); 23081050840SAvi Kivity report("mov 1", 231*18253fdeSAvi Kivity regs_equal(R_AX) && outregs.eax == 1234); 2327d36db35SAvi Kivity 2337d36db35SAvi Kivity /* test mov $imm, %eax */ 234*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r32_imm_1); 23581050840SAvi Kivity report("mov 2", 236*18253fdeSAvi Kivity regs_equal(R_AX) 23781050840SAvi Kivity && outregs.eax == 1234567890); 2387d36db35SAvi Kivity 2397d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 240*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_1); 24181050840SAvi Kivity report("mov 3", 242*18253fdeSAvi Kivity regs_equal(R_AX) && outregs.eax == 0x1200); 2437d36db35SAvi Kivity 244*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_2); 24581050840SAvi Kivity report("mov 4", 246*18253fdeSAvi Kivity regs_equal(R_AX) && outregs.eax == 0x34); 2477d36db35SAvi Kivity 248*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_3); 24981050840SAvi Kivity report("mov 5", 250*18253fdeSAvi Kivity regs_equal(R_AX) && outregs.eax == 0x1234); 2517d36db35SAvi Kivity } 2527d36db35SAvi Kivity 2537d36db35SAvi Kivity void test_sub_imm(void) 2547d36db35SAvi Kivity { 2557d36db35SAvi Kivity MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t"); 2567d36db35SAvi Kivity MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t"); 2577d36db35SAvi Kivity MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t"); 2587d36db35SAvi Kivity MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t"); 2597d36db35SAvi Kivity 260*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 261*18253fdeSAvi Kivity 262*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r16_imm_1); 26381050840SAvi Kivity report("sub 1", 264*18253fdeSAvi Kivity regs_equal(R_AX) && outregs.eax == 1224); 2657d36db35SAvi Kivity 2667d36db35SAvi Kivity /* test mov $imm, %eax */ 267*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r32_imm_1); 26881050840SAvi Kivity report("sub 2", 269*18253fdeSAvi Kivity regs_equal(R_AX) 27081050840SAvi Kivity && outregs.eax == 1234567880); 2717d36db35SAvi Kivity 2727d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 273*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r8_imm_1); 27481050840SAvi Kivity report("sub 3", 275*18253fdeSAvi Kivity regs_equal(R_AX) && outregs.eax == 0x0200); 2767d36db35SAvi Kivity 277*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r8_imm_2); 27881050840SAvi Kivity report("sub 4", 279*18253fdeSAvi Kivity regs_equal(R_AX) && outregs.eax == 0x24); 2807d36db35SAvi Kivity } 2817d36db35SAvi Kivity 2827d36db35SAvi Kivity void test_xor_imm(void) 2837d36db35SAvi Kivity { 2847d36db35SAvi Kivity MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t"); 2857d36db35SAvi Kivity MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t"); 2867d36db35SAvi Kivity MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t"); 2877d36db35SAvi Kivity MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t"); 2887d36db35SAvi Kivity 289*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 290*18253fdeSAvi Kivity 291*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r16_imm_1); 29281050840SAvi Kivity report("xor 1", 293*18253fdeSAvi Kivity regs_equal(R_AX) && outregs.eax == 0); 2947d36db35SAvi Kivity 2957d36db35SAvi Kivity /* test mov $imm, %eax */ 296*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r32_imm_1); 29781050840SAvi Kivity report("xor 2", 298*18253fdeSAvi Kivity regs_equal(R_AX) && outregs.eax == 0); 2997d36db35SAvi Kivity 3007d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 301*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r8_imm_1); 30281050840SAvi Kivity report("xor 3", 303*18253fdeSAvi Kivity regs_equal(R_AX) && outregs.eax == 0); 3047d36db35SAvi Kivity 305*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r8_imm_2); 30681050840SAvi Kivity report("xor 4", 307*18253fdeSAvi Kivity regs_equal(R_AX) && outregs.eax == 0); 3087d36db35SAvi Kivity } 3097d36db35SAvi Kivity 3107d36db35SAvi Kivity void test_cmp_imm(void) 3117d36db35SAvi Kivity { 3127d36db35SAvi Kivity MK_INSN(cmp_test1, "mov $0x34, %al\n\t" 3137d36db35SAvi Kivity "cmp $0x34, %al\n\t"); 3147d36db35SAvi Kivity MK_INSN(cmp_test2, "mov $0x34, %al\n\t" 3157d36db35SAvi Kivity "cmp $0x39, %al\n\t"); 3167d36db35SAvi Kivity MK_INSN(cmp_test3, "mov $0x34, %al\n\t" 3177d36db35SAvi Kivity "cmp $0x24, %al\n\t"); 3187d36db35SAvi Kivity 319*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 320*18253fdeSAvi Kivity 3217d36db35SAvi Kivity /* test cmp imm8 with AL */ 3227d36db35SAvi Kivity /* ZF: (bit 6) Zero Flag becomes 1 if an operation results 3237d36db35SAvi Kivity * in a 0 writeback, or 0 register 3247d36db35SAvi Kivity */ 325*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test1); 32681050840SAvi Kivity report("cmp 1", (outregs.eflags & (1<<6)) == (1<<6)); 3277d36db35SAvi Kivity 328*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test2); 32981050840SAvi Kivity report("cmp 2", (outregs.eflags & (1<<6)) == 0); 3307d36db35SAvi Kivity 331*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test3); 33281050840SAvi Kivity report("cmp 3", (outregs.eflags & (1<<6)) == 0); 3337d36db35SAvi Kivity } 3347d36db35SAvi Kivity 3357d36db35SAvi Kivity void test_add_imm(void) 3367d36db35SAvi Kivity { 3377d36db35SAvi Kivity MK_INSN(add_test1, "mov $0x43211234, %eax \n\t" 3387d36db35SAvi Kivity "add $0x12344321, %eax \n\t"); 3397d36db35SAvi Kivity MK_INSN(add_test2, "mov $0x12, %eax \n\t" 3407d36db35SAvi Kivity "add $0x21, %al\n\t"); 3417d36db35SAvi Kivity 342*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 343*18253fdeSAvi Kivity 344*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_add_test1); 34581050840SAvi Kivity report("add 1", outregs.eax == 0x55555555); 3467d36db35SAvi Kivity 347*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_add_test2); 34881050840SAvi Kivity report("add 2", outregs.eax == 0x33); 3497d36db35SAvi Kivity } 3507d36db35SAvi Kivity 3517d36db35SAvi Kivity void test_eflags_insn(void) 3527d36db35SAvi Kivity { 3537d36db35SAvi Kivity MK_INSN(clc, "clc"); 354b3261e48SMohammed Gamal MK_INSN(stc, "stc"); 3557d36db35SAvi Kivity MK_INSN(cli, "cli"); 3567d36db35SAvi Kivity MK_INSN(sti, "sti"); 3577d36db35SAvi Kivity MK_INSN(cld, "cld"); 3587d36db35SAvi Kivity MK_INSN(std, "std"); 3597d36db35SAvi Kivity 360*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 361*18253fdeSAvi Kivity 362*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_clc); 36381050840SAvi Kivity report("clc", (outregs.eflags & 1) == 0); 3647d36db35SAvi Kivity 365*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_stc); 36681050840SAvi Kivity report("stc", (outregs.eflags & 1) == 1); 367b3261e48SMohammed Gamal 368*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_cli); 36981050840SAvi Kivity report("cli", !(outregs.eflags & (1 << 9))); 3707d36db35SAvi Kivity 371*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_sti); 37281050840SAvi Kivity report("sti", outregs.eflags & (1 << 9)); 3737d36db35SAvi Kivity 374*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_cld); 37581050840SAvi Kivity report("cld", !(outregs.eflags & (1 << 10))); 3767d36db35SAvi Kivity 377*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_std); 37881050840SAvi Kivity report("std", (outregs.eflags & (1 << 10))); 3797d36db35SAvi Kivity } 3807d36db35SAvi Kivity 3817d36db35SAvi Kivity void test_io(void) 3827d36db35SAvi Kivity { 3837d36db35SAvi Kivity MK_INSN(io_test1, "mov $0xff, %al \n\t" 3847d36db35SAvi Kivity "out %al, $0xe0 \n\t" 3857d36db35SAvi Kivity "mov $0x00, %al \n\t" 3867d36db35SAvi Kivity "in $0xe0, %al \n\t"); 3877d36db35SAvi Kivity MK_INSN(io_test2, "mov $0xffff, %ax \n\t" 3887d36db35SAvi Kivity "out %ax, $0xe0 \n\t" 3897d36db35SAvi Kivity "mov $0x0000, %ax \n\t" 3907d36db35SAvi Kivity "in $0xe0, %ax \n\t"); 3917d36db35SAvi Kivity MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t" 3927d36db35SAvi Kivity "out %eax, $0xe0 \n\t" 3937d36db35SAvi Kivity "mov $0x000000, %eax \n\t" 3947d36db35SAvi Kivity "in $0xe0, %eax \n\t"); 3957d36db35SAvi Kivity MK_INSN(io_test4, "mov $0xe0, %dx \n\t" 3967d36db35SAvi Kivity "mov $0xff, %al \n\t" 3977d36db35SAvi Kivity "out %al, %dx \n\t" 3987d36db35SAvi Kivity "mov $0x00, %al \n\t" 3997d36db35SAvi Kivity "in %dx, %al \n\t"); 4007d36db35SAvi Kivity MK_INSN(io_test5, "mov $0xe0, %dx \n\t" 4017d36db35SAvi Kivity "mov $0xffff, %ax \n\t" 4027d36db35SAvi Kivity "out %ax, %dx \n\t" 4037d36db35SAvi Kivity "mov $0x0000, %ax \n\t" 4047d36db35SAvi Kivity "in %dx, %ax \n\t"); 4057d36db35SAvi Kivity MK_INSN(io_test6, "mov $0xe0, %dx \n\t" 4067d36db35SAvi Kivity "mov $0xffffffff, %eax \n\t" 4077d36db35SAvi Kivity "out %eax, %dx \n\t" 4087d36db35SAvi Kivity "mov $0x00000000, %eax \n\t" 4097d36db35SAvi Kivity "in %dx, %eax \n\t"); 4107d36db35SAvi Kivity 411*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 412*18253fdeSAvi Kivity 413*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test1); 41481050840SAvi Kivity report("pio 1", 415*18253fdeSAvi Kivity regs_equal(R_AX) && outregs.eax == 0xff); 4167d36db35SAvi Kivity 417*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test2); 41881050840SAvi Kivity report("pio 2", 419*18253fdeSAvi Kivity regs_equal(R_AX) && outregs.eax == 0xffff); 4207d36db35SAvi Kivity 421*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test3); 42281050840SAvi Kivity report("pio 3", 423*18253fdeSAvi Kivity regs_equal(R_AX) 42481050840SAvi Kivity && outregs.eax == 0xffffffff); 4257d36db35SAvi Kivity 426*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test4); 42781050840SAvi Kivity report("pio 4", 428*18253fdeSAvi Kivity regs_equal(R_AX|R_DX) && outregs.eax == 0xff); 4297d36db35SAvi Kivity 430*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test5); 43181050840SAvi Kivity report("pio 5", 432*18253fdeSAvi Kivity regs_equal(R_AX|R_DX) 43381050840SAvi Kivity && outregs.eax == 0xffff); 4347d36db35SAvi Kivity 435*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test6); 43681050840SAvi Kivity report("pio 6", 437*18253fdeSAvi Kivity regs_equal(R_AX|R_DX) 43881050840SAvi Kivity && outregs.eax == 0xffffffff); 4397d36db35SAvi Kivity } 4407d36db35SAvi Kivity 441c0b7268dSAvi Kivity asm ("retf: lretw"); 442c0b7268dSAvi Kivity extern void retf(); 443c0b7268dSAvi Kivity 4447d36db35SAvi Kivity void test_call(void) 4457d36db35SAvi Kivity { 4467d36db35SAvi Kivity u32 esp[16]; 447c0b7268dSAvi Kivity u32 addr; 4487d36db35SAvi Kivity 449*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 4507d36db35SAvi Kivity inregs.esp = (u32)esp; 4517d36db35SAvi Kivity 4527d36db35SAvi Kivity MK_INSN(call1, "mov $test_function, %eax \n\t" 4537d36db35SAvi Kivity "call *%eax\n\t"); 4547d36db35SAvi Kivity MK_INSN(call_near1, "jmp 2f\n\t" 4557d36db35SAvi Kivity "1: mov $0x1234, %eax\n\t" 4567d36db35SAvi Kivity "ret\n\t" 4577d36db35SAvi Kivity "2: call 1b\t"); 4587d36db35SAvi Kivity MK_INSN(call_near2, "call 1f\n\t" 4597d36db35SAvi Kivity "jmp 2f\n\t" 4607d36db35SAvi Kivity "1: mov $0x1234, %eax\n\t" 4617d36db35SAvi Kivity "ret\n\t" 4627d36db35SAvi Kivity "2:\t"); 463c0b7268dSAvi Kivity MK_INSN(call_far1, "lcallw *(%ebx)\n\t"); 464c6061817SAvi Kivity MK_INSN(ret_imm, "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b"); 4657d36db35SAvi Kivity 466*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_call1); 46781050840SAvi Kivity report("call 1", 468*18253fdeSAvi Kivity regs_equal(R_AX) && outregs.eax == 0x1234); 4697d36db35SAvi Kivity 470*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_near1); 47181050840SAvi Kivity report("call near 1", 472*18253fdeSAvi Kivity regs_equal(R_AX) && outregs.eax == 0x1234); 4737d36db35SAvi Kivity 474*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_near2); 47581050840SAvi Kivity report("call near 2", 476*18253fdeSAvi Kivity regs_equal(R_AX) && outregs.eax == 0x1234); 477c0b7268dSAvi Kivity 478c0b7268dSAvi Kivity addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f); 479c0b7268dSAvi Kivity inregs.ebx = (unsigned)&addr; 480*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_far1); 481*18253fdeSAvi Kivity report("call far 1", regs_equal(0)); 482c6061817SAvi Kivity 483*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_ret_imm); 484*18253fdeSAvi Kivity report("ret imm 1", regs_equal(0)); 4857d36db35SAvi Kivity } 4867d36db35SAvi Kivity 4877d36db35SAvi Kivity void test_jcc_short(void) 4887d36db35SAvi Kivity { 4897d36db35SAvi Kivity MK_INSN(jnz_short1, "jnz 1f\n\t" 4907d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 4917d36db35SAvi Kivity "1:\n\t"); 4927d36db35SAvi Kivity MK_INSN(jnz_short2, "1:\n\t" 4937d36db35SAvi Kivity "cmp $0x1234, %eax\n\t" 4947d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 4957d36db35SAvi Kivity "jnz 1b\n\t"); 4967d36db35SAvi Kivity MK_INSN(jmp_short1, "jmp 1f\n\t" 4977d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 4987d36db35SAvi Kivity "1:\n\t"); 4997d36db35SAvi Kivity 500*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 5017d36db35SAvi Kivity 502*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_short1); 503*18253fdeSAvi Kivity report("jnz short 1", regs_equal(0)); 504*18253fdeSAvi Kivity 505*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_short2); 50681050840SAvi Kivity report("jnz short 2", 507*18253fdeSAvi Kivity regs_equal(R_AX) 50881050840SAvi Kivity && (outregs.eflags & (1 << 6))); 5097d36db35SAvi Kivity 510*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_jmp_short1); 511*18253fdeSAvi Kivity report("jmp short 1", regs_equal(0)); 5127d36db35SAvi Kivity } 5137d36db35SAvi Kivity 5147d36db35SAvi Kivity void test_jcc_near(void) 5157d36db35SAvi Kivity { 5167d36db35SAvi Kivity /* encode near jmp manually. gas will not do it if offsets < 127 byte */ 5177d36db35SAvi Kivity MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t" 5187d36db35SAvi Kivity "mov $0x1234, %eax\n\t"); 5197d36db35SAvi Kivity MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t" 5207d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5217d36db35SAvi Kivity ".byte 0x0f, 0x85, 0xf0, 0xff\n\t"); 5227d36db35SAvi Kivity MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t" 5237d36db35SAvi Kivity "mov $0x1234, %eax\n\t"); 5247d36db35SAvi Kivity 525*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 5267d36db35SAvi Kivity 527*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_near1); 528*18253fdeSAvi Kivity report("jnz near 1", regs_equal(0)); 529*18253fdeSAvi Kivity 530*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_near2); 53181050840SAvi Kivity report("jnz near 2", 532*18253fdeSAvi Kivity regs_equal(R_AX) 53381050840SAvi Kivity && (outregs.eflags & (1 << 6))); 5347d36db35SAvi Kivity 535*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_jmp_near1); 536*18253fdeSAvi Kivity report("jmp near 1", regs_equal(0)); 5377d36db35SAvi Kivity } 5387d36db35SAvi Kivity 5397d36db35SAvi Kivity void test_long_jmp() 5407d36db35SAvi Kivity { 5417d36db35SAvi Kivity u32 esp[16]; 5427d36db35SAvi Kivity 543*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 5447d36db35SAvi Kivity inregs.esp = (u32)esp; 5457d36db35SAvi Kivity MK_INSN(long_jmp, "call 1f\n\t" 5467d36db35SAvi Kivity "jmp 2f\n\t" 5477d36db35SAvi Kivity "1: jmp $0, $test_function\n\t" 5487d36db35SAvi Kivity "2:\n\t"); 549*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_long_jmp); 55081050840SAvi Kivity report("jmp far 1", 551*18253fdeSAvi Kivity regs_equal(R_AX) && outregs.eax == 0x1234); 5527d36db35SAvi Kivity } 553fa74f8a6SMohammed Gamal 5547d36db35SAvi Kivity void test_push_pop() 5557d36db35SAvi Kivity { 5567d36db35SAvi Kivity MK_INSN(push32, "mov $0x12345678, %eax\n\t" 5577d36db35SAvi Kivity "push %eax\n\t" 5587d36db35SAvi Kivity "pop %ebx\n\t"); 5597d36db35SAvi Kivity MK_INSN(push16, "mov $0x1234, %ax\n\t" 5607d36db35SAvi Kivity "push %ax\n\t" 5617d36db35SAvi Kivity "pop %bx\n\t"); 5627d36db35SAvi Kivity 5637d36db35SAvi Kivity MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten 5647d36db35SAvi Kivity "mov $0x123, %ax\n\t" 5657d36db35SAvi Kivity "mov %ax, %es\n\t" 5667d36db35SAvi Kivity "push %es\n\t" 5677d36db35SAvi Kivity "pop %bx \n\t" 5687d36db35SAvi Kivity ); 5697d36db35SAvi Kivity MK_INSN(pop_es, "push %ax\n\t" 5707d36db35SAvi Kivity "pop %es\n\t" 5717d36db35SAvi Kivity "mov %es, %bx\n\t" 5727d36db35SAvi Kivity ); 5737d36db35SAvi Kivity MK_INSN(push_pop_ss, "push %ss\n\t" 5747d36db35SAvi Kivity "pushw %ax\n\t" 5757d36db35SAvi Kivity "popw %ss\n\t" 5767d36db35SAvi Kivity "mov %ss, %bx\n\t" 5777d36db35SAvi Kivity "pop %ss\n\t" 5787d36db35SAvi Kivity ); 5797d36db35SAvi Kivity MK_INSN(push_pop_fs, "push %fs\n\t" 5807d36db35SAvi Kivity "pushl %eax\n\t" 5817d36db35SAvi Kivity "popl %fs\n\t" 5827d36db35SAvi Kivity "mov %fs, %ebx\n\t" 5837d36db35SAvi Kivity "pop %fs\n\t" 5847d36db35SAvi Kivity ); 5857d36db35SAvi Kivity 586*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 587*18253fdeSAvi Kivity 588*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_push32); 58981050840SAvi Kivity report("push/pop 1", 590*18253fdeSAvi Kivity regs_equal(R_AX|R_BX) 59181050840SAvi Kivity && outregs.eax == outregs.ebx && outregs.eax == 0x12345678); 5927d36db35SAvi Kivity 593*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_push16); 59481050840SAvi Kivity report("push/pop 2", 595*18253fdeSAvi Kivity regs_equal(R_AX|R_BX) 59681050840SAvi Kivity && outregs.eax == outregs.ebx && outregs.eax == 0x1234); 5977d36db35SAvi Kivity 598*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_es); 59981050840SAvi Kivity report("push/pop 3", 600*18253fdeSAvi Kivity regs_equal(R_AX|R_BX) 60181050840SAvi Kivity && outregs.ebx == outregs.eax && outregs.eax == 0x123); 6027d36db35SAvi Kivity 603*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_pop_es); 60481050840SAvi Kivity report("push/pop 4", 605*18253fdeSAvi Kivity regs_equal(R_AX|R_BX) 60681050840SAvi Kivity && outregs.ebx == outregs.eax); 6077d36db35SAvi Kivity 608*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_pop_ss); 60981050840SAvi Kivity report("push/pop 5", 610*18253fdeSAvi Kivity regs_equal(R_AX|R_BX) 61181050840SAvi Kivity && outregs.ebx == outregs.eax); 6127d36db35SAvi Kivity 613*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_pop_fs); 61481050840SAvi Kivity report("push/pop 6", 615*18253fdeSAvi Kivity regs_equal(R_AX|R_BX) 61681050840SAvi Kivity && outregs.ebx == outregs.eax); 6177d36db35SAvi Kivity } 6187d36db35SAvi Kivity 6197d36db35SAvi Kivity void test_null(void) 6207d36db35SAvi Kivity { 621d4dc402cSAvi Kivity MK_INSN(null, ""); 622d4dc402cSAvi Kivity 623*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 624*18253fdeSAvi Kivity 625*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_null); 626*18253fdeSAvi Kivity report("null", regs_equal(0)); 6277d36db35SAvi Kivity } 6287d36db35SAvi Kivity 6297d36db35SAvi Kivity struct { 6307d36db35SAvi Kivity char stack[500]; 6317d36db35SAvi Kivity char top[]; 6327d36db35SAvi Kivity } tmp_stack; 6337d36db35SAvi Kivity 6347d36db35SAvi Kivity void test_pusha_popa() 6357d36db35SAvi Kivity { 6367d36db35SAvi Kivity MK_INSN(pusha, "pusha\n\t" 6377d36db35SAvi Kivity "pop %edi\n\t" 6387d36db35SAvi Kivity "pop %esi\n\t" 6397d36db35SAvi Kivity "pop %ebp\n\t" 6407d36db35SAvi Kivity "add $4, %esp\n\t" 6417d36db35SAvi Kivity "pop %ebx\n\t" 6427d36db35SAvi Kivity "pop %edx\n\t" 6437d36db35SAvi Kivity "pop %ecx\n\t" 6447d36db35SAvi Kivity "pop %eax\n\t" 6457d36db35SAvi Kivity ); 6467d36db35SAvi Kivity 6477d36db35SAvi Kivity MK_INSN(popa, "push %eax\n\t" 6487d36db35SAvi Kivity "push %ecx\n\t" 6497d36db35SAvi Kivity "push %edx\n\t" 6507d36db35SAvi Kivity "push %ebx\n\t" 6517d36db35SAvi Kivity "push %esp\n\t" 6527d36db35SAvi Kivity "push %ebp\n\t" 6537d36db35SAvi Kivity "push %esi\n\t" 6547d36db35SAvi Kivity "push %edi\n\t" 6557d36db35SAvi Kivity "popa\n\t" 6567d36db35SAvi Kivity ); 6577d36db35SAvi Kivity 658*18253fdeSAvi Kivity inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top }; 6597d36db35SAvi Kivity 660*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_pusha); 661*18253fdeSAvi Kivity report("pusha/popa 1", regs_equal(0)); 662*18253fdeSAvi Kivity 663*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_popa); 664*18253fdeSAvi Kivity report("pusha/popa 1", regs_equal(0)); 6657d36db35SAvi Kivity } 6667d36db35SAvi Kivity 6677d36db35SAvi Kivity void test_iret() 6687d36db35SAvi Kivity { 6697d36db35SAvi Kivity MK_INSN(iret32, "pushf\n\t" 6707d36db35SAvi Kivity "pushl %cs\n\t" 6717d36db35SAvi Kivity "call 1f\n\t" /* a near call will push eip onto the stack */ 6727d36db35SAvi Kivity "jmp 2f\n\t" 6737d36db35SAvi Kivity "1: iret\n\t" 6747d36db35SAvi Kivity "2:\n\t" 6757d36db35SAvi Kivity ); 6767d36db35SAvi Kivity 6777d36db35SAvi Kivity MK_INSN(iret16, "pushfw\n\t" 6787d36db35SAvi Kivity "pushw %cs\n\t" 6797d36db35SAvi Kivity "callw 1f\n\t" 6807d36db35SAvi Kivity "jmp 2f\n\t" 6817d36db35SAvi Kivity "1: iretw\n\t" 6827d36db35SAvi Kivity "2:\n\t"); 6837d36db35SAvi Kivity 6847d36db35SAvi Kivity MK_INSN(iret_flags32, "pushfl\n\t" 6857d36db35SAvi Kivity "popl %eax\n\t" 6867d36db35SAvi Kivity "andl $~0x2, %eax\n\t" 6877d36db35SAvi Kivity "orl $0xffc08028, %eax\n\t" 6887d36db35SAvi Kivity "pushl %eax\n\t" 6897d36db35SAvi Kivity "pushl %cs\n\t" 6907d36db35SAvi Kivity "call 1f\n\t" 6917d36db35SAvi Kivity "jmp 2f\n\t" 6927d36db35SAvi Kivity "1: iret\n\t" 6937d36db35SAvi Kivity "2:\n\t"); 6947d36db35SAvi Kivity 6957d36db35SAvi Kivity MK_INSN(iret_flags16, "pushfw\n\t" 6967d36db35SAvi Kivity "popw %ax\n\t" 6977d36db35SAvi Kivity "and $~0x2, %ax\n\t" 6987d36db35SAvi Kivity "or $0x8028, %ax\n\t" 6997d36db35SAvi Kivity "pushw %ax\n\t" 7007d36db35SAvi Kivity "pushw %cs\n\t" 7017d36db35SAvi Kivity "callw 1f\n\t" 7027d36db35SAvi Kivity "jmp 2f\n\t" 7037d36db35SAvi Kivity "1: iretw\n\t" 7047d36db35SAvi Kivity "2:\n\t"); 7057d36db35SAvi Kivity 706*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 7077d36db35SAvi Kivity 708*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret32); 709*18253fdeSAvi Kivity report("iret 1", regs_equal(0)); 7107d36db35SAvi Kivity 711*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret16); 712*18253fdeSAvi Kivity report("iret 2", regs_equal(0)); 7137d36db35SAvi Kivity 714*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret_flags32); 715*18253fdeSAvi Kivity report("iret 3", regs_equal(R_AX)); 716*18253fdeSAvi Kivity 717*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret_flags16); 718*18253fdeSAvi Kivity report("iret 4", regs_equal(R_AX)); 7197d36db35SAvi Kivity } 7207d36db35SAvi Kivity 72196b9ca1eSMohammed Gamal void test_int() 72296b9ca1eSMohammed Gamal { 723*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 72496b9ca1eSMohammed Gamal 72596b9ca1eSMohammed Gamal *(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */ 72696b9ca1eSMohammed Gamal *(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */ 72796b9ca1eSMohammed Gamal 72896b9ca1eSMohammed Gamal MK_INSN(int11, "int $0x11\n\t"); 72996b9ca1eSMohammed Gamal 730*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_int11); 731*18253fdeSAvi Kivity report("int 1", regs_equal(0)); 73296b9ca1eSMohammed Gamal } 73396b9ca1eSMohammed Gamal 734fa74f8a6SMohammed Gamal void test_imul() 735fa74f8a6SMohammed Gamal { 736fa74f8a6SMohammed Gamal MK_INSN(imul8_1, "mov $2, %al\n\t" 737fa74f8a6SMohammed Gamal "mov $-4, %cx\n\t" 738fa74f8a6SMohammed Gamal "imul %cl\n\t"); 739fa74f8a6SMohammed Gamal 740fa74f8a6SMohammed Gamal MK_INSN(imul16_1, "mov $2, %ax\n\t" 741fa74f8a6SMohammed Gamal "mov $-4, %cx\n\t" 742fa74f8a6SMohammed Gamal "imul %cx\n\t"); 743fa74f8a6SMohammed Gamal 744fa74f8a6SMohammed Gamal MK_INSN(imul32_1, "mov $2, %eax\n\t" 745fa74f8a6SMohammed Gamal "mov $-4, %ecx\n\t" 746fa74f8a6SMohammed Gamal "imul %ecx\n\t"); 747fa74f8a6SMohammed Gamal 748fa74f8a6SMohammed Gamal MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t" 749fa74f8a6SMohammed Gamal "mov $4, %cx\n\t" 750fa74f8a6SMohammed Gamal "imul %cl\n\t"); 751fa74f8a6SMohammed Gamal 752fa74f8a6SMohammed Gamal MK_INSN(imul16_2, "mov $2, %ax\n\t" 753fa74f8a6SMohammed Gamal "mov $4, %cx\n\t" 754fa74f8a6SMohammed Gamal "imul %cx\n\t"); 755fa74f8a6SMohammed Gamal 756fa74f8a6SMohammed Gamal MK_INSN(imul32_2, "mov $2, %eax\n\t" 757fa74f8a6SMohammed Gamal "mov $4, %ecx\n\t" 758fa74f8a6SMohammed Gamal "imul %ecx\n\t"); 759fa74f8a6SMohammed Gamal 760*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 761*18253fdeSAvi Kivity 762*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul8_1); 76381050840SAvi Kivity report("imul 1", 764*18253fdeSAvi Kivity regs_equal(R_AX | R_CX | R_DX) 76581050840SAvi Kivity && (outregs.eax & 0xff) == (u8)-8); 766fa74f8a6SMohammed Gamal 767*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul16_1); 76881050840SAvi Kivity report("imul 2", 769*18253fdeSAvi Kivity regs_equal(R_AX | R_CX | R_DX) 77081050840SAvi Kivity && outregs.eax == (u16)-8); 771fa74f8a6SMohammed Gamal 772*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul32_1); 77381050840SAvi Kivity report("imul 3", 774*18253fdeSAvi Kivity regs_equal(R_AX | R_CX | R_DX) 77581050840SAvi Kivity && outregs.eax == (u32)-8); 776fa74f8a6SMohammed Gamal 777*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul8_2); 77881050840SAvi Kivity report("imul 4", 779*18253fdeSAvi Kivity regs_equal(R_AX | R_CX | R_DX) 78081050840SAvi Kivity && (outregs.eax & 0xffff) == 8 78181050840SAvi Kivity && (outregs.eax & 0xffff0000) == 0x12340000); 782fa74f8a6SMohammed Gamal 783*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul16_2); 78481050840SAvi Kivity report("imul 5", 785*18253fdeSAvi Kivity regs_equal(R_AX | R_CX | R_DX) 78681050840SAvi Kivity && outregs.eax == 8); 787fa74f8a6SMohammed Gamal 788*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul32_2); 78981050840SAvi Kivity report("imul 6", 790*18253fdeSAvi Kivity regs_equal(R_AX | R_CX | R_DX) 79181050840SAvi Kivity && outregs.eax == 8); 792fa74f8a6SMohammed Gamal } 793fa74f8a6SMohammed Gamal 79459317bd1SMohammed Gamal void test_mul() 79559317bd1SMohammed Gamal { 79659317bd1SMohammed Gamal MK_INSN(mul8, "mov $2, %al\n\t" 79759317bd1SMohammed Gamal "mov $4, %cx\n\t" 79859317bd1SMohammed Gamal "imul %cl\n\t"); 79959317bd1SMohammed Gamal 80059317bd1SMohammed Gamal MK_INSN(mul16, "mov $2, %ax\n\t" 80159317bd1SMohammed Gamal "mov $4, %cx\n\t" 80259317bd1SMohammed Gamal "imul %cx\n\t"); 80359317bd1SMohammed Gamal 80459317bd1SMohammed Gamal MK_INSN(mul32, "mov $2, %eax\n\t" 80559317bd1SMohammed Gamal "mov $4, %ecx\n\t" 80659317bd1SMohammed Gamal "imul %ecx\n\t"); 80759317bd1SMohammed Gamal 808*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 809*18253fdeSAvi Kivity 810*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul8); 81181050840SAvi Kivity report("mul 1", 812*18253fdeSAvi Kivity regs_equal(R_AX | R_CX | R_DX) 81381050840SAvi Kivity && (outregs.eax & 0xff) == 8); 81459317bd1SMohammed Gamal 815*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul16); 81681050840SAvi Kivity report("mul 2", 817*18253fdeSAvi Kivity regs_equal(R_AX | R_CX | R_DX) 81881050840SAvi Kivity && outregs.eax == 8); 81959317bd1SMohammed Gamal 820*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul32); 82181050840SAvi Kivity report("mul 3", 822*18253fdeSAvi Kivity regs_equal(R_AX | R_CX | R_DX) 82381050840SAvi Kivity && outregs.eax == 8); 82459317bd1SMohammed Gamal } 82559317bd1SMohammed Gamal 8260d4c7614SMohammed Gamal void test_div() 8270d4c7614SMohammed Gamal { 8280d4c7614SMohammed Gamal MK_INSN(div8, "mov $257, %ax\n\t" 8290d4c7614SMohammed Gamal "mov $2, %cl\n\t" 8300d4c7614SMohammed Gamal "div %cl\n\t"); 8310d4c7614SMohammed Gamal 8320d4c7614SMohammed Gamal MK_INSN(div16, "mov $512, %ax\n\t" 8330d4c7614SMohammed Gamal "mov $5, %cx\n\t" 8340d4c7614SMohammed Gamal "div %cx\n\t"); 8350d4c7614SMohammed Gamal 8360d4c7614SMohammed Gamal MK_INSN(div32, "mov $512, %eax\n\t" 8370d4c7614SMohammed Gamal "mov $5, %ecx\n\t" 8380d4c7614SMohammed Gamal "div %ecx\n\t"); 8390d4c7614SMohammed Gamal 840*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 841*18253fdeSAvi Kivity 842*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_div8); 84381050840SAvi Kivity report("div 1", 844*18253fdeSAvi Kivity regs_equal(R_AX | R_CX | R_DX) 84581050840SAvi Kivity && outregs.eax == 384); 8460d4c7614SMohammed Gamal 847*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_div16); 84881050840SAvi Kivity report("div 2", 849*18253fdeSAvi Kivity regs_equal(R_AX | R_CX | R_DX) 85081050840SAvi Kivity && outregs.eax == 102 && outregs.edx == 2); 8510d4c7614SMohammed Gamal 852*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_div32); 85381050840SAvi Kivity report("div 3", 854*18253fdeSAvi Kivity regs_equal(R_AX | R_CX | R_DX) 85581050840SAvi Kivity && outregs.eax == 102 && outregs.edx == 2); 8560d4c7614SMohammed Gamal } 8570d4c7614SMohammed Gamal 8580d4c7614SMohammed Gamal void test_idiv() 8590d4c7614SMohammed Gamal { 8600d4c7614SMohammed Gamal MK_INSN(idiv8, "mov $256, %ax\n\t" 8610d4c7614SMohammed Gamal "mov $-2, %cl\n\t" 8620d4c7614SMohammed Gamal "idiv %cl\n\t"); 8630d4c7614SMohammed Gamal 8640d4c7614SMohammed Gamal MK_INSN(idiv16, "mov $512, %ax\n\t" 8650d4c7614SMohammed Gamal "mov $-2, %cx\n\t" 8660d4c7614SMohammed Gamal "idiv %cx\n\t"); 8670d4c7614SMohammed Gamal 8680d4c7614SMohammed Gamal MK_INSN(idiv32, "mov $512, %eax\n\t" 8690d4c7614SMohammed Gamal "mov $-2, %ecx\n\t" 8700d4c7614SMohammed Gamal "idiv %ecx\n\t"); 8710d4c7614SMohammed Gamal 872*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 873*18253fdeSAvi Kivity 874*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv8); 87581050840SAvi Kivity report("idiv 1", 876*18253fdeSAvi Kivity regs_equal(R_AX | R_CX | R_DX) 87781050840SAvi Kivity && outregs.eax == (u8)-128); 8780d4c7614SMohammed Gamal 879*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv16); 88081050840SAvi Kivity report("idiv 2", 881*18253fdeSAvi Kivity regs_equal(R_AX | R_CX | R_DX) 88281050840SAvi Kivity && outregs.eax == (u16)-256); 8830d4c7614SMohammed Gamal 884*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv32); 88581050840SAvi Kivity report("idiv 3", 886*18253fdeSAvi Kivity regs_equal(R_AX | R_CX | R_DX) 88781050840SAvi Kivity && outregs.eax == (u32)-256); 8880d4c7614SMohammed Gamal } 8890d4c7614SMohammed Gamal 8906e293cf5SWei Yongjun void test_cbw(void) 8916e293cf5SWei Yongjun { 8926e293cf5SWei Yongjun MK_INSN(cbw, "mov $0xFE, %eax \n\t" 8936e293cf5SWei Yongjun "cbw\n\t"); 8946e293cf5SWei Yongjun MK_INSN(cwde, "mov $0xFFFE, %eax \n\t" 8956e293cf5SWei Yongjun "cwde\n\t"); 8966e293cf5SWei Yongjun 897*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 898*18253fdeSAvi Kivity 899*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_cbw); 90081050840SAvi Kivity report("cbq 1", outregs.eax == 0xFFFE); 9016e293cf5SWei Yongjun 902*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwde); 90381050840SAvi Kivity report("cwde 1", outregs.eax == 0xFFFFFFFE); 9046e293cf5SWei Yongjun } 9056e293cf5SWei Yongjun 906eacef4e2SWei Yongjun void test_loopcc(void) 907eacef4e2SWei Yongjun { 908eacef4e2SWei Yongjun MK_INSN(loop, "mov $10, %ecx\n\t" 909eacef4e2SWei Yongjun "1: inc %eax\n\t" 910eacef4e2SWei Yongjun "loop 1b\n\t"); 911eacef4e2SWei Yongjun 912eacef4e2SWei Yongjun MK_INSN(loope, "mov $10, %ecx\n\t" 913eacef4e2SWei Yongjun "mov $1, %eax\n\t" 914eacef4e2SWei Yongjun "1: dec %eax\n\t" 915eacef4e2SWei Yongjun "loope 1b\n\t"); 916eacef4e2SWei Yongjun 917eacef4e2SWei Yongjun MK_INSN(loopne, "mov $10, %ecx\n\t" 918eacef4e2SWei Yongjun "mov $5, %eax\n\t" 919eacef4e2SWei Yongjun "1: dec %eax\n\t" 920eacef4e2SWei Yongjun "loopne 1b\n\t"); 921eacef4e2SWei Yongjun 922*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 923eacef4e2SWei Yongjun 924*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_loop); 925*18253fdeSAvi Kivity report("LOOPcc short 1", 926*18253fdeSAvi Kivity regs_equal(R_AX) && outregs.eax == 10); 927*18253fdeSAvi Kivity 928*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_loope); 92981050840SAvi Kivity report("LOOPcc short 2", 930*18253fdeSAvi Kivity regs_equal(R_AX | R_CX) 93181050840SAvi Kivity && outregs.eax == -1 && outregs.ecx == 8); 932eacef4e2SWei Yongjun 933*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_loopne); 93481050840SAvi Kivity report("LOOPcc short 3", 935*18253fdeSAvi Kivity regs_equal(R_AX | R_CX) 93681050840SAvi Kivity && outregs.eax == 0 && outregs.ecx == 5); 937eacef4e2SWei Yongjun } 938eacef4e2SWei Yongjun 939b274feedSAvi Kivity static void test_das(void) 940b274feedSAvi Kivity { 941b274feedSAvi Kivity short i; 94281050840SAvi Kivity u16 nr_fail = 0; 943b274feedSAvi Kivity static unsigned test_cases[1024] = { 944b274feedSAvi Kivity 0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00, 945b274feedSAvi Kivity 0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01, 946b274feedSAvi Kivity 0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02, 947b274feedSAvi Kivity 0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03, 948b274feedSAvi Kivity 0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04, 949b274feedSAvi Kivity 0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05, 950b274feedSAvi Kivity 0x06000606, 0x8701a606, 0x56100006, 0x9711a006, 951b274feedSAvi Kivity 0x02000707, 0x8301a707, 0x12100107, 0x9311a107, 952b274feedSAvi Kivity 0x02000808, 0x8301a808, 0x12100208, 0x9311a208, 953b274feedSAvi Kivity 0x06000909, 0x8701a909, 0x16100309, 0x9711a309, 954b274feedSAvi Kivity 0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a, 955b274feedSAvi Kivity 0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b, 956b274feedSAvi Kivity 0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c, 957b274feedSAvi Kivity 0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d, 958b274feedSAvi Kivity 0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e, 959b274feedSAvi Kivity 0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f, 960b274feedSAvi Kivity 0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10, 961b274feedSAvi Kivity 0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11, 962b274feedSAvi Kivity 0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12, 963b274feedSAvi Kivity 0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13, 964b274feedSAvi Kivity 0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14, 965b274feedSAvi Kivity 0x02001515, 0x8301b515, 0x16100f15, 0x9711af15, 966b274feedSAvi Kivity 0x02001616, 0x8301b616, 0x12101016, 0x9311b016, 967b274feedSAvi Kivity 0x06001717, 0x8701b717, 0x16101117, 0x9711b117, 968b274feedSAvi Kivity 0x06001818, 0x8701b818, 0x16101218, 0x9711b218, 969b274feedSAvi Kivity 0x02001919, 0x8301b919, 0x12101319, 0x9311b319, 970b274feedSAvi Kivity 0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a, 971b274feedSAvi Kivity 0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b, 972b274feedSAvi Kivity 0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c, 973b274feedSAvi Kivity 0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d, 974b274feedSAvi Kivity 0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e, 975b274feedSAvi Kivity 0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f, 976b274feedSAvi Kivity 0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20, 977b274feedSAvi Kivity 0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21, 978b274feedSAvi Kivity 0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22, 979b274feedSAvi Kivity 0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23, 980b274feedSAvi Kivity 0x06002424, 0x8301c424, 0x16101e24, 0x9711be24, 981b274feedSAvi Kivity 0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25, 982b274feedSAvi Kivity 0x02002626, 0x8701c626, 0x12102026, 0x9711c026, 983b274feedSAvi Kivity 0x06002727, 0x8301c727, 0x16102127, 0x9311c127, 984b274feedSAvi Kivity 0x06002828, 0x8301c828, 0x16102228, 0x9311c228, 985b274feedSAvi Kivity 0x02002929, 0x8701c929, 0x12102329, 0x9711c329, 986b274feedSAvi Kivity 0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a, 987b274feedSAvi Kivity 0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b, 988b274feedSAvi Kivity 0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c, 989b274feedSAvi Kivity 0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d, 990b274feedSAvi Kivity 0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e, 991b274feedSAvi Kivity 0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f, 992b274feedSAvi Kivity 0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30, 993b274feedSAvi Kivity 0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31, 994b274feedSAvi Kivity 0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32, 995b274feedSAvi Kivity 0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33, 996b274feedSAvi Kivity 0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34, 997b274feedSAvi Kivity 0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35, 998b274feedSAvi Kivity 0x06003636, 0x8301d636, 0x16103036, 0x9311d036, 999b274feedSAvi Kivity 0x02003737, 0x8701d737, 0x12103137, 0x9711d137, 1000b274feedSAvi Kivity 0x02003838, 0x8701d838, 0x12103238, 0x9711d238, 1001b274feedSAvi Kivity 0x06003939, 0x8301d939, 0x16103339, 0x9311d339, 1002b274feedSAvi Kivity 0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a, 1003b274feedSAvi Kivity 0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b, 1004b274feedSAvi Kivity 0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c, 1005b274feedSAvi Kivity 0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d, 1006b274feedSAvi Kivity 0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e, 1007b274feedSAvi Kivity 0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f, 1008b274feedSAvi Kivity 0x02004040, 0x8301e040, 0x16103a40, 0x9311da40, 1009b274feedSAvi Kivity 0x06004141, 0x8701e141, 0x12103b41, 0x9711db41, 1010b274feedSAvi Kivity 0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42, 1011b274feedSAvi Kivity 0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43, 1012b274feedSAvi Kivity 0x06004444, 0x8701e444, 0x12103e44, 0x9711de44, 1013b274feedSAvi Kivity 0x02004545, 0x8301e545, 0x16103f45, 0x9311df45, 1014b274feedSAvi Kivity 0x02004646, 0x8301e646, 0x12104046, 0x9311e046, 1015b274feedSAvi Kivity 0x06004747, 0x8701e747, 0x16104147, 0x9711e147, 1016b274feedSAvi Kivity 0x06004848, 0x8701e848, 0x16104248, 0x9711e248, 1017b274feedSAvi Kivity 0x02004949, 0x8301e949, 0x12104349, 0x9311e349, 1018b274feedSAvi Kivity 0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a, 1019b274feedSAvi Kivity 0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b, 1020b274feedSAvi Kivity 0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c, 1021b274feedSAvi Kivity 0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d, 1022b274feedSAvi Kivity 0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e, 1023b274feedSAvi Kivity 0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f, 1024b274feedSAvi Kivity 0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50, 1025b274feedSAvi Kivity 0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51, 1026b274feedSAvi Kivity 0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52, 1027b274feedSAvi Kivity 0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53, 1028b274feedSAvi Kivity 0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54, 1029b274feedSAvi Kivity 0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55, 1030b274feedSAvi Kivity 0x06005656, 0x8701f656, 0x16105056, 0x9711f056, 1031b274feedSAvi Kivity 0x02005757, 0x8301f757, 0x12105157, 0x9311f157, 1032b274feedSAvi Kivity 0x02005858, 0x8301f858, 0x12105258, 0x9311f258, 1033b274feedSAvi Kivity 0x06005959, 0x8701f959, 0x16105359, 0x9711f359, 1034b274feedSAvi Kivity 0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a, 1035b274feedSAvi Kivity 0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b, 1036b274feedSAvi Kivity 0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c, 1037b274feedSAvi Kivity 0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d, 1038b274feedSAvi Kivity 0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e, 1039b274feedSAvi Kivity 0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f, 1040b274feedSAvi Kivity 0x06006060, 0x47010060, 0x16105a60, 0x9711fa60, 1041b274feedSAvi Kivity 0x02006161, 0x03010161, 0x12105b61, 0x9311fb61, 1042b274feedSAvi Kivity 0x02006262, 0x03010262, 0x16105c62, 0x9711fc62, 1043b274feedSAvi Kivity 0x06006363, 0x07010363, 0x12105d63, 0x9311fd63, 1044b274feedSAvi Kivity 0x02006464, 0x03010464, 0x12105e64, 0x9311fe64, 1045b274feedSAvi Kivity 0x06006565, 0x07010565, 0x16105f65, 0x9711ff65, 1046b274feedSAvi Kivity 0x06006666, 0x07010666, 0x16106066, 0x57110066, 1047b274feedSAvi Kivity 0x02006767, 0x03010767, 0x12106167, 0x13110167, 1048b274feedSAvi Kivity 0x02006868, 0x03010868, 0x12106268, 0x13110268, 1049b274feedSAvi Kivity 0x06006969, 0x07010969, 0x16106369, 0x17110369, 1050b274feedSAvi Kivity 0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a, 1051b274feedSAvi Kivity 0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b, 1052b274feedSAvi Kivity 0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c, 1053b274feedSAvi Kivity 0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d, 1054b274feedSAvi Kivity 0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e, 1055b274feedSAvi Kivity 0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f, 1056b274feedSAvi Kivity 0x02007070, 0x03011070, 0x16106a70, 0x17110a70, 1057b274feedSAvi Kivity 0x06007171, 0x07011171, 0x12106b71, 0x13110b71, 1058b274feedSAvi Kivity 0x06007272, 0x07011272, 0x16106c72, 0x17110c72, 1059b274feedSAvi Kivity 0x02007373, 0x03011373, 0x12106d73, 0x13110d73, 1060b274feedSAvi Kivity 0x06007474, 0x07011474, 0x12106e74, 0x13110e74, 1061b274feedSAvi Kivity 0x02007575, 0x03011575, 0x16106f75, 0x17110f75, 1062b274feedSAvi Kivity 0x02007676, 0x03011676, 0x12107076, 0x13111076, 1063b274feedSAvi Kivity 0x06007777, 0x07011777, 0x16107177, 0x17111177, 1064b274feedSAvi Kivity 0x06007878, 0x07011878, 0x16107278, 0x17111278, 1065b274feedSAvi Kivity 0x02007979, 0x03011979, 0x12107379, 0x13111379, 1066b274feedSAvi Kivity 0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a, 1067b274feedSAvi Kivity 0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b, 1068b274feedSAvi Kivity 0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c, 1069b274feedSAvi Kivity 0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d, 1070b274feedSAvi Kivity 0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e, 1071b274feedSAvi Kivity 0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f, 1072b274feedSAvi Kivity 0x82008080, 0x03012080, 0x12107a80, 0x13111a80, 1073b274feedSAvi Kivity 0x86008181, 0x07012181, 0x16107b81, 0x17111b81, 1074b274feedSAvi Kivity 0x86008282, 0x07012282, 0x12107c82, 0x13111c82, 1075b274feedSAvi Kivity 0x82008383, 0x03012383, 0x16107d83, 0x17111d83, 1076b274feedSAvi Kivity 0x86008484, 0x07012484, 0x16107e84, 0x17111e84, 1077b274feedSAvi Kivity 0x82008585, 0x03012585, 0x12107f85, 0x13111f85, 1078b274feedSAvi Kivity 0x82008686, 0x03012686, 0x92108086, 0x13112086, 1079b274feedSAvi Kivity 0x86008787, 0x07012787, 0x96108187, 0x17112187, 1080b274feedSAvi Kivity 0x86008888, 0x07012888, 0x96108288, 0x17112288, 1081b274feedSAvi Kivity 0x82008989, 0x03012989, 0x92108389, 0x13112389, 1082b274feedSAvi Kivity 0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a, 1083b274feedSAvi Kivity 0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b, 1084b274feedSAvi Kivity 0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c, 1085b274feedSAvi Kivity 0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d, 1086b274feedSAvi Kivity 0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e, 1087b274feedSAvi Kivity 0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f, 1088b274feedSAvi Kivity 0x86009090, 0x07013090, 0x92108a90, 0x13112a90, 1089b274feedSAvi Kivity 0x82009191, 0x03013191, 0x96108b91, 0x17112b91, 1090b274feedSAvi Kivity 0x82009292, 0x03013292, 0x92108c92, 0x13112c92, 1091b274feedSAvi Kivity 0x86009393, 0x07013393, 0x96108d93, 0x17112d93, 1092b274feedSAvi Kivity 0x82009494, 0x03013494, 0x96108e94, 0x17112e94, 1093b274feedSAvi Kivity 0x86009595, 0x07013595, 0x92108f95, 0x13112f95, 1094b274feedSAvi Kivity 0x86009696, 0x07013696, 0x96109096, 0x17113096, 1095b274feedSAvi Kivity 0x82009797, 0x03013797, 0x92109197, 0x13113197, 1096b274feedSAvi Kivity 0x82009898, 0x03013898, 0x92109298, 0x13113298, 1097b274feedSAvi Kivity 0x86009999, 0x07013999, 0x96109399, 0x17113399, 1098b274feedSAvi Kivity 0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a, 1099b274feedSAvi Kivity 0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b, 1100b274feedSAvi Kivity 0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c, 1101b274feedSAvi Kivity 0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d, 1102b274feedSAvi Kivity 0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e, 1103b274feedSAvi Kivity 0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f, 1104b274feedSAvi Kivity 0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0, 1105b274feedSAvi Kivity 0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1, 1106b274feedSAvi Kivity 0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2, 1107b274feedSAvi Kivity 0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3, 1108b274feedSAvi Kivity 0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4, 1109b274feedSAvi Kivity 0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5, 1110b274feedSAvi Kivity 0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6, 1111b274feedSAvi Kivity 0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7, 1112b274feedSAvi Kivity 0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8, 1113b274feedSAvi Kivity 0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9, 1114b274feedSAvi Kivity 0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa, 1115b274feedSAvi Kivity 0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab, 1116b274feedSAvi Kivity 0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac, 1117b274feedSAvi Kivity 0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad, 1118b274feedSAvi Kivity 0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae, 1119b274feedSAvi Kivity 0x130049af, 0x130149af, 0x131049af, 0x131149af, 1120b274feedSAvi Kivity 0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0, 1121b274feedSAvi Kivity 0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1, 1122b274feedSAvi Kivity 0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2, 1123b274feedSAvi Kivity 0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3, 1124b274feedSAvi Kivity 0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4, 1125b274feedSAvi Kivity 0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5, 1126b274feedSAvi Kivity 0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6, 1127b274feedSAvi Kivity 0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7, 1128b274feedSAvi Kivity 0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8, 1129b274feedSAvi Kivity 0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9, 1130b274feedSAvi Kivity 0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba, 1131b274feedSAvi Kivity 0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb, 1132b274feedSAvi Kivity 0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc, 1133b274feedSAvi Kivity 0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd, 1134b274feedSAvi Kivity 0x130058be, 0x130158be, 0x131058be, 0x131158be, 1135b274feedSAvi Kivity 0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf, 1136b274feedSAvi Kivity 0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0, 1137b274feedSAvi Kivity 0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1, 1138b274feedSAvi Kivity 0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2, 1139b274feedSAvi Kivity 0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3, 1140b274feedSAvi Kivity 0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4, 1141b274feedSAvi Kivity 0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5, 1142b274feedSAvi Kivity 0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6, 1143b274feedSAvi Kivity 0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7, 1144b274feedSAvi Kivity 0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8, 1145b274feedSAvi Kivity 0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9, 1146b274feedSAvi Kivity 0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca, 1147b274feedSAvi Kivity 0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb, 1148b274feedSAvi Kivity 0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc, 1149b274feedSAvi Kivity 0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd, 1150b274feedSAvi Kivity 0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce, 1151b274feedSAvi Kivity 0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf, 1152b274feedSAvi Kivity 0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0, 1153b274feedSAvi Kivity 0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1, 1154b274feedSAvi Kivity 0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2, 1155b274feedSAvi Kivity 0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3, 1156b274feedSAvi Kivity 0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4, 1157b274feedSAvi Kivity 0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5, 1158b274feedSAvi Kivity 0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6, 1159b274feedSAvi Kivity 0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7, 1160b274feedSAvi Kivity 0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8, 1161b274feedSAvi Kivity 0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9, 1162b274feedSAvi Kivity 0x170074da, 0x170174da, 0x171074da, 0x171174da, 1163b274feedSAvi Kivity 0x130075db, 0x130175db, 0x131075db, 0x131175db, 1164b274feedSAvi Kivity 0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc, 1165b274feedSAvi Kivity 0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd, 1166b274feedSAvi Kivity 0x170078de, 0x170178de, 0x171078de, 0x171178de, 1167b274feedSAvi Kivity 0x130079df, 0x130179df, 0x131079df, 0x131179df, 1168b274feedSAvi Kivity 0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0, 1169b274feedSAvi Kivity 0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1, 1170b274feedSAvi Kivity 0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2, 1171b274feedSAvi Kivity 0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3, 1172b274feedSAvi Kivity 0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4, 1173b274feedSAvi Kivity 0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5, 1174b274feedSAvi Kivity 0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6, 1175b274feedSAvi Kivity 0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7, 1176b274feedSAvi Kivity 0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8, 1177b274feedSAvi Kivity 0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9, 1178b274feedSAvi Kivity 0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea, 1179b274feedSAvi Kivity 0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb, 1180b274feedSAvi Kivity 0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec, 1181b274feedSAvi Kivity 0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed, 1182b274feedSAvi Kivity 0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee, 1183b274feedSAvi Kivity 0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef, 1184b274feedSAvi Kivity 0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0, 1185b274feedSAvi Kivity 0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1, 1186b274feedSAvi Kivity 0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2, 1187b274feedSAvi Kivity 0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3, 1188b274feedSAvi Kivity 0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4, 1189b274feedSAvi Kivity 0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5, 1190b274feedSAvi Kivity 0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6, 1191b274feedSAvi Kivity 0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7, 1192b274feedSAvi Kivity 0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8, 1193b274feedSAvi Kivity 0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9, 1194b274feedSAvi Kivity 0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa, 1195b274feedSAvi Kivity 0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb, 1196b274feedSAvi Kivity 0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc, 1197b274feedSAvi Kivity 0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd, 1198b274feedSAvi Kivity 0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe, 1199b274feedSAvi Kivity 0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff, 1200b274feedSAvi Kivity }; 1201b274feedSAvi Kivity 1202b274feedSAvi Kivity MK_INSN(das, "das"); 1203b274feedSAvi Kivity 1204*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 1205*18253fdeSAvi Kivity 1206b274feedSAvi Kivity for (i = 0; i < 1024; ++i) { 1207b274feedSAvi Kivity unsigned tmp = test_cases[i]; 1208b274feedSAvi Kivity inregs.eax = tmp & 0xff; 1209b274feedSAvi Kivity inregs.eflags = (tmp >> 16) & 0xff; 1210*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_das); 1211*18253fdeSAvi Kivity if (!regs_equal(R_AX) 1212b274feedSAvi Kivity || outregs.eax != ((tmp >> 8) & 0xff) 1213b274feedSAvi Kivity || (outregs.eflags & 0xff) != (tmp >> 24)) { 121481050840SAvi Kivity ++nr_fail; 121581050840SAvi Kivity break; 1216b274feedSAvi Kivity } 1217b274feedSAvi Kivity } 121881050840SAvi Kivity report("DAS", nr_fail == 0); 1219b274feedSAvi Kivity } 1220b274feedSAvi Kivity 12210cbd5b06SMohammed Gamal void test_cwd_cdq() 12220cbd5b06SMohammed Gamal { 12230cbd5b06SMohammed Gamal /* Sign-bit set */ 12240cbd5b06SMohammed Gamal MK_INSN(cwd_1, "mov $0x8000, %ax\n\t" 12250cbd5b06SMohammed Gamal "cwd\n\t"); 12260cbd5b06SMohammed Gamal 12270cbd5b06SMohammed Gamal /* Sign-bit not set */ 12280cbd5b06SMohammed Gamal MK_INSN(cwd_2, "mov $0x1000, %ax\n\t" 12290cbd5b06SMohammed Gamal "cwd\n\t"); 12300cbd5b06SMohammed Gamal 12310cbd5b06SMohammed Gamal /* Sign-bit set */ 12320cbd5b06SMohammed Gamal MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t" 12330cbd5b06SMohammed Gamal "cdq\n\t"); 12340cbd5b06SMohammed Gamal 12350cbd5b06SMohammed Gamal /* Sign-bit not set */ 12360cbd5b06SMohammed Gamal MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t" 12370cbd5b06SMohammed Gamal "cdq\n\t"); 12380cbd5b06SMohammed Gamal 1239*18253fdeSAvi Kivity inregs = (struct regs){ 0 }; 1240*18253fdeSAvi Kivity 1241*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwd_1); 124281050840SAvi Kivity report("cwd 1", 1243*18253fdeSAvi Kivity regs_equal(R_AX | R_DX) 124481050840SAvi Kivity && outregs.eax == 0x8000 && outregs.edx == 0xffff); 12450cbd5b06SMohammed Gamal 1246*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwd_2); 124781050840SAvi Kivity report("cwd 2", 1248*18253fdeSAvi Kivity regs_equal(R_AX | R_DX) 124981050840SAvi Kivity && outregs.eax == 0x1000 && outregs.edx == 0); 12500cbd5b06SMohammed Gamal 1251*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_cdq_1); 125281050840SAvi Kivity report("cdq 1", 1253*18253fdeSAvi Kivity regs_equal(R_AX | R_DX) 125481050840SAvi Kivity && outregs.eax == 0x80000000 && outregs.edx == 0xffffffff); 12550cbd5b06SMohammed Gamal 1256*18253fdeSAvi Kivity exec_in_big_real_mode(&insn_cdq_2); 125781050840SAvi Kivity report("cdq 2", 1258*18253fdeSAvi Kivity regs_equal(R_AX | R_DX) 125981050840SAvi Kivity && outregs.eax == 0x10000000 && outregs.edx == 0); 12600cbd5b06SMohammed Gamal } 12610cbd5b06SMohammed Gamal 12627d36db35SAvi Kivity void realmode_start(void) 12637d36db35SAvi Kivity { 12647d36db35SAvi Kivity test_null(); 12657d36db35SAvi Kivity 12667d36db35SAvi Kivity test_shld(); 12677d36db35SAvi Kivity test_push_pop(); 12687d36db35SAvi Kivity test_pusha_popa(); 12697d36db35SAvi Kivity test_mov_imm(); 12707d36db35SAvi Kivity test_cmp_imm(); 12717d36db35SAvi Kivity test_add_imm(); 12727d36db35SAvi Kivity test_sub_imm(); 12737d36db35SAvi Kivity test_xor_imm(); 12747d36db35SAvi Kivity test_io(); 12757d36db35SAvi Kivity test_eflags_insn(); 12767d36db35SAvi Kivity test_jcc_short(); 12777d36db35SAvi Kivity test_jcc_near(); 12787d36db35SAvi Kivity /* test_call() uses short jump so call it after testing jcc */ 12797d36db35SAvi Kivity test_call(); 12807d36db35SAvi Kivity /* long jmp test uses call near so test it after testing call */ 12817d36db35SAvi Kivity test_long_jmp(); 12827d36db35SAvi Kivity test_xchg(); 12837d36db35SAvi Kivity test_iret(); 128496b9ca1eSMohammed Gamal test_int(); 1285fa74f8a6SMohammed Gamal test_imul(); 128659317bd1SMohammed Gamal test_mul(); 12870d4c7614SMohammed Gamal test_div(); 12880d4c7614SMohammed Gamal test_idiv(); 1289eacef4e2SWei Yongjun test_loopcc(); 12906e293cf5SWei Yongjun test_cbw(); 12910cbd5b06SMohammed Gamal test_cwd_cdq(); 1292b274feedSAvi Kivity test_das(); 12937d36db35SAvi Kivity 12947d36db35SAvi Kivity exit(0); 12957d36db35SAvi Kivity } 12967d36db35SAvi Kivity 12977d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff }; 12987d36db35SAvi Kivity 12997d36db35SAvi Kivity struct __attribute__((packed)) { 13007d36db35SAvi Kivity unsigned short limit; 13017d36db35SAvi Kivity void *base; 13027d36db35SAvi Kivity } r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt }; 13037d36db35SAvi Kivity 13047d36db35SAvi Kivity asm( 13057d36db35SAvi Kivity ".section .init \n\t" 13067d36db35SAvi Kivity 13077d36db35SAvi Kivity ".code32 \n\t" 13087d36db35SAvi Kivity 13097d36db35SAvi Kivity "mb_magic = 0x1BADB002 \n\t" 13107d36db35SAvi Kivity "mb_flags = 0x0 \n\t" 13117d36db35SAvi Kivity 13127d36db35SAvi Kivity "# multiboot header \n\t" 13137d36db35SAvi Kivity ".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t" 13147d36db35SAvi Kivity 13157d36db35SAvi Kivity ".globl start \n\t" 13167d36db35SAvi Kivity ".data \n\t" 13177d36db35SAvi Kivity ". = . + 4096 \n\t" 13187d36db35SAvi Kivity "stacktop: \n\t" 13197d36db35SAvi Kivity 13207d36db35SAvi Kivity ".text \n\t" 13217d36db35SAvi Kivity "start: \n\t" 13227d36db35SAvi Kivity "lgdt r_gdt_descr \n\t" 13237d36db35SAvi Kivity "ljmp $8, $1f; 1: \n\t" 13247d36db35SAvi Kivity ".code16gcc \n\t" 13257d36db35SAvi Kivity "mov $16, %eax \n\t" 13267d36db35SAvi Kivity "mov %ax, %ds \n\t" 13277d36db35SAvi Kivity "mov %ax, %es \n\t" 13287d36db35SAvi Kivity "mov %ax, %fs \n\t" 13297d36db35SAvi Kivity "mov %ax, %gs \n\t" 13307d36db35SAvi Kivity "mov %ax, %ss \n\t" 13317d36db35SAvi Kivity "mov %cr0, %eax \n\t" 13327d36db35SAvi Kivity "btc $0, %eax \n\t" 13337d36db35SAvi Kivity "mov %eax, %cr0 \n\t" 13347d36db35SAvi Kivity "ljmp $0, $realmode_entry \n\t" 13357d36db35SAvi Kivity 13367d36db35SAvi Kivity "realmode_entry: \n\t" 13377d36db35SAvi Kivity 13387d36db35SAvi Kivity "xor %ax, %ax \n\t" 13397d36db35SAvi Kivity "mov %ax, %ds \n\t" 13407d36db35SAvi Kivity "mov %ax, %es \n\t" 13417d36db35SAvi Kivity "mov %ax, %ss \n\t" 13427d36db35SAvi Kivity "mov %ax, %fs \n\t" 13437d36db35SAvi Kivity "mov %ax, %gs \n\t" 13447d36db35SAvi Kivity "mov $stacktop, %esp\n\t" 13457d36db35SAvi Kivity "ljmp $0, $realmode_start \n\t" 13467d36db35SAvi Kivity 13477d36db35SAvi Kivity ".code16gcc \n\t" 13487d36db35SAvi Kivity ); 1349