OSDN Git Service

[VM][I386] .
authorK.Ohta <whatisthis.sowhat@gmail.com>
Wed, 24 Apr 2019 10:01:39 +0000 (19:01 +0900)
committerK.Ohta <whatisthis.sowhat@gmail.com>
Wed, 24 Apr 2019 10:01:39 +0000 (19:01 +0900)
source/src/vm/mame/emu/cpu/i386/i386.c
source/src/vm/mame/emu/cpu/i386/i386op16.c
source/src/vm/mame/emu/cpu/i386/i386op32.c
source/src/vm/mame/emu/cpu/i386/i386ops.c
source/src/vm/mame/emu/cpu/i386/i386priv.h

index 885ce2d..edd3bfd 100644 (file)
@@ -1002,8 +1002,8 @@ static void i386_sreg_load(i386_state *cpustate, UINT16 selector, UINT8 reg, boo
                                        cpustate->sreg[ES].selector = 0;
                                        cpustate->VM = 0;
                                        //cpustate->eflags = get_flags(cpustate);
-                                       cpustate->eflags &= ~I386_EFLAGS_VM; // Clear VM flag
-                                       set_flags(cpustate, cpustate->eflags);
+                                       //cpustate->eflags &= ~I386_EFLAGS_VM; // Clear VM flag
+                                       //set_flags(cpustate, cpustate->eflags);
                                        i386_load_segment_descriptor(cpustate,GS);
                                        i386_load_segment_descriptor(cpustate,FS);
                                        i386_load_segment_descriptor(cpustate,DS);
@@ -2497,7 +2497,8 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
        UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1);
        UINT32 stack_size = 6;
        CPL = cpustate->CPL;
-       UINT32 ea = i386_translate(cpustate, SS, (STACK_32BIT)?REG32(ESP):REG16(SP), 0, (operand32)?12:6);
+       //UINT32 ea = i386_translate(cpustate, SS, (STACK_32BIT)?REG32(ESP):REG16(SP), 0, (operand32)?12:6);
+       UINT32 ea = i386_translate(cpustate, SS, (STACK_32BIT)?REG32(ESP):REG16(SP), 0, 1);
        if(operand32 == 0)
        {
                newEIP = READ16(cpustate, ea) & 0xffff;
@@ -2523,41 +2524,44 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
                }
                if(operand32 == 0)
                {
-                       cpustate->sreg[CS].selector = newCS & 0xffff;
-                       i386_load_segment_descriptor(cpustate,CS);
-                       if((newEIP & 0xffff) > cpustate->sreg[CS].limit) {
-                               FAULT(FAULT_GP, 0);
-                       }
+                       //if((newEIP & 0xffff) > cpustate->sreg[CS].limit) {
+                       //      FAULT(FAULT_GP, 0);
+                       //}
                        cpustate->eip = newEIP & 0xffff;
+                       cpustate->sreg[CS].selector = newCS & 0xffff;
+                       //i386_load_segment_descriptor(cpustate,CS);
                        //newflags &= ~(3<<12);
                        //newflags |= (((oldflags>>12)&3)<<12);  // IOPL cannot be changed in V86 mode
                        newflags &= ~I386_EFLAGS_IOPL;  // IOPL cannot be changed in V86 mode
                        newflags |= (oldflags & I386_EFLAGS_IOPL);
                        set_flags(cpustate,(newflags & 0xffff) | (oldflags & ~0xffff));
-                       if(STACK_32BIT) {
-                               REG32(ESP) += stack_size;
-                       } else {
-                               REG16(SP) += stack_size;
-                       }
+                       //if(STACK_32BIT) {
+                       //REG32(ESP) += stack_size;
+                               //} else {
+                       //              REG16(SP) += stack_size;
+                       REG16(SP) += 6;
+                               //}
                }
                else
                {
                        cpustate->sreg[CS].selector = newCS & 0xffff;
-                       i386_load_segment_descriptor(cpustate,CS);
-                       if(newEIP > cpustate->sreg[CS].limit) {
-                               FAULT(FAULT_GP, 0);
-                       }
+                       //i386_load_segment_descriptor(cpustate,CS);
+                       //if(newEIP > cpustate->sreg[CS].limit) {
+                       //      FAULT(FAULT_GP, 0);
+                       //}
                        cpustate->eip = newEIP;
                        //newflags &= ~(3<<12);
                        //newflags |= 0x20000 | (((oldflags>>12)&3)<<12);  // IOPL and VM cannot be changed in V86 mode
                        newflags &= ~I386_EFLAGS_IOPL;  // IOPL and VM cannot be changed in V86 mode
                        newflags |= (oldflags & I386_EFLAGS_IOPL) | I386_EFLAGS_VM;
                        set_flags(cpustate,newflags);
-                       if(STACK_32BIT) {
-                               REG32(ESP) += stack_size;
-                       } else {
-                               REG16(SP) += stack_size;
-                       }
+                       //if(STACK_32BIT) {
+                       //REG32(ESP) += stack_size;
+                       //} else {
+                       //      REG16(SP) += stack_size;
+                       //}
+                       REG32(ESP) += 12;
+                       
                }
                
        }
