From: K.Ohta Date: Wed, 22 May 2019 13:55:23 +0000 (+0900) Subject: [VM][I386] Add SEGMENT descripter (internal values) to some flags to be faster emulation. X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=6c8ac5ce72b83fafaef3c1870060362e6a910b88;p=csp-qt%2Fcommon_source_project-fm7.git [VM][I386] Add SEGMENT descripter (internal values) to some flags to be faster emulation. --- diff --git a/source/src/vm/i386.cpp b/source/src/vm/i386.cpp index f210245d5..f9a14b4d5 100644 --- a/source/src/vm/i386.cpp +++ b/source/src/vm/i386.cpp @@ -851,7 +851,7 @@ int I386::get_shutdown_flag() return cpustate->shutdown; } -#define STATE_VERSION 6 +#define STATE_VERSION 7 void process_state_SREG(I386_SREG* val, FILEIO* state_fio) { @@ -860,7 +860,13 @@ void process_state_SREG(I386_SREG* val, FILEIO* state_fio) state_fio->StateValue(val->base); state_fio->StateValue(val->limit); state_fio->StateValue(val->d); + state_fio->StateValue(val->priv); + state_fio->StateValue(val->whole_address); + state_fio->StateValue(val->expand_down); + state_fio->StateValue(val->executable); + state_fio->StateValue(val->rwn); state_fio->StateValue(val->valid); + } void process_state_SYS_TABLE(I386_SYS_TABLE* val, FILEIO* state_fio) diff --git a/source/src/vm/mame/emu/cpu/i386/i386.c b/source/src/vm/mame/emu/cpu/i386/i386.c index 774398689..3ae94ea00 100644 --- a/source/src/vm/mame/emu/cpu/i386/i386.c +++ b/source/src/vm/mame/emu/cpu/i386/i386.c @@ -104,6 +104,12 @@ static void cpu_reset_generic(i386_state* cpustate) seg->limit = 0; seg->d = 0; seg->valid = false; + seg->whole_address = false; + seg->expand_down = false; + seg->is_system = true; + seg->executable = false; + seg->rwn = false; + seg->priv = 0; return 0; } @@ -117,8 +123,17 @@ static void cpu_reset_generic(i386_state* cpustate) } entry = seg->selector & ~0x7; - if (limit == 0 || entry + 7 > limit) + if (limit == 0 || entry + 7 > limit) { + seg->whole_address = false; + seg->valid = false; + seg->whole_address = false; + seg->expand_down = (seg->flags & SREG_FLAGS_DC) ? true : false; + seg->is_system = ((seg->flags & SREG_FLAGS_NS) == 0) ? true : false; + seg->executable = (seg->flags & SREG_FLAGS_EX) ? true : false; + seg->rwn = (seg->flags & SREG_FLAGS_RW) ? true : false; + seg->priv = (seg->flags & 0x60) >> 5; return 0; + } v1 = READ32PL0(cpustate, base + entry ); v2 = READ32PL0(cpustate, base + entry + 4 ); @@ -126,10 +141,16 @@ static void cpu_reset_generic(i386_state* cpustate) seg->flags = (v2 >> 8) & 0xf0ff; seg->base = (v2 & 0xff000000) | ((v2 & 0xff) << 16) | ((v1 >> 16) & 0xffff); seg->limit = (v2 & 0xf0000) | (v1 & 0xffff); - if (seg->flags & 0x8000) + if (seg->flags & SREG_FLAGS_GR) seg->limit = (seg->limit << 12) | 0xfff; - seg->d = (seg->flags & 0x4000) ? 1 : 0; + seg->d = (seg->flags & SREG_FLAGS_SZ) ? 1 : 0; seg->valid = true; + seg->whole_address = false; + seg->expand_down = (seg->flags & SREG_FLAGS_DC) ? true : false; + seg->is_system = ((seg->flags & SREG_FLAGS_NS) == 0) ? true : false; + seg->executable = (seg->flags & SREG_FLAGS_EX) ? true : false; + seg->rwn = (seg->flags & SREG_FLAGS_RW) ? true : false; + seg->priv = (seg->flags & 0x60) >> 5; if(desc) *desc = ((UINT64)v2<<32)|v1; @@ -198,7 +219,7 @@ static void cpu_reset_generic(i386_state* cpustate) if(cpustate->sreg[segment].selector) { i386_set_descriptor_accessed(cpustate, cpustate->sreg[segment].selector); - cpustate->sreg[segment].flags |= 0x0001; + cpustate->sreg[segment].flags |= SREG_FLAGS_AC; } } else @@ -207,6 +228,12 @@ static void cpu_reset_generic(i386_state* cpustate) cpustate->sreg[segment].limit = 0xffff; cpustate->sreg[segment].flags = (segment == CS) ? 0x00fb : 0x00f3; cpustate->sreg[segment].d = 0; + cpustate->sreg[segment].expand_down = (cpustate->sreg[segment].flags & SREG_FLAGS_DC) ? true : false; + cpustate->sreg[segment].is_system = ((cpustate->sreg[segment].flags & SREG_FLAGS_NS) == 0) ? true : false; + cpustate->sreg[segment].executable = (cpustate->sreg[segment].flags & SREG_FLAGS_EX) ? true : false; + cpustate->sreg[segment].rwn = (cpustate->sreg[segment].flags & SREG_FLAGS_RW) ? true : false; + cpustate->sreg[segment].priv = (cpustate->sreg[segment].flags & 0x60) >> 5; + cpustate->sreg[segment].whole_address = false; cpustate->sreg[segment].valid = true; } // if (segment == CS && cpustate->sreg[segment].flags != old_flags) @@ -217,13 +244,26 @@ static void cpu_reset_generic(i386_state* cpustate) cpustate->sreg[segment].base = cpustate->sreg[segment].selector << 4; cpustate->sreg[segment].d = 0; cpustate->sreg[segment].valid = true; + cpustate->sreg[segment].expand_down = (cpustate->sreg[segment].flags & SREG_FLAGS_DC) ? true : false; + cpustate->sreg[segment].is_system = ((cpustate->sreg[segment].flags & SREG_FLAGS_NS) == 0) ? true : false; + cpustate->sreg[segment].executable = (cpustate->sreg[segment].flags & SREG_FLAGS_EX) ? true : false; + cpustate->sreg[segment].rwn = (cpustate->sreg[segment].flags & SREG_FLAGS_RW) ? true : false; + cpustate->sreg[segment].priv = (cpustate->sreg[segment].flags & 0x60) >> 5; + cpustate->sreg[segment].whole_address = false; + cpustate->sreg[segment].valid = true; if( segment == CS ) { if( !cpustate->performed_intersegment_jump ) cpustate->sreg[segment].base |= 0xfff00000; - if(cpustate->cpu_version < 0x5000) + if(cpustate->cpu_version < 0x5000) { cpustate->sreg[segment].flags = 0x93; + cpustate->sreg[segment].expand_down = (cpustate->sreg[segment].flags & SREG_FLAGS_DC) ? true : false; + cpustate->sreg[segment].is_system = ((cpustate->sreg[segment].flags & SREG_FLAGS_NS) == 0) ? true : false; + cpustate->sreg[segment].executable = (cpustate->sreg[segment].flags & SREG_FLAGS_EX) ? true : false; + cpustate->sreg[segment].rwn = (cpustate->sreg[segment].flags & SREG_FLAGS_RW) ? true : false; + cpustate->sreg[segment].priv = (cpustate->sreg[segment].flags & 0x60) >> 5; + } } } } @@ -307,7 +347,7 @@ static UINT32 i386_get_stack_ptr(i386_state* cpustate, UINT8 privilege) cpustate->VIP = (f & 0x100000) ? 1 : 0; cpustate->ID = (f & 0x200000) ? 1 : 0; //if(((cpustate->eflags & 0x3000) != (f & 0x3000)) && ((f & 0x3000) == 0)) logerror("SET IOPL to 0 PC=%08X\n", cpustate->pc); - //if(old_vm != cpustate->VM) logerror("Change VM flag to %d at %08X\n", cpustate->VM, cpustate->pc); +// if(old_vm != cpustate->VM) logerror("Change VM flag to %d at %08X\n", cpustate->VM, cpustate->prev_pc); //if(PROTECTED_MODE) { cpustate->eflags = f; //} else { @@ -505,13 +545,15 @@ static UINT32 i386_get_stack_ptr(i386_state* cpustate, UINT8 privilege) } /* Must be either a data or readable code segment */ - if(((desc.flags & 0x0018) == 0x0018 && (desc.flags & 0x0002)) || (desc.flags & 0x0018) == 0x0010) +// if(((desc.flags & 0x0018) == 0x0018 && (desc.flags & 0x0002)) || (desc.flags & 0x0018) == 0x0010) + if(((!(desc.is_system) && (desc.executable)) && (desc.rwn)) || (!(desc.is_system) && !(desc.executable))) invalid = 0; else invalid = 1; /* If a data segment or non-conforming code segment, then either DPL >= CPL or DPL >= RPL */ - if(((desc.flags & 0x0018) == 0x0018 && (desc.flags & 0x0004) == 0) || (desc.flags & 0x0018) == 0x0010) +// if(((desc.flags & 0x0018) == 0x0018 && (desc.flags & 0x0004) == 0) || (desc.flags & 0x0018) == 0x0010) + if(((!(desc.is_system) && (desc.executable)) && !(desc.expand_down)) || (!(desc.is_system) && !(desc.executable))) { if((DPL < CPL) || (DPL < RPL)) invalid = 1; @@ -603,6 +645,7 @@ static void i386_sreg_load(i386_state *cpustate, UINT16 selector, UINT8 reg, boo FAULT(FAULT_GP,selector & ~0x03) } if(((stack.flags & 0x0018) != 0x10) && (stack.flags & 0x0002) != 0) + //if(!(!(stack.is_system) && (stack.executable)) && (stack.rwn)) { logerror("SReg Load (%08x): Segment is not a writable data segment.\n",cpustate->pc); FAULT(FAULT_GP,selector & ~0x03) @@ -612,7 +655,7 @@ static void i386_sreg_load(i386_state *cpustate, UINT16 selector, UINT8 reg, boo logerror("SReg Load (%08x): Segment DPL does not equal CPL.\n",cpustate->pc); FAULT(FAULT_GP,selector & ~0x03) } - if(!(stack.flags & 0x0080)) + if(!(stack.flags & SREG_FLAGS_PR)) { logerror("SReg Load (%08x): Segment is not present.\n",cpustate->pc); FAULT(FAULT_SS,selector & ~0x03) @@ -651,15 +694,18 @@ static void i386_sreg_load(i386_state *cpustate, UINT16 selector, UINT8 reg, boo FAULT(FAULT_GP,selector & ~0x03) } } +// if(!(!(desc.is_system) && !(desc.executable))) if((desc.flags & 0x0018) != 0x10) { - if((((desc.flags & 0x0002) != 0) && ((desc.flags & 0x0018) != 0x18)) || !(desc.flags & 0x10)) +// if((((desc.flags & 0x0002) != 0) && ((desc.flags & 0x0018) != 0x18)) || !(desc.flags & 0x10)) + if(((desc.rwn) && !(!(desc.is_system) && (desc.executable))) || (desc.is_system)) { logerror("SReg Load (%08x): Segment is not a data segment or readable code segment.\n",cpustate->pc); FAULT(FAULT_GP,selector & ~0x03) } } - if(((desc.flags & 0x0018) == 0x10) || ((!(desc.flags & 0x0004)) && ((desc.flags & 0x0018) == 0x18))) +// if(((desc.flags & 0x0018) == 0x10) || ((!(desc.flags & 0x0004)) && ((desc.flags & 0x0018) == 0x18))) + if((!(desc.is_system) && !(desc.executable)) || (!(desc.expand_down) && (!(desc.is_system) && (desc.executable)))) { // if data or non-conforming code segment if((RPL > DPL) || (CPL > DPL)) @@ -794,7 +840,7 @@ static void i386_sreg_load(i386_state *cpustate, UINT16 selector, UINT8 reg, boo } } - if((flags & 0x0080) == 0) + if((flags & SREG_FLAGS_PR) == 0) { logerror("IRQ: Vector segment is not present.\n"); FAULT_EXP(FAULT_NP,entry+2) @@ -819,19 +865,20 @@ static void i386_sreg_load(i386_state *cpustate, UINT16 selector, UINT8 reg, boo FAULT_EXP(FAULT_TS,segment & ~0x03); } } - if((desc.flags & 0x000f) != 0x09 && (desc.flags & 0x000f) != 0x01) + UINT16 tmpflag = desc.flags & (SREG_FLAGS_AC | SREG_FLAGS_RW | SREG_FLAGS_DC | SREG_FLAGS_EX); + if(tmpflag != (SREG_FLAGS_AC | SREG_FLAGS_EX) && tmpflag != SREG_FLAGS_AC) { logerror("IRQ: Task gate: TSS is not an available TSS.\n"); FAULT_EXP(FAULT_TS,segment & ~0x03); } - if((desc.flags & 0x0080) == 0) + if((desc.flags & SREG_FLAGS_PR) == 0) { logerror("IRQ: Task gate: TSS is not present.\n"); FAULT_EXP(FAULT_NP,segment & ~0x03); } if(!(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1)) cpustate->eip = cpustate->prev_eip; - if(desc.flags & 0x08) + if(desc.flags & SREG_FLAGS_EX) i386_task_switch(cpustate,desc.selector,1); else i286_task_switch(cpustate,desc.selector,1); @@ -868,17 +915,17 @@ static void i386_sreg_load(i386_state *cpustate, UINT16 selector, UINT8 reg, boo FAULT_EXP(FAULT_GP,(segment & 0x03)+cpustate->ext) } } - if((desc.flags & 0x0018) != 0x18) + if((desc.flags & (SREG_FLAGS_NS | SREG_FLAGS_EX)) != (SREG_FLAGS_NS | SREG_FLAGS_EX)) { logerror("IRQ: Gate descriptor is not a code segment.\n"); FAULT_EXP(FAULT_GP,(segment & 0x03)+cpustate->ext) } - if((desc.flags & 0x0080) == 0) + if((desc.flags & SREG_FLAGS_PR) == 0) { logerror("IRQ: Gate segment is not present.\n"); FAULT_EXP(FAULT_NP,(segment & 0x03)+cpustate->ext) } - if((desc.flags & 0x0004) == 0 && (DPL < CPL)) + if((desc.flags & SREG_FLAGS_DC) == 0 && (DPL < CPL)) { /* IRQ to inner privilege */ I386_SREG stack; @@ -929,12 +976,12 @@ static void i386_sreg_load(i386_state *cpustate, UINT16 selector, UINT8 reg, boo logerror("IRQ: New stack segment DPL is not equal to code segment DPL.\n"); FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext) } - if(((stack.flags & 0x0018) != 0x10) && (stack.flags & 0x0002) != 0) + if(((stack.flags & (SREG_FLAGS_NS | SREG_FLAGS_EX)) != SREG_FLAGS_NS) && (stack.flags & SREG_FLAGS_RW) != 0) { logerror("IRQ: New stack segment is not a writable data segment.\n"); FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext) // #TS(stack selector + EXT) } - if((stack.flags & 0x0080) == 0) + if((stack.flags & SREG_FLAGS_PR) == 0) { logerror("IRQ: New stack segment is not present.\n"); FAULT_EXP(FAULT_SS,(stack.selector & ~0x03)+cpustate->ext) // #TS(stack selector + EXT) @@ -942,7 +989,7 @@ static void i386_sreg_load(i386_state *cpustate, UINT16 selector, UINT8 reg, boo newESP = i386_get_stack_ptr(cpustate,DPL); if(type & 0x08) // 32-bit gate { - if(((newESP < (V8086_MODE?36:20)) && !(stack.flags & 0x4)) || ((~stack.limit < (~(newESP - 1) + (V8086_MODE?36:20))) && (stack.flags & 0x4))) + if(((newESP < (V8086_MODE?36:20)) && !(stack.flags & SREG_FLAGS_DC)) || ((~stack.limit < (~(newESP - 1) + (V8086_MODE?36:20))) && (stack.flags & SREG_FLAGS_DC))) { logerror("IRQ: New stack has no space for return addresses.\n"); FAULT_EXP(FAULT_SS,0) @@ -951,7 +998,7 @@ static void i386_sreg_load(i386_state *cpustate, UINT16 selector, UINT8 reg, boo else // 16-bit gate { newESP &= 0xffff; - if(((newESP < (V8086_MODE?18:10)) && !(stack.flags & 0x4)) || ((~stack.limit < (~(newESP - 1) + (V8086_MODE?18:10))) && (stack.flags & 0x4))) + if(((newESP < (V8086_MODE?18:10)) && !(stack.flags & SREG_FLAGS_DC)) || ((~stack.limit < (~(newESP - 1) + (V8086_MODE?18:10))) && (stack.flags & SREG_FLAGS_DC))) { logerror("IRQ: New stack has no space for return addresses.\n"); FAULT_EXP(FAULT_SS,0) @@ -1019,7 +1066,7 @@ static void i386_sreg_load(i386_state *cpustate, UINT16 selector, UINT8 reg, boo else { int stack_limit; - if((desc.flags & 0x0004) || (DPL == CPL)) + if((desc.flags & SREG_FLAGS_DC) || (DPL == CPL)) { /* IRQ to same privilege */ if(V8086_MODE && !cpustate->ext) @@ -1055,8 +1102,8 @@ static void i386_sreg_load(i386_state *cpustate, UINT16 selector, UINT8 reg, boo try { // this is ugly but the alternative is worse - //if(/*type != 0x0e && type != 0x0f */(type & 0x08) == 0) // if not 386 interrupt or trap gate - if(type != 0x0e && type != 0x0f) // if not 386 interrupt or trap gate + if((type & 0x08) == 0) // if not 386 interrupt or trap gate + //if(type != 0x0e && type != 0x0f) // if not 386 interrupt or trap gate { PUSH16(cpustate, oldflags & 0xffff ); PUSH16(cpustate, cpustate->sreg[CS].selector ); @@ -1161,23 +1208,34 @@ static void i386_sreg_load(i386_state *cpustate, UINT16 selector, UINT8 reg, boo static void i386_trap_with_error(i386_state *cpustate,int irq, int irq_gate, int trap_level, UINT32 error, int is_top) { // buffering direct call from trap. + UINT32 nowESP;/* = REG32(ESP)*/; + if((irq_gate == 0) && + ((irq == FAULT_DE) || (irq == FAULT_DB) || (irq == FAULT_BR) || (irq == FAULT_UD) || (irq == FAULT_NM) || (irq == FAULT_NM))) { +// if(cpustate->backout_sp != 0) { +// REG32(ESP) = cpustate->old_esp; +// } + } if(is_top != 0) { try { i386_trap(cpustate,irq,irq_gate,trap_level); } catch(UINT64 e) { logerror("Irregular exception happened %08x for 16bit.\n", e); - return; +// return; } catch(UINT32 e) { logerror("Irregular exception happened %08x for 16bit.\n", e); - return; +// return; } } else { i386_trap(cpustate,irq,irq_gate,trap_level); } - if(irq == FAULT_DF || irq == FAULT_TS || irq == FAULT_NP || irq == FAULT_SS || irq == FAULT_GP || irq == FAULT_PF /*|| irq == FAULT_AC */) + if(irq == FAULT_DF || irq == FAULT_TS || irq == FAULT_NP || irq == FAULT_SS || irq == FAULT_GP || irq == FAULT_PF || irq == FAULT_AC) { - //if((irq == FAULT_AC) || (irq == FAULT_DF)) error = 0; +// nowESP = REG32(ESP); +// if(cpustate->backout_sp != 0) { +// REG32(ESP) = cpustate->old_esp; +// } + if((irq == FAULT_AC) || (irq == FAULT_DF)) error = 0; // for these exceptions, an error code is pushed onto the stack by the processor. // no error code is pushed for software interrupts, either. if(PROTECTED_MODE) @@ -1192,13 +1250,13 @@ static void i386_trap_with_error(i386_state *cpustate,int irq, int irq_gate, int v2 = READ32PL0(cpustate, cpustate->gdtr.base + ((v2 >> 16) & 0xfff8) + 4); type = (v2>>8) & 0x1F; } - if(type >= 9) + if(type == 9) PUSH32(cpustate,error); else PUSH16(cpustate,error); } else { - PUSH16(cpustate,error); + PUSH16(cpustate,error); } } } @@ -1509,10 +1567,11 @@ static void i386_protected_mode_jump(i386_state *cpustate, UINT16 seg, UINT32 of //logerror("JMP: protected mode PC=%08X SEG=%04x OFFSET=%08x VALID=%s BASE=%08x LIMIT=%08x FLAGS=%08x INDIRECT=%s OP32=%s V8086=%s CPL=%d DPL=%d RPL=%d\n", cpustate->prev_pc, seg, off, (desc.valid) ? "YES" : "NO", desc.base, desc.limit, desc.flags, (indirect != 0) ? "YES" : "NO", (operand32 != 0) ? "YES" : "NO" ,(V8086_MODE) ? "YES" : "NO", CPL, DPL, RPL); - if((desc.flags & 0x0018) == 0x0018) +// if((desc.flags & (SREG_FLAGS_NS | SREG_FLAGS_EX)) == (SREG_FLAGS_NS | SREG_FLAGS_EX)) + if(!(desc.is_system) && (desc.executable)) { /* code segment */ - if((desc.flags & 0x0004) == 0) + if(!(desc.expand_down)) { /* non-conforming */ if(RPL < CPL) @@ -1536,7 +1595,7 @@ static void i386_protected_mode_jump(i386_state *cpustate, UINT16 seg, UINT32 of } } SetRPL = 1; - if((desc.flags & 0x0080) == 0) + if((desc.flags & SREG_FLAGS_PR) == 0) { logerror("JMP: Segment is not present\n"); FAULT(FAULT_NP,segment & 0xfffc) @@ -1549,7 +1608,8 @@ static void i386_protected_mode_jump(i386_state *cpustate, UINT16 seg, UINT32 of } else { - if((desc.flags & 0x0010) != 0) +// if(!(desc.executable)) + if(!(desc.is_system)) { logerror("JMP: Segment is a data segment\n"); FAULT(FAULT_GP,segment & 0xfffc) // #GP (cannot execute code in a data segment) @@ -1575,15 +1635,16 @@ static void i386_protected_mode_jump(i386_state *cpustate, UINT16 seg, UINT32 of logerror("JMP: TSS: DPL %i is less than TSS RPL %i\n",DPL,RPL); FAULT(FAULT_GP,segment & 0xfffc) } - if((desc.flags & 0x0080) == 0) + if((desc.flags & SREG_FLAGS_PR) == 0) { logerror("JMP: TSS: Segment is not present\n"); FAULT(FAULT_GP,segment & 0xfffc) } - if(desc.flags & 0x0008) + if(desc.flags & SREG_FLAGS_EX) i386_task_switch(cpustate,desc.selector,0); else i286_task_switch(cpustate,desc.selector,0); + return; case 0x04: // 286 Call Gate case 0x0c: // 386 Call Gate @@ -1603,7 +1664,7 @@ static void i386_protected_mode_jump(i386_state *cpustate, UINT16 seg, UINT32 of logerror("JMP: Call Gate: DPL %i is less than RPL %i\n",DPL,RPL); FAULT(FAULT_GP,segment & 0xfffc) } - if((desc.flags & 0x0080) == 0) + if((desc.flags & SREG_FLAGS_PR) == 0) { logerror("JMP: Call Gate: Segment is not present\n"); FAULT(FAULT_NP,segment & 0xfffc) @@ -1633,7 +1694,7 @@ static void i386_protected_mode_jump(i386_state *cpustate, UINT16 seg, UINT32 of desc.selector = call_gate.selector; i386_load_protected_mode_segment(cpustate,&desc,NULL); DPL = (desc.flags >> 5) & 0x03; - if((desc.flags & 0x0018) != 0x18) + if((desc.flags & (SREG_FLAGS_NS | SREG_FLAGS_EX)) != (SREG_FLAGS_NS | SREG_FLAGS_EX)) { logerror("JMP: Call Gate: Gate does not point to a code segment\n"); FAULT(FAULT_GP,call_gate.selector & 0xfffc) @@ -1654,7 +1715,7 @@ static void i386_protected_mode_jump(i386_state *cpustate, UINT16 seg, UINT32 of FAULT(FAULT_GP,call_gate.selector & 0xfffc) } } - if((desc.flags & 0x0080) == 0) + if((desc.flags & SREG_FLAGS_PR) == 0) { logerror("JMP: Call Gate: Gate Segment is not present\n"); FAULT(FAULT_NP,call_gate.selector & 0xfffc) @@ -1720,6 +1781,7 @@ static void i386_protected_mode_jump(i386_state *cpustate, UINT16 seg, UINT32 of i386_task_switch(cpustate,call_gate.selector,0); else i286_task_switch(cpustate,call_gate.selector,0); + // CPU_SET_PREV_ESP(); return; default: // invalid segment type logerror("JMP: Invalid segment type (%i) to jump to.\n",desc.flags & 0x000f); @@ -1780,7 +1842,7 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level RPL = selector & 0x03; // requested privilege level //logerror("CALL: protected mode PC=%08X SEG=%04x OFFSET=%08x VALID=%s BASE=%08x LIMIT=%08x FLAGS=%08x INDIRECT=%s OP32=%s V8086=%s CPL=%d DPL=%d RPL=%d\n", cpustate->prev_pc, seg, off, (desc.valid) ? "YES" : "NO", desc.base, desc.limit, desc.flags, (indirect != 0) ? "YES" : "NO", (operand32 != 0) ? "YES" : "NO" ,(V8086_MODE) ? "YES" : "NO", CPL, DPL, RPL); - if((desc.flags & 0x0018) == 0x18) // is a code segment + if((desc.flags & (SREG_FLAGS_NS | SREG_FLAGS_EX)) == (SREG_FLAGS_NS | SREG_FLAGS_EX)) // is a code segment { if(desc.flags & 0x0004) { @@ -1806,7 +1868,7 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of } } SetRPL = 1; - if((desc.flags & 0x0080) == 0) + if((desc.flags & SREG_FLAGS_PR) == 0) { logerror("CALL (%08x): Code segment is not present.\n",cpustate->pc); FAULT(FAULT_NP,selector & ~0x03) // #NP(selector) @@ -1838,7 +1900,7 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of else { /* special segment type */ - if(desc.flags & 0x0010) + if(desc.flags & SREG_FLAGS_NS) { logerror("CALL: Segment is a data segment.\n"); FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector) @@ -1924,7 +1986,7 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of } } i386_load_protected_mode_segment(cpustate,&desc,NULL); - if((desc.flags & 0x0018) != 0x18) + if((desc.flags & (SREG_FLAGS_NS | SREG_FLAGS_EX)) != (SREG_FLAGS_NS | SREG_FLAGS_EX)) { logerror("CALL: Call gate: Segment is not a code segment.\n"); FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector) @@ -1935,7 +1997,7 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of logerror("CALL: Call gate: Segment DPL %i is greater than CPL %i.\n",DPL,CPL); FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector) } - if((desc.flags & 0x0080) == 0) + if((desc.flags & SREG_FLAGS_PR) == 0) { logerror("CALL (%08x): Code segment is not present.\n",cpustate->pc); FAULT(FAULT_NP,desc.selector & ~0x03) // #NP(selector) @@ -1981,12 +2043,12 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of logerror("CALL: Call gate: Stack DPL does not equal code segment DPL %i\n",DPL); FAULT(FAULT_TS,stack.selector) // #TS(SS selector) } - if((stack.flags & 0x0018) != 0x10 && (stack.flags & 0x0002)) + if((stack.flags & (SREG_FLAGS_NS | SREG_FLAGS_EX)) != SREG_FLAGS_NS && (stack.rwn)) { logerror("CALL: Call gate: Stack segment is not a writable data segment\n"); FAULT(FAULT_TS,stack.selector) // #TS(SS selector) } - if((stack.flags & 0x0080) == 0) + if((stack.flags & SREG_FLAGS_PR) == 0) { logerror("CALL: Call gate: Stack segment is not present\n"); FAULT(FAULT_SS,stack.selector) // #SS(SS selector) @@ -2146,7 +2208,7 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of logerror("CALL: Task Gate: TSS is busy.\n"); FAULT(FAULT_TS,gate.selector & ~0x03) // #TS(selector) } - if((desc.flags & 0x0080) == 0) + if((desc.flags & SREG_FLAGS_PR) == 0) { logerror("CALL: Task Gate: TSS is not present.\n"); FAULT(FAULT_NP,gate.selector & ~0x03) // #TS(selector) @@ -2267,7 +2329,7 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op FAULT(FAULT_GP,newCS & ~0x03) } } - if((desc.flags & 0x0018) != 0x0018) + if((desc.flags & (SREG_FLAGS_NS | SREG_FLAGS_EX)) != (SREG_FLAGS_NS | SREG_FLAGS_EX)) { logerror("RETF: Return segment is not a code segment.\n"); FAULT(FAULT_GP,newCS & ~0x03) @@ -2288,7 +2350,7 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op FAULT(FAULT_GP,newCS & ~0x03) } } - if((desc.flags & 0x0080) == 0) + if((desc.flags & SREG_FLAGS_PR) == 0) { logerror("RETF (%08x): Code segment is not present.\n",cpustate->pc); FAULT(FAULT_NP,newCS & ~0x03) @@ -2365,7 +2427,7 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op FAULT(FAULT_GP,newCS & ~0x03) } } - if((desc.flags & 0x0018) != 0x0018) + if((desc.flags & (SREG_FLAGS_NS | SREG_FLAGS_EX)) != (SREG_FLAGS_NS | SREG_FLAGS_EX)) { logerror("RETF: CS segment is not a code segment.\n"); FAULT(FAULT_GP,newCS & ~0x03) @@ -2386,7 +2448,7 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op FAULT(FAULT_GP,newCS & ~0x03) } } - if((desc.flags & 0x0080) == 0) + if((desc.flags & SREG_FLAGS_PR) == 0) { logerror("RETF: CS segment is not present.\n"); FAULT(FAULT_NP,newCS & ~0x03) @@ -2440,7 +2502,7 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op logerror("RETF: SS segment RPL is not equal to CS segment RPL.\n"); FAULT(FAULT_GP,newSS & ~0x03) } - if((desc.flags & 0x0018) != 0x0010 || (desc.flags & 0x0002) == 0) + if((desc.flags & (SREG_FLAGS_NS | SREG_FLAGS_EX)) != SREG_FLAGS_NS || !(desc.rwn)) { logerror("RETF: SS segment is not a writable data segment.\n"); FAULT(FAULT_GP,newSS & ~0x03) @@ -2450,7 +2512,7 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op logerror("RETF: SS DPL is not equal to CS segment RPL.\n"); FAULT(FAULT_GP,newSS & ~0x03) } - if((desc.flags & 0x0080) == 0) + if((desc.flags & SREG_FLAGS_PR) == 0) { logerror("RETF: SS segment is not present.\n"); FAULT(FAULT_GP,newSS & ~0x03) @@ -2566,7 +2628,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32) logerror("IRET (%08x): Task return: Back-linked TSS is not a busy TSS.\n",cpustate->pc); FAULT(FAULT_TS,task & ~0x03) } - if((desc.flags & 0x0080) == 0) + if((desc.flags & SREG_FLAGS_PR) == 0) { logerror("IRET: Task return: Back-linked TSS is not present.\n"); FAULT(FAULT_NP,task & ~0x03) @@ -2703,7 +2765,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32) i386_load_protected_mode_segment(cpustate,&desc,NULL); DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level RPL = newCS & 0x03; - if((desc.flags & 0x0018) != 0x0018) + if((desc.flags & (SREG_FLAGS_NS | SREG_FLAGS_EX)) != (SREG_FLAGS_NS | SREG_FLAGS_EX)) { logerror("IRET (%08x): Return CS segment is not a code segment.\n",cpustate->pc); FAULT(FAULT_GP,newCS & ~0x07) @@ -2724,7 +2786,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32) FAULT(FAULT_GP,newCS & ~0x03) } } - if((desc.flags & 0x0080) == 0) + if((desc.flags & SREG_FLAGS_PR) == 0) { logerror("IRET: (%08x) Return CS segment is not present.\n", cpustate->pc); FAULT(FAULT_NP,newCS & ~0x03) @@ -2809,7 +2871,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32) FAULT(FAULT_GP,newCS & ~0x03); } } - if((desc.flags & 0x0018) != 0x0018) + if((desc.flags & (SREG_FLAGS_NS | SREG_FLAGS_EX)) != (SREG_FLAGS_NS | SREG_FLAGS_EX)) { logerror("IRET: Return CS segment is not a code segment.\n"); FAULT(FAULT_GP,newCS & ~0x03) @@ -2830,7 +2892,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32) FAULT(FAULT_GP,newCS & ~0x03) } } - if((desc.flags & 0x0080) == 0) + if((desc.flags & SREG_FLAGS_PR) == 0) { logerror("IRET: Return CS segment is not present.\n"); FAULT(FAULT_NP,newCS & ~0x03) @@ -2877,12 +2939,12 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32) logerror("IRET: Return SS RPL is not equal to return CS RPL.\n"); FAULT(FAULT_GP,newSS & ~0x03) } - if((stack.flags & 0x0018) != 0x0010) + if((stack.flags & (SREG_FLAGS_NS | SREG_FLAGS_EX)) != SREG_FLAGS_NS) { logerror("IRET: Return SS segment is not a data segment.\n"); FAULT(FAULT_GP,newSS & ~0x03) } - if((stack.flags & 0x0002) == 0) + if(!(stack.rwn)) { logerror("IRET: Return SS segment is not writable.\n"); FAULT(FAULT_GP,newSS & ~0x03) @@ -2892,7 +2954,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32) logerror("IRET: Return SS DPL does not equal SS RPL.\n"); FAULT(FAULT_GP,newSS & ~0x03) } - if((stack.flags & 0x0080) == 0) + if((stack.flags & SREG_FLAGS_PR) == 0) { logerror("IRET: Return SS segment is not present.\n"); FAULT(FAULT_NP,newSS & ~0x03) @@ -3477,6 +3539,16 @@ static CPU_RESET( i386 ) cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093; cpustate->sreg[DS].valid = cpustate->sreg[ES].valid = cpustate->sreg[FS].valid = cpustate->sreg[GS].valid = cpustate->sreg[SS].valid =true; + for(int i = 0; i <= GS; i++) { + cpustate->sreg[i].valid = true; + cpustate->sreg[i].priv = 0; + cpustate->sreg[i].d = 0; // OK? + cpustate->sreg[i].whole_address = false; + cpustate->sreg[i].rwn = (cpustate->sreg[i].flags & SREG_FLAGS_RW) ? true : false;; + cpustate->sreg[i].expand_down = (cpustate->sreg[i].flags & SREG_FLAGS_DC) ? true : false; + cpustate->sreg[i].executable = (cpustate->sreg[i].flags & SREG_FLAGS_EX) ? true : false; + cpustate->sreg[i].is_system = ((cpustate->sreg[i].flags & SREG_FLAGS_NS) == 0) ? true : false;; + } cpustate->idtr.base = 0; cpustate->idtr.limit = 0x3ff; cpustate->smm = false; @@ -3783,16 +3855,16 @@ static CPU_EXECUTE( i386 ) catch(UINT64 e) { cpustate->ext = 1; - logerror("Illegal instruction EIP=%08x VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=%08x\n", cpustate->eip, (cpustate->VM) ? "YES" : "NO", e & 0xffffffff, e >> 32); + logerror("Illegal instruction PC=%08X EIP=%08x VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=%08x\n", cpustate->prev_pc, cpustate->eip, (cpustate->VM) ? "YES" : "NO", e & 0xffffffff, e >> 32); i386_trap_with_error(cpustate,e&0xffffffff,0,0,e>>32, 1); } catch(UINT32 e) { cpustate->ext = 1; - logerror("Illegal instruction EIP=%08x VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=%08x\n", cpustate->eip, (cpustate->VM) ? "YES" : "NO", e & 0xffffffff, e >> 32); + logerror("Illegal instruction PC=%08X EIP=%08x VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=%08x\n", cpustate->prev_pc, cpustate->eip, (cpustate->VM) ? "YES" : "NO", e & 0xffffffff, e >> 32); i386_trap_with_error(cpustate,e&0xffffffff,0,0,0, 1); } catch(...) { cpustate->ext = 1; - logerror("Illegal instruction EIP=%08x VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=UNKNOWN\n", cpustate->eip, (cpustate->VM) ? "YES" : "NO"); + logerror("Illegal instruction PC=%08X EIP=%08x VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=UNKNOWN\n", cpustate->prev_pc, cpustate->eip, (cpustate->VM) ? "YES" : "NO"); i386_trap_with_error(cpustate,0,0,0,0, 1); } @@ -3857,19 +3929,19 @@ static CPU_EXECUTE( i386 ) catch(UINT64 e) { cpustate->ext = 1; - logerror("Illegal instruction EIP=%08x VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=%08x\n", cpustate->eip, (cpustate->VM) ? "YES" : "NO", e & 0xffffffff, e >> 32); + logerror("Illegal instruction PC=%08X EIP=%08x VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=%08x\n", cpustate->prev_pc, cpustate->eip, (cpustate->VM) ? "YES" : "NO", e & 0xffffffff, e >> 32); i386_trap_with_error(cpustate,e&0xffffffff,0,0,e>>32, 1); } catch(UINT32 e) { cpustate->ext = 1; - logerror("Illegal instruction EIP=%08x VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=%08x\n", cpustate->eip, (cpustate->VM) ? "YES" : "NO", e & 0xffffffff, 0); + logerror("Illegal instruction PC=%08X EIP=%08x VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=%08x\n",cpustate->prev_pc, cpustate->eip, (cpustate->VM) ? "YES" : "NO", e & 0xffffffff, 0); i386_trap_with_error(cpustate,e,0,0,0, 1); } catch(...) { cpustate->ext = 1; - logerror("Illegal instruction EIP=%08x VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=%08x\n", cpustate->eip, (cpustate->VM) ? "YES" : "NO", 0, 0); + logerror("Illegal instruction PC=%08X EIP=%08x VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=%08x\n",cpustate->prev_pc, cpustate->eip, (cpustate->VM) ? "YES" : "NO", 0, 0); i386_trap_with_error(cpustate,0,0,0,0, 1); } //#ifdef SINGLE_MODE_DMA @@ -3939,6 +4011,16 @@ static CPU_RESET( i486 ) cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff; cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093; + for(int i = 0; i <= GS; i++) { + cpustate->sreg[i].valid = true; + cpustate->sreg[i].priv = 0; + cpustate->sreg[i].d = 0; // OK? + cpustate->sreg[i].whole_address = false; + cpustate->sreg[i].rwn = (cpustate->sreg[i].flags & SREG_FLAGS_RW) ? true : false; + cpustate->sreg[i].expand_down = (cpustate->sreg[i].flags & SREG_FLAGS_DC) ? true : false; + cpustate->sreg[i].executable = (cpustate->sreg[i].flags & SREG_FLAGS_EX) ? true : false; + cpustate->sreg[i].is_system = ((cpustate->sreg[i].flags & SREG_FLAGS_NS) == 0) ? true : false; + } cpustate->idtr.base = 0; cpustate->idtr.limit = 0x3ff; @@ -3994,6 +4076,16 @@ static CPU_RESET( pentium ) cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff; cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093; + for(int i = 0; i <= GS; i++) { + cpustate->sreg[i].valid = true; + cpustate->sreg[i].priv = 0; + cpustate->sreg[i].d = 0; // OK? + cpustate->sreg[i].whole_address = false; + cpustate->sreg[i].rwn = (cpustate->sreg[i].flags & SREG_FLAGS_RW) ? true : false; + cpustate->sreg[i].expand_down = (cpustate->sreg[i].flags & SREG_FLAGS_DC) ? true : false; + cpustate->sreg[i].executable = (cpustate->sreg[i].flags & SREG_FLAGS_EX) ? true : false; + cpustate->sreg[i].is_system = ((cpustate->sreg[i].flags & SREG_FLAGS_NS) == 0) ? true : false; + } cpustate->idtr.base = 0; cpustate->idtr.limit = 0x3ff; @@ -4065,6 +4157,16 @@ static CPU_RESET( mediagx ) cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000; cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff; cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093; + for(int i = 0; i <= GS; i++) { + cpustate->sreg[i].valid = true; + cpustate->sreg[i].priv = 0; + cpustate->sreg[i].d = 0; // OK? + cpustate->sreg[i].whole_address = false; + cpustate->sreg[i].rwn = (cpustate->sreg[i].flags & SREG_FLAGS_RW) ? true : false; + cpustate->sreg[i].expand_down = (cpustate->sreg[i].flags & SREG_FLAGS_DC) ? true : false; + cpustate->sreg[i].executable = (cpustate->sreg[i].flags & SREG_FLAGS_EX) ? true : false; + cpustate->sreg[i].is_system = ((cpustate->sreg[i].flags & SREG_FLAGS_NS) == 0) ? true : false; + } cpustate->idtr.base = 0; cpustate->idtr.limit = 0x3ff; @@ -4129,6 +4231,16 @@ static CPU_RESET( pentium_pro ) cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000; cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff; cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093; + for(int i = 0; i <= GS; i++) { + cpustate->sreg[i].valid = true; + cpustate->sreg[i].priv = 0; + cpustate->sreg[i].d = 0; // OK? + cpustate->sreg[i].whole_address = false; + cpustate->sreg[i].rwn = (cpustate->sreg[i].flags & SREG_FLAGS_RW) ? true : false;; + cpustate->sreg[i].expand_down = (cpustate->sreg[i].flags & SREG_FLAGS_DC) ? true : false; + cpustate->sreg[i].executable = (cpustate->sreg[i].flags & SREG_FLAGS_EX) ? true : false; + cpustate->sreg[i].is_system = ((cpustate->sreg[i].flags & SREG_FLAGS_NS) == 0) ? true : false;; + } cpustate->idtr.base = 0; cpustate->idtr.limit = 0x3ff; @@ -4202,6 +4314,16 @@ static CPU_RESET( pentium_mmx ) cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000; cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff; cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093; + for(int i = 0; i <= GS; i++) { + cpustate->sreg[i].valid = true; + cpustate->sreg[i].priv = 0; + cpustate->sreg[i].d = 0; // OK? + cpustate->sreg[i].whole_address = false; + cpustate->sreg[i].rwn = (cpustate->sreg[i].flags & SREG_FLAGS_RW) ? true : false;; + cpustate->sreg[i].expand_down = (cpustate->sreg[i].flags & SREG_FLAGS_DC) ? true : false; + cpustate->sreg[i].executable = (cpustate->sreg[i].flags & SREG_FLAGS_EX) ? true : false; + cpustate->sreg[i].is_system = ((cpustate->sreg[i].flags & SREG_FLAGS_NS) == 0) ? true : false;; + } cpustate->idtr.base = 0; cpustate->idtr.limit = 0x3ff; @@ -4274,6 +4396,16 @@ static CPU_RESET( pentium2 ) cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000; cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff; cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093; + for(int i = 0; i <= GS; i++) { + cpustate->sreg[i].priv = 0; + cpustate->sreg[i].valid = true; // OK? + cpustate->sreg[i].d = 0; // OK? + cpustate->sreg[i].whole_address = false; + cpustate->sreg[i].rwn = (cpustate->sreg[i].flags & SREG_FLAGS_RW) ? true : false;; + cpustate->sreg[i].expand_down = (cpustate->sreg[i].flags & SREG_FLAGS_DC) ? true : false; + cpustate->sreg[i].executable = (cpustate->sreg[i].flags & SREG_FLAGS_EX) ? true : false; + cpustate->sreg[i].is_system = ((cpustate->sreg[i].flags & SREG_FLAGS_NS) == 0) ? true : false;; + } cpustate->idtr.base = 0; cpustate->idtr.limit = 0x3ff; @@ -4340,6 +4472,16 @@ static CPU_RESET( pentium3 ) cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000; cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff; cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093; + for(int i = 0; i <= GS; i++) { + cpustate->sreg[i].priv = 0; + cpustate->sreg[i].valid = true; // OK? + cpustate->sreg[i].d = 0; // OK? + cpustate->sreg[i].whole_address = false; + cpustate->sreg[i].rwn = (cpustate->sreg[i].flags & SREG_FLAGS_RW) ? true : false;; + cpustate->sreg[i].expand_down = (cpustate->sreg[i].flags & SREG_FLAGS_DC) ? true : false; + cpustate->sreg[i].executable = (cpustate->sreg[i].flags & SREG_FLAGS_EX) ? true : false; + cpustate->sreg[i].is_system = ((cpustate->sreg[i].flags & SREG_FLAGS_NS) == 0) ? true : false;; + } cpustate->idtr.base = 0; cpustate->idtr.limit = 0x3ff; @@ -4404,11 +4546,28 @@ static CPU_RESET( pentium4 ) cpustate->sreg[CS].base = 0xffff0000; cpustate->sreg[CS].limit = 0xffff; cpustate->sreg[CS].flags = 0x0093; - + cpustate->sreg[CS].d = 0; + cpustate->sreg[CS].whole_address = false; + cpustate->sreg[CS].expand_down = false; + cpustate->sreg[CS].rwn = true; + cpustate->sreg[CS].is_system = false; + cpustate->sreg[CS].executable = true; + cpustate->sreg[CS].priv = 0; + cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000; cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff; cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093; - + for(int i = 0; i <= GS; i++) { + cpustate->sreg[i].priv = 0; + cpustate->sreg[i].valid = true; // OK? + cpustate->sreg[i].d = 0; // OK? + cpustate->sreg[i].whole_address = false; + cpustate->sreg[i].rwn = (cpustate->sreg[i].flags & SREG_FLAGS_RW) ? true : false;; + cpustate->sreg[i].expand_down = (cpustate->sreg[i].flags & SREG_FLAGS_DC) ? true : false; + cpustate->sreg[i].executable = (cpustate->sreg[i].flags & SREG_FLAGS_EX) ? true : false; + cpustate->sreg[i].is_system = ((cpustate->sreg[i].flags & SREG_FLAGS_NS) == 0) ? true : false;; + } + cpustate->idtr.base = 0; cpustate->idtr.limit = 0x3ff; diff --git a/source/src/vm/mame/emu/cpu/i386/i386op16.c b/source/src/vm/mame/emu/cpu/i386/i386op16.c index bb25a8366..e96d27977 100644 --- a/source/src/vm/mame/emu/cpu/i386/i386op16.c +++ b/source/src/vm/mame/emu/cpu/i386/i386op16.c @@ -3441,8 +3441,9 @@ static void I386OP(group0F01_16)(i386_state *cpustate) // Opcode 0x0f 01 FAULT(FAULT_GP,0) } if( modrm >= 0xc0 ) { - address = LOAD_RM16(modrm); - ea = i386_translate(cpustate, CS, address, 0, 6 ); + //address = LOAD_RM16(modrm); + //ea = i386_translate(cpustate, CS, address, 0, 6 ); + FAULT(FAULT_UD,0) } else { ea = GetEA(cpustate,modrm,0,6); } diff --git a/source/src/vm/mame/emu/cpu/i386/i386op32.c b/source/src/vm/mame/emu/cpu/i386/i386op32.c index 57f0dfa28..24ae52a77 100644 --- a/source/src/vm/mame/emu/cpu/i386/i386op32.c +++ b/source/src/vm/mame/emu/cpu/i386/i386op32.c @@ -3207,8 +3207,9 @@ static void I386OP(group0F01_32)(i386_state *cpustate) // Opcode 0x0f 01 if(PROTECTED_MODE && cpustate->CPL) FAULT(FAULT_GP,0) if( modrm >= 0xc0 ) { - address = LOAD_RM32(modrm); - ea = i386_translate(cpustate, CS, address, 0, 6 ); + // address = LOAD_RM32(modrm); + // ea = i386_translate(cpustate, CS, address, 0, 6 ); + FAULT(FAULT_UD,0) } else { ea = GetEA(cpustate,modrm,0,6); } diff --git a/source/src/vm/mame/emu/cpu/i386/i386ops.c b/source/src/vm/mame/emu/cpu/i386/i386ops.c index 3c8be1e2c..9ce14c34e 100644 --- a/source/src/vm/mame/emu/cpu/i386/i386ops.c +++ b/source/src/vm/mame/emu/cpu/i386/i386ops.c @@ -310,6 +310,11 @@ static void I386OP(cli)(i386_state *cpustate) // Opcode 0xfa if(PROTECTED_MODE) { UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1); + if(V8086_MODE) { + if(IOPL < 3) { + FAULT(FAULT_GP,0); + } + } else 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); @@ -660,7 +665,7 @@ static void I386OP(mov_r32_cr)(i386_state *cpustate) // Opcode 0x0f 20 #if 1 UINT32 oldpc = cpustate->prev_pc; if((PROTECTED_MODE && ((V8086_MODE) || (cpustate->CPL != 0)))) { - logerror("Call from non-supervisor privilege: I386OP(mov_r32_cr) at %08X", oldpc); + logerror("Call from non-supervisor privilege: I386OP(mov_r32_cr) at %08X V8086=%s CPL=%d", oldpc, (V8086_MODE) ? "YES" : "NO", cpustate->CPL); FAULT(FAULT_GP, 0); //return; } @@ -1877,6 +1882,11 @@ static void I386OP(sti)(i386_state *cpustate) // Opcode 0xfb if(PROTECTED_MODE) { UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1); + if(V8086_MODE) { + if(IOPL < 3) { + FAULT(FAULT_GP,0); + } + } else if(cpustate->CPL > IOPL) { logerror("Privilege error: I386OP(sti) CPL=%d IOPL=%d\n", cpustate->CPL, IOPL); FAULT(FAULT_GP,0); @@ -2816,11 +2826,16 @@ static void I386OP(loadall)(i386_state *cpustate) // Opcode 0x0f 0x07 (0x0 cpustate->sreg[ES].base = READ32(cpustate, ea + 0xc4); cpustate->sreg[ES].limit = READ32(cpustate, ea + 0xc8); cpustate->CPL = (cpustate->sreg[SS].flags >> 5) & 3; // cpl == dpl of ss - + for(int i = 0; i <= GS; i++) { - cpustate->sreg[i].valid = (cpustate->sreg[i].flags & 0x80) ? true : false; - cpustate->sreg[i].d = (cpustate->sreg[i].flags & 0x4000) ? 1 : 0; + cpustate->sreg[i].valid = (cpustate->sreg[i].flags & SREG_FLAGS_PR) ? true : false; + cpustate->sreg[i].d = (cpustate->sreg[i].flags & SREG_FLAGS_SZ) ? 1 : 0; + cpustate->sreg[i].whole_address = false; // From NP2 v0.83 + cpustate->sreg[i].is_system = ((cpustate->sreg[i].flags & SREG_FLAGS_NS) == 0) ? true : false; // From NP2 v0.83 + cpustate->sreg[i].executable = (cpustate->sreg[i].flags & SREG_FLAGS_EX) ? true : false; // From NP2 v0.83 + cpustate->sreg[i].expand_down = (cpustate->sreg[i].flags & SREG_FLAGS_DC) ? true : false; // From NP2 v0.83 + cpustate->sreg[i].rwn = (cpustate->sreg[i].flags & SREG_FLAGS_RW) ? true : false; // From NP2 v0.83 } CHANGE_PC(cpustate, cpustate->eip); } diff --git a/source/src/vm/mame/emu/cpu/i386/i386priv.h b/source/src/vm/mame/emu/cpu/i386/i386priv.h index 8993814cf..e8acf6239 100644 --- a/source/src/vm/mame/emu/cpu/i386/i386priv.h +++ b/source/src/vm/mame/emu/cpu/i386/i386priv.h @@ -296,12 +296,35 @@ enum smram_intel_p5 #define MXCSR_RC (3<<13) // Rounding Control #define MXCSR_FZ (1<<15) // Flush to Zero +// IN SEGMENT DESCRIPTOR TABLE +// ACCESS BYTE BITFIELDS (bit40-47) +#define SREG_FLAGS_AC 0x0001 /* '1' is before accessed */ +#define SREG_FLAGS_RW 0x0002 /* READABLE for CODE SEGMENT/WRITABLE for DATA SEGMENT*/ +#define SREG_FLAGS_DC 0x0004 /* '1' to expand down, '0' to expand up */ +#define SREG_FLAGS_EX 0x0008 /* '1' to executable */ +#define SREG_FLAGS_NS 0x0010 /* '0' to system-segment */ +#define SREG_FLAGS_PRIV_LO 0x0020 /* PRIVILEGE (0 to 3) */ +#define SREG_FLAGS_PRIV_HI 0x0040 +#define SREG_FLAGS_PR 0x0080 /* '1' = valid segment */ + +// FLAGS (bit52-55) +#define SREG_FLAGS_RESV1 0x1000 +#define SREG_FLAGS_RESV2 0x2000 +#define SREG_FLAGS_SZ 0x4000 /* '1' at 32bit protected mode */ +#define SREG_FLAGS_GR 0x8000 /* '1' at limit multiplies to $1000 */ + struct I386_SREG { UINT16 selector; UINT16 flags; UINT32 base; UINT32 limit; int d; // Operand size + uint8_t priv; + bool whole_address; + bool expand_down; + bool is_system; + bool executable; + bool rwn; bool valid; }; @@ -674,26 +697,72 @@ extern MODRM_TABLE i386_MODRM_table[256]; INLINE int i386_limit_check(i386_state *cpustate, int seg, UINT32 offset, UINT32 size) { // size = 1; // TBD + // Re-Implement From NP2 v0.83 if(PROTECTED_MODE && !V8086_MODE) { - if((cpustate->sreg[seg].flags & 0x0018) == 0x0010 && cpustate->sreg[seg].flags & 0x0004) // if expand-down data segment + UINT32 limit = cpustate->sreg[seg].limit; + bool is_32bit = (cpustate->sreg[seg].d != 0) ? true : false; + UINT32 seg_limit = (is_32bit) ? 0xffffffff : 0x0000ffff; + bool do_exception = false; + bool is_system = cpustate->sreg[seg].is_system; + bool executable = cpustate->sreg[seg].executable; + bool expand_down = cpustate->sreg[seg].expand_down; + if((is_32bit) && (cpustate->sreg[seg].whole_address)) return 0; // OK? + if(!(is_system) && !(executable) && (expand_down)) // if expand-down data segment { + if(limit == 0) { + if(!(is_32bit)) { // 16bit + if((offset + size - 1) > 0x0000ffff) { + do_exception = true; + } + } else { + cpustate->sreg[seg].whole_address = true; + // SET WHOLE ADDRESS BIT. + } + } else { // limit != 0 +// if((((offset - (size - 1)) <= limit) || ((is_32bit)?0:((offset - (size - 1)) > 0xffff)))) { + if((offset < limit) || ((offset + size - 1) > seg_limit) || ((offset + size - 1) < offset) || + (seg_limit < (limit + size - 1))) { + do_exception = true; + } + } + if(do_exception) { + logerror("Limit check at 0x%08X failed. Segment %04X, base %08X, limit %08X, offset %08X size=%d(expand-down)\n",cpustate->prev_pc,cpustate->sreg[seg].selector,cpustate->sreg[seg].base,cpustate->sreg[seg].limit,offset, size); + return 1; + } + } else { // Expand up + if((is_32bit) && ((limit == 0x00000000) || (limit == 0xffffffff))) { + cpustate->sreg[seg].whole_address = true; + // SET WHOLE ADDRESS BIT. + } //else if((limit > seg_limit) || ((size - 1) > limit) || ((offset + size - 1) > (limit + 1)) || ((offset + size - 1) < offset)) { + else if(((offset + size - 1) > limit)){ + do_exception = true; + } + if(do_exception) { + logerror("Limit check at 0x%08X failed. Segment %04X, base %08X, limit %08X, offset %08X size=%d\n",cpustate->prev_pc,cpustate->sreg[seg].selector,cpustate->sreg[seg].base,cpustate->sreg[seg].limit,offset, size); + return 1; + } + } + + /* // compare if greater then 0xffffffff when we're passed the access size //if(offset < size) size = offset; - if(/*(cpustate->sreg[seg].limit != 0) && */(((offset - (size - 1)) <= cpustate->sreg[seg].limit) || ((cpustate->sreg[seg].d)?0:((offset - (size - 1)) > 0xffff)))) + if(((cpustate->sreg[seg].flags & 0x18) == 0x0010) && (cpustate->sreg[seg].expand_down)) { + if((((offset - (size - 1)) <= 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->prev_pc,cpustate->sreg[seg].selector,cpustate->sreg[seg].limit,offset); + logerror("Limit check at 0x%08X failed. Segment %04X, base %08X, limit %08X, offset %08X size=%d(expand-down)\n",cpustate->prev_pc,cpustate->sreg[seg].selector,cpustate->sreg[seg].base,cpustate->sreg[seg].limit,offset, size); return 1; } } else { - if(((offset + size - 1) > cpustate->sreg[seg].limit) /*&& (cpustate->sreg[seg].limit != 0)*/) + if(((offset + size - 1) > cpustate->sreg[seg].limit)) { - logerror("Limit check at 0x%08x failed. Segment %04x, limit %08x, offset %08x\n",cpustate->prev_pc,cpustate->sreg[seg].selector,cpustate->sreg[seg].limit,offset); + logerror("Limit check at 0x%08X failed. Segment %04X, base %08X limit %08X, offset %08X size=%d\n",cpustate->prev_pc,cpustate->sreg[seg].selector,cpustate->sreg[seg].base,cpustate->sreg[seg].limit,offset, size); return 1; } } + */ } return 0; } @@ -703,14 +772,26 @@ INLINE UINT32 i386_translate(i386_state *cpustate, int segment, UINT32 ip, int r // TODO: segment limit access size, execution permission, handle exception thrown from exception handler if(PROTECTED_MODE && !V8086_MODE && (rwn != -1)) { + /* if(!(cpustate->sreg[segment].valid)) FAULT_THROW((segment==SS)?FAULT_SS:FAULT_GP, 0); if(i386_limit_check(cpustate, segment, ip, size)) FAULT_THROW((segment==SS)?FAULT_SS:FAULT_GP, 0); - if((rwn == 0) && ((cpustate->sreg[segment].flags & 8) && !(cpustate->sreg[segment].flags & 2))) + if((rwn == 0) && ((cpustate->sreg[segment].flags& 8) && !(cpustate->sreg[segment].flags & 2))) FAULT_THROW(FAULT_GP, 0); if((rwn == 1) && ((cpustate->sreg[segment].flags & 8) || !(cpustate->sreg[segment].flags & 2))) FAULT_THROW(FAULT_GP, 0); + */ + + if(!(cpustate->sreg[segment].valid)) + FAULT_THROW((segment==SS)?FAULT_SS:FAULT_GP, 0); + if(i386_limit_check(cpustate, segment, ip, size)) + FAULT_THROW((segment==SS)?FAULT_SS:FAULT_GP, 0); + if((rwn == 0) && ((cpustate->sreg[segment].executable) && !(cpustate->sreg[segment].rwn))) + FAULT_THROW(FAULT_GP, 0); + if((rwn == 1) && ((cpustate->sreg[segment].executable) || !(cpustate->sreg[segment].rwn))) + FAULT_THROW(FAULT_GP, 0); + } return cpustate->sreg[segment].base + ip; } diff --git a/source/src/vm/mame/emu/cpu/i386/pentops.c b/source/src/vm/mame/emu/cpu/i386/pentops.c index ea386325a..4b843a019 100644 --- a/source/src/vm/mame/emu/cpu/i386/pentops.c +++ b/source/src/vm/mame/emu/cpu/i386/pentops.c @@ -173,11 +173,24 @@ static void PENTIUMOP(rsm)(i386_state* cpustate) { if(PROTECTED_MODE && !V8086_MODE) { - cpustate->sreg[i].valid = cpustate->sreg[i].selector ? true : false; - cpustate->sreg[i].d = (cpustate->sreg[i].flags & 0x4000) ? 1 : 0; + cpustate->sreg[i].valid = cpustate->sreg[i].selector ? true : false; + cpustate->sreg[i].d = (cpustate->sreg[i].flags & SREG_FLAGS_SZ) ? 1 : 0; + cpustate->sreg[i].whole_address = false; // From NP2 v0.83 + cpustate->sreg[i].is_system = ((cpustate->sreg[i].flags & SREG_FLAGS_NS) == 0) ? true : false; // From NP2 v0.83 + cpustate->sreg[i].executable = (cpustate->sreg[i].flags & SREG_FLAGS_EX) ? true : false; // From NP2 v0.83 + cpustate->sreg[i].expand_down = (cpustate->sreg[i].flags & SREG_FLAGS_DC) ? true : false; // From NP2 v0.83 + cpustate->sreg[i].rwn = (cpustate->sreg[i].flags & SREG_FLAGS_RW) ? true : false; // From NP2 v0.83 + cpustate->sreg[i].priv = (cpustate->sreg[i].flags & 0x60) >> 5; } - else + else { cpustate->sreg[i].valid = true; + cpustate->sreg[i].whole_address = false; + cpustate->sreg[i].is_system = true; + cpustate->sreg[i].executable = true; + cpustate->sreg[i].expand_down = false; + cpustate->sreg[i].rwn = true; + cpustate->sreg[i].priv = 3; // OK? + } } // if(!cpustate->smiact.isnull()) @@ -2033,7 +2046,7 @@ static void I386OP(cyrix_svdc)(i386_state* cpustate) // Opcode 0f 78 limit = cpustate->sreg[index].limit; - if (cpustate->sreg[index].flags & 0x8000) //G bit + if (cpustate->sreg[index].flags & SREG_FLAGS_GR) //G bit { limit >>= 12; } @@ -2101,7 +2114,7 @@ static void I386OP(cyrix_rsdc)(i386_state* cpustate) // Opcode 0f 79 flags = READ16(cpustate,ea + 5); limit = READ16(cpustate,ea + 0) | ((flags & 3) << 16); - if (flags & 0x8000) //G bit + if (flags & SREG_FLAGS_GR) //G bit { limit = (limit << 12) | 0xfff; } @@ -2110,6 +2123,14 @@ static void I386OP(cyrix_rsdc)(i386_state* cpustate) // Opcode 0f 79 cpustate->sreg[index].flags = flags; cpustate->sreg[index].base = base; cpustate->sreg[index].limit = limit; + cpustate->sreg[index].whole_address = 0; + cpustate->sreg[index].rwn = (cpustate->sreg[index].flags & SREG_FLAGS_RW) ? true : false; + cpustate->sreg[index].expand_down = (cpustate->sreg[index].flags & SREG_FLAGS_DC) ? true : false; + cpustate->sreg[index].executable = (cpustate->sreg[index].flags & SREG_FLAGS_EX) ? true : false; + cpustate->sreg[index].is_system = ((cpustate->sreg[index].flags & SREG_FLAGS_NS) == 0) ? true : false; + cpustate->sreg[index].valid = true; // OK? + cpustate->sreg[index].priv = (cpustate->sreg[index].flags & 0x60) >> 5; + } else { i386_trap(cpustate, 6, 0, 0); } @@ -2126,7 +2147,7 @@ static void I386OP(cyrix_svldt)(i386_state* cpustate) // Opcode 0f 7a UINT32 ea = GetEA(cpustate,modrm,0,10); UINT32 limit = cpustate->ldtr.limit; - if (cpustate->ldtr.flags & 0x8000) //G bit + if (cpustate->ldtr.flags & SREG_FLAGS_GR) //G bit { limit >>= 12; } @@ -2161,7 +2182,7 @@ static void I386OP(cyrix_rsldt)(i386_state* cpustate) // Opcode 0f 7b UINT32 limit = READ16(cpustate,ea + 0) | ((flags & 3) << 16); I386_SREG seg; - if (flags & 0x8000) //G bit + if (flags & SREG_FLAGS_GR) //G bit { limit = (limit << 12) | 0xfff; } @@ -2191,7 +2212,7 @@ static void I386OP(cyrix_svts)(i386_state* cpustate) // Opcode 0f 7c UINT32 ea = GetEA(cpustate,modrm,0,10); UINT32 limit = cpustate->task.limit; - if (cpustate->task.flags & 0x8000) //G bit + if (cpustate->task.flags & SREG_FLAGS_GR) //G bit { limit >>= 12; } @@ -2224,7 +2245,7 @@ static void I386OP(cyrix_rsts)(i386_state* cpustate) // Opcode 0f 7d UINT32 base = (READ32(cpustate,ea + 2) | 0x00ffffff) | (READ8(cpustate,ea + 7) << 24); UINT32 limit = READ16(cpustate,ea + 0) | ((flags & 3) << 16); - if (flags & 0x8000) //G bit + if (flags & SREG_FLAGS_GR) //G bit { limit = (limit << 12) | 0xfff; }