i386: Yet more fixes from MESS.
This commit is contained in:
parent
183fecd71c
commit
f8b4906f8f
@ -363,12 +363,12 @@ static void i386_check_sreg_validity(i386_state* cpustate, int reg)
|
||||
/* Must be within the relevant descriptor table limits */
|
||||
if(selector & 0x04)
|
||||
{
|
||||
if((selector & ~0x07) > cpustate->ldtr.limit)
|
||||
if((selector & ~0x07) >= cpustate->ldtr.limit)
|
||||
invalid = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((selector & ~0x07) > cpustate->gdtr.limit)
|
||||
if((selector & ~0x07) >= cpustate->gdtr.limit)
|
||||
invalid = 1;
|
||||
}
|
||||
|
||||
@ -393,26 +393,29 @@ static void i386_check_sreg_validity(i386_state* cpustate, int reg)
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// this will be more useful once expand-down segments are supported (the FM-Towns uses these for the stack)
|
||||
static void i386_stack_check(i386_state *cpustate, INT16 offset)
|
||||
static int i386_limit_check(i386_state *cpustate, int seg, UINT32 offset)
|
||||
{
|
||||
if(PROTECTED_MODE && !V8086_MODE)
|
||||
{
|
||||
// Check that both current and eventual stack pointers are within the segment limits
|
||||
if(REG32(ESP) > cpustate->sreg[SS].limit)
|
||||
if((cpustate->sreg[seg].flags & 0x0018) == 0x0010 && cpustate->sreg[seg].flags & 0x0004) // if expand-down data segment
|
||||
{
|
||||
logerror("Stack (%08x): ESP is outside stack segment limit.\n",cpustate->pc);
|
||||
FAULT(FAULT_SS,0);
|
||||
if(offset <= cpustate->sreg[seg].limit)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
if(REG32(ESP) + offset > cpustate->sreg[SS].limit)
|
||||
else
|
||||
{
|
||||
logerror("Stack (%08x): ESP + offset (%i) is outside stack segment limit.\n",cpustate->pc,offset);
|
||||
FAULT(FAULT_SS,0);
|
||||
if(offset > cpustate->sreg[seg].limit)
|
||||
{
|
||||
logerror("Limit check at 0x%08x failed. Segment %04x, limit %08x, offset %08x\n",cpustate->pc,cpustate->sreg[seg].selector,cpustate->sreg[seg].limit,offset);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void i386_protected_mode_sreg_load(i386_state *cpustate, UINT16 selector, UINT8 reg)
|
||||
{
|
||||
@ -431,14 +434,14 @@ static void i386_protected_mode_sreg_load(i386_state *cpustate, UINT16 selector,
|
||||
i386_load_protected_mode_segment(cpustate,&stack);
|
||||
DPL = (stack.flags >> 5) & 0x03;
|
||||
|
||||
if((selector & ~0x0007) == 0)
|
||||
if((selector & ~0x0003) == 0)
|
||||
{
|
||||
logerror("SReg Load (%08x): Selector is null.\n",cpustate->pc);
|
||||
FAULT(FAULT_GP,0)
|
||||
}
|
||||
if(selector & 0x0004) // LDT
|
||||
{
|
||||
if((selector & ~0x0007) > cpustate->ldtr.limit)
|
||||
if((selector & ~0x0007) >= cpustate->ldtr.limit)
|
||||
{
|
||||
logerror("SReg Load (%08x): Selector is out of LDT bounds.\n",cpustate->pc);
|
||||
FAULT(FAULT_GP,selector & ~0x03)
|
||||
@ -446,7 +449,7 @@ static void i386_protected_mode_sreg_load(i386_state *cpustate, UINT16 selector,
|
||||
}
|
||||
else // GDT
|
||||
{
|
||||
if((selector & ~0x0007) > cpustate->gdtr.limit)
|
||||
if((selector & ~0x0007) >= cpustate->gdtr.limit)
|
||||
{
|
||||
logerror("SReg Load (%08x): Selector is out of GDT bounds.\n",cpustate->pc);
|
||||
FAULT(FAULT_GP,selector & ~0x03)
|
||||
@ -477,7 +480,7 @@ static void i386_protected_mode_sreg_load(i386_state *cpustate, UINT16 selector,
|
||||
{
|
||||
I386_SREG desc;
|
||||
|
||||
if((selector & ~0x0007) == 0)
|
||||
if((selector & ~0x0003) == 0)
|
||||
{
|
||||
cpustate->sreg[reg].selector = selector;
|
||||
i386_load_segment_descriptor(cpustate, reg );
|
||||
@ -492,7 +495,7 @@ static void i386_protected_mode_sreg_load(i386_state *cpustate, UINT16 selector,
|
||||
|
||||
if(selector & 0x0004) // LDT
|
||||
{
|
||||
if((selector & ~0x0007) > cpustate->ldtr.limit)
|
||||
if((selector & ~0x0007) >= cpustate->ldtr.limit)
|
||||
{
|
||||
logerror("SReg Load (%08x): Selector is out of LDT bounds.\n",cpustate->pc);
|
||||
FAULT(FAULT_GP,selector & ~0x03)
|
||||
@ -500,7 +503,7 @@ static void i386_protected_mode_sreg_load(i386_state *cpustate, UINT16 selector,
|
||||
}
|
||||
else // GDT
|
||||
{
|
||||
if((selector & ~0x0007) > cpustate->gdtr.limit)
|
||||
if((selector & ~0x0007) >= cpustate->gdtr.limit)
|
||||
{
|
||||
logerror("SReg Load (%08x): Selector is out of GDT bounds.\n",cpustate->pc);
|
||||
FAULT(FAULT_GP,selector & ~0x03)
|
||||
@ -607,7 +610,7 @@ static void i386_trap(i386_state *cpustate,int irq, int irq_gate, int trap_level
|
||||
}
|
||||
|
||||
/* segment privilege checks */
|
||||
if(entry > cpustate->idtr.limit)
|
||||
if(entry >= cpustate->idtr.limit)
|
||||
{
|
||||
logerror("IRQ (%08x): Vector %02xh is past IDT limit.\n",cpustate->pc,entry);
|
||||
FAULT_EXP(FAULT_GP,entry+2)
|
||||
@ -700,7 +703,7 @@ static void i386_trap(i386_state *cpustate,int irq, int irq_gate, int trap_level
|
||||
}
|
||||
else
|
||||
{
|
||||
if(segment > cpustate->gdtr.limit)
|
||||
if(segment >= cpustate->gdtr.limit)
|
||||
{
|
||||
logerror("IRQ: Task gate: TSS is past GDT limit.\n");
|
||||
FAULT_EXP(FAULT_TS,segment & ~0x07);
|
||||
@ -739,7 +742,7 @@ static void i386_trap(i386_state *cpustate,int irq, int irq_gate, int trap_level
|
||||
}
|
||||
if(segment & 0x04)
|
||||
{
|
||||
if((segment & ~0x07) > cpustate->ldtr.limit)
|
||||
if((segment & ~0x07) >= cpustate->ldtr.limit)
|
||||
{
|
||||
logerror("IRQ: Gate segment is past LDT limit.\n");
|
||||
FAULT_EXP(FAULT_GP,(segment & 0x07)+cpustate->ext)
|
||||
@ -747,7 +750,7 @@ static void i386_trap(i386_state *cpustate,int irq, int irq_gate, int trap_level
|
||||
}
|
||||
else
|
||||
{
|
||||
if((segment & ~0x07) > cpustate->gdtr.limit)
|
||||
if((segment & ~0x07) >= cpustate->gdtr.limit)
|
||||
{
|
||||
logerror("IRQ: Gate segment is past GDT limit.\n");
|
||||
FAULT_EXP(FAULT_GP,(segment & 0x07)+cpustate->ext)
|
||||
@ -788,7 +791,7 @@ static void i386_trap(i386_state *cpustate,int irq, int irq_gate, int trap_level
|
||||
}
|
||||
if(stack.selector & 0x04)
|
||||
{
|
||||
if((stack.selector & ~0x07) > cpustate->ldtr.base)
|
||||
if((stack.selector & ~0x07) >= cpustate->ldtr.base)
|
||||
{
|
||||
logerror("IRQ: New stack selector is past LDT limit.\n");
|
||||
FAULT_EXP(FAULT_TS,(stack.selector & ~0x07)+cpustate->ext)
|
||||
@ -796,7 +799,7 @@ static void i386_trap(i386_state *cpustate,int irq, int irq_gate, int trap_level
|
||||
}
|
||||
else
|
||||
{
|
||||
if((stack.selector & ~0x07) > cpustate->gdtr.base)
|
||||
if((stack.selector & ~0x07) >= cpustate->gdtr.base)
|
||||
{
|
||||
logerror("IRQ: New stack selector is past GDT limit.\n");
|
||||
FAULT_EXP(FAULT_TS,(stack.selector & ~0x07)+cpustate->ext)
|
||||
@ -1198,7 +1201,7 @@ static void i386_protected_mode_jump(i386_state *cpustate, UINT16 seg, UINT32 of
|
||||
UINT32 offset = off;
|
||||
|
||||
/* Check selector is not null */
|
||||
if((segment & ~0x07) == 0)
|
||||
if((segment & ~0x03) == 0)
|
||||
{
|
||||
logerror("JMP: Segment is null.\n");
|
||||
FAULT(FAULT_GP,0)
|
||||
@ -1207,7 +1210,7 @@ static void i386_protected_mode_jump(i386_state *cpustate, UINT16 seg, UINT32 of
|
||||
if((segment & 0x04) == 0)
|
||||
{
|
||||
/* check GDT limit */
|
||||
if((segment & ~0x07) > (cpustate->gdtr.limit))
|
||||
if((segment & ~0x07) >= (cpustate->gdtr.limit))
|
||||
{
|
||||
logerror("JMP: Segment is past GDT limit.\n");
|
||||
FAULT(FAULT_GP,segment & 0xfffc)
|
||||
@ -1216,7 +1219,7 @@ static void i386_protected_mode_jump(i386_state *cpustate, UINT16 seg, UINT32 of
|
||||
else
|
||||
{
|
||||
/* check LDT limit */
|
||||
if((segment & ~0x07) > (cpustate->ldtr.limit))
|
||||
if((segment & ~0x07) >= (cpustate->ldtr.limit))
|
||||
{
|
||||
logerror("JMP: Segment is past LDT limit.\n");
|
||||
FAULT(FAULT_GP,segment & 0xfffc)
|
||||
@ -1474,14 +1477,14 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of
|
||||
UINT32 offset = off;
|
||||
int x;
|
||||
|
||||
if((selector & ~0x07) == 0)
|
||||
if((selector & ~0x03) == 0)
|
||||
{
|
||||
logerror("CALL (%08x): Selector is null.\n",cpustate->pc);
|
||||
FAULT(FAULT_GP,0) // #GP(0)
|
||||
}
|
||||
if(selector & 0x04)
|
||||
{
|
||||
if((selector & ~0x07) > cpustate->ldtr.limit)
|
||||
if((selector & ~0x07) >= cpustate->ldtr.limit)
|
||||
{
|
||||
logerror("CALL: Selector is past LDT limit.\n");
|
||||
FAULT(FAULT_GP,selector & ~0x03) // #GP(selector)
|
||||
@ -1489,7 +1492,7 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of
|
||||
}
|
||||
else
|
||||
{
|
||||
if((selector & ~0x07) > cpustate->gdtr.limit)
|
||||
if((selector & ~0x07) >= cpustate->gdtr.limit)
|
||||
{
|
||||
logerror("CALL: Selector is past GDT limit.\n");
|
||||
FAULT(FAULT_GP,selector & ~0x03) // #GP(selector)
|
||||
@ -1942,14 +1945,14 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op
|
||||
if(RPL == CPL)
|
||||
{
|
||||
/* same privilege level */
|
||||
if((newCS & ~0x07) == 0)
|
||||
if((newCS & ~0x03) == 0)
|
||||
{
|
||||
logerror("RETF: Return segment is null.\n");
|
||||
FAULT(FAULT_GP,0)
|
||||
}
|
||||
if(newCS & 0x04)
|
||||
{
|
||||
if((newCS & ~0x07) > cpustate->ldtr.limit)
|
||||
if((newCS & ~0x07) >= cpustate->ldtr.limit)
|
||||
{
|
||||
logerror("RETF: Return segment is past LDT limit.\n");
|
||||
FAULT(FAULT_GP,newCS & ~0x03)
|
||||
@ -1957,7 +1960,7 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op
|
||||
}
|
||||
else
|
||||
{
|
||||
if((newCS & ~0x07) > cpustate->gdtr.limit)
|
||||
if((newCS & ~0x07) >= cpustate->gdtr.limit)
|
||||
{
|
||||
logerror("RETF: Return segment is past GDT limit.\n");
|
||||
FAULT(FAULT_GP,newCS & ~0x03)
|
||||
@ -1996,7 +1999,7 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op
|
||||
}
|
||||
if(operand32 == 0)
|
||||
{
|
||||
if(REG16(SP) > (cpustate->sreg[SS].limit & 0xffff)+1)
|
||||
if(i386_limit_check(cpustate,SS,REG16(SP)+count+3) != 0)
|
||||
{
|
||||
logerror("RETF (%08x): SP is past stack segment limit.\n",cpustate->pc);
|
||||
FAULT(FAULT_SS,0)
|
||||
@ -2004,7 +2007,7 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op
|
||||
}
|
||||
else
|
||||
{
|
||||
if(REG32(ESP) > cpustate->sreg[SS].limit+1)
|
||||
if(i386_limit_check(cpustate,SS,REG32(ESP)+count+7) != 0)
|
||||
{
|
||||
logerror("RETF: ESP is past stack segment limit.\n");
|
||||
FAULT(FAULT_SS,0)
|
||||
@ -2020,7 +2023,7 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op
|
||||
/* outer privilege level */
|
||||
if(operand32 == 0)
|
||||
{
|
||||
if(REG16(SP)+8+count > cpustate->sreg[SS].limit+1)
|
||||
if(i386_limit_check(cpustate,SS,REG16(SP)+count+7) != 0)
|
||||
{
|
||||
logerror("RETF (%08x): SP is past stack segment limit.\n",cpustate->pc);
|
||||
FAULT(FAULT_SS,0)
|
||||
@ -2028,7 +2031,7 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op
|
||||
}
|
||||
else
|
||||
{
|
||||
if(REG32(ESP)+16+count > cpustate->sreg[SS].limit+1)
|
||||
if(i386_limit_check(cpustate,SS,REG32(SP)+count+15) != 0)
|
||||
{
|
||||
logerror("RETF: ESP is past stack segment limit.\n");
|
||||
FAULT(FAULT_SS,0)
|
||||
@ -2036,14 +2039,14 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op
|
||||
}
|
||||
|
||||
/* Check CS selector and descriptor */
|
||||
if((newCS & ~0x07) == 0)
|
||||
if((newCS & ~0x03) == 0)
|
||||
{
|
||||
logerror("RETF: CS segment is null.\n");
|
||||
FAULT(FAULT_GP,0)
|
||||
}
|
||||
if(newCS & 0x04)
|
||||
{
|
||||
if((newCS & ~0x07) > cpustate->ldtr.limit)
|
||||
if((newCS & ~0x07) >= cpustate->ldtr.limit)
|
||||
{
|
||||
logerror("RETF: CS segment selector is past LDT limit.\n");
|
||||
FAULT(FAULT_GP,newCS & ~0x07)
|
||||
@ -2051,7 +2054,7 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op
|
||||
}
|
||||
else
|
||||
{
|
||||
if((newCS & ~0x07) > cpustate->gdtr.limit)
|
||||
if((newCS & ~0x07) >= cpustate->gdtr.limit)
|
||||
{
|
||||
logerror("RETF: CS segment selector is past GDT limit.\n");
|
||||
FAULT(FAULT_GP,newCS & ~0x07)
|
||||
@ -2232,7 +2235,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
|
||||
logerror("IRET: Task return: Back-linked TSS is not in GDT.\n");
|
||||
FAULT(FAULT_TS,task & ~0x07)
|
||||
}
|
||||
if((task & ~0x07) > cpustate->gdtr.limit)
|
||||
if((task & ~0x07) >= cpustate->gdtr.limit)
|
||||
{
|
||||
logerror("IRET: Task return: Back-linked TSS is not in GDT.\n");
|
||||
FAULT(FAULT_TS,task & ~0x07)
|
||||
@ -2408,7 +2411,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
|
||||
{
|
||||
if(operand32 == 0)
|
||||
{
|
||||
if(REG16(SP)+4 > cpustate->sreg[SS].limit+1)
|
||||
if(i386_limit_check(cpustate,SS,REG16(SP)+3) != 0)
|
||||
{
|
||||
logerror("IRET: Data on stack is past SS limit.\n");
|
||||
FAULT(FAULT_SS,0)
|
||||
@ -2416,7 +2419,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(REG32(ESP)+6 > cpustate->sreg[SS].limit+1)
|
||||
if(i386_limit_check(cpustate,SS,REG32(ESP)+7) != 0)
|
||||
{
|
||||
logerror("IRET: Data on stack is past SS limit.\n");
|
||||
FAULT(FAULT_SS,0)
|
||||
@ -2433,7 +2436,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
|
||||
/* return to same privilege level */
|
||||
if(operand32 == 0)
|
||||
{
|
||||
if(REG16(SP)+6 > cpustate->sreg[SS].limit+1)
|
||||
if(i386_limit_check(cpustate,SS,REG16(SP)+5) != 0)
|
||||
{
|
||||
logerror("IRET (%08x): Data on stack is past SS limit.\n",cpustate->pc);
|
||||
FAULT(FAULT_SS,0)
|
||||
@ -2441,20 +2444,20 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(REG32(ESP)+12 > cpustate->sreg[SS].limit+1)
|
||||
if(i386_limit_check(cpustate,SS,REG32(ESP)+11) != 0)
|
||||
{
|
||||
logerror("IRET (%08x): Data on stack is past SS limit.\n",cpustate->pc);
|
||||
FAULT(FAULT_SS,0)
|
||||
}
|
||||
}
|
||||
if((newCS & ~0x07) == 0)
|
||||
if((newCS & ~0x03) == 0)
|
||||
{
|
||||
logerror("IRET: Return CS selector is null.\n");
|
||||
FAULT(FAULT_GP,0)
|
||||
}
|
||||
if(newCS & 0x04)
|
||||
{
|
||||
if((newCS & ~0x07) > cpustate->ldtr.limit)
|
||||
if((newCS & ~0x07) >= cpustate->ldtr.limit)
|
||||
{
|
||||
logerror("IRET: Return CS selector (%04x) is past LDT limit.\n",newCS);
|
||||
FAULT(FAULT_GP,newCS & ~0x07)
|
||||
@ -2462,7 +2465,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
|
||||
}
|
||||
else
|
||||
{
|
||||
if((newCS & ~0x07) > cpustate->gdtr.limit)
|
||||
if((newCS & ~0x07) >= cpustate->gdtr.limit)
|
||||
{
|
||||
logerror("IRET: Return CS selector is past GDT limit.\n");
|
||||
FAULT(FAULT_GP,newCS & ~0x07)
|
||||
@ -2533,28 +2536,29 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
|
||||
i386_load_protected_mode_segment(cpustate,&stack);
|
||||
if(operand32 == 0)
|
||||
{
|
||||
if(REG16(SP)+10 > cpustate->sreg[SS].limit+1)
|
||||
if(i386_limit_check(cpustate,SS,REG16(SP)+9) != 0)
|
||||
{
|
||||
logerror("IRET: SP is past SS limit.\n");
|
||||
FAULT(FAULT_SS,0) }
|
||||
FAULT(FAULT_SS,0)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(REG32(ESP)+20 > cpustate->sreg[SS].limit+1)
|
||||
if(i386_limit_check(cpustate,SS,REG32(ESP)+19) != 0)
|
||||
{
|
||||
logerror("IRET: ESP is past SS limit.\n");
|
||||
FAULT(FAULT_SS,0)
|
||||
}
|
||||
}
|
||||
/* Check CS selector and descriptor */
|
||||
if((newCS & ~0x07) == 0)
|
||||
if((newCS & ~0x03) == 0)
|
||||
{
|
||||
logerror("IRET: Return CS selector is null.\n");
|
||||
FAULT(FAULT_GP,0)
|
||||
}
|
||||
if(newCS & 0x04)
|
||||
{
|
||||
if((newCS & ~0x07) > cpustate->ldtr.limit)
|
||||
if((newCS & ~0x07) >= cpustate->ldtr.limit)
|
||||
{
|
||||
logerror("IRET: Return CS selector is past LDT limit.\n");
|
||||
FAULT(FAULT_GP,newCS & ~0x07);
|
||||
@ -2562,7 +2566,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
|
||||
}
|
||||
else
|
||||
{
|
||||
if((newCS & ~0x07) > cpustate->gdtr.limit)
|
||||
if((newCS & ~0x07) >= cpustate->gdtr.limit)
|
||||
{
|
||||
logerror("IRET: Return CS selector is past GDT limit.\n");
|
||||
FAULT(FAULT_GP,newCS & ~0x07);
|
||||
@ -2597,14 +2601,14 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
|
||||
|
||||
/* Check SS selector and descriptor */
|
||||
DPL = (stack.flags >> 5) & 0x03;
|
||||
if((newSS & ~0x07) == 0)
|
||||
if((newSS & ~0x03) == 0)
|
||||
{
|
||||
logerror("IRET: Return SS selector is null.\n");
|
||||
FAULT(FAULT_GP,0)
|
||||
}
|
||||
if(newSS & 0x04)
|
||||
{
|
||||
if((newSS & ~0x07) > cpustate->ldtr.limit)
|
||||
if((newSS & ~0x07) >= cpustate->ldtr.limit)
|
||||
{
|
||||
logerror("IRET: Return SS selector is past LDT limit.\n");
|
||||
FAULT(FAULT_GP,newSS & ~0x07);
|
||||
@ -2612,7 +2616,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
|
||||
}
|
||||
else
|
||||
{
|
||||
if((newSS & ~0x07) > cpustate->gdtr.limit)
|
||||
if((newSS & ~0x07) >= cpustate->gdtr.limit)
|
||||
{
|
||||
logerror("IRET: Return SS selector is past GDT limit.\n");
|
||||
FAULT(FAULT_GP,newSS & ~0x07);
|
||||
|
@ -1189,8 +1189,8 @@ static void I386OP(lodsw)(i386_state *cpustate) // Opcode 0xad
|
||||
static void I386OP(loop16)(i386_state *cpustate) // Opcode 0xe2
|
||||
{
|
||||
INT8 disp = FETCH(cpustate);
|
||||
REG16(CX)--;
|
||||
if( REG16(CX) != 0 ) {
|
||||
INT32 val = (cpustate->address_size)?(--REG32(ECX)):(--REG16(CX));
|
||||
if( val != 0 ) {
|
||||
if (cpustate->sreg[CS].d)
|
||||
{
|
||||
cpustate->eip += disp;
|
||||
@ -1207,8 +1207,8 @@ static void I386OP(loop16)(i386_state *cpustate) // Opcode 0xe2
|
||||
static void I386OP(loopne16)(i386_state *cpustate) // Opcode 0xe0
|
||||
{
|
||||
INT8 disp = FETCH(cpustate);
|
||||
REG16(CX)--;
|
||||
if( REG16(CX) != 0 && cpustate->ZF == 0 ) {
|
||||
INT32 val = (cpustate->address_size)?(--REG32(ECX)):(--REG16(CX));
|
||||
if( val != 0 && cpustate->ZF == 0 ) {
|
||||
if (cpustate->sreg[CS].d)
|
||||
{
|
||||
cpustate->eip += disp;
|
||||
@ -1225,8 +1225,8 @@ static void I386OP(loopne16)(i386_state *cpustate) // Opcode 0xe0
|
||||
static void I386OP(loopz16)(i386_state *cpustate) // Opcode 0xe1
|
||||
{
|
||||
INT8 disp = FETCH(cpustate);
|
||||
REG16(CX)--;
|
||||
if( REG16(CX) != 0 && cpustate->ZF != 0 ) {
|
||||
INT32 val = (cpustate->address_size)?(--REG32(ECX)):(--REG16(CX));
|
||||
if( val != 0 && cpustate->ZF != 0 ) {
|
||||
if (cpustate->sreg[CS].d)
|
||||
{
|
||||
cpustate->eip += disp;
|
||||
@ -1486,110 +1486,172 @@ static void I386OP(out_ax_dx)(i386_state *cpustate) // Opcode 0xef
|
||||
|
||||
static void I386OP(pop_ax)(i386_state *cpustate) // Opcode 0x58
|
||||
{
|
||||
REG16(AX) = POP16(cpustate);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+1) == 0)
|
||||
REG16(AX) = POP16(cpustate);
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(pop_cx)(i386_state *cpustate) // Opcode 0x59
|
||||
{
|
||||
REG16(CX) = POP16(cpustate);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+1) == 0)
|
||||
REG16(CX) = POP16(cpustate);
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(pop_dx)(i386_state *cpustate) // Opcode 0x5a
|
||||
{
|
||||
REG16(DX) = POP16(cpustate);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+1) == 0)
|
||||
REG16(DX) = POP16(cpustate);
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(pop_bx)(i386_state *cpustate) // Opcode 0x5b
|
||||
{
|
||||
REG16(BX) = POP16(cpustate);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+1) == 0)
|
||||
REG16(BX) = POP16(cpustate);
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(pop_sp)(i386_state *cpustate) // Opcode 0x5c
|
||||
{
|
||||
REG16(SP) = POP16(cpustate);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+1) == 0)
|
||||
REG16(SP) = POP16(cpustate);
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(pop_bp)(i386_state *cpustate) // Opcode 0x5d
|
||||
{
|
||||
REG16(BP) = POP16(cpustate);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+1) == 0)
|
||||
REG16(BP) = POP16(cpustate);
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(pop_si)(i386_state *cpustate) // Opcode 0x5e
|
||||
{
|
||||
REG16(SI) = POP16(cpustate);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+1) == 0)
|
||||
REG16(SI) = POP16(cpustate);
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(pop_di)(i386_state *cpustate) // Opcode 0x5f
|
||||
{
|
||||
REG16(DI) = POP16(cpustate);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+1) == 0)
|
||||
REG16(DI) = POP16(cpustate);
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(pop_ds16)(i386_state *cpustate) // Opcode 0x1f
|
||||
{
|
||||
cpustate->sreg[DS].selector = POP16(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,DS);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,DS);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+1) == 0)
|
||||
{
|
||||
cpustate->sreg[DS].selector = POP16(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,DS);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,DS);
|
||||
}
|
||||
}
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(pop_es16)(i386_state *cpustate) // Opcode 0x07
|
||||
{
|
||||
cpustate->sreg[ES].selector = POP16(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,ES);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,ES);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+1) == 0)
|
||||
{
|
||||
cpustate->sreg[ES].selector = POP16(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,ES);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,ES);
|
||||
}
|
||||
}
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(pop_fs16)(i386_state *cpustate) // Opcode 0x0f a1
|
||||
{
|
||||
cpustate->sreg[FS].selector = POP16(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,FS);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,FS);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+1) == 0)
|
||||
{
|
||||
cpustate->sreg[FS].selector = POP16(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,FS);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,FS);
|
||||
}
|
||||
}
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(pop_gs16)(i386_state *cpustate) // Opcode 0x0f a9
|
||||
{
|
||||
cpustate->sreg[GS].selector = POP16(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,GS);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,GS);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+1) == 0)
|
||||
{
|
||||
cpustate->sreg[GS].selector = POP16(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,GS);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,GS);
|
||||
}
|
||||
}
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(pop_ss16)(i386_state *cpustate) // Opcode 0x17
|
||||
{
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(cpustate->IF != 0) // if external interrupts are enabled
|
||||
{
|
||||
cpustate->IF = 0; // reset IF for the next instruction
|
||||
cpustate->delayed_interrupt_enable = 1;
|
||||
}
|
||||
|
||||
cpustate->sreg[SS].selector = POP16(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,SS);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,SS);
|
||||
if(i386_limit_check(cpustate,SS,offset+1) == 0)
|
||||
{
|
||||
cpustate->sreg[SS].selector = POP16(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,SS);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,SS);
|
||||
}
|
||||
}
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_SREG);
|
||||
}
|
||||
|
||||
@ -1597,28 +1659,41 @@ static void I386OP(pop_rm16)(i386_state *cpustate) // Opcode 0x8f
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
UINT16 value;
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
|
||||
value = POP16(cpustate);
|
||||
if(i386_limit_check(cpustate,SS,offset+1) == 0)
|
||||
{
|
||||
value = POP16(cpustate);
|
||||
|
||||
if( modrm >= 0xc0 ) {
|
||||
STORE_RM16(modrm, value);
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
WRITE16(cpustate,ea, value);
|
||||
if( modrm >= 0xc0 ) {
|
||||
STORE_RM16(modrm, value);
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
WRITE16(cpustate,ea, value);
|
||||
}
|
||||
}
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_RM);
|
||||
}
|
||||
|
||||
static void I386OP(popa)(i386_state *cpustate) // Opcode 0x61
|
||||
{
|
||||
REG16(DI) = POP16(cpustate);
|
||||
REG16(SI) = POP16(cpustate);
|
||||
REG16(BP) = POP16(cpustate);
|
||||
REG16(SP) += 2;
|
||||
REG16(BX) = POP16(cpustate);
|
||||
REG16(DX) = POP16(cpustate);
|
||||
REG16(CX) = POP16(cpustate);
|
||||
REG16(AX) = POP16(cpustate);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
|
||||
if(i386_limit_check(cpustate,SS,offset+15) == 0)
|
||||
{
|
||||
REG16(DI) = POP16(cpustate);
|
||||
REG16(SI) = POP16(cpustate);
|
||||
REG16(BP) = POP16(cpustate);
|
||||
REG16(SP) += 2;
|
||||
REG16(BX) = POP16(cpustate);
|
||||
REG16(DX) = POP16(cpustate);
|
||||
REG16(CX) = POP16(cpustate);
|
||||
REG16(AX) = POP16(cpustate);
|
||||
}
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POPA);
|
||||
}
|
||||
|
||||
@ -1628,6 +1703,7 @@ static void I386OP(popf)(i386_state *cpustate) // Opcode 0x9d
|
||||
UINT32 current = get_flags(cpustate);
|
||||
UINT8 IOPL = (current >> 12) & 0x03;
|
||||
UINT32 mask = 0x7fd5;
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
|
||||
// IOPL can only change if CPL is 0
|
||||
if(cpustate->CPL != 0)
|
||||
@ -1647,119 +1723,194 @@ static void I386OP(popf)(i386_state *cpustate) // Opcode 0x9d
|
||||
mask &= ~0x00003000; // IOPL cannot be changed while in V8086 mode
|
||||
}
|
||||
|
||||
value = POP16(cpustate);
|
||||
set_flags(cpustate,(current & ~mask) | (value & mask)); // mask out reserved bits
|
||||
if(i386_limit_check(cpustate,SS,offset+1) == 0)
|
||||
{
|
||||
value = POP16(cpustate);
|
||||
set_flags(cpustate,(current & ~mask) | (value & mask)); // mask out reserved bits
|
||||
}
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POPF);
|
||||
}
|
||||
|
||||
static void I386OP(push_ax)(i386_state *cpustate) // Opcode 0x50
|
||||
{
|
||||
PUSH16(cpustate, REG16(AX) );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-2) == 0)
|
||||
PUSH16(cpustate, REG16(AX) );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(push_cx)(i386_state *cpustate) // Opcode 0x51
|
||||
{
|
||||
PUSH16(cpustate, REG16(CX) );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-2) == 0)
|
||||
PUSH16(cpustate, REG16(CX) );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(push_dx)(i386_state *cpustate) // Opcode 0x52
|
||||
{
|
||||
PUSH16(cpustate, REG16(DX) );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-2) == 0)
|
||||
PUSH16(cpustate, REG16(DX) );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(push_bx)(i386_state *cpustate) // Opcode 0x53
|
||||
{
|
||||
PUSH16(cpustate, REG16(BX) );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-2) == 0)
|
||||
PUSH16(cpustate, REG16(BX) );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(push_sp)(i386_state *cpustate) // Opcode 0x54
|
||||
{
|
||||
PUSH16(cpustate, REG16(SP) );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-2) == 0)
|
||||
PUSH16(cpustate, REG16(SP) );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(push_bp)(i386_state *cpustate) // Opcode 0x55
|
||||
{
|
||||
PUSH16(cpustate, REG16(BP) );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-2) == 0)
|
||||
PUSH16(cpustate, REG16(BP) );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(push_si)(i386_state *cpustate) // Opcode 0x56
|
||||
{
|
||||
PUSH16(cpustate, REG16(SI) );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-2) == 0)
|
||||
PUSH16(cpustate, REG16(SI) );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(push_di)(i386_state *cpustate) // Opcode 0x57
|
||||
{
|
||||
PUSH16(cpustate, REG16(DI) );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-2) == 0)
|
||||
PUSH16(cpustate, REG16(DI) );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(push_cs16)(i386_state *cpustate) // Opcode 0x0e
|
||||
{
|
||||
PUSH16(cpustate, cpustate->sreg[CS].selector );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-2) == 0)
|
||||
PUSH16(cpustate, cpustate->sreg[CS].selector );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(push_ds16)(i386_state *cpustate) // Opcode 0x1e
|
||||
{
|
||||
PUSH16(cpustate, cpustate->sreg[DS].selector );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-2) == 0)
|
||||
PUSH16(cpustate, cpustate->sreg[DS].selector );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(push_es16)(i386_state *cpustate) // Opcode 0x06
|
||||
{
|
||||
PUSH16(cpustate, cpustate->sreg[ES].selector );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-2) == 0)
|
||||
PUSH16(cpustate, cpustate->sreg[ES].selector );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(push_fs16)(i386_state *cpustate) // Opcode 0x0f a0
|
||||
{
|
||||
PUSH16(cpustate, cpustate->sreg[FS].selector );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-2) == 0)
|
||||
PUSH16(cpustate, cpustate->sreg[FS].selector );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(push_gs16)(i386_state *cpustate) // Opcode 0x0f a8
|
||||
{
|
||||
PUSH16(cpustate, cpustate->sreg[GS].selector );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-2) == 0)
|
||||
PUSH16(cpustate, cpustate->sreg[GS].selector );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(push_ss16)(i386_state *cpustate) // Opcode 0x16
|
||||
{
|
||||
PUSH16(cpustate, cpustate->sreg[SS].selector );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-2) == 0)
|
||||
PUSH16(cpustate, cpustate->sreg[SS].selector );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(push_i16)(i386_state *cpustate) // Opcode 0x68
|
||||
{
|
||||
UINT16 value = FETCH16(cpustate);
|
||||
PUSH16(cpustate,value);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-2) == 0)
|
||||
PUSH16(cpustate,value);
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_IMM);
|
||||
}
|
||||
|
||||
static void I386OP(pusha)(i386_state *cpustate) // Opcode 0x60
|
||||
{
|
||||
UINT16 temp = REG16(SP);
|
||||
PUSH16(cpustate, REG16(AX) );
|
||||
PUSH16(cpustate, REG16(CX) );
|
||||
PUSH16(cpustate, REG16(DX) );
|
||||
PUSH16(cpustate, REG16(BX) );
|
||||
PUSH16(cpustate, temp );
|
||||
PUSH16(cpustate, REG16(BP) );
|
||||
PUSH16(cpustate, REG16(SI) );
|
||||
PUSH16(cpustate, REG16(DI) );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-16) == 0)
|
||||
{
|
||||
PUSH16(cpustate, REG16(AX) );
|
||||
PUSH16(cpustate, REG16(CX) );
|
||||
PUSH16(cpustate, REG16(DX) );
|
||||
PUSH16(cpustate, REG16(BX) );
|
||||
PUSH16(cpustate, temp );
|
||||
PUSH16(cpustate, REG16(BP) );
|
||||
PUSH16(cpustate, REG16(SI) );
|
||||
PUSH16(cpustate, REG16(DI) );
|
||||
}
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSHA);
|
||||
}
|
||||
|
||||
static void I386OP(pushf)(i386_state *cpustate) // Opcode 0x9c
|
||||
{
|
||||
PUSH16(cpustate, get_flags(cpustate) & 0xffff );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-2) == 0)
|
||||
PUSH16(cpustate, get_flags(cpustate) & 0xffff );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSHF);
|
||||
}
|
||||
|
||||
@ -2672,7 +2823,9 @@ static void I386OP(groupF7_16)(i386_state *cpustate) // Opcode 0xf7
|
||||
cpustate->CF = 1;
|
||||
}
|
||||
} else {
|
||||
/* TODO: Divide by zero */
|
||||
cpustate->ext = 0;
|
||||
i386_trap(cpustate, 0, 0, 0);
|
||||
cpustate->ext = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2704,7 +2857,9 @@ static void I386OP(groupF7_16)(i386_state *cpustate) // Opcode 0xf7
|
||||
cpustate->CF = 1;
|
||||
}
|
||||
} else {
|
||||
/* TODO: Divide by zero */
|
||||
cpustate->ext = 0;
|
||||
i386_trap(cpustate, 0, 0, 0);
|
||||
cpustate->ext = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2904,6 +3059,8 @@ static void I386OP(group0F00_16)(i386_state *cpustate) // Opcode 0x0f 00
|
||||
case 2: /* LLDT */
|
||||
if ( PROTECTED_MODE && !V8086_MODE )
|
||||
{
|
||||
if(cpustate->CPL)
|
||||
FAULT(FAULT_GP,0)
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM16(modrm);
|
||||
cpustate->ldtr.segment = address;
|
||||
@ -2929,6 +3086,8 @@ static void I386OP(group0F00_16)(i386_state *cpustate) // Opcode 0x0f 00
|
||||
case 3: /* LTR */
|
||||
if ( PROTECTED_MODE && !V8086_MODE )
|
||||
{
|
||||
if(cpustate->CPL)
|
||||
FAULT(FAULT_GP,0)
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM16(modrm);
|
||||
cpustate->task.segment = address;
|
||||
@ -3117,6 +3276,8 @@ static void I386OP(group0F01_16)(i386_state *cpustate) // Opcode 0x0f 01
|
||||
}
|
||||
case 2: /* LGDT */
|
||||
{
|
||||
if(PROTECTED_MODE && cpustate->CPL)
|
||||
FAULT(FAULT_GP,0)
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM16(modrm);
|
||||
ea = i386_translate(cpustate, CS, address );
|
||||
@ -3130,6 +3291,8 @@ static void I386OP(group0F01_16)(i386_state *cpustate) // Opcode 0x0f 01
|
||||
}
|
||||
case 3: /* LIDT */
|
||||
{
|
||||
if(PROTECTED_MODE && cpustate->CPL)
|
||||
FAULT(FAULT_GP,0)
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM16(modrm);
|
||||
ea = i386_translate(cpustate, CS, address );
|
||||
@ -3155,7 +3318,8 @@ static void I386OP(group0F01_16)(i386_state *cpustate) // Opcode 0x0f 01
|
||||
}
|
||||
case 6: /* LMSW */
|
||||
{
|
||||
// TODO: Check for protection fault
|
||||
if(PROTECTED_MODE && cpustate->CPL)
|
||||
FAULT(FAULT_GP,0)
|
||||
UINT16 b;
|
||||
if( modrm >= 0xc0 ) {
|
||||
b = LOAD_RM16(modrm);
|
||||
|
@ -1361,110 +1361,172 @@ static void I386OP(out_eax_dx)(i386_state *cpustate) // Opcode 0xef
|
||||
|
||||
static void I386OP(pop_eax)(i386_state *cpustate) // Opcode 0x58
|
||||
{
|
||||
REG32(EAX) = POP32(cpustate);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+3) == 0)
|
||||
REG32(EAX) = POP32(cpustate);
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(pop_ecx)(i386_state *cpustate) // Opcode 0x59
|
||||
{
|
||||
REG32(ECX) = POP32(cpustate);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+3) == 0)
|
||||
REG32(ECX) = POP32(cpustate);
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(pop_edx)(i386_state *cpustate) // Opcode 0x5a
|
||||
{
|
||||
REG32(EDX) = POP32(cpustate);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+3) == 0)
|
||||
REG32(EDX) = POP32(cpustate);
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(pop_ebx)(i386_state *cpustate) // Opcode 0x5b
|
||||
{
|
||||
REG32(EBX) = POP32(cpustate);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+3) == 0)
|
||||
REG32(EBX) = POP32(cpustate);
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(pop_esp)(i386_state *cpustate) // Opcode 0x5c
|
||||
{
|
||||
REG32(ESP) = POP32(cpustate);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+3) == 0)
|
||||
REG32(ESP) = POP32(cpustate);
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(pop_ebp)(i386_state *cpustate) // Opcode 0x5d
|
||||
{
|
||||
REG32(EBP) = POP32(cpustate);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+3) == 0)
|
||||
REG32(EBP) = POP32(cpustate);
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(pop_esi)(i386_state *cpustate) // Opcode 0x5e
|
||||
{
|
||||
REG32(ESI) = POP32(cpustate);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+3) == 0)
|
||||
REG32(ESI) = POP32(cpustate);
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(pop_edi)(i386_state *cpustate) // Opcode 0x5f
|
||||
{
|
||||
REG32(EDI) = POP32(cpustate);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+3) == 0)
|
||||
REG32(EDI) = POP32(cpustate);
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(pop_ds32)(i386_state *cpustate) // Opcode 0x1f
|
||||
{
|
||||
cpustate->sreg[DS].selector = POP32(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,DS);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,DS);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+3) == 0)
|
||||
{
|
||||
cpustate->sreg[DS].selector = POP32(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,DS);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,DS);
|
||||
}
|
||||
}
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(pop_es32)(i386_state *cpustate) // Opcode 0x07
|
||||
{
|
||||
cpustate->sreg[ES].selector = POP32(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,ES);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,ES);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+3) == 0)
|
||||
{
|
||||
cpustate->sreg[ES].selector = POP32(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,ES);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,ES);
|
||||
}
|
||||
}
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(pop_fs32)(i386_state *cpustate) // Opcode 0x0f a1
|
||||
{
|
||||
cpustate->sreg[FS].selector = POP32(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,FS);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,FS);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+3) == 0)
|
||||
{
|
||||
cpustate->sreg[FS].selector = POP32(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,FS);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,FS);
|
||||
}
|
||||
}
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(pop_gs32)(i386_state *cpustate) // Opcode 0x0f a9
|
||||
{
|
||||
cpustate->sreg[GS].selector = POP32(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,GS);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,GS);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+3) == 0)
|
||||
{
|
||||
cpustate->sreg[GS].selector = POP32(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,GS);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,GS);
|
||||
}
|
||||
}
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(pop_ss32)(i386_state *cpustate) // Opcode 0x17
|
||||
{
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(cpustate->IF != 0) // if external interrupts are enabled
|
||||
{
|
||||
cpustate->IF = 0; // reset IF for the next instruction
|
||||
cpustate->delayed_interrupt_enable = 1;
|
||||
}
|
||||
|
||||
cpustate->sreg[SS].selector = POP32(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,SS);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,SS);
|
||||
if(i386_limit_check(cpustate,SS,offset+3) == 0)
|
||||
{
|
||||
cpustate->sreg[SS].selector = POP32(cpustate);
|
||||
if( PROTECTED_MODE ) {
|
||||
i386_load_segment_descriptor(cpustate,SS);
|
||||
} else {
|
||||
i386_load_segment_descriptor(cpustate,SS);
|
||||
}
|
||||
}
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_SREG);
|
||||
}
|
||||
|
||||
@ -1472,28 +1534,39 @@ static void I386OP(pop_rm32)(i386_state *cpustate) // Opcode 0x8f
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
UINT32 value;
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+3) == 0)
|
||||
{
|
||||
value = POP32(cpustate);
|
||||
|
||||
value = POP32(cpustate);
|
||||
|
||||
if( modrm >= 0xc0 ) {
|
||||
STORE_RM32(modrm, value);
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
WRITE32(cpustate,ea, value);
|
||||
if( modrm >= 0xc0 ) {
|
||||
STORE_RM32(modrm, value);
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
WRITE32(cpustate,ea, value);
|
||||
}
|
||||
}
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POP_RM);
|
||||
}
|
||||
|
||||
static void I386OP(popad)(i386_state *cpustate) // Opcode 0x61
|
||||
{
|
||||
REG32(EDI) = POP32(cpustate);
|
||||
REG32(ESI) = POP32(cpustate);
|
||||
REG32(EBP) = POP32(cpustate);
|
||||
REG32(ESP) += 4;
|
||||
REG32(EBX) = POP32(cpustate);
|
||||
REG32(EDX) = POP32(cpustate);
|
||||
REG32(ECX) = POP32(cpustate);
|
||||
REG32(EAX) = POP32(cpustate);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset+31) == 0)
|
||||
{
|
||||
REG32(EDI) = POP32(cpustate);
|
||||
REG32(ESI) = POP32(cpustate);
|
||||
REG32(EBP) = POP32(cpustate);
|
||||
REG32(ESP) += 4;
|
||||
REG32(EBX) = POP32(cpustate);
|
||||
REG32(EDX) = POP32(cpustate);
|
||||
REG32(ECX) = POP32(cpustate);
|
||||
REG32(EAX) = POP32(cpustate);
|
||||
}
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POPA);
|
||||
}
|
||||
|
||||
@ -1503,6 +1576,7 @@ static void I386OP(popfd)(i386_state *cpustate) // Opcode 0x9d
|
||||
UINT32 current = get_flags(cpustate);
|
||||
UINT8 IOPL = (current >> 12) & 0x03;
|
||||
UINT32 mask = 0x00257fd5; // VM, VIP and VIF cannot be set by POPF/POPFD
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
|
||||
// IOPL can only change if CPL is 0
|
||||
if(cpustate->CPL != 0)
|
||||
@ -1522,120 +1596,195 @@ static void I386OP(popfd)(i386_state *cpustate) // Opcode 0x9d
|
||||
mask &= ~0x00003000; // IOPL cannot be changed while in V8086 mode
|
||||
}
|
||||
|
||||
value = POP32(cpustate);
|
||||
value &= ~0x00010000; // RF will always return zero
|
||||
set_flags(cpustate,(current & ~mask) | (value & mask)); // mask out reserved bits
|
||||
if(i386_limit_check(cpustate,SS,offset+3) == 0)
|
||||
{
|
||||
value = POP32(cpustate);
|
||||
value &= ~0x00010000; // RF will always return zero
|
||||
set_flags(cpustate,(current & ~mask) | (value & mask)); // mask out reserved bits
|
||||
}
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_POPF);
|
||||
}
|
||||
|
||||
static void I386OP(push_eax)(i386_state *cpustate) // Opcode 0x50
|
||||
{
|
||||
PUSH32(cpustate, REG32(EAX) );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-4) == 0)
|
||||
PUSH32(cpustate, REG32(EAX) );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(push_ecx)(i386_state *cpustate) // Opcode 0x51
|
||||
{
|
||||
PUSH32(cpustate, REG32(ECX) );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-4) == 0)
|
||||
PUSH32(cpustate, REG32(ECX) );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(push_edx)(i386_state *cpustate) // Opcode 0x52
|
||||
{
|
||||
PUSH32(cpustate, REG32(EDX) );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-4) == 0)
|
||||
PUSH32(cpustate, REG32(EDX) );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(push_ebx)(i386_state *cpustate) // Opcode 0x53
|
||||
{
|
||||
PUSH32(cpustate, REG32(EBX) );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-4) == 0)
|
||||
PUSH32(cpustate, REG32(EBX) );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(push_esp)(i386_state *cpustate) // Opcode 0x54
|
||||
{
|
||||
PUSH32(cpustate, REG32(ESP) );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-4) == 0)
|
||||
PUSH32(cpustate, REG32(ESP) );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(push_ebp)(i386_state *cpustate) // Opcode 0x55
|
||||
{
|
||||
PUSH32(cpustate, REG32(EBP) );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-4) == 0)
|
||||
PUSH32(cpustate, REG32(EBP) );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(push_esi)(i386_state *cpustate) // Opcode 0x56
|
||||
{
|
||||
PUSH32(cpustate, REG32(ESI) );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-4) == 0)
|
||||
PUSH32(cpustate, REG32(ESI) );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(push_edi)(i386_state *cpustate) // Opcode 0x57
|
||||
{
|
||||
PUSH32(cpustate, REG32(EDI) );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-4) == 0)
|
||||
PUSH32(cpustate, REG32(EDI) );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
|
||||
}
|
||||
|
||||
static void I386OP(push_cs32)(i386_state *cpustate) // Opcode 0x0e
|
||||
{
|
||||
PUSH32(cpustate, cpustate->sreg[CS].selector );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-4) == 0)
|
||||
PUSH32(cpustate, cpustate->sreg[CS].selector );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(push_ds32)(i386_state *cpustate) // Opcode 0x1e
|
||||
{
|
||||
PUSH32(cpustate, cpustate->sreg[DS].selector );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-4) == 0)
|
||||
PUSH32(cpustate, cpustate->sreg[DS].selector );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(push_es32)(i386_state *cpustate) // Opcode 0x06
|
||||
{
|
||||
PUSH32(cpustate, cpustate->sreg[ES].selector );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-4) == 0)
|
||||
PUSH32(cpustate, cpustate->sreg[ES].selector );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(push_fs32)(i386_state *cpustate) // Opcode 0x0f a0
|
||||
{
|
||||
PUSH32(cpustate, cpustate->sreg[FS].selector );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-4) == 0)
|
||||
PUSH32(cpustate, cpustate->sreg[FS].selector );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(push_gs32)(i386_state *cpustate) // Opcode 0x0f a8
|
||||
{
|
||||
PUSH32(cpustate, cpustate->sreg[GS].selector );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-4) == 0)
|
||||
PUSH32(cpustate, cpustate->sreg[GS].selector );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(push_ss32)(i386_state *cpustate) // Opcode 0x16
|
||||
{
|
||||
PUSH32(cpustate, cpustate->sreg[SS].selector );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-4) == 0)
|
||||
PUSH32(cpustate, cpustate->sreg[SS].selector );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_SREG);
|
||||
}
|
||||
|
||||
static void I386OP(push_i32)(i386_state *cpustate) // Opcode 0x68
|
||||
{
|
||||
UINT32 value = FETCH32(cpustate);
|
||||
PUSH32(cpustate,value);
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-4) == 0)
|
||||
PUSH32(cpustate,value);
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSH_IMM);
|
||||
}
|
||||
|
||||
static void I386OP(pushad)(i386_state *cpustate) // Opcode 0x60
|
||||
{
|
||||
UINT32 temp = REG32(ESP);
|
||||
PUSH32(cpustate, REG32(EAX) );
|
||||
PUSH32(cpustate, REG32(ECX) );
|
||||
PUSH32(cpustate, REG32(EDX) );
|
||||
PUSH32(cpustate, REG32(EBX) );
|
||||
PUSH32(cpustate, temp );
|
||||
PUSH32(cpustate, REG32(EBP) );
|
||||
PUSH32(cpustate, REG32(ESI) );
|
||||
PUSH32(cpustate, REG32(EDI) );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-32) == 0)
|
||||
{
|
||||
PUSH32(cpustate, REG32(EAX) );
|
||||
PUSH32(cpustate, REG32(ECX) );
|
||||
PUSH32(cpustate, REG32(EDX) );
|
||||
PUSH32(cpustate, REG32(EBX) );
|
||||
PUSH32(cpustate, temp );
|
||||
PUSH32(cpustate, REG32(EBP) );
|
||||
PUSH32(cpustate, REG32(ESI) );
|
||||
PUSH32(cpustate, REG32(EDI) );
|
||||
}
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSHA);
|
||||
}
|
||||
|
||||
static void I386OP(pushfd)(i386_state *cpustate) // Opcode 0x9c
|
||||
{
|
||||
PUSH32(cpustate, get_flags(cpustate) & 0x00fcffff );
|
||||
UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
|
||||
if(i386_limit_check(cpustate,SS,offset-4) == 0)
|
||||
PUSH32(cpustate, get_flags(cpustate) & 0x00fcffff );
|
||||
else
|
||||
FAULT(FAULT_SS,0)
|
||||
CYCLES(cpustate,CYCLES_PUSHF);
|
||||
}
|
||||
|
||||
@ -2021,8 +2170,8 @@ static void I386OP(xchg_r32_rm32)(i386_state *cpustate) // Opcode 0x87
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
UINT32 src = READ32(cpustate,ea);
|
||||
UINT32 dst = LOAD_REG32(modrm);
|
||||
STORE_REG32(modrm, src);
|
||||
WRITE32(cpustate,ea, dst);
|
||||
STORE_REG32(modrm, src);
|
||||
CYCLES(cpustate,CYCLES_XCHG_REG_MEM);
|
||||
}
|
||||
}
|
||||
@ -2526,7 +2675,9 @@ static void I386OP(groupF7_32)(i386_state *cpustate) // Opcode 0xf7
|
||||
REG32(EAX) = (UINT32)result;
|
||||
}
|
||||
} else {
|
||||
/* TODO: Divide by zero */
|
||||
cpustate->ext = 0;
|
||||
i386_trap(cpustate, 0, 0, 0);
|
||||
cpustate->ext = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2554,7 +2705,9 @@ static void I386OP(groupF7_32)(i386_state *cpustate) // Opcode 0xf7
|
||||
REG32(EAX) = (UINT32)result;
|
||||
}
|
||||
} else {
|
||||
/* TODO: Divide by zero */
|
||||
cpustate->ext = 0;
|
||||
i386_trap(cpustate, 0, 0, 0);
|
||||
cpustate->ext = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2753,6 +2906,8 @@ static void I386OP(group0F00_32)(i386_state *cpustate) // Opcode 0x0f 00
|
||||
case 2: /* LLDT */
|
||||
if ( PROTECTED_MODE && !V8086_MODE )
|
||||
{
|
||||
if(cpustate->CPL)
|
||||
FAULT(FAULT_GP,0)
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM32(modrm);
|
||||
cpustate->ldtr.segment = address;
|
||||
@ -2778,6 +2933,8 @@ static void I386OP(group0F00_32)(i386_state *cpustate) // Opcode 0x0f 00
|
||||
case 3: /* LTR */
|
||||
if ( PROTECTED_MODE && !V8086_MODE )
|
||||
{
|
||||
if(cpustate->CPL)
|
||||
FAULT(FAULT_GP,0)
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM32(modrm);
|
||||
cpustate->task.segment = address;
|
||||
@ -2965,6 +3122,8 @@ static void I386OP(group0F01_32)(i386_state *cpustate) // Opcode 0x0f 01
|
||||
}
|
||||
case 2: /* LGDT */
|
||||
{
|
||||
if(PROTECTED_MODE && cpustate->CPL)
|
||||
FAULT(FAULT_GP,0)
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM32(modrm);
|
||||
ea = i386_translate(cpustate, CS, address );
|
||||
@ -2978,6 +3137,8 @@ static void I386OP(group0F01_32)(i386_state *cpustate) // Opcode 0x0f 01
|
||||
}
|
||||
case 3: /* LIDT */
|
||||
{
|
||||
if(PROTECTED_MODE && cpustate->CPL)
|
||||
FAULT(FAULT_GP,0)
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM32(modrm);
|
||||
ea = i386_translate(cpustate, CS, address );
|
||||
|
@ -1701,8 +1701,8 @@ static void I386OP(xchg_r8_rm8)(i386_state *cpustate) // Opcode 0x86
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
UINT8 src = READ8(cpustate,ea);
|
||||
UINT8 dst = LOAD_REG8(modrm);
|
||||
STORE_REG8(modrm, src);
|
||||
WRITE8(cpustate,ea, dst);
|
||||
STORE_REG8(modrm, src);
|
||||
CYCLES(cpustate,CYCLES_XCHG_REG_MEM);
|
||||
}
|
||||
}
|
||||
@ -2071,7 +2071,9 @@ static void I386OP(groupF6_8)(i386_state *cpustate) // Opcode 0xf6
|
||||
cpustate->CF = 1;
|
||||
}
|
||||
} else {
|
||||
/* TODO: Divide by zero */
|
||||
cpustate->ext = 0;
|
||||
i386_trap(cpustate, 0, 0, 0);
|
||||
cpustate->ext = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2103,7 +2105,9 @@ static void I386OP(groupF6_8)(i386_state *cpustate) // Opcode 0xf6
|
||||
cpustate->CF = 1;
|
||||
}
|
||||
} else {
|
||||
/* TODO: Divide by zero */
|
||||
cpustate->ext = 0;
|
||||
i386_trap(cpustate, 0, 0, 0);
|
||||
cpustate->ext = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user