Commit d8bc1fd0aeb0423074b5063c8dc94dddd7285321
1 parent
7501267e
ring 0 ops
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@254 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
469 additions
and
51 deletions
exec-i386.h
| @@ -123,6 +123,11 @@ typedef struct CCTable { | @@ -123,6 +123,11 @@ typedef struct CCTable { | ||
| 123 | extern CCTable cc_table[]; | 123 | extern CCTable cc_table[]; |
| 124 | 124 | ||
| 125 | void load_seg(int seg_reg, int selector, unsigned cur_eip); | 125 | void load_seg(int seg_reg, int selector, unsigned cur_eip); |
| 126 | +void jmp_seg(int selector, unsigned int new_eip); | ||
| 127 | +void helper_lldt_T0(void); | ||
| 128 | +void helper_ltr_T0(void); | ||
| 129 | +void helper_movl_crN_T0(int reg); | ||
| 130 | +void helper_movl_drN_T0(int reg); | ||
| 126 | void __hidden cpu_lock(void); | 131 | void __hidden cpu_lock(void); |
| 127 | void __hidden cpu_unlock(void); | 132 | void __hidden cpu_unlock(void); |
| 128 | void raise_interrupt(int intno, int is_int, int error_code, | 133 | void raise_interrupt(int intno, int is_int, int error_code, |
helper-i386.c
| @@ -157,7 +157,7 @@ void raise_interrupt(int intno, int is_int, int error_code, | @@ -157,7 +157,7 @@ void raise_interrupt(int intno, int is_int, int error_code, | ||
| 157 | break; | 157 | break; |
| 158 | } | 158 | } |
| 159 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; | 159 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
| 160 | - cpl = env->segs[R_CS] & 3; | 160 | + cpl = env->segs[R_CS].selector & 3; |
| 161 | /* check privledge if software int */ | 161 | /* check privledge if software int */ |
| 162 | if (is_int && dpl < cpl) | 162 | if (is_int && dpl < cpl) |
| 163 | raise_exception_err(EXCP0D_GPF, intno * 8 + 2); | 163 | raise_exception_err(EXCP0D_GPF, intno * 8 + 2); |
| @@ -176,7 +176,7 @@ void raise_interrupt(int intno, int is_int, int error_code, | @@ -176,7 +176,7 @@ void raise_interrupt(int intno, int is_int, int error_code, | ||
| 176 | void raise_interrupt(int intno, int is_int, int error_code, | 176 | void raise_interrupt(int intno, int is_int, int error_code, |
| 177 | unsigned int next_eip) | 177 | unsigned int next_eip) |
| 178 | { | 178 | { |
| 179 | - SegmentDescriptorTable *dt; | 179 | + SegmentCache *dt; |
| 180 | uint8_t *ptr; | 180 | uint8_t *ptr; |
| 181 | int dpl, cpl; | 181 | int dpl, cpl; |
| 182 | uint32_t e2; | 182 | uint32_t e2; |
| @@ -331,21 +331,98 @@ void helper_cpuid(void) | @@ -331,21 +331,98 @@ void helper_cpuid(void) | ||
| 331 | } | 331 | } |
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | +static inline void load_seg_cache(SegmentCache *sc, uint32_t e1, uint32_t e2) | ||
| 335 | +{ | ||
| 336 | + sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000)); | ||
| 337 | + sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000); | ||
| 338 | + if (e2 & (1 << 23)) | ||
| 339 | + sc->limit = (sc->limit << 12) | 0xfff; | ||
| 340 | + sc->seg_32bit = (e2 >> 22) & 1; | ||
| 341 | +} | ||
| 342 | + | ||
| 343 | +void helper_lldt_T0(void) | ||
| 344 | +{ | ||
| 345 | + int selector; | ||
| 346 | + SegmentCache *dt; | ||
| 347 | + uint32_t e1, e2; | ||
| 348 | + int index; | ||
| 349 | + uint8_t *ptr; | ||
| 350 | + | ||
| 351 | + selector = T0 & 0xffff; | ||
| 352 | + if ((selector & 0xfffc) == 0) { | ||
| 353 | + /* XXX: NULL selector case: invalid LDT */ | ||
| 354 | + env->ldt.base = NULL; | ||
| 355 | + env->ldt.limit = 0; | ||
| 356 | + } else { | ||
| 357 | + if (selector & 0x4) | ||
| 358 | + raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
| 359 | + dt = &env->gdt; | ||
| 360 | + index = selector & ~7; | ||
| 361 | + if ((index + 7) > dt->limit) | ||
| 362 | + raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
| 363 | + ptr = dt->base + index; | ||
| 364 | + e1 = ldl(ptr); | ||
| 365 | + e2 = ldl(ptr + 4); | ||
| 366 | + if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2) | ||
| 367 | + raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
| 368 | + if (!(e2 & DESC_P_MASK)) | ||
| 369 | + raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); | ||
| 370 | + load_seg_cache(&env->ldt, e1, e2); | ||
| 371 | + } | ||
| 372 | + env->ldt.selector = selector; | ||
| 373 | +} | ||
| 374 | + | ||
| 375 | +void helper_ltr_T0(void) | ||
| 376 | +{ | ||
| 377 | + int selector; | ||
| 378 | + SegmentCache *dt; | ||
| 379 | + uint32_t e1, e2; | ||
| 380 | + int index, type; | ||
| 381 | + uint8_t *ptr; | ||
| 382 | + | ||
| 383 | + selector = T0 & 0xffff; | ||
| 384 | + if ((selector & 0xfffc) == 0) { | ||
| 385 | + /* XXX: NULL selector case: invalid LDT */ | ||
| 386 | + env->tr.base = NULL; | ||
| 387 | + env->tr.limit = 0; | ||
| 388 | + } else { | ||
| 389 | + if (selector & 0x4) | ||
| 390 | + raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
| 391 | + dt = &env->gdt; | ||
| 392 | + index = selector & ~7; | ||
| 393 | + if ((index + 7) > dt->limit) | ||
| 394 | + raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
| 395 | + ptr = dt->base + index; | ||
| 396 | + e1 = ldl(ptr); | ||
| 397 | + e2 = ldl(ptr + 4); | ||
| 398 | + type = (e2 >> DESC_TYPE_SHIFT) & 0xf; | ||
| 399 | + if ((e2 & DESC_S_MASK) || | ||
| 400 | + (type != 2 && type != 9)) | ||
| 401 | + raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
| 402 | + if (!(e2 & DESC_P_MASK)) | ||
| 403 | + raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); | ||
| 404 | + load_seg_cache(&env->tr, e1, e2); | ||
| 405 | + e2 |= 0x00000200; /* set the busy bit */ | ||
| 406 | + stl(ptr + 4, e2); | ||
| 407 | + } | ||
| 408 | + env->tr.selector = selector; | ||
| 409 | +} | ||
| 410 | + | ||
| 334 | /* only works if protected mode and not VM86 */ | 411 | /* only works if protected mode and not VM86 */ |
| 335 | -void load_seg(int seg_reg, int selector, unsigned cur_eip) | 412 | +void load_seg(int seg_reg, int selector, unsigned int cur_eip) |
| 336 | { | 413 | { |
| 337 | SegmentCache *sc; | 414 | SegmentCache *sc; |
| 338 | - SegmentDescriptorTable *dt; | 415 | + SegmentCache *dt; |
| 339 | int index; | 416 | int index; |
| 340 | uint32_t e1, e2; | 417 | uint32_t e1, e2; |
| 341 | uint8_t *ptr; | 418 | uint8_t *ptr; |
| 342 | - | ||
| 343 | - sc = &env->seg_cache[seg_reg]; | 419 | + |
| 420 | + sc = &env->segs[seg_reg]; | ||
| 344 | if ((selector & 0xfffc) == 0) { | 421 | if ((selector & 0xfffc) == 0) { |
| 345 | /* null selector case */ | 422 | /* null selector case */ |
| 346 | if (seg_reg == R_SS) { | 423 | if (seg_reg == R_SS) { |
| 347 | EIP = cur_eip; | 424 | EIP = cur_eip; |
| 348 | - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | 425 | + raise_exception_err(EXCP0D_GPF, 0); |
| 349 | } else { | 426 | } else { |
| 350 | /* XXX: each access should trigger an exception */ | 427 | /* XXX: each access should trigger an exception */ |
| 351 | sc->base = NULL; | 428 | sc->base = NULL; |
| @@ -390,18 +467,93 @@ void load_seg(int seg_reg, int selector, unsigned cur_eip) | @@ -390,18 +467,93 @@ void load_seg(int seg_reg, int selector, unsigned cur_eip) | ||
| 390 | else | 467 | else |
| 391 | raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); | 468 | raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); |
| 392 | } | 469 | } |
| 393 | - | ||
| 394 | - sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000)); | ||
| 395 | - sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000); | ||
| 396 | - if (e2 & (1 << 23)) | ||
| 397 | - sc->limit = (sc->limit << 12) | 0xfff; | ||
| 398 | - sc->seg_32bit = (e2 >> 22) & 1; | 470 | + load_seg_cache(sc, e1, e2); |
| 399 | #if 0 | 471 | #if 0 |
| 400 | fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n", | 472 | fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n", |
| 401 | selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit); | 473 | selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit); |
| 402 | #endif | 474 | #endif |
| 403 | } | 475 | } |
| 404 | - env->segs[seg_reg] = selector; | 476 | + sc->selector = selector; |
| 477 | +} | ||
| 478 | + | ||
| 479 | +/* protected mode jump */ | ||
| 480 | +void jmp_seg(int selector, unsigned int new_eip) | ||
| 481 | +{ | ||
| 482 | + SegmentCache sc1; | ||
| 483 | + SegmentCache *dt; | ||
| 484 | + int index; | ||
| 485 | + uint32_t e1, e2, cpl, dpl, rpl; | ||
| 486 | + uint8_t *ptr; | ||
| 487 | + | ||
| 488 | + if ((selector & 0xfffc) == 0) { | ||
| 489 | + raise_exception_err(EXCP0D_GPF, 0); | ||
| 490 | + } | ||
| 491 | + | ||
| 492 | + if (selector & 0x4) | ||
| 493 | + dt = &env->ldt; | ||
| 494 | + else | ||
| 495 | + dt = &env->gdt; | ||
| 496 | + index = selector & ~7; | ||
| 497 | + if ((index + 7) > dt->limit) | ||
| 498 | + raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
| 499 | + ptr = dt->base + index; | ||
| 500 | + e1 = ldl(ptr); | ||
| 501 | + e2 = ldl(ptr + 4); | ||
| 502 | + cpl = env->segs[R_CS].selector & 3; | ||
| 503 | + if (e2 & DESC_S_MASK) { | ||
| 504 | + if (!(e2 & DESC_CS_MASK)) | ||
| 505 | + raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
| 506 | + dpl = (e2 >> DESC_DPL_SHIFT) & 3; | ||
| 507 | + if (e2 & DESC_CS_MASK) { | ||
| 508 | + /* conforming code segment */ | ||
| 509 | + if (dpl > cpl) | ||
| 510 | + raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
| 511 | + } else { | ||
| 512 | + /* non conforming code segment */ | ||
| 513 | + rpl = selector & 3; | ||
| 514 | + if (rpl > cpl) | ||
| 515 | + raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
| 516 | + if (dpl != cpl) | ||
| 517 | + raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
| 518 | + } | ||
| 519 | + if (!(e2 & DESC_P_MASK)) | ||
| 520 | + raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); | ||
| 521 | + load_seg_cache(&sc1, e1, e2); | ||
| 522 | + if (new_eip > sc1.limit) | ||
| 523 | + raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
| 524 | + env->segs[R_CS] = sc1; | ||
| 525 | + env->segs[R_CS].selector = (selector & 0xfffc) | cpl; | ||
| 526 | + EIP = new_eip; | ||
| 527 | + } else { | ||
| 528 | + cpu_abort(env, "jmp to call/task gate not supported 0x%04x:0x%08x", | ||
| 529 | + selector, new_eip); | ||
| 530 | + } | ||
| 531 | +} | ||
| 532 | + | ||
| 533 | +/* XXX: do more */ | ||
| 534 | +void helper_movl_crN_T0(int reg) | ||
| 535 | +{ | ||
| 536 | + switch(reg) { | ||
| 537 | + case 0: | ||
| 538 | + default: | ||
| 539 | + env->cr[0] = reg; | ||
| 540 | + break; | ||
| 541 | + case 2: | ||
| 542 | + env->cr[2] = reg; | ||
| 543 | + break; | ||
| 544 | + case 3: | ||
| 545 | + env->cr[3] = reg; | ||
| 546 | + break; | ||
| 547 | + case 4: | ||
| 548 | + env->cr[4] = reg; | ||
| 549 | + break; | ||
| 550 | + } | ||
| 551 | +} | ||
| 552 | + | ||
| 553 | +/* XXX: do more */ | ||
| 554 | +void helper_movl_drN_T0(int reg) | ||
| 555 | +{ | ||
| 556 | + env->dr[reg] = T0; | ||
| 405 | } | 557 | } |
| 406 | 558 | ||
| 407 | /* rdtsc */ | 559 | /* rdtsc */ |
| @@ -425,7 +577,7 @@ void helper_rdtsc(void) | @@ -425,7 +577,7 @@ void helper_rdtsc(void) | ||
| 425 | void helper_lsl(void) | 577 | void helper_lsl(void) |
| 426 | { | 578 | { |
| 427 | unsigned int selector, limit; | 579 | unsigned int selector, limit; |
| 428 | - SegmentDescriptorTable *dt; | 580 | + SegmentCache *dt; |
| 429 | int index; | 581 | int index; |
| 430 | uint32_t e1, e2; | 582 | uint32_t e1, e2; |
| 431 | uint8_t *ptr; | 583 | uint8_t *ptr; |
| @@ -452,7 +604,7 @@ void helper_lsl(void) | @@ -452,7 +604,7 @@ void helper_lsl(void) | ||
| 452 | void helper_lar(void) | 604 | void helper_lar(void) |
| 453 | { | 605 | { |
| 454 | unsigned int selector; | 606 | unsigned int selector; |
| 455 | - SegmentDescriptorTable *dt; | 607 | + SegmentCache *dt; |
| 456 | int index; | 608 | int index; |
| 457 | uint32_t e2; | 609 | uint32_t e2; |
| 458 | uint8_t *ptr; | 610 | uint8_t *ptr; |
op-i386.c
| @@ -357,6 +357,11 @@ void OPPROTO op_andl_T0_ffff(void) | @@ -357,6 +357,11 @@ void OPPROTO op_andl_T0_ffff(void) | ||
| 357 | T0 = T0 & 0xffff; | 357 | T0 = T0 & 0xffff; |
| 358 | } | 358 | } |
| 359 | 359 | ||
| 360 | +void OPPROTO op_andl_T0_im(void) | ||
| 361 | +{ | ||
| 362 | + T0 = T0 & PARAM1; | ||
| 363 | +} | ||
| 364 | + | ||
| 360 | void OPPROTO op_movl_T0_T1(void) | 365 | void OPPROTO op_movl_T0_T1(void) |
| 361 | { | 366 | { |
| 362 | T0 = T1; | 367 | T0 = T1; |
| @@ -665,7 +670,7 @@ void op_pushl_ss32_T0(void) | @@ -665,7 +670,7 @@ void op_pushl_ss32_T0(void) | ||
| 665 | { | 670 | { |
| 666 | uint32_t offset; | 671 | uint32_t offset; |
| 667 | offset = ESP - 4; | 672 | offset = ESP - 4; |
| 668 | - stl(env->seg_cache[R_SS].base + offset, T0); | 673 | + stl(env->segs[R_SS].base + offset, T0); |
| 669 | /* modify ESP after to handle exceptions correctly */ | 674 | /* modify ESP after to handle exceptions correctly */ |
| 670 | ESP = offset; | 675 | ESP = offset; |
| 671 | } | 676 | } |
| @@ -674,7 +679,7 @@ void op_pushw_ss32_T0(void) | @@ -674,7 +679,7 @@ void op_pushw_ss32_T0(void) | ||
| 674 | { | 679 | { |
| 675 | uint32_t offset; | 680 | uint32_t offset; |
| 676 | offset = ESP - 2; | 681 | offset = ESP - 2; |
| 677 | - stw(env->seg_cache[R_SS].base + offset, T0); | 682 | + stw(env->segs[R_SS].base + offset, T0); |
| 678 | /* modify ESP after to handle exceptions correctly */ | 683 | /* modify ESP after to handle exceptions correctly */ |
| 679 | ESP = offset; | 684 | ESP = offset; |
| 680 | } | 685 | } |
| @@ -683,7 +688,7 @@ void op_pushl_ss16_T0(void) | @@ -683,7 +688,7 @@ void op_pushl_ss16_T0(void) | ||
| 683 | { | 688 | { |
| 684 | uint32_t offset; | 689 | uint32_t offset; |
| 685 | offset = (ESP - 4) & 0xffff; | 690 | offset = (ESP - 4) & 0xffff; |
| 686 | - stl(env->seg_cache[R_SS].base + offset, T0); | 691 | + stl(env->segs[R_SS].base + offset, T0); |
| 687 | /* modify ESP after to handle exceptions correctly */ | 692 | /* modify ESP after to handle exceptions correctly */ |
| 688 | ESP = (ESP & ~0xffff) | offset; | 693 | ESP = (ESP & ~0xffff) | offset; |
| 689 | } | 694 | } |
| @@ -692,7 +697,7 @@ void op_pushw_ss16_T0(void) | @@ -692,7 +697,7 @@ void op_pushw_ss16_T0(void) | ||
| 692 | { | 697 | { |
| 693 | uint32_t offset; | 698 | uint32_t offset; |
| 694 | offset = (ESP - 2) & 0xffff; | 699 | offset = (ESP - 2) & 0xffff; |
| 695 | - stw(env->seg_cache[R_SS].base + offset, T0); | 700 | + stw(env->segs[R_SS].base + offset, T0); |
| 696 | /* modify ESP after to handle exceptions correctly */ | 701 | /* modify ESP after to handle exceptions correctly */ |
| 697 | ESP = (ESP & ~0xffff) | offset; | 702 | ESP = (ESP & ~0xffff) | offset; |
| 698 | } | 703 | } |
| @@ -710,22 +715,22 @@ void op_popw_T0(void) | @@ -710,22 +715,22 @@ void op_popw_T0(void) | ||
| 710 | 715 | ||
| 711 | void op_popl_ss32_T0(void) | 716 | void op_popl_ss32_T0(void) |
| 712 | { | 717 | { |
| 713 | - T0 = ldl(env->seg_cache[R_SS].base + ESP); | 718 | + T0 = ldl(env->segs[R_SS].base + ESP); |
| 714 | } | 719 | } |
| 715 | 720 | ||
| 716 | void op_popw_ss32_T0(void) | 721 | void op_popw_ss32_T0(void) |
| 717 | { | 722 | { |
| 718 | - T0 = lduw(env->seg_cache[R_SS].base + ESP); | 723 | + T0 = lduw(env->segs[R_SS].base + ESP); |
| 719 | } | 724 | } |
| 720 | 725 | ||
| 721 | void op_popl_ss16_T0(void) | 726 | void op_popl_ss16_T0(void) |
| 722 | { | 727 | { |
| 723 | - T0 = ldl(env->seg_cache[R_SS].base + (ESP & 0xffff)); | 728 | + T0 = ldl(env->segs[R_SS].base + (ESP & 0xffff)); |
| 724 | } | 729 | } |
| 725 | 730 | ||
| 726 | void op_popw_ss16_T0(void) | 731 | void op_popw_ss16_T0(void) |
| 727 | { | 732 | { |
| 728 | - T0 = lduw(env->seg_cache[R_SS].base + (ESP & 0xffff)); | 733 | + T0 = lduw(env->segs[R_SS].base + (ESP & 0xffff)); |
| 729 | } | 734 | } |
| 730 | 735 | ||
| 731 | void op_addl_ESP_4(void) | 736 | void op_addl_ESP_4(void) |
| @@ -909,17 +914,18 @@ void OPPROTO op_movl_seg_T0(void) | @@ -909,17 +914,18 @@ void OPPROTO op_movl_seg_T0(void) | ||
| 909 | void OPPROTO op_movl_seg_T0_vm(void) | 914 | void OPPROTO op_movl_seg_T0_vm(void) |
| 910 | { | 915 | { |
| 911 | int selector; | 916 | int selector; |
| 917 | + SegmentCache *sc; | ||
| 912 | 918 | ||
| 913 | selector = T0 & 0xffff; | 919 | selector = T0 & 0xffff; |
| 914 | /* env->segs[] access */ | 920 | /* env->segs[] access */ |
| 915 | - *(uint32_t *)((char *)env + PARAM1) = selector; | ||
| 916 | - /* env->seg_cache[] access */ | ||
| 917 | - ((SegmentCache *)((char *)env + PARAM2))->base = (void *)(selector << 4); | 921 | + sc = (SegmentCache *)((char *)env + PARAM1); |
| 922 | + sc->selector = selector; | ||
| 923 | + sc->base = (void *)(selector << 4); | ||
| 918 | } | 924 | } |
| 919 | 925 | ||
| 920 | void OPPROTO op_movl_T0_seg(void) | 926 | void OPPROTO op_movl_T0_seg(void) |
| 921 | { | 927 | { |
| 922 | - T0 = env->segs[PARAM1]; | 928 | + T0 = env->segs[PARAM1].selector; |
| 923 | } | 929 | } |
| 924 | 930 | ||
| 925 | void OPPROTO op_movl_A0_seg(void) | 931 | void OPPROTO op_movl_A0_seg(void) |
| @@ -942,6 +948,61 @@ void OPPROTO op_lar(void) | @@ -942,6 +948,61 @@ void OPPROTO op_lar(void) | ||
| 942 | helper_lar(); | 948 | helper_lar(); |
| 943 | } | 949 | } |
| 944 | 950 | ||
| 951 | +/* T0: segment, T1:eip */ | ||
| 952 | +void OPPROTO op_ljmp_T0_T1(void) | ||
| 953 | +{ | ||
| 954 | + jmp_seg(T0 & 0xffff, T1); | ||
| 955 | +} | ||
| 956 | + | ||
| 957 | +void OPPROTO op_lldt_T0(void) | ||
| 958 | +{ | ||
| 959 | + helper_lldt_T0(); | ||
| 960 | +} | ||
| 961 | + | ||
| 962 | +void OPPROTO op_ltr_T0(void) | ||
| 963 | +{ | ||
| 964 | + helper_ltr_T0(); | ||
| 965 | +} | ||
| 966 | + | ||
| 967 | +/* CR registers access */ | ||
| 968 | +void OPPROTO op_movl_crN_T0(void) | ||
| 969 | +{ | ||
| 970 | + helper_movl_crN_T0(PARAM1); | ||
| 971 | +} | ||
| 972 | + | ||
| 973 | +/* DR registers access */ | ||
| 974 | +void OPPROTO op_movl_drN_T0(void) | ||
| 975 | +{ | ||
| 976 | + helper_movl_drN_T0(PARAM1); | ||
| 977 | +} | ||
| 978 | + | ||
| 979 | +void OPPROTO op_lmsw_T0(void) | ||
| 980 | +{ | ||
| 981 | + /* only 4 lower bits of CR0 are modified */ | ||
| 982 | + T0 = (env->cr[0] & ~0xf) | (T0 & 0xf); | ||
| 983 | + helper_movl_crN_T0(0); | ||
| 984 | +} | ||
| 985 | + | ||
| 986 | +void OPPROTO op_movl_T0_env(void) | ||
| 987 | +{ | ||
| 988 | + T0 = *(uint32_t *)((char *)env + PARAM1); | ||
| 989 | +} | ||
| 990 | + | ||
| 991 | +void OPPROTO op_movl_env_T0(void) | ||
| 992 | +{ | ||
| 993 | + *(uint32_t *)((char *)env + PARAM1) = T0; | ||
| 994 | +} | ||
| 995 | + | ||
| 996 | +void OPPROTO op_movl_env_T1(void) | ||
| 997 | +{ | ||
| 998 | + *(uint32_t *)((char *)env + PARAM1) = T1; | ||
| 999 | +} | ||
| 1000 | + | ||
| 1001 | +void OPPROTO op_clts(void) | ||
| 1002 | +{ | ||
| 1003 | + env->cr[0] &= ~CR0_TS_MASK; | ||
| 1004 | +} | ||
| 1005 | + | ||
| 945 | /* flags handling */ | 1006 | /* flags handling */ |
| 946 | 1007 | ||
| 947 | /* slow jumps cases : in order to avoid calling a function with a | 1008 | /* slow jumps cases : in order to avoid calling a function with a |
translate-i386.c
| @@ -575,7 +575,7 @@ static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func) | @@ -575,7 +575,7 @@ static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func) | ||
| 575 | if (s->addseg && override < 0) | 575 | if (s->addseg && override < 0) |
| 576 | override = R_DS; | 576 | override = R_DS; |
| 577 | if (override >= 0) { | 577 | if (override >= 0) { |
| 578 | - gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); | 578 | + gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base)); |
| 579 | index = 3 + ot; | 579 | index = 3 + ot; |
| 580 | } else { | 580 | } else { |
| 581 | index = ot; | 581 | index = ot; |
| @@ -583,7 +583,7 @@ static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func) | @@ -583,7 +583,7 @@ static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func) | ||
| 583 | } else { | 583 | } else { |
| 584 | if (override < 0) | 584 | if (override < 0) |
| 585 | override = R_DS; | 585 | override = R_DS; |
| 586 | - gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); | 586 | + gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base)); |
| 587 | /* 16 address, always override */ | 587 | /* 16 address, always override */ |
| 588 | index = 6 + ot; | 588 | index = 6 + ot; |
| 589 | } | 589 | } |
| @@ -878,7 +878,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ | @@ -878,7 +878,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ | ||
| 878 | else | 878 | else |
| 879 | override = R_DS; | 879 | override = R_DS; |
| 880 | } | 880 | } |
| 881 | - gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); | 881 | + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); |
| 882 | } | 882 | } |
| 883 | } else { | 883 | } else { |
| 884 | switch (mod) { | 884 | switch (mod) { |
| @@ -944,7 +944,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ | @@ -944,7 +944,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ | ||
| 944 | else | 944 | else |
| 945 | override = R_DS; | 945 | override = R_DS; |
| 946 | } | 946 | } |
| 947 | - gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); | 947 | + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); |
| 948 | } | 948 | } |
| 949 | } | 949 | } |
| 950 | 950 | ||
| @@ -1146,8 +1146,7 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip) | @@ -1146,8 +1146,7 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip) | ||
| 1146 | if (!s->vm86) | 1146 | if (!s->vm86) |
| 1147 | gen_op_movl_seg_T0(seg_reg, cur_eip); | 1147 | gen_op_movl_seg_T0(seg_reg, cur_eip); |
| 1148 | else | 1148 | else |
| 1149 | - gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]), | ||
| 1150 | - offsetof(CPUX86State,seg_cache[seg_reg].base)); | 1149 | + gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg])); |
| 1151 | if (!s->addseg && seg_reg < R_FS) | 1150 | if (!s->addseg && seg_reg < R_FS) |
| 1152 | s->is_jmp = 2; /* abort translation because the register may | 1151 | s->is_jmp = 2; /* abort translation because the register may |
| 1153 | have a non zero base */ | 1152 | have a non zero base */ |
| @@ -1230,7 +1229,7 @@ static void gen_stack_A0(DisasContext *s) | @@ -1230,7 +1229,7 @@ static void gen_stack_A0(DisasContext *s) | ||
| 1230 | gen_op_andl_A0_ffff(); | 1229 | gen_op_andl_A0_ffff(); |
| 1231 | gen_op_movl_T1_A0(); | 1230 | gen_op_movl_T1_A0(); |
| 1232 | if (s->addseg) | 1231 | if (s->addseg) |
| 1233 | - gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base)); | 1232 | + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); |
| 1234 | } | 1233 | } |
| 1235 | 1234 | ||
| 1236 | /* NOTE: wrap around in 16 bit not fully handled */ | 1235 | /* NOTE: wrap around in 16 bit not fully handled */ |
| @@ -1243,7 +1242,7 @@ static void gen_pusha(DisasContext *s) | @@ -1243,7 +1242,7 @@ static void gen_pusha(DisasContext *s) | ||
| 1243 | gen_op_andl_A0_ffff(); | 1242 | gen_op_andl_A0_ffff(); |
| 1244 | gen_op_movl_T1_A0(); | 1243 | gen_op_movl_T1_A0(); |
| 1245 | if (s->addseg) | 1244 | if (s->addseg) |
| 1246 | - gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base)); | 1245 | + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); |
| 1247 | for(i = 0;i < 8; i++) { | 1246 | for(i = 0;i < 8; i++) { |
| 1248 | gen_op_mov_TN_reg[OT_LONG][0][7 - i](); | 1247 | gen_op_mov_TN_reg[OT_LONG][0][7 - i](); |
| 1249 | gen_op_st_T0_A0[OT_WORD + s->dflag](); | 1248 | gen_op_st_T0_A0[OT_WORD + s->dflag](); |
| @@ -1262,7 +1261,7 @@ static void gen_popa(DisasContext *s) | @@ -1262,7 +1261,7 @@ static void gen_popa(DisasContext *s) | ||
| 1262 | gen_op_movl_T1_A0(); | 1261 | gen_op_movl_T1_A0(); |
| 1263 | gen_op_addl_T1_im(16 << s->dflag); | 1262 | gen_op_addl_T1_im(16 << s->dflag); |
| 1264 | if (s->addseg) | 1263 | if (s->addseg) |
| 1265 | - gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base)); | 1264 | + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); |
| 1266 | for(i = 0;i < 8; i++) { | 1265 | for(i = 0;i < 8; i++) { |
| 1267 | /* ESP is not reloaded */ | 1266 | /* ESP is not reloaded */ |
| 1268 | if (i != 3) { | 1267 | if (i != 3) { |
| @@ -1291,7 +1290,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) | @@ -1291,7 +1290,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) | ||
| 1291 | gen_op_andl_A0_ffff(); | 1290 | gen_op_andl_A0_ffff(); |
| 1292 | gen_op_movl_T1_A0(); | 1291 | gen_op_movl_T1_A0(); |
| 1293 | if (s->addseg) | 1292 | if (s->addseg) |
| 1294 | - gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base)); | 1293 | + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); |
| 1295 | /* push bp */ | 1294 | /* push bp */ |
| 1296 | gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); | 1295 | gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); |
| 1297 | gen_op_st_T0_A0[ot](); | 1296 | gen_op_st_T0_A0[ot](); |
| @@ -1714,9 +1713,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1714,9 +1713,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1714 | gen_op_ld_T1_A0[ot](); | 1713 | gen_op_ld_T1_A0[ot](); |
| 1715 | gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); | 1714 | gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
| 1716 | gen_op_lduw_T0_A0(); | 1715 | gen_op_lduw_T0_A0(); |
| 1717 | - gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base); | ||
| 1718 | - gen_op_movl_T0_T1(); | ||
| 1719 | - gen_op_jmp_T0(); | 1716 | + if (!s->vm86) { |
| 1717 | + /* we compute EIP to handle the exception case */ | ||
| 1718 | + gen_op_jmp_im(pc_start - s->cs_base); | ||
| 1719 | + gen_op_ljmp_T0_T1(); | ||
| 1720 | + } else { | ||
| 1721 | + gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); | ||
| 1722 | + gen_op_movl_T0_T1(); | ||
| 1723 | + gen_op_jmp_T0(); | ||
| 1724 | + } | ||
| 1720 | s->is_jmp = 1; | 1725 | s->is_jmp = 1; |
| 1721 | break; | 1726 | break; |
| 1722 | case 6: /* push Ev */ | 1727 | case 6: /* push Ev */ |
| @@ -2085,7 +2090,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2085,7 +2090,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2085 | override = R_DS; | 2090 | override = R_DS; |
| 2086 | } | 2091 | } |
| 2087 | if (must_add_seg) { | 2092 | if (must_add_seg) { |
| 2088 | - gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); | 2093 | + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); |
| 2089 | } | 2094 | } |
| 2090 | } | 2095 | } |
| 2091 | if ((b & 2) == 0) { | 2096 | if ((b & 2) == 0) { |
| @@ -2113,7 +2118,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2113,7 +2118,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2113 | override = R_DS; | 2118 | override = R_DS; |
| 2114 | } | 2119 | } |
| 2115 | if (must_add_seg) { | 2120 | if (must_add_seg) { |
| 2116 | - gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); | 2121 | + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); |
| 2117 | } | 2122 | } |
| 2118 | } | 2123 | } |
| 2119 | gen_op_ldub_T0_A0(); | 2124 | gen_op_ldub_T0_A0(); |
| @@ -2619,12 +2624,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2619,12 +2624,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2619 | break; | 2624 | break; |
| 2620 | case 0x1c: | 2625 | case 0x1c: |
| 2621 | switch(rm) { | 2626 | switch(rm) { |
| 2627 | + case 0: /* feni (287 only, just do nop here) */ | ||
| 2628 | + break; | ||
| 2629 | + case 1: /* fdisi (287 only, just do nop here) */ | ||
| 2630 | + break; | ||
| 2622 | case 2: /* fclex */ | 2631 | case 2: /* fclex */ |
| 2623 | gen_op_fclex(); | 2632 | gen_op_fclex(); |
| 2624 | break; | 2633 | break; |
| 2625 | case 3: /* fninit */ | 2634 | case 3: /* fninit */ |
| 2626 | gen_op_fninit(); | 2635 | gen_op_fninit(); |
| 2627 | break; | 2636 | break; |
| 2637 | + case 4: /* fsetpm (287 only, just do nop here) */ | ||
| 2638 | + break; | ||
| 2628 | default: | 2639 | default: |
| 2629 | goto illegal_op; | 2640 | goto illegal_op; |
| 2630 | } | 2641 | } |
| @@ -3011,8 +3022,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3011,8 +3022,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3011 | 3022 | ||
| 3012 | /* change cs and pc */ | 3023 | /* change cs and pc */ |
| 3013 | gen_op_movl_T0_im(selector); | 3024 | gen_op_movl_T0_im(selector); |
| 3014 | - gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base); | ||
| 3015 | - gen_op_jmp_im((unsigned long)offset); | 3025 | + if (!s->vm86) { |
| 3026 | + /* we compute EIP to handle the exception case */ | ||
| 3027 | + gen_op_jmp_im(pc_start - s->cs_base); | ||
| 3028 | + gen_op_movl_T1_im(offset); | ||
| 3029 | + gen_op_ljmp_T0_T1(); | ||
| 3030 | + } else { | ||
| 3031 | + gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); | ||
| 3032 | + gen_op_jmp_im((unsigned long)offset); | ||
| 3033 | + } | ||
| 3016 | s->is_jmp = 1; | 3034 | s->is_jmp = 1; |
| 3017 | } | 3035 | } |
| 3018 | break; | 3036 | break; |
| @@ -3343,6 +3361,111 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3343,6 +3361,111 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3343 | /* XXX: if cpl == 0, then should do something else */ | 3361 | /* XXX: if cpl == 0, then should do something else */ |
| 3344 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 3362 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 3345 | break; | 3363 | break; |
| 3364 | + case 0x100: | ||
| 3365 | + modrm = ldub(s->pc++); | ||
| 3366 | + mod = (modrm >> 6) & 3; | ||
| 3367 | + op = (modrm >> 3) & 7; | ||
| 3368 | + switch(op) { | ||
| 3369 | + case 0: /* sldt */ | ||
| 3370 | + gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector)); | ||
| 3371 | + ot = OT_WORD; | ||
| 3372 | + if (mod == 3) | ||
| 3373 | + ot += s->dflag; | ||
| 3374 | + gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); | ||
| 3375 | + break; | ||
| 3376 | + case 2: /* lldt */ | ||
| 3377 | + if (s->cpl != 0) { | ||
| 3378 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | ||
| 3379 | + } else { | ||
| 3380 | + gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); | ||
| 3381 | + gen_op_jmp_im(pc_start - s->cs_base); | ||
| 3382 | + gen_op_lldt_T0(); | ||
| 3383 | + } | ||
| 3384 | + break; | ||
| 3385 | + case 1: /* str */ | ||
| 3386 | + gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector)); | ||
| 3387 | + ot = OT_WORD; | ||
| 3388 | + if (mod == 3) | ||
| 3389 | + ot += s->dflag; | ||
| 3390 | + gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); | ||
| 3391 | + break; | ||
| 3392 | + case 3: /* ltr */ | ||
| 3393 | + if (s->cpl != 0) { | ||
| 3394 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | ||
| 3395 | + } else { | ||
| 3396 | + gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); | ||
| 3397 | + gen_op_jmp_im(pc_start - s->cs_base); | ||
| 3398 | + gen_op_ltr_T0(); | ||
| 3399 | + } | ||
| 3400 | + break; | ||
| 3401 | + case 4: /* verr */ | ||
| 3402 | + case 5: /* verw */ | ||
| 3403 | + default: | ||
| 3404 | + goto illegal_op; | ||
| 3405 | + } | ||
| 3406 | + break; | ||
| 3407 | + case 0x101: | ||
| 3408 | + modrm = ldub(s->pc++); | ||
| 3409 | + mod = (modrm >> 6) & 3; | ||
| 3410 | + op = (modrm >> 3) & 7; | ||
| 3411 | + switch(op) { | ||
| 3412 | + case 0: /* sgdt */ | ||
| 3413 | + case 1: /* sidt */ | ||
| 3414 | + if (mod == 3) | ||
| 3415 | + goto illegal_op; | ||
| 3416 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | ||
| 3417 | + if (op == 0) | ||
| 3418 | + gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit)); | ||
| 3419 | + else | ||
| 3420 | + gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit)); | ||
| 3421 | + gen_op_stw_T0_A0(); | ||
| 3422 | + gen_op_addl_A0_im(2); | ||
| 3423 | + if (op == 0) | ||
| 3424 | + gen_op_movl_T0_env(offsetof(CPUX86State,gdt.base)); | ||
| 3425 | + else | ||
| 3426 | + gen_op_movl_T0_env(offsetof(CPUX86State,idt.base)); | ||
| 3427 | + if (!s->dflag) | ||
| 3428 | + gen_op_andl_T0_im(0xffffff); | ||
| 3429 | + gen_op_stl_T0_A0(); | ||
| 3430 | + break; | ||
| 3431 | + case 2: /* lgdt */ | ||
| 3432 | + case 3: /* lidt */ | ||
| 3433 | + if (mod == 3) | ||
| 3434 | + goto illegal_op; | ||
| 3435 | + if (s->cpl != 0) { | ||
| 3436 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | ||
| 3437 | + } else { | ||
| 3438 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | ||
| 3439 | + gen_op_lduw_T1_A0(); | ||
| 3440 | + gen_op_addl_A0_im(2); | ||
| 3441 | + gen_op_ldl_T0_A0(); | ||
| 3442 | + if (!s->dflag) | ||
| 3443 | + gen_op_andl_T0_im(0xffffff); | ||
| 3444 | + if (op == 2) { | ||
| 3445 | + gen_op_movl_env_T0(offsetof(CPUX86State,gdt.base)); | ||
| 3446 | + gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit)); | ||
| 3447 | + } else { | ||
| 3448 | + gen_op_movl_env_T0(offsetof(CPUX86State,idt.base)); | ||
| 3449 | + gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit)); | ||
| 3450 | + } | ||
| 3451 | + } | ||
| 3452 | + break; | ||
| 3453 | + case 4: /* smsw */ | ||
| 3454 | + gen_op_movl_T0_env(offsetof(CPUX86State,cr[0])); | ||
| 3455 | + gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1); | ||
| 3456 | + break; | ||
| 3457 | + case 6: /* lmsw */ | ||
| 3458 | + if (s->cpl != 0) { | ||
| 3459 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | ||
| 3460 | + } else { | ||
| 3461 | + gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); | ||
| 3462 | + gen_op_lmsw_T0(); | ||
| 3463 | + } | ||
| 3464 | + break; | ||
| 3465 | + default: | ||
| 3466 | + goto illegal_op; | ||
| 3467 | + } | ||
| 3468 | + break; | ||
| 3346 | case 0x102: /* lar */ | 3469 | case 0x102: /* lar */ |
| 3347 | case 0x103: /* lsl */ | 3470 | case 0x103: /* lsl */ |
| 3348 | if (s->vm86) | 3471 | if (s->vm86) |
| @@ -3361,6 +3484,83 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3361,6 +3484,83 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3361 | s->cc_op = CC_OP_EFLAGS; | 3484 | s->cc_op = CC_OP_EFLAGS; |
| 3362 | gen_op_mov_reg_T1[ot][reg](); | 3485 | gen_op_mov_reg_T1[ot][reg](); |
| 3363 | break; | 3486 | break; |
| 3487 | + case 0x118: | ||
| 3488 | + modrm = ldub(s->pc++); | ||
| 3489 | + mod = (modrm >> 6) & 3; | ||
| 3490 | + op = (modrm >> 3) & 7; | ||
| 3491 | + switch(op) { | ||
| 3492 | + case 0: /* prefetchnta */ | ||
| 3493 | + case 1: /* prefetchnt0 */ | ||
| 3494 | + case 2: /* prefetchnt0 */ | ||
| 3495 | + case 3: /* prefetchnt0 */ | ||
| 3496 | + if (mod == 3) | ||
| 3497 | + goto illegal_op; | ||
| 3498 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | ||
| 3499 | + /* nothing more to do */ | ||
| 3500 | + break; | ||
| 3501 | + default: | ||
| 3502 | + goto illegal_op; | ||
| 3503 | + } | ||
| 3504 | + break; | ||
| 3505 | + case 0x120: /* mov reg, crN */ | ||
| 3506 | + case 0x122: /* mov crN, reg */ | ||
| 3507 | + if (s->cpl != 0) { | ||
| 3508 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | ||
| 3509 | + } else { | ||
| 3510 | + modrm = ldub(s->pc++); | ||
| 3511 | + if ((modrm & 0xc0) != 0xc0) | ||
| 3512 | + goto illegal_op; | ||
| 3513 | + rm = modrm & 7; | ||
| 3514 | + reg = (modrm >> 3) & 7; | ||
| 3515 | + switch(reg) { | ||
| 3516 | + case 0: | ||
| 3517 | + case 2: | ||
| 3518 | + case 3: | ||
| 3519 | + case 4: | ||
| 3520 | + if (b & 2) { | ||
| 3521 | + gen_op_mov_TN_reg[OT_LONG][0][rm](); | ||
| 3522 | + gen_op_movl_crN_T0(reg); | ||
| 3523 | + s->is_jmp = 2; | ||
| 3524 | + } else { | ||
| 3525 | + gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg])); | ||
| 3526 | + gen_op_mov_reg_T0[OT_LONG][rm](); | ||
| 3527 | + } | ||
| 3528 | + break; | ||
| 3529 | + default: | ||
| 3530 | + goto illegal_op; | ||
| 3531 | + } | ||
| 3532 | + } | ||
| 3533 | + break; | ||
| 3534 | + case 0x121: /* mov reg, drN */ | ||
| 3535 | + case 0x123: /* mov drN, reg */ | ||
| 3536 | + if (s->cpl != 0) { | ||
| 3537 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | ||
| 3538 | + } else { | ||
| 3539 | + modrm = ldub(s->pc++); | ||
| 3540 | + if ((modrm & 0xc0) != 0xc0) | ||
| 3541 | + goto illegal_op; | ||
| 3542 | + rm = modrm & 7; | ||
| 3543 | + reg = (modrm >> 3) & 7; | ||
| 3544 | + /* XXX: do it dynamically with CR4.DE bit */ | ||
| 3545 | + if (reg == 4 || reg == 5) | ||
| 3546 | + goto illegal_op; | ||
| 3547 | + if (b & 2) { | ||
| 3548 | + gen_op_mov_TN_reg[OT_LONG][0][rm](); | ||
| 3549 | + gen_op_movl_drN_T0(reg); | ||
| 3550 | + s->is_jmp = 2; | ||
| 3551 | + } else { | ||
| 3552 | + gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg])); | ||
| 3553 | + gen_op_mov_reg_T0[OT_LONG][rm](); | ||
| 3554 | + } | ||
| 3555 | + } | ||
| 3556 | + break; | ||
| 3557 | + case 0x106: /* clts */ | ||
| 3558 | + if (s->cpl != 0) { | ||
| 3559 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | ||
| 3560 | + } else { | ||
| 3561 | + gen_op_clts(); | ||
| 3562 | + } | ||
| 3563 | + break; | ||
| 3364 | default: | 3564 | default: |
| 3365 | goto illegal_op; | 3565 | goto illegal_op; |
| 3366 | } | 3566 | } |
| @@ -3859,12 +4059,12 @@ void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags) | @@ -3859,12 +4059,12 @@ void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags) | ||
| 3859 | eflags & CC_P ? 'P' : '-', | 4059 | eflags & CC_P ? 'P' : '-', |
| 3860 | eflags & CC_C ? 'C' : '-'); | 4060 | eflags & CC_C ? 'C' : '-'); |
| 3861 | fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n", | 4061 | fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n", |
| 3862 | - env->segs[R_CS], | ||
| 3863 | - env->segs[R_SS], | ||
| 3864 | - env->segs[R_DS], | ||
| 3865 | - env->segs[R_ES], | ||
| 3866 | - env->segs[R_FS], | ||
| 3867 | - env->segs[R_GS]); | 4062 | + env->segs[R_CS].selector, |
| 4063 | + env->segs[R_SS].selector, | ||
| 4064 | + env->segs[R_DS].selector, | ||
| 4065 | + env->segs[R_ES].selector, | ||
| 4066 | + env->segs[R_FS].selector, | ||
| 4067 | + env->segs[R_GS].selector); | ||
| 3868 | if (flags & X86_DUMP_CCOP) { | 4068 | if (flags & X86_DUMP_CCOP) { |
| 3869 | if ((unsigned)env->cc_op < CC_OP_NB) | 4069 | if ((unsigned)env->cc_op < CC_OP_NB) |
| 3870 | strcpy(cc_op_name, cc_op_str[env->cc_op]); | 4070 | strcpy(cc_op_name, cc_op_str[env->cc_op]); |