i386: various fixes to 486 and Pentium eflags from MESS, and Carl's small

IRQ fix. (no whatsnew)
This commit is contained in:
mahlemiut 2012-01-13 06:37:18 +00:00
parent 2642f11217
commit 814eebb930
4 changed files with 42 additions and 6 deletions

View File

@ -169,7 +169,12 @@ static UINT32 get_flags(i386_state *cpustate)
f |= cpustate->IOP1 << 12;
f |= cpustate->IOP2 << 13;
f |= cpustate->NT << 14;
f |= cpustate->RF << 16;
f |= cpustate->VM << 17;
f |= cpustate->AC << 18;
f |= cpustate->VIF << 19;
f |= cpustate->VIP << 20;
f |= cpustate->ID << 21;
return (cpustate->eflags & ~cpustate->eflags_mask) | (f & cpustate->eflags_mask);
}
@ -187,7 +192,12 @@ static void set_flags(i386_state *cpustate, UINT32 f )
cpustate->IOP1 = (f & 0x1000) ? 1 : 0;
cpustate->IOP2 = (f & 0x2000) ? 1 : 0;
cpustate->NT = (f & 0x4000) ? 1 : 0;
cpustate->RF = (f & 0x10000) ? 1 : 0;
cpustate->VM = (f & 0x20000) ? 1 : 0;
cpustate->AC = (f & 0x40000) ? 1 : 0;
cpustate->VIF = (f & 0x80000) ? 1 : 0;
cpustate->VIP = (f & 0x100000) ? 1 : 0;
cpustate->ID = (f & 0x200000) ? 1 : 0;
cpustate->eflags = f & cpustate->eflags_mask;
}
@ -2193,7 +2203,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
{
UINT32 task = READ32(cpustate,cpustate->task.base);
/* Task Return */
popmessage("IRET: Nested task return.");
logerror("IRET (%08x): Nested task return.\n",cpustate->pc);
/* Check back-link selector in TSS */
if(task & 0x04)
{
@ -3022,6 +3032,7 @@ static CPU_EXECUTE( i386 )
while( cpustate->cycles > 0 )
{
i386_check_irq_line(cpustate);
cpustate->operand_size = cpustate->sreg[CS].d;
cpustate->address_size = cpustate->sreg[CS].d;
cpustate->operand_prefix = 0;
@ -3034,7 +3045,6 @@ static CPU_EXECUTE( i386 )
debugger_instruction_hook(device, cpustate->pc);
i386_check_irq_line(cpustate);
if(cpustate->delayed_interrupt_enable != 0)
{
cpustate->IF = 1;
@ -3540,8 +3550,8 @@ static CPU_RESET( pentium )
cpustate->a20_mask = ~0;
cpustate->cr[0] = 0x00000010;
cpustate->eflags = 0;
cpustate->eflags_mask = 0x003b7fd7;
cpustate->eflags = 0x00200000;
cpustate->eflags_mask = 0x003f7fd7;
cpustate->eip = 0xfff0;
// [11:8] Family
@ -3672,7 +3682,7 @@ static CPU_RESET( mediagx )
cpustate->a20_mask = ~0;
cpustate->cr[0] = 0x00000010;
cpustate->eflags = 0;
cpustate->eflags = 0x00200000;
cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */
cpustate->eip = 0xfff0;

View File

@ -1626,6 +1626,16 @@ static void I386OP(popf)(i386_state *cpustate) // Opcode 0x9d
if(cpustate->CPL > IOPL)
mask &= ~0x00000200;
if(V8086_MODE)
{
if(IOPL < 3)
{
logerror("POPFD(%08x): IOPL < 3 while in V86 mode.\n",cpustate->pc);
FAULT(FAULT_GP,0) // #GP(0)
}
mask &= ~0x00003000; // IOPL cannot be changed while in V8086 mode
}
set_flags(cpustate,(current & ~mask) | (value & mask)); // mask out reserved bits
CYCLES(cpustate,CYCLES_POPF);
}

View File

@ -1492,7 +1492,9 @@ static void I386OP(popfd)(i386_state *cpustate) // Opcode 0x9d
UINT32 value = POP32(cpustate);
UINT32 current = get_flags(cpustate);
UINT8 IOPL = (current >> 12) & 0x03;
UINT32 mask = 0x00007fd5; // VM and RF are not affected by POPF or POPFD, same for higher (486+) bits?
UINT32 mask = 0x00257fd5; // VM, VIP and VIF cannot be set by POPF/POPFD
value &= ~0x00010000; // RF will always return zero
// IOPL can only change if CPL is 0
if(cpustate->CPL != 0)
@ -1502,6 +1504,15 @@ static void I386OP(popfd)(i386_state *cpustate) // Opcode 0x9d
if(cpustate->CPL > IOPL)
mask &= ~0x00000200;
if(V8086_MODE)
{
if(IOPL < 3)
{
logerror("POPFD(%08x): IOPL < 3 while in V86 mode.\n",cpustate->pc);
FAULT(FAULT_GP,0) // #GP(0)
}
mask &= ~0x00003000; // IOPL cannot be changed while in V8086 mode
}
set_flags(cpustate,(current & ~mask) | (value & mask)); // mask out reserved bits
CYCLES(cpustate,CYCLES_POPF);
}

View File

@ -225,7 +225,12 @@ struct _i386_state
UINT8 IOP1;
UINT8 IOP2;
UINT8 NT;
UINT8 RF;
UINT8 VM;
UINT8 AC;
UINT8 VIF;
UINT8 VIP;
UINT8 ID;
UINT8 CPL; // current privilege level