1f366255fSPaolo Bonzini #ifndef USE_SERIAL 2f366255fSPaolo Bonzini #define USE_SERIAL 3f366255fSPaolo Bonzini #endif 4f366255fSPaolo Bonzini 547086996SBill Wendling #define ARRAY_SIZE(_a) (sizeof(_a)/sizeof((_a)[0])) 647086996SBill Wendling 77d36db35SAvi Kivity asm(".code16gcc"); 87d36db35SAvi Kivity 97d36db35SAvi Kivity typedef unsigned char u8; 107d36db35SAvi Kivity typedef unsigned short u16; 117d36db35SAvi Kivity typedef unsigned u32; 127d36db35SAvi Kivity typedef unsigned long long u64; 137d36db35SAvi Kivity 14bd62e289SBill Wendling #ifndef NULL 15bd62e289SBill Wendling #define NULL ((void*)0) 16bd62e289SBill Wendling #endif 17bd62e289SBill Wendling 182e3f9f1fSThomas Huth void realmode_start(void); 197d36db35SAvi Kivity void test_function(void); 207d36db35SAvi Kivity 217d36db35SAvi Kivity asm( 227d36db35SAvi Kivity "test_function: \n\t" 237d36db35SAvi Kivity "mov $0x1234, %eax \n\t" 247d36db35SAvi Kivity "ret" 257d36db35SAvi Kivity ); 267d36db35SAvi Kivity 277d36db35SAvi Kivity static int strlen(const char *str) 287d36db35SAvi Kivity { 297d36db35SAvi Kivity int n; 307d36db35SAvi Kivity 317d36db35SAvi Kivity for (n = 0; *str; ++str) 327d36db35SAvi Kivity ++n; 337d36db35SAvi Kivity return n; 347d36db35SAvi Kivity } 357d36db35SAvi Kivity 36f366255fSPaolo Bonzini static void outb(u8 data, u16 port) 37f366255fSPaolo Bonzini { 38f366255fSPaolo Bonzini asm volatile("out %0, %1" : : "a"(data), "d"(port)); 39f366255fSPaolo Bonzini } 40f366255fSPaolo Bonzini 41f366255fSPaolo Bonzini #ifdef USE_SERIAL 42f366255fSPaolo Bonzini static int serial_iobase = 0x3f8; 43f366255fSPaolo Bonzini static int serial_inited = 0; 44f366255fSPaolo Bonzini 45f366255fSPaolo Bonzini static u8 inb(u16 port) 46f366255fSPaolo Bonzini { 47f366255fSPaolo Bonzini u8 data; 48f366255fSPaolo Bonzini asm volatile("in %1, %0" : "=a"(data) : "d"(port)); 49f366255fSPaolo Bonzini return data; 50f366255fSPaolo Bonzini } 51f366255fSPaolo Bonzini 52f366255fSPaolo Bonzini static void serial_outb(char ch) 53f366255fSPaolo Bonzini { 54f366255fSPaolo Bonzini u8 lsr; 55f366255fSPaolo Bonzini 56f366255fSPaolo Bonzini do { 57f366255fSPaolo Bonzini lsr = inb(serial_iobase + 0x05); 58f366255fSPaolo Bonzini } while (!(lsr & 0x20)); 59f366255fSPaolo Bonzini 60f366255fSPaolo Bonzini outb(ch, serial_iobase + 0x00); 61f366255fSPaolo Bonzini } 62f366255fSPaolo Bonzini 63f366255fSPaolo Bonzini static void serial_init(void) 64f366255fSPaolo Bonzini { 65f366255fSPaolo Bonzini u8 lcr; 66f366255fSPaolo Bonzini 67f366255fSPaolo Bonzini /* set DLAB */ 68f366255fSPaolo Bonzini lcr = inb(serial_iobase + 0x03); 69f366255fSPaolo Bonzini lcr |= 0x80; 70f366255fSPaolo Bonzini outb(lcr, serial_iobase + 0x03); 71f366255fSPaolo Bonzini 72f366255fSPaolo Bonzini /* set baud rate to 115200 */ 73f366255fSPaolo Bonzini outb(0x01, serial_iobase + 0x00); 74f366255fSPaolo Bonzini outb(0x00, serial_iobase + 0x01); 75f366255fSPaolo Bonzini 76f366255fSPaolo Bonzini /* clear DLAB */ 77f366255fSPaolo Bonzini lcr = inb(serial_iobase + 0x03); 78f366255fSPaolo Bonzini lcr &= ~0x80; 79f366255fSPaolo Bonzini outb(lcr, serial_iobase + 0x03); 80f366255fSPaolo Bonzini } 81f366255fSPaolo Bonzini #endif 82f366255fSPaolo Bonzini 837d36db35SAvi Kivity static void print_serial(const char *buf) 847d36db35SAvi Kivity { 857d36db35SAvi Kivity unsigned long len = strlen(buf); 86f366255fSPaolo Bonzini #ifdef USE_SERIAL 87f366255fSPaolo Bonzini unsigned long i; 88f366255fSPaolo Bonzini if (!serial_inited) { 89f366255fSPaolo Bonzini serial_init(); 90f366255fSPaolo Bonzini serial_inited = 1; 91f366255fSPaolo Bonzini } 927d36db35SAvi Kivity 93f366255fSPaolo Bonzini for (i = 0; i < len; i++) { 94f366255fSPaolo Bonzini serial_outb(buf[i]); 95f366255fSPaolo Bonzini } 96f366255fSPaolo Bonzini #else 975edbb9aeSPaolo Bonzini asm volatile ("addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1)); 98f366255fSPaolo Bonzini #endif 997d36db35SAvi Kivity } 1007d36db35SAvi Kivity 101b5105e8bSPaolo Bonzini static void print_serial_u32(u32 value) 102b5105e8bSPaolo Bonzini { 103b5105e8bSPaolo Bonzini char n[12], *p; 104b5105e8bSPaolo Bonzini p = &n[11]; 105b5105e8bSPaolo Bonzini *p = 0; 106b5105e8bSPaolo Bonzini do { 107b5105e8bSPaolo Bonzini *--p = '0' + (value % 10); 108b5105e8bSPaolo Bonzini value /= 10; 109b5105e8bSPaolo Bonzini } while (value > 0); 110b5105e8bSPaolo Bonzini print_serial(p); 111b5105e8bSPaolo Bonzini } 112b5105e8bSPaolo Bonzini 113b393fe28SNadav Amit static int failed; 114b393fe28SNadav Amit 1157d36db35SAvi Kivity static void exit(int code) 1167d36db35SAvi Kivity { 117f366255fSPaolo Bonzini outb(code, 0xf4); 1183b9b2d55SNadav Amit 1193b9b2d55SNadav Amit while (1) { 1203b9b2d55SNadav Amit asm volatile("hlt" ::: "memory"); 1213b9b2d55SNadav Amit } 1227d36db35SAvi Kivity } 1237d36db35SAvi Kivity 1247d36db35SAvi Kivity struct regs { 1257d36db35SAvi Kivity u32 eax, ebx, ecx, edx; 1267d36db35SAvi Kivity u32 esi, edi, esp, ebp; 1277d36db35SAvi Kivity u32 eip, eflags; 1287d36db35SAvi Kivity }; 1297d36db35SAvi Kivity 130975ca087SPeter Feiner struct table_descr { 131975ca087SPeter Feiner u16 limit; 132975ca087SPeter Feiner void *base; 133975ca087SPeter Feiner } __attribute__((packed)); 134975ca087SPeter Feiner 1357d36db35SAvi Kivity static u64 gdt[] = { 1367d36db35SAvi Kivity 0, 1377d36db35SAvi Kivity 0x00cf9b000000ffffull, // flat 32-bit code segment 1387d36db35SAvi Kivity 0x00cf93000000ffffull, // flat 32-bit data segment 1397d36db35SAvi Kivity }; 1407d36db35SAvi Kivity 141975ca087SPeter Feiner static struct table_descr gdt_descr = { 1427d36db35SAvi Kivity sizeof(gdt) - 1, 1437d36db35SAvi Kivity gdt, 1447d36db35SAvi Kivity }; 1457d36db35SAvi Kivity 146d4dc402cSAvi Kivity struct insn_desc { 147d4dc402cSAvi Kivity u16 ptr; 148d4dc402cSAvi Kivity u16 len; 149d4dc402cSAvi Kivity }; 150d4dc402cSAvi Kivity 151bd62e289SBill Wendling struct { 152bd62e289SBill Wendling u32 stack[128]; 153bd62e289SBill Wendling char top[]; 154bd62e289SBill Wendling } tmp_stack; 155bd62e289SBill Wendling 15618253fdeSAvi Kivity static struct regs inregs, outregs; 15718253fdeSAvi Kivity 158bd62e289SBill Wendling static inline void init_inregs(struct regs *regs) 159bd62e289SBill Wendling { 160bd62e289SBill Wendling inregs = (struct regs){ 0 }; 161bd62e289SBill Wendling if (regs) 162bd62e289SBill Wendling inregs = *regs; 163bd62e289SBill Wendling if (!inregs.esp) 164bd62e289SBill Wendling inregs.esp = (unsigned long)&tmp_stack.top; 165bd62e289SBill Wendling } 166bd62e289SBill Wendling 16718253fdeSAvi Kivity static void exec_in_big_real_mode(struct insn_desc *insn) 1687d36db35SAvi Kivity { 1697d36db35SAvi Kivity unsigned long tmp; 1707d36db35SAvi Kivity static struct regs save; 1717d36db35SAvi Kivity int i; 1727d36db35SAvi Kivity extern u8 test_insn[], test_insn_end[]; 1737d36db35SAvi Kivity 174d4dc402cSAvi Kivity for (i = 0; i < insn->len; ++i) 175d4dc402cSAvi Kivity test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i]; 1767d36db35SAvi Kivity for (; i < test_insn_end - test_insn; ++i) 1777d36db35SAvi Kivity test_insn[i] = 0x90; // nop 1787d36db35SAvi Kivity 17918253fdeSAvi Kivity save = inregs; 1807d36db35SAvi Kivity asm volatile( 1817d36db35SAvi Kivity "lgdtl %[gdt_descr] \n\t" 1827d36db35SAvi Kivity "mov %%cr0, %[tmp] \n\t" 1837d36db35SAvi Kivity "or $1, %[tmp] \n\t" 1847d36db35SAvi Kivity "mov %[tmp], %%cr0 \n\t" 1857d36db35SAvi Kivity "mov %[bigseg], %%gs \n\t" 1867d36db35SAvi Kivity "and $-2, %[tmp] \n\t" 1877d36db35SAvi Kivity "mov %[tmp], %%cr0 \n\t" 1887d36db35SAvi Kivity 189eb6687a2SBill Wendling /* Save ES, because it is clobbered by some tests. */ 190eb6687a2SBill Wendling "pushw %%es \n\t" 191eb6687a2SBill Wendling 19232001692SAvi Kivity "pushw %[save]+36; popfw \n\t" 1937d36db35SAvi Kivity "xchg %%eax, %[save]+0 \n\t" 1947d36db35SAvi Kivity "xchg %%ebx, %[save]+4 \n\t" 1957d36db35SAvi Kivity "xchg %%ecx, %[save]+8 \n\t" 1967d36db35SAvi Kivity "xchg %%edx, %[save]+12 \n\t" 1977d36db35SAvi Kivity "xchg %%esi, %[save]+16 \n\t" 1987d36db35SAvi Kivity "xchg %%edi, %[save]+20 \n\t" 1997d36db35SAvi Kivity "xchg %%esp, %[save]+24 \n\t" 2007d36db35SAvi Kivity "xchg %%ebp, %[save]+28 \n\t" 2017d36db35SAvi Kivity 2027d36db35SAvi Kivity "test_insn: . = . + 32\n\t" 2037d36db35SAvi Kivity "test_insn_end: \n\t" 2047d36db35SAvi Kivity 2057d36db35SAvi Kivity "xchg %%eax, %[save]+0 \n\t" 2067d36db35SAvi Kivity "xchg %%ebx, %[save]+4 \n\t" 2077d36db35SAvi Kivity "xchg %%ecx, %[save]+8 \n\t" 2087d36db35SAvi Kivity "xchg %%edx, %[save]+12 \n\t" 2097d36db35SAvi Kivity "xchg %%esi, %[save]+16 \n\t" 2107d36db35SAvi Kivity "xchg %%edi, %[save]+20 \n\t" 2117d36db35SAvi Kivity "xchg %%esp, %[save]+24 \n\t" 2127d36db35SAvi Kivity "xchg %%ebp, %[save]+28 \n\t" 2137d36db35SAvi Kivity 2147d36db35SAvi Kivity /* Save EFLAGS in outregs*/ 2157d36db35SAvi Kivity "pushfl \n\t" 2167d36db35SAvi Kivity "popl %[save]+36 \n\t" 2177d36db35SAvi Kivity 218eb6687a2SBill Wendling /* Restore ES for future rep string operations. */ 219eb6687a2SBill Wendling "popw %%es \n\t" 220eb6687a2SBill Wendling 2215edbb9aeSPaolo Bonzini /* Restore DF for the harness code */ 2225edbb9aeSPaolo Bonzini "cld\n\t" 2237d36db35SAvi Kivity "xor %[tmp], %[tmp] \n\t" 2247d36db35SAvi Kivity "mov %[tmp], %%gs \n\t" 2257d36db35SAvi Kivity : [tmp]"=&r"(tmp), [save]"+m"(save) 2267d36db35SAvi Kivity : [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16) 2277d36db35SAvi Kivity : "cc", "memory" 2287d36db35SAvi Kivity ); 22918253fdeSAvi Kivity outregs = save; 2307d36db35SAvi Kivity } 2317d36db35SAvi Kivity 2327d36db35SAvi Kivity #define R_AX 1 2337d36db35SAvi Kivity #define R_BX 2 2347d36db35SAvi Kivity #define R_CX 4 2357d36db35SAvi Kivity #define R_DX 8 2367d36db35SAvi Kivity #define R_SI 16 2377d36db35SAvi Kivity #define R_DI 32 2387d36db35SAvi Kivity #define R_SP 64 2397d36db35SAvi Kivity #define R_BP 128 2407d36db35SAvi Kivity 2412e3f9f1fSThomas Huth static int regs_equal(int ignore) 2427d36db35SAvi Kivity { 24318253fdeSAvi Kivity const u32 *p1 = &inregs.eax, *p2 = &outregs.eax; // yuck 2447d36db35SAvi Kivity int i; 2457d36db35SAvi Kivity 2467d36db35SAvi Kivity for (i = 0; i < 8; ++i) 2477d36db35SAvi Kivity if (!(ignore & (1 << i)) && p1[i] != p2[i]) 2487d36db35SAvi Kivity return 0; 2497d36db35SAvi Kivity return 1; 2507d36db35SAvi Kivity } 2517d36db35SAvi Kivity 2526055ea1fSAvi Kivity static void report(const char *name, u16 regs_ignore, _Bool ok) 25381050840SAvi Kivity { 2546055ea1fSAvi Kivity if (!regs_equal(regs_ignore)) { 2556055ea1fSAvi Kivity ok = 0; 2566055ea1fSAvi Kivity } 25781050840SAvi Kivity print_serial(ok ? "PASS: " : "FAIL: "); 25881050840SAvi Kivity print_serial(name); 25981050840SAvi Kivity print_serial("\n"); 260b393fe28SNadav Amit if (!ok) 261b393fe28SNadav Amit failed = 1; 26281050840SAvi Kivity } 26381050840SAvi Kivity 2647d36db35SAvi Kivity #define MK_INSN(name, str) \ 2657d36db35SAvi Kivity asm ( \ 266d4dc402cSAvi Kivity ".pushsection .data.insn \n\t" \ 267d4dc402cSAvi Kivity "insn_" #name ": \n\t" \ 268d4dc402cSAvi Kivity ".word 1001f, 1002f - 1001f \n\t" \ 269d4dc402cSAvi Kivity ".popsection \n\t" \ 270d4dc402cSAvi Kivity ".pushsection .text.insn, \"ax\" \n\t" \ 271d4dc402cSAvi Kivity "1001: \n\t" \ 272d4dc402cSAvi Kivity "insn_code_" #name ": " str " \n\t" \ 273d4dc402cSAvi Kivity "1002: \n\t" \ 274d4dc402cSAvi Kivity ".popsection" \ 2757d36db35SAvi Kivity ); \ 276d4dc402cSAvi Kivity extern struct insn_desc insn_##name; 2777d36db35SAvi Kivity 2782e3f9f1fSThomas Huth static void test_xchg(void) 2797d36db35SAvi Kivity { 2807d36db35SAvi Kivity MK_INSN(xchg_test1, "xchg %eax,%eax\n\t"); 2817d36db35SAvi Kivity MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t"); 2827d36db35SAvi Kivity MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t"); 2837d36db35SAvi Kivity MK_INSN(xchg_test4, "xchg %eax,%edx\n\t"); 2847d36db35SAvi Kivity MK_INSN(xchg_test5, "xchg %eax,%esi\n\t"); 2857d36db35SAvi Kivity MK_INSN(xchg_test6, "xchg %eax,%edi\n\t"); 2867d36db35SAvi Kivity MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t"); 2877d36db35SAvi Kivity MK_INSN(xchg_test8, "xchg %eax,%esp\n\t"); 2887d36db35SAvi Kivity 28918253fdeSAvi Kivity inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7}; 2907d36db35SAvi Kivity 29118253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test1); 2926055ea1fSAvi Kivity report("xchg 1", 0, 1); 29318253fdeSAvi Kivity 29418253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test2); 2956055ea1fSAvi Kivity report("xchg 2", R_AX | R_BX, 2966055ea1fSAvi Kivity outregs.eax == inregs.ebx && outregs.ebx == inregs.eax); 2977d36db35SAvi Kivity 29818253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test3); 2996055ea1fSAvi Kivity report("xchg 3", R_AX | R_CX, 3006055ea1fSAvi Kivity outregs.eax == inregs.ecx && outregs.ecx == inregs.eax); 3017d36db35SAvi Kivity 30218253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test4); 3036055ea1fSAvi Kivity report("xchg 4", R_AX | R_DX, 3046055ea1fSAvi Kivity outregs.eax == inregs.edx && outregs.edx == inregs.eax); 3057d36db35SAvi Kivity 30618253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test5); 3076055ea1fSAvi Kivity report("xchg 5", R_AX | R_SI, 3086055ea1fSAvi Kivity outregs.eax == inregs.esi && outregs.esi == inregs.eax); 3097d36db35SAvi Kivity 31018253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test6); 3116055ea1fSAvi Kivity report("xchg 6", R_AX | R_DI, 3126055ea1fSAvi Kivity outregs.eax == inregs.edi && outregs.edi == inregs.eax); 3137d36db35SAvi Kivity 31418253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test7); 3156055ea1fSAvi Kivity report("xchg 7", R_AX | R_BP, 3166055ea1fSAvi Kivity outregs.eax == inregs.ebp && outregs.ebp == inregs.eax); 3177d36db35SAvi Kivity 31818253fdeSAvi Kivity exec_in_big_real_mode(&insn_xchg_test8); 3196055ea1fSAvi Kivity report("xchg 8", R_AX | R_SP, 3206055ea1fSAvi Kivity outregs.eax == inregs.esp && outregs.esp == inregs.eax); 3217d36db35SAvi Kivity } 3227d36db35SAvi Kivity 3232e3f9f1fSThomas Huth static void test_shld(void) 3247d36db35SAvi Kivity { 3257d36db35SAvi Kivity MK_INSN(shld_test, "shld $8,%edx,%eax\n\t"); 3267d36db35SAvi Kivity 327bd62e289SBill Wendling init_inregs(&(struct regs){ .eax = 0xbe, .edx = 0xef000000 }); 328bd62e289SBill Wendling 32918253fdeSAvi Kivity exec_in_big_real_mode(&insn_shld_test); 3306055ea1fSAvi Kivity report("shld", ~0, outregs.eax == 0xbeef); 3317d36db35SAvi Kivity } 3327d36db35SAvi Kivity 3332e3f9f1fSThomas Huth static void test_mov_imm(void) 3347d36db35SAvi Kivity { 3357d36db35SAvi Kivity MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax"); 3367d36db35SAvi Kivity MK_INSN(mov_r16_imm_1, "mov $1234, %ax"); 3377d36db35SAvi Kivity MK_INSN(mov_r8_imm_1, "mov $0x12, %ah"); 3387d36db35SAvi Kivity MK_INSN(mov_r8_imm_2, "mov $0x34, %al"); 3397d36db35SAvi Kivity MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t"); 3407d36db35SAvi Kivity 341bd62e289SBill Wendling init_inregs(NULL); 34218253fdeSAvi Kivity 34318253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r16_imm_1); 3446055ea1fSAvi Kivity report("mov 1", R_AX, outregs.eax == 1234); 3457d36db35SAvi Kivity 3467d36db35SAvi Kivity /* test mov $imm, %eax */ 34718253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r32_imm_1); 3486055ea1fSAvi Kivity report("mov 2", R_AX, outregs.eax == 1234567890); 3497d36db35SAvi Kivity 3507d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 35118253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_1); 3526055ea1fSAvi Kivity report("mov 3", R_AX, outregs.eax == 0x1200); 3537d36db35SAvi Kivity 35418253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_2); 3556055ea1fSAvi Kivity report("mov 4", R_AX, outregs.eax == 0x34); 3567d36db35SAvi Kivity 35718253fdeSAvi Kivity exec_in_big_real_mode(&insn_mov_r8_imm_3); 3586055ea1fSAvi Kivity report("mov 5", R_AX, outregs.eax == 0x1234); 3597d36db35SAvi Kivity } 3607d36db35SAvi Kivity 3612e3f9f1fSThomas Huth static void test_sub_imm(void) 3627d36db35SAvi Kivity { 3637d36db35SAvi Kivity MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t"); 3647d36db35SAvi Kivity MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t"); 3657d36db35SAvi Kivity MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t"); 3667d36db35SAvi Kivity MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t"); 3677d36db35SAvi Kivity 368bd62e289SBill Wendling init_inregs(NULL); 36918253fdeSAvi Kivity 37018253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r16_imm_1); 3716055ea1fSAvi Kivity report("sub 1", R_AX, outregs.eax == 1224); 3727d36db35SAvi Kivity 3737d36db35SAvi Kivity /* test mov $imm, %eax */ 37418253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r32_imm_1); 3756055ea1fSAvi Kivity report("sub 2", R_AX, outregs.eax == 1234567880); 3767d36db35SAvi Kivity 3777d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 37818253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r8_imm_1); 3796055ea1fSAvi Kivity report("sub 3", R_AX, outregs.eax == 0x0200); 3807d36db35SAvi Kivity 38118253fdeSAvi Kivity exec_in_big_real_mode(&insn_sub_r8_imm_2); 3826055ea1fSAvi Kivity report("sub 4", R_AX, outregs.eax == 0x24); 3837d36db35SAvi Kivity } 3847d36db35SAvi Kivity 3852e3f9f1fSThomas Huth static void test_xor_imm(void) 3867d36db35SAvi Kivity { 3877d36db35SAvi Kivity MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t"); 3887d36db35SAvi Kivity MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t"); 3897d36db35SAvi Kivity MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t"); 3907d36db35SAvi Kivity MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t"); 3917d36db35SAvi Kivity 392bd62e289SBill Wendling init_inregs(NULL); 39318253fdeSAvi Kivity 39418253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r16_imm_1); 3956055ea1fSAvi Kivity report("xor 1", R_AX, outregs.eax == 0); 3967d36db35SAvi Kivity 3977d36db35SAvi Kivity /* test mov $imm, %eax */ 39818253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r32_imm_1); 3996055ea1fSAvi Kivity report("xor 2", R_AX, outregs.eax == 0); 4007d36db35SAvi Kivity 4017d36db35SAvi Kivity /* test mov $imm, %al/%ah */ 40218253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r8_imm_1); 4036055ea1fSAvi Kivity report("xor 3", R_AX, outregs.eax == 0); 4047d36db35SAvi Kivity 40518253fdeSAvi Kivity exec_in_big_real_mode(&insn_xor_r8_imm_2); 4066055ea1fSAvi Kivity report("xor 4", R_AX, outregs.eax == 0); 4077d36db35SAvi Kivity } 4087d36db35SAvi Kivity 4092e3f9f1fSThomas Huth static void test_cmp_imm(void) 4107d36db35SAvi Kivity { 4117d36db35SAvi Kivity MK_INSN(cmp_test1, "mov $0x34, %al\n\t" 4127d36db35SAvi Kivity "cmp $0x34, %al\n\t"); 4137d36db35SAvi Kivity MK_INSN(cmp_test2, "mov $0x34, %al\n\t" 4147d36db35SAvi Kivity "cmp $0x39, %al\n\t"); 4157d36db35SAvi Kivity MK_INSN(cmp_test3, "mov $0x34, %al\n\t" 4167d36db35SAvi Kivity "cmp $0x24, %al\n\t"); 4177d36db35SAvi Kivity 418bd62e289SBill Wendling init_inregs(NULL); 41918253fdeSAvi Kivity 4207d36db35SAvi Kivity /* test cmp imm8 with AL */ 4217d36db35SAvi Kivity /* ZF: (bit 6) Zero Flag becomes 1 if an operation results 4227d36db35SAvi Kivity * in a 0 writeback, or 0 register 4237d36db35SAvi Kivity */ 42418253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test1); 4256055ea1fSAvi Kivity report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6)); 4267d36db35SAvi Kivity 42718253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test2); 4286055ea1fSAvi Kivity report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0); 4297d36db35SAvi Kivity 43018253fdeSAvi Kivity exec_in_big_real_mode(&insn_cmp_test3); 4316055ea1fSAvi Kivity report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0); 4327d36db35SAvi Kivity } 4337d36db35SAvi Kivity 4342e3f9f1fSThomas Huth static void test_add_imm(void) 4357d36db35SAvi Kivity { 4367d36db35SAvi Kivity MK_INSN(add_test1, "mov $0x43211234, %eax \n\t" 4377d36db35SAvi Kivity "add $0x12344321, %eax \n\t"); 4387d36db35SAvi Kivity MK_INSN(add_test2, "mov $0x12, %eax \n\t" 4397d36db35SAvi Kivity "add $0x21, %al\n\t"); 4407d36db35SAvi Kivity 441bd62e289SBill Wendling init_inregs(NULL); 44218253fdeSAvi Kivity 44318253fdeSAvi Kivity exec_in_big_real_mode(&insn_add_test1); 4446055ea1fSAvi Kivity report("add 1", ~0, outregs.eax == 0x55555555); 4457d36db35SAvi Kivity 44618253fdeSAvi Kivity exec_in_big_real_mode(&insn_add_test2); 4476055ea1fSAvi Kivity report("add 2", ~0, outregs.eax == 0x33); 4487d36db35SAvi Kivity } 4497d36db35SAvi Kivity 4502e3f9f1fSThomas Huth static void test_eflags_insn(void) 4517d36db35SAvi Kivity { 4527d36db35SAvi Kivity MK_INSN(clc, "clc"); 453b3261e48SMohammed Gamal MK_INSN(stc, "stc"); 4547d36db35SAvi Kivity MK_INSN(cli, "cli"); 4557d36db35SAvi Kivity MK_INSN(sti, "sti"); 4567d36db35SAvi Kivity MK_INSN(cld, "cld"); 4577d36db35SAvi Kivity MK_INSN(std, "std"); 4587d36db35SAvi Kivity 459bd62e289SBill Wendling init_inregs(NULL); 46018253fdeSAvi Kivity 46118253fdeSAvi Kivity exec_in_big_real_mode(&insn_clc); 4626055ea1fSAvi Kivity report("clc", ~0, (outregs.eflags & 1) == 0); 4637d36db35SAvi Kivity 46418253fdeSAvi Kivity exec_in_big_real_mode(&insn_stc); 4656055ea1fSAvi Kivity report("stc", ~0, (outregs.eflags & 1) == 1); 466b3261e48SMohammed Gamal 46718253fdeSAvi Kivity exec_in_big_real_mode(&insn_cli); 4686055ea1fSAvi Kivity report("cli", ~0, !(outregs.eflags & (1 << 9))); 4697d36db35SAvi Kivity 47018253fdeSAvi Kivity exec_in_big_real_mode(&insn_sti); 4716055ea1fSAvi Kivity report("sti", ~0, outregs.eflags & (1 << 9)); 4727d36db35SAvi Kivity 47318253fdeSAvi Kivity exec_in_big_real_mode(&insn_cld); 4746055ea1fSAvi Kivity report("cld", ~0, !(outregs.eflags & (1 << 10))); 4757d36db35SAvi Kivity 47618253fdeSAvi Kivity exec_in_big_real_mode(&insn_std); 4776055ea1fSAvi Kivity report("std", ~0, (outregs.eflags & (1 << 10))); 4787d36db35SAvi Kivity } 4797d36db35SAvi Kivity 4802e3f9f1fSThomas Huth static void test_io(void) 4817d36db35SAvi Kivity { 4827d36db35SAvi Kivity MK_INSN(io_test1, "mov $0xff, %al \n\t" 4837d36db35SAvi Kivity "out %al, $0xe0 \n\t" 4847d36db35SAvi Kivity "mov $0x00, %al \n\t" 4857d36db35SAvi Kivity "in $0xe0, %al \n\t"); 4867d36db35SAvi Kivity MK_INSN(io_test2, "mov $0xffff, %ax \n\t" 4877d36db35SAvi Kivity "out %ax, $0xe0 \n\t" 4887d36db35SAvi Kivity "mov $0x0000, %ax \n\t" 4897d36db35SAvi Kivity "in $0xe0, %ax \n\t"); 4907d36db35SAvi Kivity MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t" 4917d36db35SAvi Kivity "out %eax, $0xe0 \n\t" 4927d36db35SAvi Kivity "mov $0x000000, %eax \n\t" 4937d36db35SAvi Kivity "in $0xe0, %eax \n\t"); 4947d36db35SAvi Kivity MK_INSN(io_test4, "mov $0xe0, %dx \n\t" 4957d36db35SAvi Kivity "mov $0xff, %al \n\t" 4967d36db35SAvi Kivity "out %al, %dx \n\t" 4977d36db35SAvi Kivity "mov $0x00, %al \n\t" 4987d36db35SAvi Kivity "in %dx, %al \n\t"); 4997d36db35SAvi Kivity MK_INSN(io_test5, "mov $0xe0, %dx \n\t" 5007d36db35SAvi Kivity "mov $0xffff, %ax \n\t" 5017d36db35SAvi Kivity "out %ax, %dx \n\t" 5027d36db35SAvi Kivity "mov $0x0000, %ax \n\t" 5037d36db35SAvi Kivity "in %dx, %ax \n\t"); 5047d36db35SAvi Kivity MK_INSN(io_test6, "mov $0xe0, %dx \n\t" 5057d36db35SAvi Kivity "mov $0xffffffff, %eax \n\t" 5067d36db35SAvi Kivity "out %eax, %dx \n\t" 5077d36db35SAvi Kivity "mov $0x00000000, %eax \n\t" 5087d36db35SAvi Kivity "in %dx, %eax \n\t"); 5097d36db35SAvi Kivity 510bd62e289SBill Wendling init_inregs(NULL); 51118253fdeSAvi Kivity 51218253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test1); 5136055ea1fSAvi Kivity report("pio 1", R_AX, outregs.eax == 0xff); 5147d36db35SAvi Kivity 51518253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test2); 5166055ea1fSAvi Kivity report("pio 2", R_AX, outregs.eax == 0xffff); 5177d36db35SAvi Kivity 51818253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test3); 5196055ea1fSAvi Kivity report("pio 3", R_AX, outregs.eax == 0xffffffff); 5207d36db35SAvi Kivity 52118253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test4); 5226055ea1fSAvi Kivity report("pio 4", R_AX|R_DX, outregs.eax == 0xff); 5237d36db35SAvi Kivity 52418253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test5); 5256055ea1fSAvi Kivity report("pio 5", R_AX|R_DX, outregs.eax == 0xffff); 5267d36db35SAvi Kivity 52718253fdeSAvi Kivity exec_in_big_real_mode(&insn_io_test6); 5286055ea1fSAvi Kivity report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff); 5297d36db35SAvi Kivity } 5307d36db35SAvi Kivity 531c0b7268dSAvi Kivity asm ("retf: lretw"); 5322e3f9f1fSThomas Huth extern void retf(void); 533c0b7268dSAvi Kivity 5344f66bc86SBruce Rogers asm ("retf_imm: lretw $10"); 5352e3f9f1fSThomas Huth extern void retf_imm(void); 5364f66bc86SBruce Rogers 5372e3f9f1fSThomas Huth static void test_call(void) 5387d36db35SAvi Kivity { 539c0b7268dSAvi Kivity u32 addr; 5407d36db35SAvi Kivity 5417d36db35SAvi Kivity MK_INSN(call1, "mov $test_function, %eax \n\t" 5427d36db35SAvi Kivity "call *%eax\n\t"); 5437d36db35SAvi Kivity MK_INSN(call_near1, "jmp 2f\n\t" 5447d36db35SAvi Kivity "1: mov $0x1234, %eax\n\t" 5457d36db35SAvi Kivity "ret\n\t" 5467d36db35SAvi Kivity "2: call 1b\t"); 5477d36db35SAvi Kivity MK_INSN(call_near2, "call 1f\n\t" 5487d36db35SAvi Kivity "jmp 2f\n\t" 5497d36db35SAvi Kivity "1: mov $0x1234, %eax\n\t" 5507d36db35SAvi Kivity "ret\n\t" 5517d36db35SAvi Kivity "2:\t"); 552c0b7268dSAvi Kivity MK_INSN(call_far1, "lcallw *(%ebx)\n\t"); 553556d2680SWei Yongjun MK_INSN(call_far2, "lcallw $0, $retf\n\t"); 554c6061817SAvi Kivity MK_INSN(ret_imm, "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b"); 5554f66bc86SBruce Rogers MK_INSN(retf_imm, "sub $10, %sp; lcallw $0, $retf_imm"); 5567d36db35SAvi Kivity 557bd62e289SBill Wendling init_inregs(NULL); 558bd62e289SBill Wendling 55918253fdeSAvi Kivity exec_in_big_real_mode(&insn_call1); 5606055ea1fSAvi Kivity report("call 1", R_AX, outregs.eax == 0x1234); 5617d36db35SAvi Kivity 56218253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_near1); 5636055ea1fSAvi Kivity report("call near 1", R_AX, outregs.eax == 0x1234); 5647d36db35SAvi Kivity 56518253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_near2); 5666055ea1fSAvi Kivity report("call near 2", R_AX, outregs.eax == 0x1234); 567c0b7268dSAvi Kivity 568c0b7268dSAvi Kivity addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f); 569c0b7268dSAvi Kivity inregs.ebx = (unsigned)&addr; 57018253fdeSAvi Kivity exec_in_big_real_mode(&insn_call_far1); 5716055ea1fSAvi Kivity report("call far 1", 0, 1); 572c6061817SAvi Kivity 573556d2680SWei Yongjun exec_in_big_real_mode(&insn_call_far2); 574556d2680SWei Yongjun report("call far 2", 0, 1); 575556d2680SWei Yongjun 57618253fdeSAvi Kivity exec_in_big_real_mode(&insn_ret_imm); 5776055ea1fSAvi Kivity report("ret imm 1", 0, 1); 5784f66bc86SBruce Rogers 5794f66bc86SBruce Rogers exec_in_big_real_mode(&insn_retf_imm); 5804f66bc86SBruce Rogers report("retf imm 1", 0, 1); 5817d36db35SAvi Kivity } 5827d36db35SAvi Kivity 5832e3f9f1fSThomas Huth static void test_jcc_short(void) 5847d36db35SAvi Kivity { 5857d36db35SAvi Kivity MK_INSN(jnz_short1, "jnz 1f\n\t" 5867d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5877d36db35SAvi Kivity "1:\n\t"); 5887d36db35SAvi Kivity MK_INSN(jnz_short2, "1:\n\t" 5897d36db35SAvi Kivity "cmp $0x1234, %eax\n\t" 5907d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5917d36db35SAvi Kivity "jnz 1b\n\t"); 5927d36db35SAvi Kivity MK_INSN(jmp_short1, "jmp 1f\n\t" 5937d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 5947d36db35SAvi Kivity "1:\n\t"); 5957d36db35SAvi Kivity 596bd62e289SBill Wendling init_inregs(NULL); 5977d36db35SAvi Kivity 59818253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_short1); 5996055ea1fSAvi Kivity report("jnz short 1", ~0, 1); 60018253fdeSAvi Kivity 60118253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_short2); 6026055ea1fSAvi Kivity report("jnz short 2", R_AX, (outregs.eflags & (1 << 6))); 6037d36db35SAvi Kivity 60418253fdeSAvi Kivity exec_in_big_real_mode(&insn_jmp_short1); 6056055ea1fSAvi Kivity report("jmp short 1", ~0, 1); 6067d36db35SAvi Kivity } 6077d36db35SAvi Kivity 6082e3f9f1fSThomas Huth static void test_jcc_near(void) 6097d36db35SAvi Kivity { 6107d36db35SAvi Kivity /* encode near jmp manually. gas will not do it if offsets < 127 byte */ 6117d36db35SAvi Kivity MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t" 6127d36db35SAvi Kivity "mov $0x1234, %eax\n\t"); 6137d36db35SAvi Kivity MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t" 6147d36db35SAvi Kivity "mov $0x1234, %eax\n\t" 6157d36db35SAvi Kivity ".byte 0x0f, 0x85, 0xf0, 0xff\n\t"); 6167d36db35SAvi Kivity MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t" 6177d36db35SAvi Kivity "mov $0x1234, %eax\n\t"); 6187d36db35SAvi Kivity 619bd62e289SBill Wendling init_inregs(NULL); 6207d36db35SAvi Kivity 62118253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_near1); 6226055ea1fSAvi Kivity report("jnz near 1", 0, 1); 62318253fdeSAvi Kivity 62418253fdeSAvi Kivity exec_in_big_real_mode(&insn_jnz_near2); 6256055ea1fSAvi Kivity report("jnz near 2", R_AX, outregs.eflags & (1 << 6)); 6267d36db35SAvi Kivity 62718253fdeSAvi Kivity exec_in_big_real_mode(&insn_jmp_near1); 6286055ea1fSAvi Kivity report("jmp near 1", 0, 1); 6297d36db35SAvi Kivity } 6307d36db35SAvi Kivity 6312e3f9f1fSThomas Huth static void test_long_jmp(void) 6327d36db35SAvi Kivity { 6337d36db35SAvi Kivity MK_INSN(long_jmp, "call 1f\n\t" 6347d36db35SAvi Kivity "jmp 2f\n\t" 6357d36db35SAvi Kivity "1: jmp $0, $test_function\n\t" 6367d36db35SAvi Kivity "2:\n\t"); 637bd62e289SBill Wendling 638bd62e289SBill Wendling init_inregs(NULL); 639bd62e289SBill Wendling 64018253fdeSAvi Kivity exec_in_big_real_mode(&insn_long_jmp); 6416055ea1fSAvi Kivity report("jmp far 1", R_AX, outregs.eax == 0x1234); 6427d36db35SAvi Kivity } 643fa74f8a6SMohammed Gamal 6442e3f9f1fSThomas Huth static void test_push_pop(void) 6457d36db35SAvi Kivity { 6467d36db35SAvi Kivity MK_INSN(push32, "mov $0x12345678, %eax\n\t" 6477d36db35SAvi Kivity "push %eax\n\t" 6487d36db35SAvi Kivity "pop %ebx\n\t"); 6497d36db35SAvi Kivity MK_INSN(push16, "mov $0x1234, %ax\n\t" 6507d36db35SAvi Kivity "push %ax\n\t" 6517d36db35SAvi Kivity "pop %bx\n\t"); 6527d36db35SAvi Kivity 6537d36db35SAvi Kivity MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten 6547d36db35SAvi Kivity "mov $0x123, %ax\n\t" 6557d36db35SAvi Kivity "mov %ax, %es\n\t" 656231b4c3bSRoman Bolshakov "pushw %es\n\t" 6577d36db35SAvi Kivity "pop %bx \n\t" 6587d36db35SAvi Kivity ); 6597d36db35SAvi Kivity MK_INSN(pop_es, "push %ax\n\t" 660231b4c3bSRoman Bolshakov "popw %es\n\t" 6617d36db35SAvi Kivity "mov %es, %bx\n\t" 6627d36db35SAvi Kivity ); 663231b4c3bSRoman Bolshakov MK_INSN(push_pop_ss, "pushw %ss\n\t" 6647d36db35SAvi Kivity "pushw %ax\n\t" 6657d36db35SAvi Kivity "popw %ss\n\t" 6667d36db35SAvi Kivity "mov %ss, %bx\n\t" 667231b4c3bSRoman Bolshakov "popw %ss\n\t" 6687d36db35SAvi Kivity ); 669231b4c3bSRoman Bolshakov MK_INSN(push_pop_fs, "pushl %fs\n\t" 6707d36db35SAvi Kivity "pushl %eax\n\t" 6717d36db35SAvi Kivity "popl %fs\n\t" 6727d36db35SAvi Kivity "mov %fs, %ebx\n\t" 673231b4c3bSRoman Bolshakov "popl %fs\n\t" 6747d36db35SAvi Kivity ); 67509b657b6SAvi Kivity MK_INSN(push_pop_high_esp_bits, 67609b657b6SAvi Kivity "xor $0x12340000, %esp \n\t" 67709b657b6SAvi Kivity "push %ax; \n\t" 67809b657b6SAvi Kivity "xor $0x12340000, %esp \n\t" 67909b657b6SAvi Kivity "pop %bx"); 6807d36db35SAvi Kivity 681bd62e289SBill Wendling init_inregs(NULL); 68218253fdeSAvi Kivity 68318253fdeSAvi Kivity exec_in_big_real_mode(&insn_push32); 6846055ea1fSAvi Kivity report("push/pop 1", R_AX|R_BX, 6856055ea1fSAvi Kivity outregs.eax == outregs.ebx && outregs.eax == 0x12345678); 6867d36db35SAvi Kivity 68718253fdeSAvi Kivity exec_in_big_real_mode(&insn_push16); 6886055ea1fSAvi Kivity report("push/pop 2", R_AX|R_BX, 6896055ea1fSAvi Kivity outregs.eax == outregs.ebx && outregs.eax == 0x1234); 6907d36db35SAvi Kivity 69118253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_es); 6926055ea1fSAvi Kivity report("push/pop 3", R_AX|R_BX, 6936055ea1fSAvi Kivity outregs.ebx == outregs.eax && outregs.eax == 0x123); 6947d36db35SAvi Kivity 69518253fdeSAvi Kivity exec_in_big_real_mode(&insn_pop_es); 6966055ea1fSAvi Kivity report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax); 6977d36db35SAvi Kivity 69818253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_pop_ss); 6996055ea1fSAvi Kivity report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax); 7007d36db35SAvi Kivity 70118253fdeSAvi Kivity exec_in_big_real_mode(&insn_push_pop_fs); 7026055ea1fSAvi Kivity report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax); 70309b657b6SAvi Kivity 70409b657b6SAvi Kivity inregs.eax = 0x9977; 70509b657b6SAvi Kivity inregs.ebx = 0x7799; 70609b657b6SAvi Kivity exec_in_big_real_mode(&insn_push_pop_high_esp_bits); 70709b657b6SAvi Kivity report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977); 7087d36db35SAvi Kivity } 7097d36db35SAvi Kivity 7102e3f9f1fSThomas Huth static void test_null(void) 7117d36db35SAvi Kivity { 712d4dc402cSAvi Kivity MK_INSN(null, ""); 713d4dc402cSAvi Kivity 714bd62e289SBill Wendling init_inregs(NULL); 71518253fdeSAvi Kivity 71618253fdeSAvi Kivity exec_in_big_real_mode(&insn_null); 7176055ea1fSAvi Kivity report("null", 0, 1); 7187d36db35SAvi Kivity } 7197d36db35SAvi Kivity 7202e3f9f1fSThomas Huth static void test_pusha_popa(void) 7217d36db35SAvi Kivity { 7227d36db35SAvi Kivity MK_INSN(pusha, "pusha\n\t" 7237d36db35SAvi Kivity "pop %edi\n\t" 7247d36db35SAvi Kivity "pop %esi\n\t" 7257d36db35SAvi Kivity "pop %ebp\n\t" 7267d36db35SAvi Kivity "add $4, %esp\n\t" 7277d36db35SAvi Kivity "pop %ebx\n\t" 7287d36db35SAvi Kivity "pop %edx\n\t" 7297d36db35SAvi Kivity "pop %ecx\n\t" 7307d36db35SAvi Kivity "pop %eax\n\t" 7317d36db35SAvi Kivity ); 7327d36db35SAvi Kivity 7337d36db35SAvi Kivity MK_INSN(popa, "push %eax\n\t" 7347d36db35SAvi Kivity "push %ecx\n\t" 7357d36db35SAvi Kivity "push %edx\n\t" 7367d36db35SAvi Kivity "push %ebx\n\t" 7377d36db35SAvi Kivity "push %esp\n\t" 7387d36db35SAvi Kivity "push %ebp\n\t" 7397d36db35SAvi Kivity "push %esi\n\t" 7407d36db35SAvi Kivity "push %edi\n\t" 7417d36db35SAvi Kivity "popa\n\t" 7427d36db35SAvi Kivity ); 7437d36db35SAvi Kivity 744bd62e289SBill Wendling init_inregs(&(struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6 }); 7457d36db35SAvi Kivity 74618253fdeSAvi Kivity exec_in_big_real_mode(&insn_pusha); 7476055ea1fSAvi Kivity report("pusha/popa 1", 0, 1); 74818253fdeSAvi Kivity 74918253fdeSAvi Kivity exec_in_big_real_mode(&insn_popa); 7506055ea1fSAvi Kivity report("pusha/popa 1", 0, 1); 7517d36db35SAvi Kivity } 7527d36db35SAvi Kivity 7532e3f9f1fSThomas Huth static void test_iret(void) 7547d36db35SAvi Kivity { 7557d36db35SAvi Kivity MK_INSN(iret32, "pushf\n\t" 7567d36db35SAvi Kivity "pushl %cs\n\t" 7577d36db35SAvi Kivity "call 1f\n\t" /* a near call will push eip onto the stack */ 7587d36db35SAvi Kivity "jmp 2f\n\t" 759231b4c3bSRoman Bolshakov "1: iretl\n\t" 7607d36db35SAvi Kivity "2:\n\t" 7617d36db35SAvi Kivity ); 7627d36db35SAvi Kivity 7637d36db35SAvi Kivity MK_INSN(iret16, "pushfw\n\t" 7647d36db35SAvi Kivity "pushw %cs\n\t" 7657d36db35SAvi Kivity "callw 1f\n\t" 7667d36db35SAvi Kivity "jmp 2f\n\t" 7677d36db35SAvi Kivity "1: iretw\n\t" 7687d36db35SAvi Kivity "2:\n\t"); 7697d36db35SAvi Kivity 7707d36db35SAvi Kivity MK_INSN(iret_flags32, "pushfl\n\t" 7717d36db35SAvi Kivity "popl %eax\n\t" 7727d36db35SAvi Kivity "andl $~0x2, %eax\n\t" 773964942e8SNadav Amit "orl $0xffc18028, %eax\n\t" 7747d36db35SAvi Kivity "pushl %eax\n\t" 7757d36db35SAvi Kivity "pushl %cs\n\t" 7767d36db35SAvi Kivity "call 1f\n\t" 7777d36db35SAvi Kivity "jmp 2f\n\t" 778231b4c3bSRoman Bolshakov "1: iretl\n\t" 7797d36db35SAvi Kivity "2:\n\t"); 7807d36db35SAvi Kivity 7817d36db35SAvi Kivity MK_INSN(iret_flags16, "pushfw\n\t" 7827d36db35SAvi Kivity "popw %ax\n\t" 7837d36db35SAvi Kivity "and $~0x2, %ax\n\t" 7847d36db35SAvi Kivity "or $0x8028, %ax\n\t" 7857d36db35SAvi Kivity "pushw %ax\n\t" 7867d36db35SAvi Kivity "pushw %cs\n\t" 7877d36db35SAvi Kivity "callw 1f\n\t" 7887d36db35SAvi Kivity "jmp 2f\n\t" 7897d36db35SAvi Kivity "1: iretw\n\t" 7907d36db35SAvi Kivity "2:\n\t"); 7917d36db35SAvi Kivity 792bd62e289SBill Wendling init_inregs(NULL); 7937d36db35SAvi Kivity 79418253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret32); 7956055ea1fSAvi Kivity report("iret 1", 0, 1); 7967d36db35SAvi Kivity 79718253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret16); 7986055ea1fSAvi Kivity report("iret 2", 0, 1); 7997d36db35SAvi Kivity 80018253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret_flags32); 8016055ea1fSAvi Kivity report("iret 3", R_AX, 1); 802964942e8SNadav Amit report("rflags.rf", ~0, !(outregs.eflags & (1 << 16))); 80318253fdeSAvi Kivity 80418253fdeSAvi Kivity exec_in_big_real_mode(&insn_iret_flags16); 8056055ea1fSAvi Kivity report("iret 4", R_AX, 1); 8067d36db35SAvi Kivity } 8077d36db35SAvi Kivity 8082e3f9f1fSThomas Huth static void test_int(void) 80996b9ca1eSMohammed Gamal { 810bd62e289SBill Wendling init_inregs(NULL); 81196b9ca1eSMohammed Gamal 81296b9ca1eSMohammed Gamal *(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */ 81396b9ca1eSMohammed Gamal *(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */ 81496b9ca1eSMohammed Gamal 81596b9ca1eSMohammed Gamal MK_INSN(int11, "int $0x11\n\t"); 81696b9ca1eSMohammed Gamal 81718253fdeSAvi Kivity exec_in_big_real_mode(&insn_int11); 8186055ea1fSAvi Kivity report("int 1", 0, 1); 81996b9ca1eSMohammed Gamal } 82096b9ca1eSMohammed Gamal 8218202cf84SRoman Bolshakov static void test_sti_inhibit(void) 8228202cf84SRoman Bolshakov { 8238202cf84SRoman Bolshakov init_inregs(NULL); 8248202cf84SRoman Bolshakov 8258202cf84SRoman Bolshakov *(u32 *)(0x73 * 4) = 0x1000; /* Store IRQ 11 handler in the IDT */ 8268202cf84SRoman Bolshakov *(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */ 8278202cf84SRoman Bolshakov 8288202cf84SRoman Bolshakov MK_INSN(sti_inhibit, "cli\n\t" 8298202cf84SRoman Bolshakov "movw $0x200b, %dx\n\t" 8308202cf84SRoman Bolshakov "movl $1, %eax\n\t" 8318202cf84SRoman Bolshakov "outl %eax, %dx\n\t" /* Set IRQ11 */ 8328202cf84SRoman Bolshakov "movl $0, %eax\n\t" 8338202cf84SRoman Bolshakov "outl %eax, %dx\n\t" /* Clear IRQ11 */ 8348202cf84SRoman Bolshakov "sti\n\t" 8358202cf84SRoman Bolshakov "hlt\n\t"); 8368202cf84SRoman Bolshakov exec_in_big_real_mode(&insn_sti_inhibit); 8378202cf84SRoman Bolshakov 8388202cf84SRoman Bolshakov report("sti inhibit", ~0, 1); 8398202cf84SRoman Bolshakov } 8408202cf84SRoman Bolshakov 8412e3f9f1fSThomas Huth static void test_imul(void) 842fa74f8a6SMohammed Gamal { 843fa74f8a6SMohammed Gamal MK_INSN(imul8_1, "mov $2, %al\n\t" 844fa74f8a6SMohammed Gamal "mov $-4, %cx\n\t" 845fa74f8a6SMohammed Gamal "imul %cl\n\t"); 846fa74f8a6SMohammed Gamal 847fa74f8a6SMohammed Gamal MK_INSN(imul16_1, "mov $2, %ax\n\t" 848fa74f8a6SMohammed Gamal "mov $-4, %cx\n\t" 849fa74f8a6SMohammed Gamal "imul %cx\n\t"); 850fa74f8a6SMohammed Gamal 851fa74f8a6SMohammed Gamal MK_INSN(imul32_1, "mov $2, %eax\n\t" 852fa74f8a6SMohammed Gamal "mov $-4, %ecx\n\t" 853fa74f8a6SMohammed Gamal "imul %ecx\n\t"); 854fa74f8a6SMohammed Gamal 855fa74f8a6SMohammed Gamal MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t" 856fa74f8a6SMohammed Gamal "mov $4, %cx\n\t" 857fa74f8a6SMohammed Gamal "imul %cl\n\t"); 858fa74f8a6SMohammed Gamal 859fa74f8a6SMohammed Gamal MK_INSN(imul16_2, "mov $2, %ax\n\t" 860fa74f8a6SMohammed Gamal "mov $4, %cx\n\t" 861fa74f8a6SMohammed Gamal "imul %cx\n\t"); 862fa74f8a6SMohammed Gamal 863fa74f8a6SMohammed Gamal MK_INSN(imul32_2, "mov $2, %eax\n\t" 864fa74f8a6SMohammed Gamal "mov $4, %ecx\n\t" 865fa74f8a6SMohammed Gamal "imul %ecx\n\t"); 866fa74f8a6SMohammed Gamal 867bd62e289SBill Wendling init_inregs(NULL); 86818253fdeSAvi Kivity 86918253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul8_1); 8706055ea1fSAvi Kivity report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8); 871fa74f8a6SMohammed Gamal 87218253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul16_1); 8736055ea1fSAvi Kivity report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8); 874fa74f8a6SMohammed Gamal 87518253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul32_1); 8766055ea1fSAvi Kivity report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8); 877fa74f8a6SMohammed Gamal 87818253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul8_2); 8796055ea1fSAvi Kivity report("imul 4", R_AX | R_CX | R_DX, 8806055ea1fSAvi Kivity (outregs.eax & 0xffff) == 8 88181050840SAvi Kivity && (outregs.eax & 0xffff0000) == 0x12340000); 882fa74f8a6SMohammed Gamal 88318253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul16_2); 8846055ea1fSAvi Kivity report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8); 885fa74f8a6SMohammed Gamal 88618253fdeSAvi Kivity exec_in_big_real_mode(&insn_imul32_2); 8876055ea1fSAvi Kivity report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8); 888fa74f8a6SMohammed Gamal } 889fa74f8a6SMohammed Gamal 8902e3f9f1fSThomas Huth static void test_mul(void) 89159317bd1SMohammed Gamal { 89259317bd1SMohammed Gamal MK_INSN(mul8, "mov $2, %al\n\t" 89359317bd1SMohammed Gamal "mov $4, %cx\n\t" 89459317bd1SMohammed Gamal "imul %cl\n\t"); 89559317bd1SMohammed Gamal 89659317bd1SMohammed Gamal MK_INSN(mul16, "mov $2, %ax\n\t" 89759317bd1SMohammed Gamal "mov $4, %cx\n\t" 89859317bd1SMohammed Gamal "imul %cx\n\t"); 89959317bd1SMohammed Gamal 90059317bd1SMohammed Gamal MK_INSN(mul32, "mov $2, %eax\n\t" 90159317bd1SMohammed Gamal "mov $4, %ecx\n\t" 90259317bd1SMohammed Gamal "imul %ecx\n\t"); 90359317bd1SMohammed Gamal 904bd62e289SBill Wendling init_inregs(NULL); 90518253fdeSAvi Kivity 90618253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul8); 9076055ea1fSAvi Kivity report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8); 90859317bd1SMohammed Gamal 90918253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul16); 9106055ea1fSAvi Kivity report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8); 91159317bd1SMohammed Gamal 91218253fdeSAvi Kivity exec_in_big_real_mode(&insn_mul32); 9136055ea1fSAvi Kivity report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8); 91459317bd1SMohammed Gamal } 91559317bd1SMohammed Gamal 9162e3f9f1fSThomas Huth static void test_div(void) 9170d4c7614SMohammed Gamal { 9180d4c7614SMohammed Gamal MK_INSN(div8, "mov $257, %ax\n\t" 9190d4c7614SMohammed Gamal "mov $2, %cl\n\t" 9200d4c7614SMohammed Gamal "div %cl\n\t"); 9210d4c7614SMohammed Gamal 9220d4c7614SMohammed Gamal MK_INSN(div16, "mov $512, %ax\n\t" 9230d4c7614SMohammed Gamal "mov $5, %cx\n\t" 9240d4c7614SMohammed Gamal "div %cx\n\t"); 9250d4c7614SMohammed Gamal 9260d4c7614SMohammed Gamal MK_INSN(div32, "mov $512, %eax\n\t" 9270d4c7614SMohammed Gamal "mov $5, %ecx\n\t" 9280d4c7614SMohammed Gamal "div %ecx\n\t"); 9290d4c7614SMohammed Gamal 930bd62e289SBill Wendling init_inregs(NULL); 93118253fdeSAvi Kivity 93218253fdeSAvi Kivity exec_in_big_real_mode(&insn_div8); 9336055ea1fSAvi Kivity report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384); 9340d4c7614SMohammed Gamal 93518253fdeSAvi Kivity exec_in_big_real_mode(&insn_div16); 9366055ea1fSAvi Kivity report("div 2", R_AX | R_CX | R_DX, 9376055ea1fSAvi Kivity outregs.eax == 102 && outregs.edx == 2); 9380d4c7614SMohammed Gamal 93918253fdeSAvi Kivity exec_in_big_real_mode(&insn_div32); 9406055ea1fSAvi Kivity report("div 3", R_AX | R_CX | R_DX, 9416055ea1fSAvi Kivity outregs.eax == 102 && outregs.edx == 2); 9420d4c7614SMohammed Gamal } 9430d4c7614SMohammed Gamal 9442e3f9f1fSThomas Huth static void test_idiv(void) 9450d4c7614SMohammed Gamal { 9460d4c7614SMohammed Gamal MK_INSN(idiv8, "mov $256, %ax\n\t" 9470d4c7614SMohammed Gamal "mov $-2, %cl\n\t" 9480d4c7614SMohammed Gamal "idiv %cl\n\t"); 9490d4c7614SMohammed Gamal 9500d4c7614SMohammed Gamal MK_INSN(idiv16, "mov $512, %ax\n\t" 9510d4c7614SMohammed Gamal "mov $-2, %cx\n\t" 9520d4c7614SMohammed Gamal "idiv %cx\n\t"); 9530d4c7614SMohammed Gamal 9540d4c7614SMohammed Gamal MK_INSN(idiv32, "mov $512, %eax\n\t" 9550d4c7614SMohammed Gamal "mov $-2, %ecx\n\t" 9560d4c7614SMohammed Gamal "idiv %ecx\n\t"); 9570d4c7614SMohammed Gamal 958bd62e289SBill Wendling init_inregs(NULL); 95918253fdeSAvi Kivity 96018253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv8); 9616055ea1fSAvi Kivity report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128); 9620d4c7614SMohammed Gamal 96318253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv16); 9646055ea1fSAvi Kivity report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256); 9650d4c7614SMohammed Gamal 96618253fdeSAvi Kivity exec_in_big_real_mode(&insn_idiv32); 9676055ea1fSAvi Kivity report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256); 9680d4c7614SMohammed Gamal } 9690d4c7614SMohammed Gamal 9702e3f9f1fSThomas Huth static void test_cbw(void) 9716e293cf5SWei Yongjun { 9726e293cf5SWei Yongjun MK_INSN(cbw, "mov $0xFE, %eax \n\t" 9736e293cf5SWei Yongjun "cbw\n\t"); 9746e293cf5SWei Yongjun MK_INSN(cwde, "mov $0xFFFE, %eax \n\t" 9756e293cf5SWei Yongjun "cwde\n\t"); 9766e293cf5SWei Yongjun 977bd62e289SBill Wendling init_inregs(NULL); 97818253fdeSAvi Kivity 97918253fdeSAvi Kivity exec_in_big_real_mode(&insn_cbw); 9806055ea1fSAvi Kivity report("cbq 1", ~0, outregs.eax == 0xFFFE); 9816e293cf5SWei Yongjun 98218253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwde); 9836055ea1fSAvi Kivity report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE); 9846e293cf5SWei Yongjun } 9856e293cf5SWei Yongjun 9862e3f9f1fSThomas Huth static void test_loopcc(void) 987eacef4e2SWei Yongjun { 988eacef4e2SWei Yongjun MK_INSN(loop, "mov $10, %ecx\n\t" 989eacef4e2SWei Yongjun "1: inc %eax\n\t" 990eacef4e2SWei Yongjun "loop 1b\n\t"); 991eacef4e2SWei Yongjun 992eacef4e2SWei Yongjun MK_INSN(loope, "mov $10, %ecx\n\t" 993eacef4e2SWei Yongjun "mov $1, %eax\n\t" 994eacef4e2SWei Yongjun "1: dec %eax\n\t" 995eacef4e2SWei Yongjun "loope 1b\n\t"); 996eacef4e2SWei Yongjun 997eacef4e2SWei Yongjun MK_INSN(loopne, "mov $10, %ecx\n\t" 998eacef4e2SWei Yongjun "mov $5, %eax\n\t" 999eacef4e2SWei Yongjun "1: dec %eax\n\t" 1000eacef4e2SWei Yongjun "loopne 1b\n\t"); 1001eacef4e2SWei Yongjun 1002bd62e289SBill Wendling init_inregs(NULL); 1003eacef4e2SWei Yongjun 100418253fdeSAvi Kivity exec_in_big_real_mode(&insn_loop); 10056055ea1fSAvi Kivity report("LOOPcc short 1", R_AX, outregs.eax == 10); 100618253fdeSAvi Kivity 100718253fdeSAvi Kivity exec_in_big_real_mode(&insn_loope); 10086055ea1fSAvi Kivity report("LOOPcc short 2", R_AX | R_CX, 10096055ea1fSAvi Kivity outregs.eax == -1 && outregs.ecx == 8); 1010eacef4e2SWei Yongjun 101118253fdeSAvi Kivity exec_in_big_real_mode(&insn_loopne); 10126055ea1fSAvi Kivity report("LOOPcc short 3", R_AX | R_CX, 10136055ea1fSAvi Kivity outregs.eax == 0 && outregs.ecx == 5); 1014eacef4e2SWei Yongjun } 1015eacef4e2SWei Yongjun 1016b274feedSAvi Kivity static void test_das(void) 1017b274feedSAvi Kivity { 1018b274feedSAvi Kivity short i; 101981050840SAvi Kivity u16 nr_fail = 0; 1020b274feedSAvi Kivity static unsigned test_cases[1024] = { 1021b274feedSAvi Kivity 0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00, 1022b274feedSAvi Kivity 0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01, 1023b274feedSAvi Kivity 0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02, 1024b274feedSAvi Kivity 0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03, 1025b274feedSAvi Kivity 0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04, 1026b274feedSAvi Kivity 0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05, 1027b274feedSAvi Kivity 0x06000606, 0x8701a606, 0x56100006, 0x9711a006, 1028b274feedSAvi Kivity 0x02000707, 0x8301a707, 0x12100107, 0x9311a107, 1029b274feedSAvi Kivity 0x02000808, 0x8301a808, 0x12100208, 0x9311a208, 1030b274feedSAvi Kivity 0x06000909, 0x8701a909, 0x16100309, 0x9711a309, 1031b274feedSAvi Kivity 0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a, 1032b274feedSAvi Kivity 0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b, 1033b274feedSAvi Kivity 0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c, 1034b274feedSAvi Kivity 0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d, 1035b274feedSAvi Kivity 0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e, 1036b274feedSAvi Kivity 0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f, 1037b274feedSAvi Kivity 0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10, 1038b274feedSAvi Kivity 0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11, 1039b274feedSAvi Kivity 0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12, 1040b274feedSAvi Kivity 0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13, 1041b274feedSAvi Kivity 0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14, 1042b274feedSAvi Kivity 0x02001515, 0x8301b515, 0x16100f15, 0x9711af15, 1043b274feedSAvi Kivity 0x02001616, 0x8301b616, 0x12101016, 0x9311b016, 1044b274feedSAvi Kivity 0x06001717, 0x8701b717, 0x16101117, 0x9711b117, 1045b274feedSAvi Kivity 0x06001818, 0x8701b818, 0x16101218, 0x9711b218, 1046b274feedSAvi Kivity 0x02001919, 0x8301b919, 0x12101319, 0x9311b319, 1047b274feedSAvi Kivity 0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a, 1048b274feedSAvi Kivity 0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b, 1049b274feedSAvi Kivity 0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c, 1050b274feedSAvi Kivity 0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d, 1051b274feedSAvi Kivity 0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e, 1052b274feedSAvi Kivity 0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f, 1053b274feedSAvi Kivity 0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20, 1054b274feedSAvi Kivity 0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21, 1055b274feedSAvi Kivity 0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22, 1056b274feedSAvi Kivity 0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23, 1057b274feedSAvi Kivity 0x06002424, 0x8301c424, 0x16101e24, 0x9711be24, 1058b274feedSAvi Kivity 0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25, 1059b274feedSAvi Kivity 0x02002626, 0x8701c626, 0x12102026, 0x9711c026, 1060b274feedSAvi Kivity 0x06002727, 0x8301c727, 0x16102127, 0x9311c127, 1061b274feedSAvi Kivity 0x06002828, 0x8301c828, 0x16102228, 0x9311c228, 1062b274feedSAvi Kivity 0x02002929, 0x8701c929, 0x12102329, 0x9711c329, 1063b274feedSAvi Kivity 0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a, 1064b274feedSAvi Kivity 0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b, 1065b274feedSAvi Kivity 0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c, 1066b274feedSAvi Kivity 0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d, 1067b274feedSAvi Kivity 0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e, 1068b274feedSAvi Kivity 0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f, 1069b274feedSAvi Kivity 0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30, 1070b274feedSAvi Kivity 0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31, 1071b274feedSAvi Kivity 0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32, 1072b274feedSAvi Kivity 0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33, 1073b274feedSAvi Kivity 0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34, 1074b274feedSAvi Kivity 0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35, 1075b274feedSAvi Kivity 0x06003636, 0x8301d636, 0x16103036, 0x9311d036, 1076b274feedSAvi Kivity 0x02003737, 0x8701d737, 0x12103137, 0x9711d137, 1077b274feedSAvi Kivity 0x02003838, 0x8701d838, 0x12103238, 0x9711d238, 1078b274feedSAvi Kivity 0x06003939, 0x8301d939, 0x16103339, 0x9311d339, 1079b274feedSAvi Kivity 0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a, 1080b274feedSAvi Kivity 0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b, 1081b274feedSAvi Kivity 0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c, 1082b274feedSAvi Kivity 0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d, 1083b274feedSAvi Kivity 0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e, 1084b274feedSAvi Kivity 0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f, 1085b274feedSAvi Kivity 0x02004040, 0x8301e040, 0x16103a40, 0x9311da40, 1086b274feedSAvi Kivity 0x06004141, 0x8701e141, 0x12103b41, 0x9711db41, 1087b274feedSAvi Kivity 0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42, 1088b274feedSAvi Kivity 0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43, 1089b274feedSAvi Kivity 0x06004444, 0x8701e444, 0x12103e44, 0x9711de44, 1090b274feedSAvi Kivity 0x02004545, 0x8301e545, 0x16103f45, 0x9311df45, 1091b274feedSAvi Kivity 0x02004646, 0x8301e646, 0x12104046, 0x9311e046, 1092b274feedSAvi Kivity 0x06004747, 0x8701e747, 0x16104147, 0x9711e147, 1093b274feedSAvi Kivity 0x06004848, 0x8701e848, 0x16104248, 0x9711e248, 1094b274feedSAvi Kivity 0x02004949, 0x8301e949, 0x12104349, 0x9311e349, 1095b274feedSAvi Kivity 0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a, 1096b274feedSAvi Kivity 0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b, 1097b274feedSAvi Kivity 0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c, 1098b274feedSAvi Kivity 0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d, 1099b274feedSAvi Kivity 0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e, 1100b274feedSAvi Kivity 0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f, 1101b274feedSAvi Kivity 0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50, 1102b274feedSAvi Kivity 0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51, 1103b274feedSAvi Kivity 0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52, 1104b274feedSAvi Kivity 0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53, 1105b274feedSAvi Kivity 0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54, 1106b274feedSAvi Kivity 0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55, 1107b274feedSAvi Kivity 0x06005656, 0x8701f656, 0x16105056, 0x9711f056, 1108b274feedSAvi Kivity 0x02005757, 0x8301f757, 0x12105157, 0x9311f157, 1109b274feedSAvi Kivity 0x02005858, 0x8301f858, 0x12105258, 0x9311f258, 1110b274feedSAvi Kivity 0x06005959, 0x8701f959, 0x16105359, 0x9711f359, 1111b274feedSAvi Kivity 0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a, 1112b274feedSAvi Kivity 0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b, 1113b274feedSAvi Kivity 0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c, 1114b274feedSAvi Kivity 0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d, 1115b274feedSAvi Kivity 0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e, 1116b274feedSAvi Kivity 0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f, 1117b274feedSAvi Kivity 0x06006060, 0x47010060, 0x16105a60, 0x9711fa60, 1118b274feedSAvi Kivity 0x02006161, 0x03010161, 0x12105b61, 0x9311fb61, 1119b274feedSAvi Kivity 0x02006262, 0x03010262, 0x16105c62, 0x9711fc62, 1120b274feedSAvi Kivity 0x06006363, 0x07010363, 0x12105d63, 0x9311fd63, 1121b274feedSAvi Kivity 0x02006464, 0x03010464, 0x12105e64, 0x9311fe64, 1122b274feedSAvi Kivity 0x06006565, 0x07010565, 0x16105f65, 0x9711ff65, 1123b274feedSAvi Kivity 0x06006666, 0x07010666, 0x16106066, 0x57110066, 1124b274feedSAvi Kivity 0x02006767, 0x03010767, 0x12106167, 0x13110167, 1125b274feedSAvi Kivity 0x02006868, 0x03010868, 0x12106268, 0x13110268, 1126b274feedSAvi Kivity 0x06006969, 0x07010969, 0x16106369, 0x17110369, 1127b274feedSAvi Kivity 0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a, 1128b274feedSAvi Kivity 0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b, 1129b274feedSAvi Kivity 0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c, 1130b274feedSAvi Kivity 0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d, 1131b274feedSAvi Kivity 0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e, 1132b274feedSAvi Kivity 0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f, 1133b274feedSAvi Kivity 0x02007070, 0x03011070, 0x16106a70, 0x17110a70, 1134b274feedSAvi Kivity 0x06007171, 0x07011171, 0x12106b71, 0x13110b71, 1135b274feedSAvi Kivity 0x06007272, 0x07011272, 0x16106c72, 0x17110c72, 1136b274feedSAvi Kivity 0x02007373, 0x03011373, 0x12106d73, 0x13110d73, 1137b274feedSAvi Kivity 0x06007474, 0x07011474, 0x12106e74, 0x13110e74, 1138b274feedSAvi Kivity 0x02007575, 0x03011575, 0x16106f75, 0x17110f75, 1139b274feedSAvi Kivity 0x02007676, 0x03011676, 0x12107076, 0x13111076, 1140b274feedSAvi Kivity 0x06007777, 0x07011777, 0x16107177, 0x17111177, 1141b274feedSAvi Kivity 0x06007878, 0x07011878, 0x16107278, 0x17111278, 1142b274feedSAvi Kivity 0x02007979, 0x03011979, 0x12107379, 0x13111379, 1143b274feedSAvi Kivity 0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a, 1144b274feedSAvi Kivity 0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b, 1145b274feedSAvi Kivity 0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c, 1146b274feedSAvi Kivity 0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d, 1147b274feedSAvi Kivity 0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e, 1148b274feedSAvi Kivity 0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f, 1149b274feedSAvi Kivity 0x82008080, 0x03012080, 0x12107a80, 0x13111a80, 1150b274feedSAvi Kivity 0x86008181, 0x07012181, 0x16107b81, 0x17111b81, 1151b274feedSAvi Kivity 0x86008282, 0x07012282, 0x12107c82, 0x13111c82, 1152b274feedSAvi Kivity 0x82008383, 0x03012383, 0x16107d83, 0x17111d83, 1153b274feedSAvi Kivity 0x86008484, 0x07012484, 0x16107e84, 0x17111e84, 1154b274feedSAvi Kivity 0x82008585, 0x03012585, 0x12107f85, 0x13111f85, 1155b274feedSAvi Kivity 0x82008686, 0x03012686, 0x92108086, 0x13112086, 1156b274feedSAvi Kivity 0x86008787, 0x07012787, 0x96108187, 0x17112187, 1157b274feedSAvi Kivity 0x86008888, 0x07012888, 0x96108288, 0x17112288, 1158b274feedSAvi Kivity 0x82008989, 0x03012989, 0x92108389, 0x13112389, 1159b274feedSAvi Kivity 0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a, 1160b274feedSAvi Kivity 0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b, 1161b274feedSAvi Kivity 0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c, 1162b274feedSAvi Kivity 0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d, 1163b274feedSAvi Kivity 0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e, 1164b274feedSAvi Kivity 0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f, 1165b274feedSAvi Kivity 0x86009090, 0x07013090, 0x92108a90, 0x13112a90, 1166b274feedSAvi Kivity 0x82009191, 0x03013191, 0x96108b91, 0x17112b91, 1167b274feedSAvi Kivity 0x82009292, 0x03013292, 0x92108c92, 0x13112c92, 1168b274feedSAvi Kivity 0x86009393, 0x07013393, 0x96108d93, 0x17112d93, 1169b274feedSAvi Kivity 0x82009494, 0x03013494, 0x96108e94, 0x17112e94, 1170b274feedSAvi Kivity 0x86009595, 0x07013595, 0x92108f95, 0x13112f95, 1171b274feedSAvi Kivity 0x86009696, 0x07013696, 0x96109096, 0x17113096, 1172b274feedSAvi Kivity 0x82009797, 0x03013797, 0x92109197, 0x13113197, 1173b274feedSAvi Kivity 0x82009898, 0x03013898, 0x92109298, 0x13113298, 1174b274feedSAvi Kivity 0x86009999, 0x07013999, 0x96109399, 0x17113399, 1175b274feedSAvi Kivity 0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a, 1176b274feedSAvi Kivity 0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b, 1177b274feedSAvi Kivity 0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c, 1178b274feedSAvi Kivity 0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d, 1179b274feedSAvi Kivity 0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e, 1180b274feedSAvi Kivity 0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f, 1181b274feedSAvi Kivity 0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0, 1182b274feedSAvi Kivity 0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1, 1183b274feedSAvi Kivity 0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2, 1184b274feedSAvi Kivity 0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3, 1185b274feedSAvi Kivity 0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4, 1186b274feedSAvi Kivity 0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5, 1187b274feedSAvi Kivity 0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6, 1188b274feedSAvi Kivity 0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7, 1189b274feedSAvi Kivity 0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8, 1190b274feedSAvi Kivity 0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9, 1191b274feedSAvi Kivity 0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa, 1192b274feedSAvi Kivity 0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab, 1193b274feedSAvi Kivity 0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac, 1194b274feedSAvi Kivity 0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad, 1195b274feedSAvi Kivity 0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae, 1196b274feedSAvi Kivity 0x130049af, 0x130149af, 0x131049af, 0x131149af, 1197b274feedSAvi Kivity 0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0, 1198b274feedSAvi Kivity 0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1, 1199b274feedSAvi Kivity 0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2, 1200b274feedSAvi Kivity 0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3, 1201b274feedSAvi Kivity 0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4, 1202b274feedSAvi Kivity 0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5, 1203b274feedSAvi Kivity 0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6, 1204b274feedSAvi Kivity 0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7, 1205b274feedSAvi Kivity 0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8, 1206b274feedSAvi Kivity 0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9, 1207b274feedSAvi Kivity 0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba, 1208b274feedSAvi Kivity 0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb, 1209b274feedSAvi Kivity 0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc, 1210b274feedSAvi Kivity 0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd, 1211b274feedSAvi Kivity 0x130058be, 0x130158be, 0x131058be, 0x131158be, 1212b274feedSAvi Kivity 0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf, 1213b274feedSAvi Kivity 0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0, 1214b274feedSAvi Kivity 0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1, 1215b274feedSAvi Kivity 0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2, 1216b274feedSAvi Kivity 0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3, 1217b274feedSAvi Kivity 0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4, 1218b274feedSAvi Kivity 0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5, 1219b274feedSAvi Kivity 0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6, 1220b274feedSAvi Kivity 0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7, 1221b274feedSAvi Kivity 0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8, 1222b274feedSAvi Kivity 0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9, 1223b274feedSAvi Kivity 0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca, 1224b274feedSAvi Kivity 0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb, 1225b274feedSAvi Kivity 0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc, 1226b274feedSAvi Kivity 0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd, 1227b274feedSAvi Kivity 0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce, 1228b274feedSAvi Kivity 0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf, 1229b274feedSAvi Kivity 0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0, 1230b274feedSAvi Kivity 0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1, 1231b274feedSAvi Kivity 0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2, 1232b274feedSAvi Kivity 0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3, 1233b274feedSAvi Kivity 0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4, 1234b274feedSAvi Kivity 0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5, 1235b274feedSAvi Kivity 0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6, 1236b274feedSAvi Kivity 0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7, 1237b274feedSAvi Kivity 0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8, 1238b274feedSAvi Kivity 0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9, 1239b274feedSAvi Kivity 0x170074da, 0x170174da, 0x171074da, 0x171174da, 1240b274feedSAvi Kivity 0x130075db, 0x130175db, 0x131075db, 0x131175db, 1241b274feedSAvi Kivity 0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc, 1242b274feedSAvi Kivity 0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd, 1243b274feedSAvi Kivity 0x170078de, 0x170178de, 0x171078de, 0x171178de, 1244b274feedSAvi Kivity 0x130079df, 0x130179df, 0x131079df, 0x131179df, 1245b274feedSAvi Kivity 0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0, 1246b274feedSAvi Kivity 0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1, 1247b274feedSAvi Kivity 0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2, 1248b274feedSAvi Kivity 0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3, 1249b274feedSAvi Kivity 0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4, 1250b274feedSAvi Kivity 0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5, 1251b274feedSAvi Kivity 0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6, 1252b274feedSAvi Kivity 0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7, 1253b274feedSAvi Kivity 0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8, 1254b274feedSAvi Kivity 0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9, 1255b274feedSAvi Kivity 0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea, 1256b274feedSAvi Kivity 0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb, 1257b274feedSAvi Kivity 0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec, 1258b274feedSAvi Kivity 0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed, 1259b274feedSAvi Kivity 0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee, 1260b274feedSAvi Kivity 0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef, 1261b274feedSAvi Kivity 0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0, 1262b274feedSAvi Kivity 0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1, 1263b274feedSAvi Kivity 0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2, 1264b274feedSAvi Kivity 0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3, 1265b274feedSAvi Kivity 0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4, 1266b274feedSAvi Kivity 0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5, 1267b274feedSAvi Kivity 0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6, 1268b274feedSAvi Kivity 0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7, 1269b274feedSAvi Kivity 0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8, 1270b274feedSAvi Kivity 0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9, 1271b274feedSAvi Kivity 0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa, 1272b274feedSAvi Kivity 0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb, 1273b274feedSAvi Kivity 0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc, 1274b274feedSAvi Kivity 0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd, 1275b274feedSAvi Kivity 0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe, 1276b274feedSAvi Kivity 0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff, 1277b274feedSAvi Kivity }; 1278b274feedSAvi Kivity 1279b274feedSAvi Kivity MK_INSN(das, "das"); 1280b274feedSAvi Kivity 1281bd62e289SBill Wendling init_inregs(NULL); 128218253fdeSAvi Kivity 1283b274feedSAvi Kivity for (i = 0; i < 1024; ++i) { 1284b274feedSAvi Kivity unsigned tmp = test_cases[i]; 1285b274feedSAvi Kivity inregs.eax = tmp & 0xff; 1286b274feedSAvi Kivity inregs.eflags = (tmp >> 16) & 0xff; 128718253fdeSAvi Kivity exec_in_big_real_mode(&insn_das); 128818253fdeSAvi Kivity if (!regs_equal(R_AX) 1289b274feedSAvi Kivity || outregs.eax != ((tmp >> 8) & 0xff) 1290b274feedSAvi Kivity || (outregs.eflags & 0xff) != (tmp >> 24)) { 129181050840SAvi Kivity ++nr_fail; 129281050840SAvi Kivity break; 1293b274feedSAvi Kivity } 1294b274feedSAvi Kivity } 12956055ea1fSAvi Kivity report("DAS", ~0, nr_fail == 0); 1296b274feedSAvi Kivity } 1297b274feedSAvi Kivity 12982e3f9f1fSThomas Huth static void test_cwd_cdq(void) 12990cbd5b06SMohammed Gamal { 13000cbd5b06SMohammed Gamal /* Sign-bit set */ 13010cbd5b06SMohammed Gamal MK_INSN(cwd_1, "mov $0x8000, %ax\n\t" 13020cbd5b06SMohammed Gamal "cwd\n\t"); 13030cbd5b06SMohammed Gamal 13040cbd5b06SMohammed Gamal /* Sign-bit not set */ 13050cbd5b06SMohammed Gamal MK_INSN(cwd_2, "mov $0x1000, %ax\n\t" 13060cbd5b06SMohammed Gamal "cwd\n\t"); 13070cbd5b06SMohammed Gamal 13080cbd5b06SMohammed Gamal /* Sign-bit set */ 13090cbd5b06SMohammed Gamal MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t" 13100cbd5b06SMohammed Gamal "cdq\n\t"); 13110cbd5b06SMohammed Gamal 13120cbd5b06SMohammed Gamal /* Sign-bit not set */ 13130cbd5b06SMohammed Gamal MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t" 13140cbd5b06SMohammed Gamal "cdq\n\t"); 13150cbd5b06SMohammed Gamal 1316bd62e289SBill Wendling init_inregs(NULL); 131718253fdeSAvi Kivity 131818253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwd_1); 13196055ea1fSAvi Kivity report("cwd 1", R_AX | R_DX, 13206055ea1fSAvi Kivity outregs.eax == 0x8000 && outregs.edx == 0xffff); 13210cbd5b06SMohammed Gamal 132218253fdeSAvi Kivity exec_in_big_real_mode(&insn_cwd_2); 13236055ea1fSAvi Kivity report("cwd 2", R_AX | R_DX, 13246055ea1fSAvi Kivity outregs.eax == 0x1000 && outregs.edx == 0); 13250cbd5b06SMohammed Gamal 132618253fdeSAvi Kivity exec_in_big_real_mode(&insn_cdq_1); 13276055ea1fSAvi Kivity report("cdq 1", R_AX | R_DX, 13286055ea1fSAvi Kivity outregs.eax == 0x80000000 && outregs.edx == 0xffffffff); 13290cbd5b06SMohammed Gamal 133018253fdeSAvi Kivity exec_in_big_real_mode(&insn_cdq_2); 13316055ea1fSAvi Kivity report("cdq 2", R_AX | R_DX, 13326055ea1fSAvi Kivity outregs.eax == 0x10000000 && outregs.edx == 0); 13330cbd5b06SMohammed Gamal } 13340cbd5b06SMohammed Gamal 133537f51a4aSWei Yongjun static struct { 133637f51a4aSWei Yongjun void *address; 133737f51a4aSWei Yongjun unsigned short sel; 133837f51a4aSWei Yongjun } __attribute__((packed)) desc = { 133937f51a4aSWei Yongjun (void *)0x1234, 134037f51a4aSWei Yongjun 0x10, 134137f51a4aSWei Yongjun }; 134237f51a4aSWei Yongjun 13432e3f9f1fSThomas Huth static void test_lds_lss(void) 134437f51a4aSWei Yongjun { 1345bd62e289SBill Wendling init_inregs(&(struct regs){ .ebx = (unsigned long)&desc }); 134637f51a4aSWei Yongjun 1347231b4c3bSRoman Bolshakov MK_INSN(lds, "pushl %ds\n\t" 134837f51a4aSWei Yongjun "lds (%ebx), %eax\n\t" 134937f51a4aSWei Yongjun "mov %ds, %ebx\n\t" 1350231b4c3bSRoman Bolshakov "popl %ds\n\t"); 135137f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lds); 135237f51a4aSWei Yongjun report("lds", R_AX | R_BX, 135337f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 135437f51a4aSWei Yongjun outregs.ebx == desc.sel); 135537f51a4aSWei Yongjun 1356eb6687a2SBill Wendling MK_INSN(les, "les (%ebx), %eax\n\t" 1357eb6687a2SBill Wendling "mov %es, %ebx\n\t"); 135837f51a4aSWei Yongjun exec_in_big_real_mode(&insn_les); 135937f51a4aSWei Yongjun report("les", R_AX | R_BX, 136037f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 136137f51a4aSWei Yongjun outregs.ebx == desc.sel); 136237f51a4aSWei Yongjun 1363231b4c3bSRoman Bolshakov MK_INSN(lfs, "pushl %fs\n\t" 136437f51a4aSWei Yongjun "lfs (%ebx), %eax\n\t" 136537f51a4aSWei Yongjun "mov %fs, %ebx\n\t" 1366231b4c3bSRoman Bolshakov "popl %fs\n\t"); 136737f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lfs); 136837f51a4aSWei Yongjun report("lfs", R_AX | R_BX, 136937f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 137037f51a4aSWei Yongjun outregs.ebx == desc.sel); 137137f51a4aSWei Yongjun 1372231b4c3bSRoman Bolshakov MK_INSN(lgs, "pushl %gs\n\t" 137337f51a4aSWei Yongjun "lgs (%ebx), %eax\n\t" 137437f51a4aSWei Yongjun "mov %gs, %ebx\n\t" 1375231b4c3bSRoman Bolshakov "popl %gs\n\t"); 137637f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lgs); 137737f51a4aSWei Yongjun report("lgs", R_AX | R_BX, 137837f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 137937f51a4aSWei Yongjun outregs.ebx == desc.sel); 138037f51a4aSWei Yongjun 1381*d7903be6SNadav Amit MK_INSN(lss, "mov %ss, %dx\n\t" 138237f51a4aSWei Yongjun "lss (%ebx), %eax\n\t" 138337f51a4aSWei Yongjun "mov %ss, %ebx\n\t" 1384*d7903be6SNadav Amit "mov %dx, %ss\n\t"); 138537f51a4aSWei Yongjun exec_in_big_real_mode(&insn_lss); 138637f51a4aSWei Yongjun report("lss", R_AX | R_BX, 138737f51a4aSWei Yongjun outregs.eax == (unsigned long)desc.address && 138837f51a4aSWei Yongjun outregs.ebx == desc.sel); 138937f51a4aSWei Yongjun } 139037f51a4aSWei Yongjun 13912e3f9f1fSThomas Huth static void test_jcxz(void) 1392b1c7c575SWei Yongjun { 1393b1c7c575SWei Yongjun MK_INSN(jcxz1, "jcxz 1f\n\t" 1394b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1395b1c7c575SWei Yongjun "1:\n\t"); 1396b1c7c575SWei Yongjun MK_INSN(jcxz2, "mov $0x100, %ecx\n\t" 1397b1c7c575SWei Yongjun "jcxz 1f\n\t" 1398b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1399b1c7c575SWei Yongjun "mov $0, %ecx\n\t" 1400b1c7c575SWei Yongjun "1:\n\t"); 1401b1c7c575SWei Yongjun MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t" 1402b1c7c575SWei Yongjun "jcxz 1f\n\t" 1403b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1404b1c7c575SWei Yongjun "1:\n\t"); 1405b1c7c575SWei Yongjun MK_INSN(jecxz1, "jecxz 1f\n\t" 1406b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1407b1c7c575SWei Yongjun "1:\n\t"); 1408b1c7c575SWei Yongjun MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t" 1409b1c7c575SWei Yongjun "jecxz 1f\n\t" 1410b1c7c575SWei Yongjun "mov $0x1234, %eax\n\t" 1411b1c7c575SWei Yongjun "mov $0, %ecx\n\t" 1412b1c7c575SWei Yongjun "1:\n\t"); 1413b1c7c575SWei Yongjun 1414bd62e289SBill Wendling init_inregs(NULL); 1415b1c7c575SWei Yongjun 1416b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jcxz1); 1417b1c7c575SWei Yongjun report("jcxz short 1", 0, 1); 1418b1c7c575SWei Yongjun 1419b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jcxz2); 1420b1c7c575SWei Yongjun report("jcxz short 2", R_AX, outregs.eax == 0x1234); 1421b1c7c575SWei Yongjun 1422b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jcxz3); 1423b1c7c575SWei Yongjun report("jcxz short 3", R_CX, outregs.ecx == 0x10000); 1424b1c7c575SWei Yongjun 1425b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jecxz1); 1426b1c7c575SWei Yongjun report("jecxz short 1", 0, 1); 1427b1c7c575SWei Yongjun 1428b1c7c575SWei Yongjun exec_in_big_real_mode(&insn_jecxz2); 1429b1c7c575SWei Yongjun report("jecxz short 2", R_AX, outregs.eax == 0x1234); 1430b1c7c575SWei Yongjun } 1431b1c7c575SWei Yongjun 14328f578e98SAvi Kivity static void test_cpuid(void) 14338f578e98SAvi Kivity { 14348f578e98SAvi Kivity MK_INSN(cpuid, "cpuid"); 14358f578e98SAvi Kivity unsigned function = 0x1234; 14368f578e98SAvi Kivity unsigned eax, ebx, ecx, edx; 14378f578e98SAvi Kivity 1438bd62e289SBill Wendling init_inregs(&(struct regs){ .eax = function }); 1439bd62e289SBill Wendling 1440bd62e289SBill Wendling eax = inregs.eax; 1441bd62e289SBill Wendling ecx = inregs.ecx; 1442674d2dbeSPaolo Bonzini asm("cpuid" : "+a"(eax), "=b"(ebx), "+c"(ecx), "=d"(edx)); 14438f578e98SAvi Kivity exec_in_big_real_mode(&insn_cpuid); 14448f578e98SAvi Kivity report("cpuid", R_AX|R_BX|R_CX|R_DX, 14458f578e98SAvi Kivity outregs.eax == eax && outregs.ebx == ebx 14468f578e98SAvi Kivity && outregs.ecx == ecx && outregs.edx == edx); 14478f578e98SAvi Kivity } 14488f578e98SAvi Kivity 1449ed93f43bSAvi Kivity static void test_ss_base_for_esp_ebp(void) 1450ed93f43bSAvi Kivity { 1451ed93f43bSAvi Kivity MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss"); 1452ed93f43bSAvi Kivity MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss"); 1453ed93f43bSAvi Kivity static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 }; 1454ed93f43bSAvi Kivity 1455bd62e289SBill Wendling init_inregs(&(struct regs){ .ebx = 1, .ebp = (unsigned)array }); 1456bd62e289SBill Wendling 1457ed93f43bSAvi Kivity exec_in_big_real_mode(&insn_ssrel1); 1458ed93f43bSAvi Kivity report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321); 1459bd62e289SBill Wendling 1460ed93f43bSAvi Kivity inregs.ebx = 1; 1461ed93f43bSAvi Kivity inregs.ebp = (unsigned)array; 1462ed93f43bSAvi Kivity inregs.edi = 0; 1463ed93f43bSAvi Kivity exec_in_big_real_mode(&insn_ssrel2); 1464ed93f43bSAvi Kivity report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321); 1465ed93f43bSAvi Kivity } 1466ed93f43bSAvi Kivity 1467975ca087SPeter Feiner extern unsigned long long r_gdt[]; 1468975ca087SPeter Feiner 1469c2281fa4SAvi Kivity static void test_sgdt_sidt(void) 1470c2281fa4SAvi Kivity { 1471c2281fa4SAvi Kivity MK_INSN(sgdt, "sgdtw (%eax)"); 1472c2281fa4SAvi Kivity MK_INSN(sidt, "sidtw (%eax)"); 1473975ca087SPeter Feiner struct table_descr x, y; 1474c2281fa4SAvi Kivity 1475bd62e289SBill Wendling init_inregs(&(struct regs){ .eax = (unsigned)&y }); 1476bd62e289SBill Wendling 1477c2281fa4SAvi Kivity asm volatile("sgdtw %0" : "=m"(x)); 1478c2281fa4SAvi Kivity exec_in_big_real_mode(&insn_sgdt); 1479975ca087SPeter Feiner report("sgdt", 0, x.limit == y.limit && x.base == y.base); 1480c2281fa4SAvi Kivity 1481c2281fa4SAvi Kivity inregs.eax = (unsigned)&y; 1482c2281fa4SAvi Kivity asm volatile("sidtw %0" : "=m"(x)); 1483c2281fa4SAvi Kivity exec_in_big_real_mode(&insn_sidt); 1484975ca087SPeter Feiner report("sidt", 0, x.limit == y.limit && x.base == y.base); 1485c2281fa4SAvi Kivity } 1486c2281fa4SAvi Kivity 148788b6dac4SPaolo Bonzini static void test_sahf(void) 148888b6dac4SPaolo Bonzini { 148988b6dac4SPaolo Bonzini MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw"); 149088b6dac4SPaolo Bonzini 1491bd62e289SBill Wendling init_inregs(&(struct regs){ .eax = 0xfd00 }); 1492bd62e289SBill Wendling 149388b6dac4SPaolo Bonzini exec_in_big_real_mode(&insn_sahf); 149488b6dac4SPaolo Bonzini report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7)); 149588b6dac4SPaolo Bonzini } 149688b6dac4SPaolo Bonzini 14977ae3645aSAvi Kivity static void test_lahf(void) 14987ae3645aSAvi Kivity { 14997ae3645aSAvi Kivity MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf"); 15007ae3645aSAvi Kivity 1501bd62e289SBill Wendling init_inregs(&(struct regs){ .eax = 0xc7 }); 1502bd62e289SBill Wendling 15037ae3645aSAvi Kivity exec_in_big_real_mode(&insn_lahf); 15047ae3645aSAvi Kivity report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax); 15057ae3645aSAvi Kivity } 15067ae3645aSAvi Kivity 1507fd9ea640SAvi Kivity static void test_movzx_movsx(void) 1508fd9ea640SAvi Kivity { 1509fd9ea640SAvi Kivity MK_INSN(movsx, "movsx %al, %ebx"); 1510fd9ea640SAvi Kivity MK_INSN(movzx, "movzx %al, %ebx"); 15113013e079SGleb Natapov MK_INSN(movzsah, "movsx %ah, %ebx"); 15123013e079SGleb Natapov MK_INSN(movzxah, "movzx %ah, %ebx"); 1513fd9ea640SAvi Kivity 1514bd62e289SBill Wendling init_inregs(&(struct regs){ .eax = 0x1234569c }); 1515bd62e289SBill Wendling 1516fd9ea640SAvi Kivity exec_in_big_real_mode(&insn_movsx); 1517fd9ea640SAvi Kivity report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax); 1518fd9ea640SAvi Kivity exec_in_big_real_mode(&insn_movzx); 1519fd9ea640SAvi Kivity report("movzx", R_BX, outregs.ebx == (unsigned char)inregs.eax); 15203013e079SGleb Natapov exec_in_big_real_mode(&insn_movzsah); 15213013e079SGleb Natapov report("movsx ah", R_BX, outregs.ebx == (signed char)(inregs.eax>>8)); 15223013e079SGleb Natapov exec_in_big_real_mode(&insn_movzxah); 15233013e079SGleb Natapov report("movzx ah", R_BX, outregs.ebx == (unsigned char)(inregs.eax >> 8)); 1524fd9ea640SAvi Kivity } 1525fd9ea640SAvi Kivity 1526b493b2e8SAvi Kivity static void test_bswap(void) 1527b493b2e8SAvi Kivity { 1528b493b2e8SAvi Kivity MK_INSN(bswap, "bswap %ecx"); 1529b493b2e8SAvi Kivity 1530bd62e289SBill Wendling init_inregs(&(struct regs){ .ecx = 0x12345678 }); 1531bd62e289SBill Wendling 1532b493b2e8SAvi Kivity exec_in_big_real_mode(&insn_bswap); 1533b493b2e8SAvi Kivity report("bswap", R_CX, outregs.ecx == 0x78563412); 1534b493b2e8SAvi Kivity } 1535b493b2e8SAvi Kivity 15368cd86387SGleb Natapov static void test_aad(void) 15378cd86387SGleb Natapov { 15388cd86387SGleb Natapov MK_INSN(aad, "aad"); 15398cd86387SGleb Natapov 1540bd62e289SBill Wendling init_inregs(&(struct regs){ .eax = 0x12345678 }); 1541bd62e289SBill Wendling 15428cd86387SGleb Natapov exec_in_big_real_mode(&insn_aad); 15438cd86387SGleb Natapov report("aad", R_AX, outregs.eax == 0x123400d4); 15448cd86387SGleb Natapov } 15458cd86387SGleb Natapov 15462a9b5718SPaolo Bonzini static void test_aam(void) 15472a9b5718SPaolo Bonzini { 15482a9b5718SPaolo Bonzini MK_INSN(aam, "aam"); 15492a9b5718SPaolo Bonzini 1550bd62e289SBill Wendling init_inregs(&(struct regs){ .eax = 0x76543210 }); 1551bd62e289SBill Wendling 15522a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_aam); 15532a9b5718SPaolo Bonzini report("aam", R_AX, outregs.eax == 0x76540106); 15542a9b5718SPaolo Bonzini } 15552a9b5718SPaolo Bonzini 15562a9b5718SPaolo Bonzini static void test_xlat(void) 15572a9b5718SPaolo Bonzini { 15582a9b5718SPaolo Bonzini MK_INSN(xlat, "xlat"); 15592a9b5718SPaolo Bonzini u8 table[256]; 15602a9b5718SPaolo Bonzini int i; 15612a9b5718SPaolo Bonzini 15622a9b5718SPaolo Bonzini for (i = 0; i < 256; i++) { 15632a9b5718SPaolo Bonzini table[i] = i + 1; 15642a9b5718SPaolo Bonzini } 15652a9b5718SPaolo Bonzini 1566bd62e289SBill Wendling init_inregs(&(struct regs){ .eax = 0x89abcdef, .ebx = (u32)table }); 1567bd62e289SBill Wendling 15682a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_xlat); 15692a9b5718SPaolo Bonzini report("xlat", R_AX, outregs.eax == 0x89abcdf0); 15702a9b5718SPaolo Bonzini } 15712a9b5718SPaolo Bonzini 15722a9b5718SPaolo Bonzini static void test_salc(void) 15732a9b5718SPaolo Bonzini { 15742a9b5718SPaolo Bonzini MK_INSN(clc_salc, "clc; .byte 0xd6"); 15752a9b5718SPaolo Bonzini MK_INSN(stc_salc, "stc; .byte 0xd6"); 15762a9b5718SPaolo Bonzini 1577bd62e289SBill Wendling init_inregs(&(struct regs){ .eax = 0x12345678 }); 1578bd62e289SBill Wendling 15792a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_clc_salc); 15802a9b5718SPaolo Bonzini report("salc (1)", R_AX, outregs.eax == 0x12345600); 15812a9b5718SPaolo Bonzini exec_in_big_real_mode(&insn_stc_salc); 15822a9b5718SPaolo Bonzini report("salc (2)", R_AX, outregs.eax == 0x123456ff); 15832a9b5718SPaolo Bonzini } 15842a9b5718SPaolo Bonzini 15850987db7aSGleb Natapov static void test_fninit(void) 15860987db7aSGleb Natapov { 15870987db7aSGleb Natapov u16 fcw = -1, fsw = -1; 15880987db7aSGleb Natapov MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)"); 15890987db7aSGleb Natapov 1590bd62e289SBill Wendling init_inregs(&(struct regs){ .eax = (u32)&fsw, .ebx = (u32)&fcw }); 15910987db7aSGleb Natapov 15920987db7aSGleb Natapov exec_in_big_real_mode(&insn_fninit); 15930987db7aSGleb Natapov report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f); 15940987db7aSGleb Natapov } 15950987db7aSGleb Natapov 15961a4c03a0SArthur Chunqi Li static void test_nopl(void) 15971a4c03a0SArthur Chunqi Li { 15981a4c03a0SArthur Chunqi Li MK_INSN(nopl1, ".byte 0x90\n\r"); // 1 byte nop 15991a4c03a0SArthur Chunqi Li MK_INSN(nopl2, ".byte 0x66, 0x90\n\r"); // 2 bytes nop 16001a4c03a0SArthur Chunqi Li MK_INSN(nopl3, ".byte 0x0f, 0x1f, 0x00\n\r"); // 3 bytes nop 16011a4c03a0SArthur Chunqi Li MK_INSN(nopl4, ".byte 0x0f, 0x1f, 0x40, 0x00\n\r"); // 4 bytes nop 16021a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl1); 16031a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl2); 16041a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl3); 16051a4c03a0SArthur Chunqi Li exec_in_big_real_mode(&insn_nopl4); 16061a4c03a0SArthur Chunqi Li report("nopl", 0, 1); 16071a4c03a0SArthur Chunqi Li } 16081a4c03a0SArthur Chunqi Li 1609b5105e8bSPaolo Bonzini static u32 perf_baseline; 1610b5105e8bSPaolo Bonzini 16117505ea23SPaolo Bonzini #define PERF_COUNT 1000000 1612b5105e8bSPaolo Bonzini 1613b5105e8bSPaolo Bonzini #define MK_INSN_PERF(name, insn) \ 1614b5105e8bSPaolo Bonzini MK_INSN(name, "rdtsc; mov %eax, %ebx; mov %edx, %esi\n" \ 1615b5105e8bSPaolo Bonzini "1:" insn "\n" \ 16167505ea23SPaolo Bonzini ".byte 0x67; loop 1b\n" \ 1617b5105e8bSPaolo Bonzini "rdtsc"); 1618b5105e8bSPaolo Bonzini 1619b5105e8bSPaolo Bonzini static u32 cycles_in_big_real_mode(struct insn_desc *insn) 1620b5105e8bSPaolo Bonzini { 1621b5105e8bSPaolo Bonzini u64 start, end; 1622b5105e8bSPaolo Bonzini 1623bd62e289SBill Wendling init_inregs(&(struct regs){ .ecx = PERF_COUNT }); 1624bd62e289SBill Wendling 1625b5105e8bSPaolo Bonzini exec_in_big_real_mode(insn); 1626b5105e8bSPaolo Bonzini start = ((u64)outregs.esi << 32) | outregs.ebx; 1627b5105e8bSPaolo Bonzini end = ((u64)outregs.edx << 32) | outregs.eax; 1628b5105e8bSPaolo Bonzini 1629b5105e8bSPaolo Bonzini return end - start; 1630b5105e8bSPaolo Bonzini } 1631b5105e8bSPaolo Bonzini 1632b5105e8bSPaolo Bonzini static void test_perf_loop(void) 1633b5105e8bSPaolo Bonzini { 1634b5105e8bSPaolo Bonzini /* 1635b5105e8bSPaolo Bonzini * This test runs simple instructions that should roughly take the 1636b5105e8bSPaolo Bonzini * the same time to emulate: PERF_COUNT iterations of "loop" and 3 1637b5105e8bSPaolo Bonzini * setup instructions. Other performance tests can run PERF_COUNT 1638b5105e8bSPaolo Bonzini * iterations of the same instruction and subtract the cycle count 1639b5105e8bSPaolo Bonzini * of this test. 1640b5105e8bSPaolo Bonzini */ 1641b5105e8bSPaolo Bonzini MK_INSN_PERF(perf_loop, ""); 1642b5105e8bSPaolo Bonzini perf_baseline = cycles_in_big_real_mode(&insn_perf_loop); 1643b5105e8bSPaolo Bonzini print_serial_u32(perf_baseline / (PERF_COUNT + 3)); 1644b5105e8bSPaolo Bonzini print_serial(" cycles/emulated jump instruction\n"); 1645b5105e8bSPaolo Bonzini } 1646b5105e8bSPaolo Bonzini 1647b5105e8bSPaolo Bonzini static void test_perf_mov(void) 1648b5105e8bSPaolo Bonzini { 1649b5105e8bSPaolo Bonzini u32 cyc; 1650b5105e8bSPaolo Bonzini 1651b5105e8bSPaolo Bonzini MK_INSN_PERF(perf_move, "mov %esi, %edi"); 1652b5105e8bSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_move); 1653b5105e8bSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 1654b5105e8bSPaolo Bonzini print_serial(" cycles/emulated move instruction\n"); 1655b5105e8bSPaolo Bonzini } 1656b5105e8bSPaolo Bonzini 1657b5105e8bSPaolo Bonzini static void test_perf_arith(void) 1658b5105e8bSPaolo Bonzini { 1659b5105e8bSPaolo Bonzini u32 cyc; 1660b5105e8bSPaolo Bonzini 1661b5105e8bSPaolo Bonzini MK_INSN_PERF(perf_arith, "add $4, %edi"); 1662b5105e8bSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_arith); 1663b5105e8bSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 1664b5105e8bSPaolo Bonzini print_serial(" cycles/emulated arithmetic instruction\n"); 1665b5105e8bSPaolo Bonzini } 1666b5105e8bSPaolo Bonzini 1667b5105e8bSPaolo Bonzini static void test_perf_memory_load(void) 1668b5105e8bSPaolo Bonzini { 1669b5105e8bSPaolo Bonzini u32 cyc, tmp; 1670b5105e8bSPaolo Bonzini 1671576718d0SBill Wendling MK_INSN_PERF(perf_memory_load, "cmpw $0, (%edi)"); 1672bd62e289SBill Wendling 1673bd62e289SBill Wendling init_inregs(&(struct regs){ .edi = (u32)&tmp }); 1674bd62e289SBill Wendling 1675b5105e8bSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_memory_load); 1676b5105e8bSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 1677b5105e8bSPaolo Bonzini print_serial(" cycles/emulated memory load instruction\n"); 1678b5105e8bSPaolo Bonzini } 1679b5105e8bSPaolo Bonzini 16809306cb8eSPaolo Bonzini static void test_perf_memory_store(void) 16819306cb8eSPaolo Bonzini { 16829306cb8eSPaolo Bonzini u32 cyc, tmp; 16839306cb8eSPaolo Bonzini 1684576718d0SBill Wendling MK_INSN_PERF(perf_memory_store, "movw %ax, (%edi)"); 1685bd62e289SBill Wendling 1686bd62e289SBill Wendling init_inregs(&(struct regs){ .edi = (u32)&tmp }); 1687bd62e289SBill Wendling 16889306cb8eSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_memory_store); 16899306cb8eSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 16909306cb8eSPaolo Bonzini print_serial(" cycles/emulated memory store instruction\n"); 16919306cb8eSPaolo Bonzini } 16929306cb8eSPaolo Bonzini 1693b5105e8bSPaolo Bonzini static void test_perf_memory_rmw(void) 1694b5105e8bSPaolo Bonzini { 1695b5105e8bSPaolo Bonzini u32 cyc, tmp; 1696b5105e8bSPaolo Bonzini 1697576718d0SBill Wendling MK_INSN_PERF(perf_memory_rmw, "addw $1, (%edi)"); 1698bd62e289SBill Wendling 1699bd62e289SBill Wendling init_inregs(&(struct regs){ .edi = (u32)&tmp }); 1700bd62e289SBill Wendling 1701b5105e8bSPaolo Bonzini cyc = cycles_in_big_real_mode(&insn_perf_memory_rmw); 1702b5105e8bSPaolo Bonzini print_serial_u32((cyc - perf_baseline) / PERF_COUNT); 1703b5105e8bSPaolo Bonzini print_serial(" cycles/emulated memory RMW instruction\n"); 1704b5105e8bSPaolo Bonzini } 1705b5105e8bSPaolo Bonzini 17062e3f9f1fSThomas Huth static void test_dr_mod(void) 17070a5701edSNadav Amit { 17080a5701edSNadav Amit MK_INSN(drmod, "movl %ebx, %dr0\n\t" 17090a5701edSNadav Amit ".byte 0x0f \n\t .byte 0x21 \n\t .byte 0x0\n\t"); 1710bd62e289SBill Wendling 1711bd62e289SBill Wendling init_inregs(&(struct regs){ .eax = 0xdead, .ebx = 0xaced }); 1712bd62e289SBill Wendling 17130a5701edSNadav Amit exec_in_big_real_mode(&insn_drmod); 17140a5701edSNadav Amit report("mov dr with mod bits", R_AX | R_BX, outregs.eax == 0xaced); 17150a5701edSNadav Amit } 17160a5701edSNadav Amit 17172e3f9f1fSThomas Huth static void test_smsw(void) 171899ee878cSNadav Amit { 171999ee878cSNadav Amit MK_INSN(smsw, "movl %cr0, %ebx\n\t" 172099ee878cSNadav Amit "movl %ebx, %ecx\n\t" 172199ee878cSNadav Amit "or $0x40000000, %ebx\n\t" 172299ee878cSNadav Amit "movl %ebx, %cr0\n\t" 172399ee878cSNadav Amit "smswl %eax\n\t" 172499ee878cSNadav Amit "movl %ecx, %cr0\n\t"); 1725bd62e289SBill Wendling 1726bd62e289SBill Wendling init_inregs(&(struct regs){ .eax = 0x12345678 }); 1727bd62e289SBill Wendling 172899ee878cSNadav Amit exec_in_big_real_mode(&insn_smsw); 172999ee878cSNadav Amit report("smsw", R_AX | R_BX | R_CX, outregs.eax == outregs.ebx); 173099ee878cSNadav Amit } 173199ee878cSNadav Amit 17322e3f9f1fSThomas Huth static void test_xadd(void) 17337bee560dSNadav Amit { 17347bee560dSNadav Amit MK_INSN(xadd, "xaddl %eax, %eax\n\t"); 1735bd62e289SBill Wendling 1736bd62e289SBill Wendling init_inregs(&(struct regs){ .eax = 0x12345678 }); 1737bd62e289SBill Wendling 17387bee560dSNadav Amit exec_in_big_real_mode(&insn_xadd); 17397bee560dSNadav Amit report("xadd", R_AX, outregs.eax == inregs.eax * 2); 17407bee560dSNadav Amit } 17417bee560dSNadav Amit 174299ee878cSNadav Amit 17437d36db35SAvi Kivity void realmode_start(void) 17447d36db35SAvi Kivity { 17457d36db35SAvi Kivity test_null(); 17467d36db35SAvi Kivity 17477d36db35SAvi Kivity test_shld(); 17487d36db35SAvi Kivity test_push_pop(); 17497d36db35SAvi Kivity test_pusha_popa(); 17507d36db35SAvi Kivity test_mov_imm(); 17517d36db35SAvi Kivity test_cmp_imm(); 17527d36db35SAvi Kivity test_add_imm(); 17537d36db35SAvi Kivity test_sub_imm(); 17547d36db35SAvi Kivity test_xor_imm(); 17557d36db35SAvi Kivity test_io(); 17567d36db35SAvi Kivity test_eflags_insn(); 17577d36db35SAvi Kivity test_jcc_short(); 17587d36db35SAvi Kivity test_jcc_near(); 17597d36db35SAvi Kivity /* test_call() uses short jump so call it after testing jcc */ 17607d36db35SAvi Kivity test_call(); 17617d36db35SAvi Kivity /* long jmp test uses call near so test it after testing call */ 17627d36db35SAvi Kivity test_long_jmp(); 17637d36db35SAvi Kivity test_xchg(); 17647d36db35SAvi Kivity test_iret(); 176596b9ca1eSMohammed Gamal test_int(); 17668202cf84SRoman Bolshakov test_sti_inhibit(); 1767fa74f8a6SMohammed Gamal test_imul(); 176859317bd1SMohammed Gamal test_mul(); 17690d4c7614SMohammed Gamal test_div(); 17700d4c7614SMohammed Gamal test_idiv(); 1771eacef4e2SWei Yongjun test_loopcc(); 17726e293cf5SWei Yongjun test_cbw(); 17730cbd5b06SMohammed Gamal test_cwd_cdq(); 1774b274feedSAvi Kivity test_das(); 177537f51a4aSWei Yongjun test_lds_lss(); 1776b1c7c575SWei Yongjun test_jcxz(); 17778f578e98SAvi Kivity test_cpuid(); 1778ed93f43bSAvi Kivity test_ss_base_for_esp_ebp(); 1779c2281fa4SAvi Kivity test_sgdt_sidt(); 17807ae3645aSAvi Kivity test_lahf(); 178188b6dac4SPaolo Bonzini test_sahf(); 1782fd9ea640SAvi Kivity test_movzx_movsx(); 1783b493b2e8SAvi Kivity test_bswap(); 17848cd86387SGleb Natapov test_aad(); 17852a9b5718SPaolo Bonzini test_aam(); 17862a9b5718SPaolo Bonzini test_xlat(); 17872a9b5718SPaolo Bonzini test_salc(); 17880987db7aSGleb Natapov test_fninit(); 17890a5701edSNadav Amit test_dr_mod(); 179099ee878cSNadav Amit test_smsw(); 17911a4c03a0SArthur Chunqi Li test_nopl(); 17927bee560dSNadav Amit test_xadd(); 1793b5105e8bSPaolo Bonzini test_perf_loop(); 1794b5105e8bSPaolo Bonzini test_perf_mov(); 1795b5105e8bSPaolo Bonzini test_perf_arith(); 1796b5105e8bSPaolo Bonzini test_perf_memory_load(); 17979306cb8eSPaolo Bonzini test_perf_memory_store(); 1798b5105e8bSPaolo Bonzini test_perf_memory_rmw(); 17997d36db35SAvi Kivity 1800b393fe28SNadav Amit exit(failed); 18017d36db35SAvi Kivity } 18027d36db35SAvi Kivity 18037d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff }; 18047d36db35SAvi Kivity 1805975ca087SPeter Feiner struct table_descr r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt }; 1806a529af7cSNadav Amit struct table_descr r_idt_descr = { 0x3ff, 0 }; 18077d36db35SAvi Kivity 18087d36db35SAvi Kivity asm( 18097d36db35SAvi Kivity ".section .init \n\t" 18107d36db35SAvi Kivity 18117d36db35SAvi Kivity ".code32 \n\t" 18127d36db35SAvi Kivity 18137d36db35SAvi Kivity "mb_magic = 0x1BADB002 \n\t" 18147d36db35SAvi Kivity "mb_flags = 0x0 \n\t" 18157d36db35SAvi Kivity 18167d36db35SAvi Kivity "# multiboot header \n\t" 18177d36db35SAvi Kivity ".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t" 18187d36db35SAvi Kivity 18197d36db35SAvi Kivity ".globl start \n\t" 18207d36db35SAvi Kivity ".data \n\t" 18217d36db35SAvi Kivity ". = . + 4096 \n\t" 18227d36db35SAvi Kivity "stacktop: \n\t" 18237d36db35SAvi Kivity 18247d36db35SAvi Kivity ".text \n\t" 18257d36db35SAvi Kivity "start: \n\t" 18267d36db35SAvi Kivity "lgdt r_gdt_descr \n\t" 1827a529af7cSNadav Amit "lidt r_idt_descr \n\t" 18287d36db35SAvi Kivity "ljmp $8, $1f; 1: \n\t" 18297d36db35SAvi Kivity ".code16gcc \n\t" 18307d36db35SAvi Kivity "mov $16, %eax \n\t" 18317d36db35SAvi Kivity "mov %ax, %ds \n\t" 18327d36db35SAvi Kivity "mov %ax, %es \n\t" 18337d36db35SAvi Kivity "mov %ax, %fs \n\t" 18347d36db35SAvi Kivity "mov %ax, %gs \n\t" 18357d36db35SAvi Kivity "mov %ax, %ss \n\t" 18367d36db35SAvi Kivity "mov %cr0, %eax \n\t" 18377d36db35SAvi Kivity "btc $0, %eax \n\t" 18387d36db35SAvi Kivity "mov %eax, %cr0 \n\t" 18397d36db35SAvi Kivity "ljmp $0, $realmode_entry \n\t" 18407d36db35SAvi Kivity 18417d36db35SAvi Kivity "realmode_entry: \n\t" 18427d36db35SAvi Kivity 18437d36db35SAvi Kivity "xor %ax, %ax \n\t" 18447d36db35SAvi Kivity "mov %ax, %ds \n\t" 18457d36db35SAvi Kivity "mov %ax, %es \n\t" 18467d36db35SAvi Kivity "mov %ax, %ss \n\t" 18477d36db35SAvi Kivity "mov %ax, %fs \n\t" 18487d36db35SAvi Kivity "mov %ax, %gs \n\t" 18497d36db35SAvi Kivity "mov $stacktop, %esp\n\t" 18507d36db35SAvi Kivity "ljmp $0, $realmode_start \n\t" 18517d36db35SAvi Kivity 18527d36db35SAvi Kivity ".code16gcc \n\t" 18537d36db35SAvi Kivity ); 1854