@@ -2689,7 +2693,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
                                }
                                if(newCS & 0x04)
                                {
-                                       if((newCS & ~0x07) >= cpustate->ldtr.limit)
+                                       if((newCS & ~0x07) >= (cpustate->ldtr.limit & ~0x07))
                                        {
                                                logerror("IRET: Return CS selector (%04x) is past LDT limit.\n",newCS);
                                                FAULT(FAULT_GP,newCS & ~0x03)
@@ -2697,9 +2701,9 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
                                }
                                else
                                {
-                                       if((newCS & ~0x07) >= cpustate->gdtr.limit)
+                                       if((newCS & ~0x07) >= (cpustate->gdtr.limit & ~0x07))
                                        {
-                                               logerror("IRET: Return CS selector is past GDT limit.\n");
+                                               logerror("IRET: Return CS selector is past GDT limit.GDTR:LIMIT=%04X CS=%04X\n",cpustate->gdtr.limit, newCS);
                                                FAULT(FAULT_GP,newCS & ~0x03)
                                        }
                                }
index b4d6a61..886143e 100644 (file)
@@ -2042,14 +2042,14 @@ static void I386OP(pushf)(i386_state *cpustate)             // Opcode 0x9c
                offset = REG32(ESP) - 2;
        else
                offset = (REG16(SP) - 2) & 0xffff;
-       if(!PROTECTED_MODE || !V8086_MODE || ((cpustate->IOP1) && (cpustate->IOP2))) { 
+       //if(!PROTECTED_MODE || !V8086_MODE || ((cpustate->IOP1) && (cpustate->IOP2))) { 
                if(i386_limit_check(cpustate,SS,offset,2) == 0)
-                       PUSH16(cpustate, (get_flags(cpustate) & 0xffff) | 0x0002 );
+                       PUSH16(cpustate, (get_flags(cpustate) & 0xffff));
                else
                        FAULT(FAULT_SS,0)
-       } else {
-               FAULT(FAULT_GP, 0)
-       }
+                               //} else {
+                               //      FAULT(FAULT_GP, 0)
+                               //}
        CYCLES(cpustate,CYCLES_PUSHF);
 }
 
@@ -3432,7 +3432,6 @@ static void I386OP(group0F01_16)(i386_state *cpustate)      // Opcode 0x0f 01
                        }
                case 2:         /* LGDT */
                        {
-                               //printf("LGDT %08x\n", modrm);
                                if(PROTECTED_MODE && cpustate->CPL) {
                                        logerror("group0F01_16: LGDT() EXCEPTION(PROTECTED_MODE) / CPL set.\n");
                                        FAULT(FAULT_GP,0)
@@ -3445,6 +3444,7 @@ static void I386OP(group0F01_16)(i386_state *cpustate)      // Opcode 0x0f 01
                                }
                                cpustate->gdtr.limit = READ16(cpustate,ea);
                                cpustate->gdtr.base = READ32(cpustate,ea + 2) & 0xffffff;
+                               logerror("LGDT(16) PC=%08X MODRM=%02X BASE=%08X LIMIT=%04X\n", cpustate->prev_pc, modrm, cpustate->gdtr.base, cpustate->gdtr.limit);
                                CYCLES(cpustate,CYCLES_LGDT);
                                break;
                        }
index a2ea4d3..cb06a50 100644 (file)
@@ -1624,7 +1624,7 @@ static void I386OP(popfd)(i386_state *cpustate)             // Opcode 0x9d
        if(i386_limit_check(cpustate,SS,offset,4) == 0)
        {
                value = POP32(cpustate);
-               value = value & expect_flags;
+               value = /*value & expect_flags;*/ value & ~0x00010000; // RF will always return zero
                set_flags(cpustate,(current & ~mask) | (value & mask));  // mask out reserved bits
        }
        else
