1 asm(".code16gcc"); 2 3 typedef unsigned char u8; 4 typedef unsigned short u16; 5 typedef unsigned u32; 6 typedef unsigned long long u64; 7 8 void test_function(void); 9 10 asm( 11 "test_function: \n\t" 12 "mov $0x1234, %eax \n\t" 13 "ret" 14 ); 15 16 static int strlen(const char *str) 17 { 18 int n; 19 20 for (n = 0; *str; ++str) 21 ++n; 22 return n; 23 } 24 25 static void print_serial(const char *buf) 26 { 27 unsigned long len = strlen(buf); 28 29 asm volatile ("cld; addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1)); 30 } 31 32 static void exit(int code) 33 { 34 asm volatile("out %0, %1" : : "a"(code), "d"((short)0xf4)); 35 } 36 37 struct regs { 38 u32 eax, ebx, ecx, edx; 39 u32 esi, edi, esp, ebp; 40 u32 eip, eflags; 41 }; 42 43 static u64 gdt[] = { 44 0, 45 0x00cf9b000000ffffull, // flat 32-bit code segment 46 0x00cf93000000ffffull, // flat 32-bit data segment 47 }; 48 49 static struct { 50 u16 limit; 51 void *base; 52 } __attribute__((packed)) gdt_descr = { 53 sizeof(gdt) - 1, 54 gdt, 55 }; 56 57 static void exec_in_big_real_mode(const struct regs *inregs, 58 struct regs *outregs, 59 const u8 *insn, int insn_len) 60 { 61 unsigned long tmp; 62 static struct regs save; 63 int i; 64 extern u8 test_insn[], test_insn_end[]; 65 66 for (i = 0; i < insn_len; ++i) 67 test_insn[i] = insn[i]; 68 for (; i < test_insn_end - test_insn; ++i) 69 test_insn[i] = 0x90; // nop 70 71 save = *inregs; 72 asm volatile( 73 "lgdtl %[gdt_descr] \n\t" 74 "mov %%cr0, %[tmp] \n\t" 75 "or $1, %[tmp] \n\t" 76 "mov %[tmp], %%cr0 \n\t" 77 "mov %[bigseg], %%gs \n\t" 78 "and $-2, %[tmp] \n\t" 79 "mov %[tmp], %%cr0 \n\t" 80 81 "pushw %[save]+36; popfw \n\t" 82 "xchg %%eax, %[save]+0 \n\t" 83 "xchg %%ebx, %[save]+4 \n\t" 84 "xchg %%ecx, %[save]+8 \n\t" 85 "xchg %%edx, %[save]+12 \n\t" 86 "xchg %%esi, %[save]+16 \n\t" 87 "xchg %%edi, %[save]+20 \n\t" 88 "xchg %%esp, %[save]+24 \n\t" 89 "xchg %%ebp, %[save]+28 \n\t" 90 91 "test_insn: . = . + 32\n\t" 92 "test_insn_end: \n\t" 93 94 "xchg %%eax, %[save]+0 \n\t" 95 "xchg %%ebx, %[save]+4 \n\t" 96 "xchg %%ecx, %[save]+8 \n\t" 97 "xchg %%edx, %[save]+12 \n\t" 98 "xchg %%esi, %[save]+16 \n\t" 99 "xchg %%edi, %[save]+20 \n\t" 100 "xchg %%esp, %[save]+24 \n\t" 101 "xchg %%ebp, %[save]+28 \n\t" 102 103 /* Save EFLAGS in outregs*/ 104 "pushfl \n\t" 105 "popl %[save]+36 \n\t" 106 107 "xor %[tmp], %[tmp] \n\t" 108 "mov %[tmp], %%gs \n\t" 109 : [tmp]"=&r"(tmp), [save]"+m"(save) 110 : [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16) 111 : "cc", "memory" 112 ); 113 *outregs = save; 114 } 115 116 #define R_AX 1 117 #define R_BX 2 118 #define R_CX 4 119 #define R_DX 8 120 #define R_SI 16 121 #define R_DI 32 122 #define R_SP 64 123 #define R_BP 128 124 125 int regs_equal(const struct regs *r1, const struct regs *r2, int ignore) 126 { 127 const u32 *p1 = &r1->eax, *p2 = &r2->eax; // yuck 128 int i; 129 130 for (i = 0; i < 8; ++i) 131 if (!(ignore & (1 << i)) && p1[i] != p2[i]) 132 return 0; 133 return 1; 134 } 135 136 #define MK_INSN(name, str) \ 137 asm ( \ 138 ".text 1\n\t" \ 139 "insn_" #name ": " str " \n\t" \ 140 "insn_" #name "_end: \n\t" \ 141 ".text\n\t" \ 142 ); \ 143 extern u8 insn_##name[], insn_##name##_end[] 144 145 void test_xchg(void) 146 { 147 struct regs inregs = { .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7}, outregs; 148 149 MK_INSN(xchg_test1, "xchg %eax,%eax\n\t"); 150 MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t"); 151 MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t"); 152 MK_INSN(xchg_test4, "xchg %eax,%edx\n\t"); 153 MK_INSN(xchg_test5, "xchg %eax,%esi\n\t"); 154 MK_INSN(xchg_test6, "xchg %eax,%edi\n\t"); 155 MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t"); 156 MK_INSN(xchg_test8, "xchg %eax,%esp\n\t"); 157 158 exec_in_big_real_mode(&inregs, &outregs, 159 insn_xchg_test1, 160 insn_xchg_test1_end - insn_xchg_test1); 161 162 if (!regs_equal(&inregs, &outregs, 0)) 163 print_serial("xchg test 1: FAIL\n"); 164 else 165 print_serial("xchg test 1: PASS\n"); 166 167 exec_in_big_real_mode(&inregs, &outregs, 168 insn_xchg_test2, 169 insn_xchg_test2_end - insn_xchg_test2); 170 171 if (!regs_equal(&inregs, &outregs, R_AX | R_BX) || 172 outregs.eax != inregs.ebx || 173 outregs.ebx != inregs.eax) 174 print_serial("xchg test 2: FAIL\n"); 175 else 176 print_serial("xchg test 2: PASS\n"); 177 178 exec_in_big_real_mode(&inregs, &outregs, 179 insn_xchg_test3, 180 insn_xchg_test3_end - insn_xchg_test3); 181 182 if (!regs_equal(&inregs, &outregs, R_AX | R_CX) || 183 outregs.eax != inregs.ecx || 184 outregs.ecx != inregs.eax) 185 print_serial("xchg test 3: FAIL\n"); 186 else 187 print_serial("xchg test 3: PASS\n"); 188 189 exec_in_big_real_mode(&inregs, &outregs, 190 insn_xchg_test4, 191 insn_xchg_test4_end - insn_xchg_test4); 192 193 if (!regs_equal(&inregs, &outregs, R_AX | R_DX) || 194 outregs.eax != inregs.edx || 195 outregs.edx != inregs.eax) 196 print_serial("xchg test 4: FAIL\n"); 197 else 198 print_serial("xchg test 4: PASS\n"); 199 200 exec_in_big_real_mode(&inregs, &outregs, 201 insn_xchg_test5, 202 insn_xchg_test5_end - insn_xchg_test5); 203 204 if (!regs_equal(&inregs, &outregs, R_AX | R_SI) || 205 outregs.eax != inregs.esi || 206 outregs.esi != inregs.eax) 207 print_serial("xchg test 5: FAIL\n"); 208 else 209 print_serial("xchg test 5: PASS\n"); 210 211 exec_in_big_real_mode(&inregs, &outregs, 212 insn_xchg_test6, 213 insn_xchg_test6_end - insn_xchg_test6); 214 215 if (!regs_equal(&inregs, &outregs, R_AX | R_DI) || 216 outregs.eax != inregs.edi || 217 outregs.edi != inregs.eax) 218 print_serial("xchg test 6: FAIL\n"); 219 else 220 print_serial("xchg test 6: PASS\n"); 221 222 exec_in_big_real_mode(&inregs, &outregs, 223 insn_xchg_test7, 224 insn_xchg_test7_end - insn_xchg_test7); 225 226 if (!regs_equal(&inregs, &outregs, R_AX | R_BP) || 227 outregs.eax != inregs.ebp || 228 outregs.ebp != inregs.eax) 229 print_serial("xchg test 7: FAIL\n"); 230 else 231 print_serial("xchg test 7: PASS\n"); 232 233 exec_in_big_real_mode(&inregs, &outregs, 234 insn_xchg_test8, 235 insn_xchg_test8_end - insn_xchg_test8); 236 237 if (!regs_equal(&inregs, &outregs, R_AX | R_SP) || 238 outregs.eax != inregs.esp || 239 outregs.esp != inregs.eax) 240 print_serial("xchg test 8: FAIL\n"); 241 else 242 print_serial("xchg test 8: PASS\n"); 243 } 244 245 void test_shld(void) 246 { 247 struct regs inregs = { .eax = 0xbe, .edx = 0xef000000 }, outregs; 248 MK_INSN(shld_test, "shld $8,%edx,%eax\n\t"); 249 250 exec_in_big_real_mode(&inregs, &outregs, 251 insn_shld_test, 252 insn_shld_test_end - insn_shld_test); 253 if (outregs.eax != 0xbeef) 254 print_serial("shld: FAIL\n"); 255 else 256 print_serial("shld: PASS\n"); 257 } 258 259 void test_mov_imm(void) 260 { 261 struct regs inregs = { 0 }, outregs; 262 MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax"); 263 MK_INSN(mov_r16_imm_1, "mov $1234, %ax"); 264 MK_INSN(mov_r8_imm_1, "mov $0x12, %ah"); 265 MK_INSN(mov_r8_imm_2, "mov $0x34, %al"); 266 MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t"); 267 268 exec_in_big_real_mode(&inregs, &outregs, 269 insn_mov_r16_imm_1, 270 insn_mov_r16_imm_1_end - insn_mov_r16_imm_1); 271 if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 1234) 272 print_serial("mov test 1: FAIL\n"); 273 else 274 print_serial("mov test 1: PASS\n"); 275 276 /* test mov $imm, %eax */ 277 exec_in_big_real_mode(&inregs, &outregs, 278 insn_mov_r32_imm_1, 279 insn_mov_r32_imm_1_end - insn_mov_r32_imm_1); 280 if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 1234567890) 281 print_serial("mov test 2: FAIL\n"); 282 else 283 print_serial("mov test 2: PASS\n"); 284 285 /* test mov $imm, %al/%ah */ 286 exec_in_big_real_mode(&inregs, &outregs, 287 insn_mov_r8_imm_1, 288 insn_mov_r8_imm_1_end - insn_mov_r8_imm_1); 289 if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1200) 290 print_serial("mov test 3: FAIL\n"); 291 else 292 print_serial("mov test 3: PASS\n"); 293 294 exec_in_big_real_mode(&inregs, &outregs, 295 insn_mov_r8_imm_2, 296 insn_mov_r8_imm_2_end - insn_mov_r8_imm_2); 297 if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x34) 298 print_serial("mov test 4: FAIL\n"); 299 else 300 print_serial("mov test 4: PASS\n"); 301 302 exec_in_big_real_mode(&inregs, &outregs, 303 insn_mov_r8_imm_3, 304 insn_mov_r8_imm_3_end - insn_mov_r8_imm_3); 305 if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234) 306 print_serial("mov test 5: FAIL\n"); 307 else 308 print_serial("mov test 5: PASS\n"); 309 } 310 311 void test_sub_imm(void) 312 { 313 struct regs inregs = { 0 }, outregs; 314 MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t"); 315 MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t"); 316 MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t"); 317 MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t"); 318 319 exec_in_big_real_mode(&inregs, &outregs, 320 insn_sub_r16_imm_1, 321 insn_sub_r16_imm_1_end - insn_sub_r16_imm_1); 322 if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 1224) 323 print_serial("sub test 1: FAIL\n"); 324 else 325 print_serial("sub test 1: PASS\n"); 326 327 /* test mov $imm, %eax */ 328 exec_in_big_real_mode(&inregs, &outregs, 329 insn_sub_r32_imm_1, 330 insn_sub_r32_imm_1_end - insn_sub_r32_imm_1); 331 if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 1234567880) 332 print_serial("sub test 2: FAIL\n"); 333 else 334 print_serial("sub test 2: PASS\n"); 335 336 /* test mov $imm, %al/%ah */ 337 exec_in_big_real_mode(&inregs, &outregs, 338 insn_sub_r8_imm_1, 339 insn_sub_r8_imm_1_end - insn_sub_r8_imm_1); 340 if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x0200) 341 print_serial("sub test 3: FAIL\n"); 342 else 343 print_serial("sub test 3: PASS\n"); 344 345 exec_in_big_real_mode(&inregs, &outregs, 346 insn_sub_r8_imm_2, 347 insn_sub_r8_imm_2_end - insn_sub_r8_imm_2); 348 if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x24) 349 print_serial("sub test 4: FAIL\n"); 350 else 351 print_serial("sub test 4: PASS\n"); 352 } 353 354 355 void test_xor_imm(void) 356 { 357 struct regs inregs = { 0 }, outregs; 358 MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t"); 359 MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t"); 360 MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t"); 361 MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t"); 362 363 exec_in_big_real_mode(&inregs, &outregs, 364 insn_xor_r16_imm_1, 365 insn_xor_r16_imm_1_end - insn_xor_r16_imm_1); 366 if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0) 367 print_serial("xor test 1: FAIL\n"); 368 else 369 print_serial("xor test 1: PASS\n"); 370 371 /* test mov $imm, %eax */ 372 exec_in_big_real_mode(&inregs, &outregs, 373 insn_xor_r32_imm_1, 374 insn_xor_r32_imm_1_end - insn_xor_r32_imm_1); 375 if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0) 376 print_serial("xor test 2: FAIL\n"); 377 else 378 print_serial("xor test 2: PASS\n"); 379 380 /* test mov $imm, %al/%ah */ 381 exec_in_big_real_mode(&inregs, &outregs, 382 insn_xor_r8_imm_1, 383 insn_xor_r8_imm_1_end - insn_xor_r8_imm_1); 384 if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0) 385 print_serial("xor test 3: FAIL\n"); 386 else 387 print_serial("xor test 3: PASS\n"); 388 389 exec_in_big_real_mode(&inregs, &outregs, 390 insn_xor_r8_imm_2, 391 insn_xor_r8_imm_2_end - insn_xor_r8_imm_2); 392 if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0) 393 print_serial("xor test 4: FAIL\n"); 394 else 395 print_serial("xor test 4: PASS\n"); 396 } 397 398 void test_cmp_imm(void) 399 { 400 struct regs inregs = { 0 }, outregs; 401 MK_INSN(cmp_test1, "mov $0x34, %al\n\t" 402 "cmp $0x34, %al\n\t"); 403 MK_INSN(cmp_test2, "mov $0x34, %al\n\t" 404 "cmp $0x39, %al\n\t"); 405 MK_INSN(cmp_test3, "mov $0x34, %al\n\t" 406 "cmp $0x24, %al\n\t"); 407 408 /* test cmp imm8 with AL */ 409 /* ZF: (bit 6) Zero Flag becomes 1 if an operation results 410 * in a 0 writeback, or 0 register 411 */ 412 exec_in_big_real_mode(&inregs, &outregs, 413 insn_cmp_test1, 414 insn_cmp_test1_end - insn_cmp_test1); 415 if ((outregs.eflags & (1<<6)) != (1<<6)) 416 print_serial("cmp test 1: FAIL\n"); 417 else 418 print_serial("cmp test 1: PASS\n"); 419 420 exec_in_big_real_mode(&inregs, &outregs, 421 insn_cmp_test2, 422 insn_cmp_test2_end - insn_cmp_test2); 423 if ((outregs.eflags & (1<<6)) != 0) 424 print_serial("cmp test 2: FAIL\n"); 425 else 426 print_serial("cmp test 2: PASS\n"); 427 428 exec_in_big_real_mode(&inregs, &outregs, 429 insn_cmp_test3, 430 insn_cmp_test3_end - insn_cmp_test3); 431 if ((outregs.eflags & (1<<6)) != 0) 432 print_serial("cmp test 3: FAIL\n"); 433 else 434 print_serial("cmp test 3: PASS\n"); 435 } 436 437 void test_add_imm(void) 438 { 439 struct regs inregs = { 0 }, outregs; 440 MK_INSN(add_test1, "mov $0x43211234, %eax \n\t" 441 "add $0x12344321, %eax \n\t"); 442 MK_INSN(add_test2, "mov $0x12, %eax \n\t" 443 "add $0x21, %al\n\t"); 444 445 exec_in_big_real_mode(&inregs, &outregs, 446 insn_add_test1, 447 insn_add_test1_end - insn_add_test1); 448 if (outregs.eax != 0x55555555) 449 print_serial("add test 1: FAIL\n"); 450 else 451 print_serial("add test 1: PASS\n"); 452 453 exec_in_big_real_mode(&inregs, &outregs, 454 insn_add_test2, 455 insn_add_test2_end - insn_add_test2); 456 if (outregs.eax != 0x33) 457 print_serial("add test 2: FAIL\n"); 458 else 459 print_serial("add test 2: PASS\n"); 460 } 461 462 void test_eflags_insn(void) 463 { 464 struct regs inregs = { 0 }, outregs; 465 MK_INSN(clc, "clc"); 466 MK_INSN(stc, "stc"); 467 MK_INSN(cli, "cli"); 468 MK_INSN(sti, "sti"); 469 MK_INSN(cld, "cld"); 470 MK_INSN(std, "std"); 471 472 exec_in_big_real_mode(&inregs, &outregs, 473 insn_clc, 474 insn_clc_end - insn_clc); 475 if (outregs.eflags & 1) 476 print_serial("clc test: FAIL\n"); 477 else 478 print_serial("clc test: PASS\n"); 479 480 exec_in_big_real_mode(&inregs, &outregs, 481 insn_stc, 482 insn_stc_end - insn_stc); 483 if (!(outregs.eflags & 1)) 484 print_serial("stc test: FAIL\n"); 485 else 486 print_serial("stc test: PASS\n"); 487 488 exec_in_big_real_mode(&inregs, &outregs, 489 insn_cli, 490 insn_cli_end - insn_cli); 491 if (outregs.eflags & (1 << 9)) 492 print_serial("cli test: FAIL\n"); 493 else 494 print_serial("cli test: PASS\n"); 495 496 exec_in_big_real_mode(&inregs, &outregs, 497 insn_sti, 498 insn_sti_end - insn_sti); 499 if (!(outregs.eflags & (1 << 9))) 500 print_serial("sti test: FAIL\n"); 501 else 502 print_serial("sti test: PASS\n"); 503 504 exec_in_big_real_mode(&inregs, &outregs, 505 insn_cld, 506 insn_cld_end - insn_cld); 507 if (outregs.eflags & (1 << 10)) 508 print_serial("cld test: FAIL\n"); 509 else 510 print_serial("cld test: PASS\n"); 511 512 exec_in_big_real_mode(&inregs, &outregs, 513 insn_std, 514 insn_std_end - insn_std); 515 if (!(outregs.eflags & (1 << 10))) 516 print_serial("std test: FAIL\n"); 517 else 518 print_serial("std test: PASS\n"); 519 } 520 521 void test_io(void) 522 { 523 struct regs inregs = { 0 }, outregs; 524 MK_INSN(io_test1, "mov $0xff, %al \n\t" 525 "out %al, $0xe0 \n\t" 526 "mov $0x00, %al \n\t" 527 "in $0xe0, %al \n\t"); 528 MK_INSN(io_test2, "mov $0xffff, %ax \n\t" 529 "out %ax, $0xe0 \n\t" 530 "mov $0x0000, %ax \n\t" 531 "in $0xe0, %ax \n\t"); 532 MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t" 533 "out %eax, $0xe0 \n\t" 534 "mov $0x000000, %eax \n\t" 535 "in $0xe0, %eax \n\t"); 536 MK_INSN(io_test4, "mov $0xe0, %dx \n\t" 537 "mov $0xff, %al \n\t" 538 "out %al, %dx \n\t" 539 "mov $0x00, %al \n\t" 540 "in %dx, %al \n\t"); 541 MK_INSN(io_test5, "mov $0xe0, %dx \n\t" 542 "mov $0xffff, %ax \n\t" 543 "out %ax, %dx \n\t" 544 "mov $0x0000, %ax \n\t" 545 "in %dx, %ax \n\t"); 546 MK_INSN(io_test6, "mov $0xe0, %dx \n\t" 547 "mov $0xffffffff, %eax \n\t" 548 "out %eax, %dx \n\t" 549 "mov $0x00000000, %eax \n\t" 550 "in %dx, %eax \n\t"); 551 552 exec_in_big_real_mode(&inregs, &outregs, 553 insn_io_test1, 554 insn_io_test1_end - insn_io_test1); 555 556 if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0xff) 557 print_serial("I/O test 1: FAIL\n"); 558 else 559 print_serial("I/O test 1: PASS\n"); 560 561 exec_in_big_real_mode(&inregs, &outregs, 562 insn_io_test2, 563 insn_io_test2_end - insn_io_test2); 564 565 if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0xffff) 566 print_serial("I/O test 2: FAIL\n"); 567 else 568 print_serial("I/O test 2: PASS\n"); 569 570 exec_in_big_real_mode(&inregs, &outregs, 571 insn_io_test3, 572 insn_io_test3_end - insn_io_test3); 573 574 if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0xffffffff) 575 print_serial("I/O test 3: FAIL\n"); 576 else 577 print_serial("I/O test 3: PASS\n"); 578 579 exec_in_big_real_mode(&inregs, &outregs, 580 insn_io_test4, 581 insn_io_test4_end - insn_io_test4); 582 583 if (!regs_equal(&inregs, &outregs, R_AX|R_DX) || outregs.eax != 0xff) 584 print_serial("I/O test 4: FAIL\n"); 585 else 586 print_serial("I/O test 4: PASS\n"); 587 588 exec_in_big_real_mode(&inregs, &outregs, 589 insn_io_test5, 590 insn_io_test5_end - insn_io_test5); 591 592 if (!regs_equal(&inregs, &outregs, R_AX|R_DX) || outregs.eax != 0xffff) 593 print_serial("I/O test 5: FAIL\n"); 594 else 595 print_serial("I/O test 5: PASS\n"); 596 597 exec_in_big_real_mode(&inregs, &outregs, 598 insn_io_test6, 599 insn_io_test6_end - insn_io_test6); 600 601 if (!regs_equal(&inregs, &outregs, R_AX|R_DX) || outregs.eax != 0xffffffff) 602 print_serial("I/O test 6: FAIL\n"); 603 else 604 print_serial("I/O test 6: PASS\n"); 605 } 606 607 asm ("retf: lretw"); 608 extern void retf(); 609 610 void test_call(void) 611 { 612 struct regs inregs = { 0 }, outregs; 613 u32 esp[16]; 614 u32 addr; 615 616 inregs.esp = (u32)esp; 617 618 MK_INSN(call1, "mov $test_function, %eax \n\t" 619 "call *%eax\n\t"); 620 MK_INSN(call_near1, "jmp 2f\n\t" 621 "1: mov $0x1234, %eax\n\t" 622 "ret\n\t" 623 "2: call 1b\t"); 624 MK_INSN(call_near2, "call 1f\n\t" 625 "jmp 2f\n\t" 626 "1: mov $0x1234, %eax\n\t" 627 "ret\n\t" 628 "2:\t"); 629 MK_INSN(call_far1, "lcallw *(%ebx)\n\t"); 630 MK_INSN(ret_imm, "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b"); 631 632 exec_in_big_real_mode(&inregs, &outregs, 633 insn_call1, 634 insn_call1_end - insn_call1); 635 if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234) 636 print_serial("Call Test 1: FAIL\n"); 637 else 638 print_serial("Call Test 1: PASS\n"); 639 640 exec_in_big_real_mode(&inregs, &outregs, 641 insn_call_near1, insn_call_near1_end - insn_call_near1); 642 if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234) 643 print_serial("Call near Test 1: FAIL\n"); 644 else 645 print_serial("Call near Test 1: PASS\n"); 646 647 exec_in_big_real_mode(&inregs, &outregs, 648 insn_call_near2, insn_call_near2_end - insn_call_near2); 649 if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234) 650 print_serial("Call near Test 2: FAIL\n"); 651 else 652 print_serial("Call near Test 2: PASS\n"); 653 654 addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f); 655 inregs.ebx = (unsigned)&addr; 656 exec_in_big_real_mode(&inregs, &outregs, insn_call_far1, 657 insn_call_far1_end - insn_call_far1); 658 if (!regs_equal(&inregs, &outregs, 0)) 659 print_serial("Call far Test 1: FAIL\n"); 660 else 661 print_serial("Call far Test 1: PASS\n"); 662 663 exec_in_big_real_mode(&inregs, &outregs, insn_ret_imm, 664 insn_ret_imm_end - insn_ret_imm); 665 if (!regs_equal(&inregs, &outregs, 0)) 666 print_serial("ret imm Test 1: FAIL\n"); 667 else 668 print_serial("ret imm Test 1: PASS\n"); 669 } 670 671 void test_jcc_short(void) 672 { 673 struct regs inregs = { 0 }, outregs; 674 MK_INSN(jnz_short1, "jnz 1f\n\t" 675 "mov $0x1234, %eax\n\t" 676 "1:\n\t"); 677 MK_INSN(jnz_short2, "1:\n\t" 678 "cmp $0x1234, %eax\n\t" 679 "mov $0x1234, %eax\n\t" 680 "jnz 1b\n\t"); 681 MK_INSN(jmp_short1, "jmp 1f\n\t" 682 "mov $0x1234, %eax\n\t" 683 "1:\n\t"); 684 685 exec_in_big_real_mode(&inregs, &outregs, 686 insn_jnz_short1, insn_jnz_short1_end - insn_jnz_short1); 687 if(!regs_equal(&inregs, &outregs, 0)) 688 print_serial("JNZ short Test 1: FAIL\n"); 689 else 690 print_serial("JNZ short Test 1: PASS\n"); 691 692 exec_in_big_real_mode(&inregs, &outregs, 693 insn_jnz_short2, insn_jnz_short2_end - insn_jnz_short2); 694 if(!regs_equal(&inregs, &outregs, R_AX) || !(outregs.eflags & (1 << 6))) 695 print_serial("JNZ short Test 2: FAIL\n"); 696 else 697 print_serial("JNZ short Test 2: PASS\n"); 698 699 exec_in_big_real_mode(&inregs, &outregs, 700 insn_jmp_short1, insn_jmp_short1_end - insn_jmp_short1); 701 if(!regs_equal(&inregs, &outregs, 0)) 702 print_serial("JMP short Test 1: FAIL\n"); 703 else 704 print_serial("JMP short Test 1: PASS\n"); 705 } 706 707 void test_jcc_near(void) 708 { 709 struct regs inregs = { 0 }, outregs; 710 /* encode near jmp manually. gas will not do it if offsets < 127 byte */ 711 MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t" 712 "mov $0x1234, %eax\n\t"); 713 MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t" 714 "mov $0x1234, %eax\n\t" 715 ".byte 0x0f, 0x85, 0xf0, 0xff\n\t"); 716 MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t" 717 "mov $0x1234, %eax\n\t"); 718 719 exec_in_big_real_mode(&inregs, &outregs, 720 insn_jnz_near1, insn_jnz_near1_end - insn_jnz_near1); 721 if(!regs_equal(&inregs, &outregs, 0)) 722 print_serial("JNZ near Test 1: FAIL\n"); 723 else 724 print_serial("JNZ near Test 1: PASS\n"); 725 726 exec_in_big_real_mode(&inregs, &outregs, 727 insn_jnz_near2, insn_jnz_near2_end - insn_jnz_near2); 728 if(!regs_equal(&inregs, &outregs, R_AX) || !(outregs.eflags & (1 << 6))) 729 print_serial("JNZ near Test 2: FAIL\n"); 730 else 731 print_serial("JNZ near Test 2: PASS\n"); 732 733 exec_in_big_real_mode(&inregs, &outregs, 734 insn_jmp_near1, insn_jmp_near1_end - insn_jmp_near1); 735 if(!regs_equal(&inregs, &outregs, 0)) 736 print_serial("JMP near Test 1: FAIL\n"); 737 else 738 print_serial("JMP near Test 1: PASS\n"); 739 } 740 741 void test_long_jmp() 742 { 743 struct regs inregs = { 0 }, outregs; 744 u32 esp[16]; 745 746 inregs.esp = (u32)esp; 747 MK_INSN(long_jmp, "call 1f\n\t" 748 "jmp 2f\n\t" 749 "1: jmp $0, $test_function\n\t" 750 "2:\n\t"); 751 exec_in_big_real_mode(&inregs, &outregs, 752 insn_long_jmp, 753 insn_long_jmp_end - insn_long_jmp); 754 if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234) 755 print_serial("Long JMP Test: FAIL\n"); 756 else 757 print_serial("Long JMP Test: PASS\n"); 758 } 759 760 void test_push_pop() 761 { 762 struct regs inregs = { 0 }, outregs; 763 MK_INSN(push32, "mov $0x12345678, %eax\n\t" 764 "push %eax\n\t" 765 "pop %ebx\n\t"); 766 MK_INSN(push16, "mov $0x1234, %ax\n\t" 767 "push %ax\n\t" 768 "pop %bx\n\t"); 769 770 MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten 771 "mov $0x123, %ax\n\t" 772 "mov %ax, %es\n\t" 773 "push %es\n\t" 774 "pop %bx \n\t" 775 ); 776 MK_INSN(pop_es, "push %ax\n\t" 777 "pop %es\n\t" 778 "mov %es, %bx\n\t" 779 ); 780 MK_INSN(push_pop_ss, "push %ss\n\t" 781 "pushw %ax\n\t" 782 "popw %ss\n\t" 783 "mov %ss, %bx\n\t" 784 "pop %ss\n\t" 785 ); 786 MK_INSN(push_pop_fs, "push %fs\n\t" 787 "pushl %eax\n\t" 788 "popl %fs\n\t" 789 "mov %fs, %ebx\n\t" 790 "pop %fs\n\t" 791 ); 792 793 exec_in_big_real_mode(&inregs, &outregs, 794 insn_push32, 795 insn_push32_end - insn_push32); 796 if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.eax != outregs.ebx || outregs.eax != 0x12345678) 797 print_serial("Push/Pop Test 1: FAIL\n"); 798 else 799 print_serial("Push/Pop Test 1: PASS\n"); 800 801 exec_in_big_real_mode(&inregs, &outregs, 802 insn_push16, 803 insn_push16_end - insn_push16); 804 805 if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.eax != outregs.ebx || outregs.eax != 0x1234) 806 print_serial("Push/Pop Test 2: FAIL\n"); 807 else 808 print_serial("Push/Pop Test 2: PASS\n"); 809 810 exec_in_big_real_mode(&inregs, &outregs, 811 insn_push_es, 812 insn_push_es_end - insn_push_es); 813 if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.ebx != outregs.eax || outregs.eax != 0x123) 814 print_serial("Push/Pop Test 3: FAIL\n"); 815 else 816 print_serial("Push/Pop Test 3: PASS\n"); 817 818 exec_in_big_real_mode(&inregs, &outregs, 819 insn_pop_es, 820 insn_pop_es_end - insn_pop_es); 821 822 if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.ebx != outregs.eax) 823 print_serial("Push/Pop Test 4: FAIL\n"); 824 else 825 print_serial("Push/Pop Test 4: PASS\n"); 826 827 exec_in_big_real_mode(&inregs, &outregs, 828 insn_push_pop_ss, 829 insn_push_pop_ss_end - insn_push_pop_ss); 830 831 if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.ebx != outregs.eax) 832 print_serial("Push/Pop Test 5: FAIL\n"); 833 else 834 print_serial("Push/Pop Test 5: PASS\n"); 835 836 exec_in_big_real_mode(&inregs, &outregs, 837 insn_push_pop_fs, 838 insn_push_pop_fs_end - insn_push_pop_fs); 839 840 if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.ebx != outregs.eax) 841 print_serial("Push/Pop Test 6: FAIL\n"); 842 else 843 print_serial("Push/Pop Test 6: PASS\n"); 844 } 845 846 void test_null(void) 847 { 848 struct regs inregs = { 0 }, outregs; 849 exec_in_big_real_mode(&inregs, &outregs, 0, 0); 850 if (!regs_equal(&inregs, &outregs, 0)) 851 print_serial("null test: FAIL\n"); 852 else 853 print_serial("null test: PASS\n"); 854 } 855 856 struct { 857 char stack[500]; 858 char top[]; 859 } tmp_stack; 860 861 void test_pusha_popa() 862 { 863 struct regs inregs = { .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top }, outregs; 864 865 MK_INSN(pusha, "pusha\n\t" 866 "pop %edi\n\t" 867 "pop %esi\n\t" 868 "pop %ebp\n\t" 869 "add $4, %esp\n\t" 870 "pop %ebx\n\t" 871 "pop %edx\n\t" 872 "pop %ecx\n\t" 873 "pop %eax\n\t" 874 ); 875 876 MK_INSN(popa, "push %eax\n\t" 877 "push %ecx\n\t" 878 "push %edx\n\t" 879 "push %ebx\n\t" 880 "push %esp\n\t" 881 "push %ebp\n\t" 882 "push %esi\n\t" 883 "push %edi\n\t" 884 "popa\n\t" 885 ); 886 887 exec_in_big_real_mode(&inregs, &outregs, 888 insn_pusha, 889 insn_pusha_end - insn_pusha); 890 891 if (!regs_equal(&inregs, &outregs, 0)) 892 print_serial("Pusha/Popa Test1: FAIL\n"); 893 else 894 print_serial("Pusha/Popa Test1: PASS\n"); 895 896 exec_in_big_real_mode(&inregs, &outregs, 897 insn_popa, 898 insn_popa_end - insn_popa); 899 if (!regs_equal(&inregs, &outregs, 0)) 900 print_serial("Pusha/Popa Test2: FAIL\n"); 901 else 902 print_serial("Pusha/Popa Test2: PASS\n"); 903 } 904 905 void test_iret() 906 { 907 struct regs inregs = { 0 }, outregs; 908 909 MK_INSN(iret32, "pushf\n\t" 910 "pushl %cs\n\t" 911 "call 1f\n\t" /* a near call will push eip onto the stack */ 912 "jmp 2f\n\t" 913 "1: iret\n\t" 914 "2:\n\t" 915 ); 916 917 MK_INSN(iret16, "pushfw\n\t" 918 "pushw %cs\n\t" 919 "callw 1f\n\t" 920 "jmp 2f\n\t" 921 "1: iretw\n\t" 922 "2:\n\t"); 923 924 MK_INSN(iret_flags32, "pushfl\n\t" 925 "popl %eax\n\t" 926 "andl $~0x2, %eax\n\t" 927 "orl $0xffc08028, %eax\n\t" 928 "pushl %eax\n\t" 929 "pushl %cs\n\t" 930 "call 1f\n\t" 931 "jmp 2f\n\t" 932 "1: iret\n\t" 933 "2:\n\t"); 934 935 MK_INSN(iret_flags16, "pushfw\n\t" 936 "popw %ax\n\t" 937 "and $~0x2, %ax\n\t" 938 "or $0x8028, %ax\n\t" 939 "pushw %ax\n\t" 940 "pushw %cs\n\t" 941 "callw 1f\n\t" 942 "jmp 2f\n\t" 943 "1: iretw\n\t" 944 "2:\n\t"); 945 946 exec_in_big_real_mode(&inregs, &outregs, 947 insn_iret32, 948 insn_iret32_end - insn_iret32); 949 950 if (!regs_equal(&inregs, &outregs, 0)) 951 print_serial("iret Test 1: FAIL\n"); 952 else 953 print_serial("iret Test 1: PASS\n"); 954 955 exec_in_big_real_mode(&inregs, &outregs, 956 insn_iret16, 957 insn_iret16_end - insn_iret16); 958 959 if (!regs_equal(&inregs, &outregs, 0)) 960 print_serial("iret Test 2: FAIL\n"); 961 else 962 print_serial("iret Test 2: PASS\n"); 963 964 exec_in_big_real_mode(&inregs, &outregs, 965 insn_iret_flags32, 966 insn_iret_flags32_end - insn_iret_flags32); 967 968 if (!regs_equal(&inregs, &outregs, R_AX)) 969 print_serial("iret Test 3: FAIL\n"); 970 else 971 print_serial("iret Test 3: PASS\n"); 972 973 exec_in_big_real_mode(&inregs, &outregs, 974 insn_iret_flags16, 975 insn_iret_flags16_end - insn_iret_flags16); 976 977 if (!regs_equal(&inregs, &outregs, R_AX)) 978 print_serial("iret Test 4: FAIL\n"); 979 else 980 print_serial("iret Test 4: PASS\n"); 981 } 982 983 void test_int() 984 { 985 struct regs inregs = { 0 }, outregs; 986 987 *(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */ 988 *(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */ 989 990 MK_INSN(int11, "int $0x11\n\t"); 991 992 exec_in_big_real_mode(&inregs, &outregs, 993 insn_int11, 994 insn_int11_end - insn_int11); 995 996 if (!regs_equal(&inregs, &outregs, 0)) 997 print_serial("int Test 1: FAIL\n"); 998 else 999 print_serial("int Test 1: PASS\n"); 1000 } 1001 1002 void test_imul() 1003 { 1004 struct regs inregs = { 0 }, outregs; 1005 1006 MK_INSN(imul8_1, "mov $2, %al\n\t" 1007 "mov $-4, %cx\n\t" 1008 "imul %cl\n\t"); 1009 1010 MK_INSN(imul16_1, "mov $2, %ax\n\t" 1011 "mov $-4, %cx\n\t" 1012 "imul %cx\n\t"); 1013 1014 MK_INSN(imul32_1, "mov $2, %eax\n\t" 1015 "mov $-4, %ecx\n\t" 1016 "imul %ecx\n\t"); 1017 1018 MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t" 1019 "mov $4, %cx\n\t" 1020 "imul %cl\n\t"); 1021 1022 MK_INSN(imul16_2, "mov $2, %ax\n\t" 1023 "mov $4, %cx\n\t" 1024 "imul %cx\n\t"); 1025 1026 MK_INSN(imul32_2, "mov $2, %eax\n\t" 1027 "mov $4, %ecx\n\t" 1028 "imul %ecx\n\t"); 1029 1030 exec_in_big_real_mode(&inregs, &outregs, 1031 insn_imul8_1, 1032 insn_imul8_1_end - insn_imul8_1); 1033 1034 if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || (outregs.eax & 0xff) != (u8)-8) 1035 print_serial("imul Test 1: FAIL\n"); 1036 else 1037 print_serial("imul Test 1: PASS\n"); 1038 1039 exec_in_big_real_mode(&inregs, &outregs, 1040 insn_imul16_1, 1041 insn_imul16_1_end - insn_imul16_1); 1042 1043 if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u16)-8) 1044 print_serial("imul Test 2: FAIL\n"); 1045 else 1046 print_serial("imul Test 2: PASS\n"); 1047 1048 exec_in_big_real_mode(&inregs, &outregs, 1049 insn_imul32_1, 1050 insn_imul32_1_end - insn_imul32_1); 1051 1052 if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u32)-8) 1053 print_serial("imul Test 3: FAIL\n"); 1054 else 1055 print_serial("imul Test 3: PASS\n"); 1056 1057 exec_in_big_real_mode(&inregs, &outregs, 1058 insn_imul8_2, 1059 insn_imul8_2_end - insn_imul8_2); 1060 1061 if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || (outregs.eax & 0xffff) != 8 || 1062 (outregs.eax & 0xffff0000) != 0x12340000) 1063 print_serial("imul Test 4: FAIL\n"); 1064 else 1065 print_serial("imul Test 4: PASS\n"); 1066 1067 exec_in_big_real_mode(&inregs, &outregs, 1068 insn_imul16_2, 1069 insn_imul16_2_end - insn_imul16_2); 1070 1071 if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 8) 1072 print_serial("imul Test 5: FAIL\n"); 1073 else 1074 print_serial("imul Test 5: PASS\n"); 1075 1076 exec_in_big_real_mode(&inregs, &outregs, 1077 insn_imul32_2, 1078 insn_imul32_2_end - insn_imul32_2); 1079 1080 if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 8) 1081 print_serial("imul Test 6: FAIL\n"); 1082 else 1083 print_serial("imul Test 6: PASS\n"); 1084 } 1085 1086 void test_mul() 1087 { 1088 struct regs inregs = { 0 }, outregs; 1089 1090 MK_INSN(mul8, "mov $2, %al\n\t" 1091 "mov $4, %cx\n\t" 1092 "imul %cl\n\t"); 1093 1094 MK_INSN(mul16, "mov $2, %ax\n\t" 1095 "mov $4, %cx\n\t" 1096 "imul %cx\n\t"); 1097 1098 MK_INSN(mul32, "mov $2, %eax\n\t" 1099 "mov $4, %ecx\n\t" 1100 "imul %ecx\n\t"); 1101 1102 exec_in_big_real_mode(&inregs, &outregs, 1103 insn_mul8, 1104 insn_mul8_end - insn_mul8); 1105 1106 if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || (outregs.eax & 0xff) != 8) 1107 print_serial("mul Test 1: FAIL\n"); 1108 else 1109 print_serial("mul Test 1: PASS\n"); 1110 1111 exec_in_big_real_mode(&inregs, &outregs, 1112 insn_mul16, 1113 insn_mul16_end - insn_mul16); 1114 1115 if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 8) 1116 print_serial("mul Test 2: FAIL\n"); 1117 else 1118 print_serial("mul Test 2: PASS\n"); 1119 1120 exec_in_big_real_mode(&inregs, &outregs, 1121 insn_mul32, 1122 insn_mul32_end - insn_mul32); 1123 1124 if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 8) 1125 print_serial("mul Test 3: FAIL\n"); 1126 else 1127 print_serial("mul Test 3: PASS\n"); 1128 } 1129 1130 void test_div() 1131 { 1132 struct regs inregs = { 0 }, outregs; 1133 1134 MK_INSN(div8, "mov $257, %ax\n\t" 1135 "mov $2, %cl\n\t" 1136 "div %cl\n\t"); 1137 1138 MK_INSN(div16, "mov $512, %ax\n\t" 1139 "mov $5, %cx\n\t" 1140 "div %cx\n\t"); 1141 1142 MK_INSN(div32, "mov $512, %eax\n\t" 1143 "mov $5, %ecx\n\t" 1144 "div %ecx\n\t"); 1145 1146 exec_in_big_real_mode(&inregs, &outregs, 1147 insn_div8, 1148 insn_div8_end - insn_div8); 1149 1150 if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 384) 1151 print_serial("div Test 1: FAIL\n"); 1152 else 1153 print_serial("div Test 1: PASS\n"); 1154 1155 exec_in_big_real_mode(&inregs, &outregs, 1156 insn_div16, 1157 insn_div16_end - insn_div16); 1158 1159 if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 102 || 1160 outregs.edx != 2) 1161 print_serial("div Test 2: FAIL\n"); 1162 else 1163 print_serial("div Test 2: PASS\n"); 1164 1165 exec_in_big_real_mode(&inregs, &outregs, 1166 insn_div32, 1167 insn_div32_end - insn_div32); 1168 1169 if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != 102 || 1170 outregs.edx != 2) 1171 print_serial("div Test 3: FAIL\n"); 1172 else 1173 print_serial("div Test 3: PASS\n"); 1174 } 1175 1176 void test_idiv() 1177 { 1178 struct regs inregs = { 0 }, outregs; 1179 1180 MK_INSN(idiv8, "mov $256, %ax\n\t" 1181 "mov $-2, %cl\n\t" 1182 "idiv %cl\n\t"); 1183 1184 MK_INSN(idiv16, "mov $512, %ax\n\t" 1185 "mov $-2, %cx\n\t" 1186 "idiv %cx\n\t"); 1187 1188 MK_INSN(idiv32, "mov $512, %eax\n\t" 1189 "mov $-2, %ecx\n\t" 1190 "idiv %ecx\n\t"); 1191 1192 exec_in_big_real_mode(&inregs, &outregs, 1193 insn_idiv8, 1194 insn_idiv8_end - insn_idiv8); 1195 1196 if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u8)-128) 1197 print_serial("idiv Test 1: FAIL\n"); 1198 else 1199 print_serial("idiv Test 1: PASS\n"); 1200 1201 exec_in_big_real_mode(&inregs, &outregs, 1202 insn_idiv16, 1203 insn_idiv16_end - insn_idiv16); 1204 1205 if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u16)-256) 1206 print_serial("idiv Test 2: FAIL\n"); 1207 else 1208 print_serial("idiv Test 2: PASS\n"); 1209 1210 exec_in_big_real_mode(&inregs, &outregs, 1211 insn_idiv32, 1212 insn_idiv32_end - insn_idiv32); 1213 1214 if (!regs_equal(&inregs, &outregs, R_AX | R_CX | R_DX) || outregs.eax != (u32)-256) 1215 print_serial("idiv Test 3: FAIL\n"); 1216 else 1217 print_serial("idiv Test 3: PASS\n"); 1218 } 1219 1220 void test_cbw(void) 1221 { 1222 struct regs inregs = { 0 }, outregs; 1223 1224 MK_INSN(cbw, "mov $0xFE, %eax \n\t" 1225 "cbw\n\t"); 1226 MK_INSN(cwde, "mov $0xFFFE, %eax \n\t" 1227 "cwde\n\t"); 1228 1229 exec_in_big_real_mode(&inregs, &outregs, 1230 insn_cbw, 1231 insn_cbw_end - insn_cbw); 1232 if (outregs.eax != 0xFFFE) 1233 print_serial("cbw test1: FAIL\n"); 1234 else 1235 print_serial("cbw test 1: PASS\n"); 1236 1237 exec_in_big_real_mode(&inregs, &outregs, 1238 insn_cwde, 1239 insn_cwde_end - insn_cwde); 1240 if (outregs.eax != 0xFFFFFFFE) 1241 print_serial("cwde test1: FAIL\n"); 1242 else 1243 print_serial("cwde test 1: PASS\n"); 1244 } 1245 1246 void test_loopcc(void) 1247 { 1248 struct regs inregs = { 0 }, outregs; 1249 1250 MK_INSN(loop, "mov $10, %ecx\n\t" 1251 "1: inc %eax\n\t" 1252 "loop 1b\n\t"); 1253 1254 MK_INSN(loope, "mov $10, %ecx\n\t" 1255 "mov $1, %eax\n\t" 1256 "1: dec %eax\n\t" 1257 "loope 1b\n\t"); 1258 1259 MK_INSN(loopne, "mov $10, %ecx\n\t" 1260 "mov $5, %eax\n\t" 1261 "1: dec %eax\n\t" 1262 "loopne 1b\n\t"); 1263 1264 exec_in_big_real_mode(&inregs, &outregs, 1265 insn_loop, insn_loop_end - insn_loop); 1266 if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 10) 1267 print_serial("LOOPcc short Test 1: FAIL\n"); 1268 else 1269 print_serial("LOOPcc short Test 1: PASS\n"); 1270 1271 exec_in_big_real_mode(&inregs, &outregs, 1272 insn_loope, insn_loope_end - insn_loope); 1273 if(!regs_equal(&inregs, &outregs, R_AX | R_CX) || 1274 outregs.eax != -1 || outregs.ecx != 8) 1275 print_serial("LOOPcc short Test 2: FAIL\n"); 1276 else 1277 print_serial("LOOPcc short Test 2: PASS\n"); 1278 1279 exec_in_big_real_mode(&inregs, &outregs, 1280 insn_loopne, insn_loopne_end - insn_loopne); 1281 if(!regs_equal(&inregs, &outregs, R_AX | R_CX) || 1282 outregs.eax != 0 || outregs.ecx != 5) 1283 print_serial("LOOPcc short Test 3: FAIL\n"); 1284 else 1285 print_serial("LOOPcc short Test 3: PASS\n"); 1286 } 1287 1288 static void test_das(void) 1289 { 1290 struct regs inregs = { 0 }, outregs = { 0 }; 1291 short i; 1292 static unsigned test_cases[1024] = { 1293 0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00, 1294 0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01, 1295 0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02, 1296 0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03, 1297 0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04, 1298 0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05, 1299 0x06000606, 0x8701a606, 0x56100006, 0x9711a006, 1300 0x02000707, 0x8301a707, 0x12100107, 0x9311a107, 1301 0x02000808, 0x8301a808, 0x12100208, 0x9311a208, 1302 0x06000909, 0x8701a909, 0x16100309, 0x9711a309, 1303 0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a, 1304 0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b, 1305 0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c, 1306 0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d, 1307 0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e, 1308 0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f, 1309 0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10, 1310 0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11, 1311 0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12, 1312 0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13, 1313 0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14, 1314 0x02001515, 0x8301b515, 0x16100f15, 0x9711af15, 1315 0x02001616, 0x8301b616, 0x12101016, 0x9311b016, 1316 0x06001717, 0x8701b717, 0x16101117, 0x9711b117, 1317 0x06001818, 0x8701b818, 0x16101218, 0x9711b218, 1318 0x02001919, 0x8301b919, 0x12101319, 0x9311b319, 1319 0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a, 1320 0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b, 1321 0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c, 1322 0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d, 1323 0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e, 1324 0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f, 1325 0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20, 1326 0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21, 1327 0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22, 1328 0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23, 1329 0x06002424, 0x8301c424, 0x16101e24, 0x9711be24, 1330 0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25, 1331 0x02002626, 0x8701c626, 0x12102026, 0x9711c026, 1332 0x06002727, 0x8301c727, 0x16102127, 0x9311c127, 1333 0x06002828, 0x8301c828, 0x16102228, 0x9311c228, 1334 0x02002929, 0x8701c929, 0x12102329, 0x9711c329, 1335 0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a, 1336 0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b, 1337 0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c, 1338 0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d, 1339 0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e, 1340 0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f, 1341 0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30, 1342 0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31, 1343 0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32, 1344 0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33, 1345 0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34, 1346 0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35, 1347 0x06003636, 0x8301d636, 0x16103036, 0x9311d036, 1348 0x02003737, 0x8701d737, 0x12103137, 0x9711d137, 1349 0x02003838, 0x8701d838, 0x12103238, 0x9711d238, 1350 0x06003939, 0x8301d939, 0x16103339, 0x9311d339, 1351 0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a, 1352 0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b, 1353 0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c, 1354 0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d, 1355 0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e, 1356 0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f, 1357 0x02004040, 0x8301e040, 0x16103a40, 0x9311da40, 1358 0x06004141, 0x8701e141, 0x12103b41, 0x9711db41, 1359 0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42, 1360 0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43, 1361 0x06004444, 0x8701e444, 0x12103e44, 0x9711de44, 1362 0x02004545, 0x8301e545, 0x16103f45, 0x9311df45, 1363 0x02004646, 0x8301e646, 0x12104046, 0x9311e046, 1364 0x06004747, 0x8701e747, 0x16104147, 0x9711e147, 1365 0x06004848, 0x8701e848, 0x16104248, 0x9711e248, 1366 0x02004949, 0x8301e949, 0x12104349, 0x9311e349, 1367 0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a, 1368 0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b, 1369 0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c, 1370 0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d, 1371 0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e, 1372 0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f, 1373 0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50, 1374 0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51, 1375 0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52, 1376 0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53, 1377 0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54, 1378 0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55, 1379 0x06005656, 0x8701f656, 0x16105056, 0x9711f056, 1380 0x02005757, 0x8301f757, 0x12105157, 0x9311f157, 1381 0x02005858, 0x8301f858, 0x12105258, 0x9311f258, 1382 0x06005959, 0x8701f959, 0x16105359, 0x9711f359, 1383 0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a, 1384 0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b, 1385 0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c, 1386 0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d, 1387 0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e, 1388 0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f, 1389 0x06006060, 0x47010060, 0x16105a60, 0x9711fa60, 1390 0x02006161, 0x03010161, 0x12105b61, 0x9311fb61, 1391 0x02006262, 0x03010262, 0x16105c62, 0x9711fc62, 1392 0x06006363, 0x07010363, 0x12105d63, 0x9311fd63, 1393 0x02006464, 0x03010464, 0x12105e64, 0x9311fe64, 1394 0x06006565, 0x07010565, 0x16105f65, 0x9711ff65, 1395 0x06006666, 0x07010666, 0x16106066, 0x57110066, 1396 0x02006767, 0x03010767, 0x12106167, 0x13110167, 1397 0x02006868, 0x03010868, 0x12106268, 0x13110268, 1398 0x06006969, 0x07010969, 0x16106369, 0x17110369, 1399 0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a, 1400 0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b, 1401 0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c, 1402 0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d, 1403 0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e, 1404 0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f, 1405 0x02007070, 0x03011070, 0x16106a70, 0x17110a70, 1406 0x06007171, 0x07011171, 0x12106b71, 0x13110b71, 1407 0x06007272, 0x07011272, 0x16106c72, 0x17110c72, 1408 0x02007373, 0x03011373, 0x12106d73, 0x13110d73, 1409 0x06007474, 0x07011474, 0x12106e74, 0x13110e74, 1410 0x02007575, 0x03011575, 0x16106f75, 0x17110f75, 1411 0x02007676, 0x03011676, 0x12107076, 0x13111076, 1412 0x06007777, 0x07011777, 0x16107177, 0x17111177, 1413 0x06007878, 0x07011878, 0x16107278, 0x17111278, 1414 0x02007979, 0x03011979, 0x12107379, 0x13111379, 1415 0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a, 1416 0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b, 1417 0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c, 1418 0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d, 1419 0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e, 1420 0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f, 1421 0x82008080, 0x03012080, 0x12107a80, 0x13111a80, 1422 0x86008181, 0x07012181, 0x16107b81, 0x17111b81, 1423 0x86008282, 0x07012282, 0x12107c82, 0x13111c82, 1424 0x82008383, 0x03012383, 0x16107d83, 0x17111d83, 1425 0x86008484, 0x07012484, 0x16107e84, 0x17111e84, 1426 0x82008585, 0x03012585, 0x12107f85, 0x13111f85, 1427 0x82008686, 0x03012686, 0x92108086, 0x13112086, 1428 0x86008787, 0x07012787, 0x96108187, 0x17112187, 1429 0x86008888, 0x07012888, 0x96108288, 0x17112288, 1430 0x82008989, 0x03012989, 0x92108389, 0x13112389, 1431 0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a, 1432 0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b, 1433 0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c, 1434 0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d, 1435 0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e, 1436 0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f, 1437 0x86009090, 0x07013090, 0x92108a90, 0x13112a90, 1438 0x82009191, 0x03013191, 0x96108b91, 0x17112b91, 1439 0x82009292, 0x03013292, 0x92108c92, 0x13112c92, 1440 0x86009393, 0x07013393, 0x96108d93, 0x17112d93, 1441 0x82009494, 0x03013494, 0x96108e94, 0x17112e94, 1442 0x86009595, 0x07013595, 0x92108f95, 0x13112f95, 1443 0x86009696, 0x07013696, 0x96109096, 0x17113096, 1444 0x82009797, 0x03013797, 0x92109197, 0x13113197, 1445 0x82009898, 0x03013898, 0x92109298, 0x13113298, 1446 0x86009999, 0x07013999, 0x96109399, 0x17113399, 1447 0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a, 1448 0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b, 1449 0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c, 1450 0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d, 1451 0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e, 1452 0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f, 1453 0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0, 1454 0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1, 1455 0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2, 1456 0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3, 1457 0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4, 1458 0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5, 1459 0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6, 1460 0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7, 1461 0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8, 1462 0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9, 1463 0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa, 1464 0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab, 1465 0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac, 1466 0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad, 1467 0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae, 1468 0x130049af, 0x130149af, 0x131049af, 0x131149af, 1469 0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0, 1470 0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1, 1471 0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2, 1472 0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3, 1473 0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4, 1474 0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5, 1475 0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6, 1476 0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7, 1477 0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8, 1478 0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9, 1479 0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba, 1480 0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb, 1481 0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc, 1482 0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd, 1483 0x130058be, 0x130158be, 0x131058be, 0x131158be, 1484 0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf, 1485 0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0, 1486 0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1, 1487 0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2, 1488 0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3, 1489 0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4, 1490 0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5, 1491 0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6, 1492 0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7, 1493 0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8, 1494 0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9, 1495 0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca, 1496 0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb, 1497 0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc, 1498 0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd, 1499 0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce, 1500 0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf, 1501 0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0, 1502 0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1, 1503 0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2, 1504 0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3, 1505 0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4, 1506 0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5, 1507 0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6, 1508 0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7, 1509 0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8, 1510 0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9, 1511 0x170074da, 0x170174da, 0x171074da, 0x171174da, 1512 0x130075db, 0x130175db, 0x131075db, 0x131175db, 1513 0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc, 1514 0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd, 1515 0x170078de, 0x170178de, 0x171078de, 0x171178de, 1516 0x130079df, 0x130179df, 0x131079df, 0x131179df, 1517 0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0, 1518 0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1, 1519 0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2, 1520 0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3, 1521 0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4, 1522 0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5, 1523 0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6, 1524 0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7, 1525 0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8, 1526 0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9, 1527 0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea, 1528 0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb, 1529 0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec, 1530 0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed, 1531 0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee, 1532 0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef, 1533 0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0, 1534 0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1, 1535 0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2, 1536 0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3, 1537 0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4, 1538 0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5, 1539 0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6, 1540 0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7, 1541 0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8, 1542 0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9, 1543 0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa, 1544 0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb, 1545 0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc, 1546 0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd, 1547 0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe, 1548 0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff, 1549 }; 1550 1551 MK_INSN(das, "das"); 1552 1553 for (i = 0; i < 1024; ++i) { 1554 unsigned tmp = test_cases[i]; 1555 inregs.eax = tmp & 0xff; 1556 inregs.eflags = (tmp >> 16) & 0xff; 1557 exec_in_big_real_mode(&inregs, &outregs, 1558 insn_das, 1559 insn_das_end - insn_das); 1560 1561 if (!regs_equal(&inregs, &outregs, R_AX) 1562 || outregs.eax != ((tmp >> 8) & 0xff) 1563 || (outregs.eflags & 0xff) != (tmp >> 24)) { 1564 print_serial("DAS Test: FAIL\n"); 1565 return; 1566 } 1567 } 1568 print_serial("DAS Test: PASS\n"); 1569 } 1570 1571 void test_cwd_cdq() 1572 { 1573 struct regs inregs = { 0 }, outregs; 1574 1575 /* Sign-bit set */ 1576 MK_INSN(cwd_1, "mov $0x8000, %ax\n\t" 1577 "cwd\n\t"); 1578 1579 /* Sign-bit not set */ 1580 MK_INSN(cwd_2, "mov $0x1000, %ax\n\t" 1581 "cwd\n\t"); 1582 1583 /* Sign-bit set */ 1584 MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t" 1585 "cdq\n\t"); 1586 1587 /* Sign-bit not set */ 1588 MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t" 1589 "cdq\n\t"); 1590 1591 exec_in_big_real_mode(&inregs, &outregs, 1592 insn_cwd_1, 1593 insn_cwd_1_end - insn_cwd_1); 1594 1595 if (!regs_equal(&inregs, &outregs, R_AX | R_DX) || outregs.eax != 0x8000 || outregs.edx != 0xffff) 1596 print_serial("cwd Test 1: FAIL\n"); 1597 else 1598 print_serial("cwd Test 1: PASS\n"); 1599 1600 exec_in_big_real_mode(&inregs, &outregs, 1601 insn_cwd_2, 1602 insn_cwd_2_end - insn_cwd_2); 1603 1604 if (!regs_equal(&inregs, &outregs, R_AX | R_DX) || outregs.eax != 0x1000 || outregs.edx != 0) 1605 print_serial("cwd Test 2: FAIL\n"); 1606 else 1607 print_serial("cwd Test 2: PASS\n"); 1608 1609 exec_in_big_real_mode(&inregs, &outregs, 1610 insn_cdq_1, 1611 insn_cdq_1_end - insn_cdq_1); 1612 1613 if (!regs_equal(&inregs, &outregs, R_AX | R_DX) || outregs.eax != 0x80000000 || outregs.edx != 0xffffffff) 1614 print_serial("cdq Test 1: FAIL\n"); 1615 else 1616 print_serial("cdq Test 1: PASS\n"); 1617 1618 exec_in_big_real_mode(&inregs, &outregs, 1619 insn_cdq_2, 1620 insn_cdq_2_end - insn_cdq_2); 1621 1622 if (!regs_equal(&inregs, &outregs, R_AX | R_DX) || outregs.eax != 0x10000000 || outregs.edx != 0) 1623 print_serial("cdq Test 2: FAIL\n"); 1624 else 1625 print_serial("cdq Test 2: PASS\n"); 1626 } 1627 1628 void realmode_start(void) 1629 { 1630 test_null(); 1631 1632 test_shld(); 1633 test_push_pop(); 1634 test_pusha_popa(); 1635 test_mov_imm(); 1636 test_cmp_imm(); 1637 test_add_imm(); 1638 test_sub_imm(); 1639 test_xor_imm(); 1640 test_io(); 1641 test_eflags_insn(); 1642 test_jcc_short(); 1643 test_jcc_near(); 1644 /* test_call() uses short jump so call it after testing jcc */ 1645 test_call(); 1646 /* long jmp test uses call near so test it after testing call */ 1647 test_long_jmp(); 1648 test_xchg(); 1649 test_iret(); 1650 test_int(); 1651 test_imul(); 1652 test_mul(); 1653 test_div(); 1654 test_idiv(); 1655 test_loopcc(); 1656 test_cbw(); 1657 test_cwd_cdq(); 1658 test_das(); 1659 1660 exit(0); 1661 } 1662 1663 unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff }; 1664 1665 struct __attribute__((packed)) { 1666 unsigned short limit; 1667 void *base; 1668 } r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt }; 1669 1670 asm( 1671 ".section .init \n\t" 1672 1673 ".code32 \n\t" 1674 1675 "mb_magic = 0x1BADB002 \n\t" 1676 "mb_flags = 0x0 \n\t" 1677 1678 "# multiboot header \n\t" 1679 ".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t" 1680 1681 ".globl start \n\t" 1682 ".data \n\t" 1683 ". = . + 4096 \n\t" 1684 "stacktop: \n\t" 1685 1686 ".text \n\t" 1687 "start: \n\t" 1688 "lgdt r_gdt_descr \n\t" 1689 "ljmp $8, $1f; 1: \n\t" 1690 ".code16gcc \n\t" 1691 "mov $16, %eax \n\t" 1692 "mov %ax, %ds \n\t" 1693 "mov %ax, %es \n\t" 1694 "mov %ax, %fs \n\t" 1695 "mov %ax, %gs \n\t" 1696 "mov %ax, %ss \n\t" 1697 "mov %cr0, %eax \n\t" 1698 "btc $0, %eax \n\t" 1699 "mov %eax, %cr0 \n\t" 1700 "ljmp $0, $realmode_entry \n\t" 1701 1702 "realmode_entry: \n\t" 1703 1704 "xor %ax, %ax \n\t" 1705 "mov %ax, %ds \n\t" 1706 "mov %ax, %es \n\t" 1707 "mov %ax, %ss \n\t" 1708 "mov %ax, %fs \n\t" 1709 "mov %ax, %gs \n\t" 1710 "mov $stacktop, %esp\n\t" 1711 "ljmp $0, $realmode_start \n\t" 1712 1713 ".code16gcc \n\t" 1714 ); 1715