trunk/src/emu/cpu/i386/i386priv.h
| r18625 | r18626 | |
| 393 | 393 | #define STACK_32BIT (cpustate->sreg[SS].d) |
| 394 | 394 | #define V8086_MODE (cpustate->VM) |
| 395 | 395 | #define NESTED_TASK (cpustate->NT) |
| 396 | #define WP (cpustate->cr[0] & 0x10000) |
| 396 | 397 | |
| 397 | 398 | #define SetOF_Add32(r,s,d) (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x80000000) ? 1: 0) |
| 398 | 399 | #define SetOF_Add16(r,s,d) (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x8000) ? 1 : 0) |
| r18625 | r18626 | |
| 487 | 488 | bool user = (cpustate->CPL == 3) && (rwn >= 0); |
| 488 | 489 | *error = 0; |
| 489 | 490 | |
| 490 | | // TODO: cr0 wp bit, 486 and higher |
| 491 | 491 | UINT32 page_dir = cpustate->program->read_dword(pdbr + directory * 4); |
| 492 | 492 | if((page_dir & 1) && ((page_dir & 4) || !user)) |
| 493 | 493 | { |
| r18625 | r18626 | |
| 496 | 496 | page_entry = cpustate->program->read_dword((page_dir & 0xfffff000) + (table * 4)); |
| 497 | 497 | if(!(page_entry & 1)) |
| 498 | 498 | ret = 0; |
| 499 | | else if((!(page_entry & 2) && user && (rwn == 1)) || (!(page_entry & 4) && user)) |
| 499 | else if((!(page_entry & 2) && (user || WP) && (rwn == 1)) || (!(page_entry & 4) && user)) |
| 500 | 500 | { |
| 501 | 501 | *error = 1; |
| 502 | 502 | ret = 0; |
| r18625 | r18626 | |
| 516 | 516 | { |
| 517 | 517 | if (page_dir & 0x80) |
| 518 | 518 | { |
| 519 | | if(!(page_dir & 2) && user && (rwn == 1)) |
| 519 | if(!(page_dir & 2) && (user || WP) && (rwn == 1)) |
| 520 | 520 | { |
| 521 | 521 | *error = 1; |
| 522 | 522 | ret = 0; |
| r18625 | r18626 | |
| 535 | 535 | page_entry = cpustate->program->read_dword((page_dir & 0xfffff000) + (table * 4)); |
| 536 | 536 | if(!(page_entry & 1)) |
| 537 | 537 | ret = 0; |
| 538 | | else if((!(page_entry & 2) && user && (rwn == 1)) || (!(page_entry & 4) && user)) |
| 538 | else if((!(page_entry & 2) && (user || WP) && (rwn == 1)) || (!(page_entry & 4) && user)) |
| 539 | 539 | { |
| 540 | 540 | *error = 1; |
| 541 | 541 | ret = 0; |
| r18625 | r18626 | |
| 562 | 562 | if(!ret) |
| 563 | 563 | { |
| 564 | 564 | if(rwn != -1) |
| 565 | | *error |= ((rwn & 1)<<1) | ((cpustate->CPL == 3)<<2); |
| 565 | *error |= ((rwn == 1)<<1) | ((cpustate->CPL == 3)<<2); |
| 566 | 566 | return 0; |
| 567 | 567 | } |
| 568 | 568 | return 1; |
trunk/src/emu/cpu/i386/i386ops.h
| r18625 | r18626 | |
| 301 | 301 | { 0x20, OP_2BYTE|OP_I386, I386OP(mov_r32_cr), I386OP(mov_r32_cr), }, |
| 302 | 302 | { 0x21, OP_2BYTE|OP_I386, I386OP(mov_r32_dr), I386OP(mov_r32_dr), }, |
| 303 | 303 | { 0x22, OP_2BYTE|OP_I386, I386OP(mov_cr_r32), I386OP(mov_cr_r32), }, |
| 304 | { 0x22, OP_2BYTE|OP_I486, I486OP(mov_cr_r32), I386OP(mov_cr_r32), }, |
| 304 | 305 | { 0x23, OP_2BYTE|OP_I386, I386OP(mov_dr_r32), I386OP(mov_dr_r32), }, |
| 305 | 306 | { 0x24, OP_2BYTE|OP_I386, I386OP(mov_r32_tr), I386OP(mov_r32_tr), }, |
| 306 | 307 | { 0x26, OP_2BYTE|OP_I386, I386OP(mov_tr_r32), I386OP(mov_tr_r32), }, |
trunk/src/emu/cpu/i386/i386ops.c
| r18625 | r18626 | |
| 653 | 653 | |
| 654 | 654 | static void I386OP(mov_r32_cr)(i386_state *cpustate) // Opcode 0x0f 20 |
| 655 | 655 | { |
| 656 | if(PROTECTED_MODE && cpustate->CPL) |
| 657 | FAULT(FAULT_GP, 0); |
| 656 | 658 | UINT8 modrm = FETCH(cpustate); |
| 657 | 659 | UINT8 cr = (modrm >> 3) & 0x7; |
| 658 | 660 | |
| r18625 | r18626 | |
| 662 | 664 | |
| 663 | 665 | static void I386OP(mov_r32_dr)(i386_state *cpustate) // Opcode 0x0f 21 |
| 664 | 666 | { |
| 667 | if(PROTECTED_MODE && cpustate->CPL) |
| 668 | FAULT(FAULT_GP, 0); |
| 665 | 669 | UINT8 modrm = FETCH(cpustate); |
| 666 | 670 | UINT8 dr = (modrm >> 3) & 0x7; |
| 667 | 671 | |
| r18625 | r18626 | |
| 683 | 687 | |
| 684 | 688 | static void I386OP(mov_cr_r32)(i386_state *cpustate) // Opcode 0x0f 22 |
| 685 | 689 | { |
| 690 | if(PROTECTED_MODE && cpustate->CPL) |
| 691 | FAULT(FAULT_GP, 0); |
| 686 | 692 | UINT8 modrm = FETCH(cpustate); |
| 687 | 693 | UINT8 cr = (modrm >> 3) & 0x7; |
| 688 | | |
| 689 | | cpustate->cr[cr] = LOAD_RM32(modrm); |
| 694 | UINT32 data = LOAD_RM32(modrm); |
| 690 | 695 | switch(cr) |
| 691 | 696 | { |
| 692 | | case 0: CYCLES(cpustate,CYCLES_MOV_REG_CR0); break; |
| 697 | case 0: |
| 698 | data &= 0xfffeffff; // wp not supported on 386 |
| 699 | CYCLES(cpustate,CYCLES_MOV_REG_CR0); |
| 700 | break; |
| 693 | 701 | case 2: CYCLES(cpustate,CYCLES_MOV_REG_CR2); break; |
| 694 | 702 | case 3: CYCLES(cpustate,CYCLES_MOV_REG_CR3); break; |
| 695 | 703 | case 4: CYCLES(cpustate,1); break; // TODO |
| r18625 | r18626 | |
| 697 | 705 | fatalerror("i386: mov_cr_r32 CR%d!\n", cr); |
| 698 | 706 | break; |
| 699 | 707 | } |
| 708 | cpustate->cr[cr] = data; |
| 700 | 709 | } |
| 701 | 710 | |
| 702 | 711 | static void I386OP(mov_dr_r32)(i386_state *cpustate) // Opcode 0x0f 23 |
| 703 | 712 | { |
| 713 | if(PROTECTED_MODE && cpustate->CPL) |
| 714 | FAULT(FAULT_GP, 0); |
| 704 | 715 | UINT8 modrm = FETCH(cpustate); |
| 705 | 716 | UINT8 dr = (modrm >> 3) & 0x7; |
| 706 | 717 | |
trunk/src/emu/cpu/i386/i486ops.c
| r18625 | r18626 | |
| 466 | 466 | REG32(EDI) = SWITCH_ENDIAN_32(REG32(EDI)); |
| 467 | 467 | CYCLES(cpustate,1); // TODO |
| 468 | 468 | } |
| 469 | |
| 470 | static void I486OP(mov_cr_r32)(i386_state *cpustate) // Opcode 0x0f 22 |
| 471 | { |
| 472 | if(PROTECTED_MODE && cpustate->CPL) |
| 473 | FAULT(FAULT_GP, 0); |
| 474 | UINT8 modrm = FETCH(cpustate); |
| 475 | UINT8 cr = (modrm >> 3) & 0x7; |
| 476 | cpustate->cr[cr] = LOAD_RM32(modrm); |
| 477 | switch(cr) |
| 478 | { |
| 479 | case 0: CYCLES(cpustate,CYCLES_MOV_REG_CR0); break; |
| 480 | case 2: CYCLES(cpustate,CYCLES_MOV_REG_CR2); break; |
| 481 | case 3: CYCLES(cpustate,CYCLES_MOV_REG_CR3); break; |
| 482 | case 4: CYCLES(cpustate,1); break; // TODO |
| 483 | default: |
| 484 | fatalerror("i386: mov_cr_r32 CR%d !", cr); |
| 485 | break; |
| 486 | } |
| 487 | } |