@@ -3212,6 +3212,7 @@ static void I386OP(group0F01_32)(i386_state *cpustate)      // Opcode 0x0f 01
                                }
                                cpustate->gdtr.limit = READ16(cpustate,ea);
                                cpustate->gdtr.base = READ32(cpustate,ea + 2);
+                               logerror("LGDT(32) PC=%08X MODRM=%02X BASE=%08X LIMIT=%04X\n", cpustate->prev_pc, modrm, cpustate->gdtr.base, cpustate->gdtr.limit);
                                CYCLES(cpustate,CYCLES_LGDT);
                                break;
                        }
index 03bf376..84904b1 100644 (file)
@@ -313,7 +313,7 @@ static void I386OP(cli)(i386_state *cpustate)               // Opcode 0xfa
                if(cpustate->CPL > IOPL) {
                        logerror("Privilege error: I386OP(cli) CPL=%d IOPL=%d PC=%08X\n", cpustate->CPL, IOPL, cpustate->pc); 
                        FAULT(FAULT_GP,0);
-                       return;
+                       //return;
                }
        }
        cpustate->IF = 0;
@@ -659,27 +659,27 @@ static void I386OP(mov_r32_cr)(i386_state *cpustate)        // Opcode 0x0f 20
 {
        UINT32 oldpc = cpustate->pc;
        UINT8 modrm = FETCH(cpustate);
-       if(modrm < 0xc0) {
-               FAULT(FAULT_UD, 0);
-               return;
-       }
-       if((PROTECTED_MODE && ((V8086_MODE) || (cpustate->CPL != 0)))) {
+       //if(modrm < 0xc0) {
+       //      FAULT(FAULT_UD, 0);
+       //      return;
+       //}
+       if((PROTECTED_MODE && (/*(V8086_MODE) ||*/ (cpustate->CPL != 0)))) {
                logerror("Call from non-supervisor privilege: I386OP(mov_r32_cr) at %08X", oldpc); 
                FAULT(FAULT_GP, 0);
-               return;
+               //return;
        }
        UINT8 cr = (modrm >> 3) & 0x7;
        //logdebug("MOV r32 CR%d VAL=(%08X)\n", cr, cpustate->cr[cr], oldpc);
-       if(cr < 5) {
-               if(cr == 1) {
-                       FAULT(FAULT_UD, 0);
-                       return;
-               }
+//     if(cr < 5) {
+//             if(cr == 1) {
+//                     FAULT(FAULT_UD, 0);
+//                     return;
+//             }
                STORE_RM32(modrm, cpustate->cr[cr]);
                CYCLES(cpustate,CYCLES_MOV_CR_REG);
-       } else {
-               logerror("Index error");
-       }
+//     } else {
+//             logerror("Index error");
+//     }
 }
 
 
@@ -1841,7 +1841,7 @@ static void I386OP(sti)(i386_state *cpustate)               // Opcode 0xfb
                if(cpustate->CPL > IOPL) {
                        logerror("Privilege error: I386OP(sti) CPL=%d IOPL=%d\n", cpustate->CPL, IOPL); 
                        FAULT(FAULT_GP,0);
-                       return;
+                       //return;
                }
        }
        cpustate->delayed_interrupt_enable = 1;  // IF is set after the next instruction.
index fa947d8..daa8f87 100644 (file)
@@ -671,12 +671,14 @@ extern MODRM_TABLE i386_MODRM_table[256];
 
 INLINE int i386_limit_check(i386_state *cpustate, int seg, UINT32 offset, UINT32 size)
 {
+//     size = 1; // TBD
        if(PROTECTED_MODE && !V8086_MODE)
        {
                if((cpustate->sreg[seg].flags & 0x0018) == 0x0010 && cpustate->sreg[seg].flags & 0x0004) // if expand-down data segment
                {
                        // compare if greater then 0xffffffff when we're passed the access size
-                       if(((offset + size - 1) <= cpustate->sreg[seg].limit) || ((cpustate->sreg[seg].d)?0:((offset + size - 1) > 0xffff)))
+                       if(offset < size) size = offset;
+                       if(((offset - size) <= cpustate->sreg[seg].limit) || ((cpustate->sreg[seg].d)?0:((offset + size - 1) > 0xffff)))
                        {
                                logerror("Limit check at 0x%08x failed. Segment %04x, limit %08x, offset %08x (expand-down)\n",cpustate->pc,cpustate->sreg[seg].selector,cpustate->sreg[seg].limit,offset);
                                return 1;