i386: Further fixes from MESS, including Carl's JCXZ fix.

This commit is contained in:
mahlemiut 2012-01-21 09:12:25 +00:00
parent 4ec18df667
commit ab7b9c2cd1
3 changed files with 71 additions and 55 deletions

View File

@ -441,7 +441,7 @@ static void i386_protected_mode_sreg_load(i386_state *cpustate, UINT16 selector,
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); logerror("SReg Load (%08x): Selector is out of LDT bounds.\n",cpustate->pc);
FAULT(FAULT_GP,selector) FAULT(FAULT_GP,selector & ~0x03)
} }
} }
else // GDT else // GDT
@ -449,28 +449,28 @@ static void i386_protected_mode_sreg_load(i386_state *cpustate, UINT16 selector,
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); logerror("SReg Load (%08x): Selector is out of GDT bounds.\n",cpustate->pc);
FAULT(FAULT_GP,selector) FAULT(FAULT_GP,selector & ~0x03)
} }
} }
if (RPL != CPL) if (RPL != CPL)
{ {
logerror("SReg Load (%08x): Selector RPL does not equal CPL.\n",cpustate->pc); logerror("SReg Load (%08x): Selector RPL does not equal CPL.\n",cpustate->pc);
FAULT(FAULT_GP,selector) FAULT(FAULT_GP,selector & ~0x03)
} }
if(((stack.flags & 0x0018) != 0x10) && (stack.flags & 0x0002) != 0) if(((stack.flags & 0x0018) != 0x10) && (stack.flags & 0x0002) != 0)
{ {
logerror("SReg Load (%08x): Segment is not a writable data segment.\n",cpustate->pc); logerror("SReg Load (%08x): Segment is not a writable data segment.\n",cpustate->pc);
FAULT(FAULT_GP,selector) FAULT(FAULT_GP,selector & ~0x03)
} }
if(DPL != CPL) if(DPL != CPL)
{ {
logerror("SReg Load (%08x): Segment DPL does not equal CPL.\n",cpustate->pc); logerror("SReg Load (%08x): Segment DPL does not equal CPL.\n",cpustate->pc);
FAULT(FAULT_GP,selector) FAULT(FAULT_GP,selector & ~0x03)
} }
if(!(stack.flags & 0x0080)) if(!(stack.flags & 0x0080))
{ {
logerror("SReg Load (%08x): Segment is not present.\n",cpustate->pc); logerror("SReg Load (%08x): Segment is not present.\n",cpustate->pc);
FAULT(FAULT_SS,selector) FAULT(FAULT_SS,selector & ~0x03)
} }
} }
if(reg == DS || reg == ES || reg == FS || reg == GS) if(reg == DS || reg == ES || reg == FS || reg == GS)
@ -495,7 +495,7 @@ static void i386_protected_mode_sreg_load(i386_state *cpustate, UINT16 selector,
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); logerror("SReg Load (%08x): Selector is out of LDT bounds.\n",cpustate->pc);
FAULT(FAULT_GP,selector) FAULT(FAULT_GP,selector & ~0x03)
} }
} }
else // GDT else // GDT
@ -503,7 +503,7 @@ static void i386_protected_mode_sreg_load(i386_state *cpustate, UINT16 selector,
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); logerror("SReg Load (%08x): Selector is out of GDT bounds.\n",cpustate->pc);
FAULT(FAULT_GP,selector) FAULT(FAULT_GP,selector & ~0x03)
} }
} }
if((desc.flags & 0x0018) != 0x10) if((desc.flags & 0x0018) != 0x10)
@ -511,7 +511,7 @@ static void i386_protected_mode_sreg_load(i386_state *cpustate, UINT16 selector,
if(((desc.flags & 0x0002) != 0) && ((desc.flags & 0x0018) != 0x18)) if(((desc.flags & 0x0002) != 0) && ((desc.flags & 0x0018) != 0x18))
{ {
logerror("SReg Load (%08x): Segment is not a data segment or readable code segment.\n",cpustate->pc); logerror("SReg Load (%08x): Segment is not a data segment or readable code segment.\n",cpustate->pc);
FAULT(FAULT_GP,selector) 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)))
@ -520,13 +520,13 @@ static void i386_protected_mode_sreg_load(i386_state *cpustate, UINT16 selector,
if((RPL > DPL) || (CPL > DPL)) if((RPL > DPL) || (CPL > DPL))
{ {
logerror("SReg Load (%08x): Selector RPL or CPL is not less or equal to segment DPL.\n",cpustate->pc); logerror("SReg Load (%08x): Selector RPL or CPL is not less or equal to segment DPL.\n",cpustate->pc);
FAULT(FAULT_GP,selector) FAULT(FAULT_GP,selector & ~0x03)
} }
} }
if(!(desc.flags & 0x0080)) if(!(desc.flags & 0x0080))
{ {
logerror("SReg Load (%08x): Segment is not present.\n",cpustate->pc); logerror("SReg Load (%08x): Segment is not present.\n",cpustate->pc);
FAULT(FAULT_NP,selector) FAULT(FAULT_NP,selector & ~0x03)
} }
} }
@ -1484,7 +1484,7 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of
if((selector & ~0x07) > cpustate->ldtr.limit) if((selector & ~0x07) > cpustate->ldtr.limit)
{ {
logerror("CALL: Selector is past LDT limit.\n"); logerror("CALL: Selector is past LDT limit.\n");
FAULT(FAULT_GP,selector & ~0x07) // #GP(selector) FAULT(FAULT_GP,selector & ~0x03) // #GP(selector)
} }
} }
else else
@ -1492,7 +1492,7 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of
if((selector & ~0x07) > cpustate->gdtr.limit) if((selector & ~0x07) > cpustate->gdtr.limit)
{ {
logerror("CALL: Selector is past GDT limit.\n"); logerror("CALL: Selector is past GDT limit.\n");
FAULT(FAULT_GP,selector & ~0x07) // #GP(selector) FAULT(FAULT_GP,selector & ~0x03) // #GP(selector)
} }
} }
@ -1511,7 +1511,7 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of
if(DPL > CPL) if(DPL > CPL)
{ {
logerror("CALL: Code segment DPL %i is greater than CPL %i\n",DPL,CPL); logerror("CALL: Code segment DPL %i is greater than CPL %i\n",DPL,CPL);
FAULT(FAULT_GP,selector & ~0x07) // #GP(selector) FAULT(FAULT_GP,selector & ~0x03) // #GP(selector)
} }
} }
else else
@ -1520,19 +1520,19 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of
if(RPL > CPL) if(RPL > CPL)
{ {
logerror("CALL: RPL %i is greater than CPL %i\n",RPL,CPL); logerror("CALL: RPL %i is greater than CPL %i\n",RPL,CPL);
FAULT(FAULT_GP,selector & ~0x07) // #GP(selector) FAULT(FAULT_GP,selector & ~0x03) // #GP(selector)
} }
if(DPL != CPL) if(DPL != CPL)
{ {
logerror("CALL: Code segment DPL %i is not equal to CPL %i\n",DPL,CPL); logerror("CALL: Code segment DPL %i is not equal to CPL %i\n",DPL,CPL);
FAULT(FAULT_GP,selector & ~0x07) // #GP(selector) FAULT(FAULT_GP,selector & ~0x03) // #GP(selector)
} }
SetRPL = 1; SetRPL = 1;
} }
if((desc.flags & 0x0080) == 0) if((desc.flags & 0x0080) == 0)
{ {
logerror("CALL (%08x): Code segment is not present.\n",cpustate->pc); logerror("CALL (%08x): Code segment is not present.\n",cpustate->pc);
FAULT(FAULT_NP,selector & ~0x07) // #NP(selector) FAULT(FAULT_NP,selector & ~0x03) // #NP(selector)
} }
if (operand32 != 0) // if 32-bit if (operand32 != 0) // if 32-bit
{ {
@ -1562,7 +1562,7 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of
if(desc.flags & 0x0010) if(desc.flags & 0x0010)
{ {
logerror("CALL: Segment is a data segment.\n"); logerror("CALL: Segment is a data segment.\n");
FAULT(FAULT_GP,desc.selector & ~0x07) // #GP(selector) FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector)
} }
else else
{ {
@ -1574,22 +1574,22 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of
if(DPL < CPL) if(DPL < CPL)
{ {
logerror("CALL: TSS: DPL is less than CPL.\n"); logerror("CALL: TSS: DPL is less than CPL.\n");
FAULT(FAULT_TS,selector & ~0x07) // #TS(selector) FAULT(FAULT_TS,selector & ~0x03) // #TS(selector)
} }
if(DPL < RPL) if(DPL < RPL)
{ {
logerror("CALL: TSS: DPL is less than RPL.\n"); logerror("CALL: TSS: DPL is less than RPL.\n");
FAULT(FAULT_TS,selector & ~0x07) // #TS(selector) FAULT(FAULT_TS,selector & ~0x03) // #TS(selector)
} }
if(desc.flags & 0x0002) if(desc.flags & 0x0002)
{ {
logerror("CALL: TSS: TSS is busy.\n"); logerror("CALL: TSS: TSS is busy.\n");
FAULT(FAULT_TS,selector & ~0x07) // #TS(selector) FAULT(FAULT_TS,selector & ~0x03) // #TS(selector)
} }
if(desc.flags & 0x0080) if(desc.flags & 0x0080)
{ {
logerror("CALL: TSS: Segment is not present.\n"); logerror("CALL: TSS: Segment is not present.\n");
FAULT(FAULT_NP,selector & ~0x07) // #NP(selector) FAULT(FAULT_NP,selector & ~0x03) // #NP(selector)
} }
if(desc.flags & 0x08) if(desc.flags & 0x08)
i386_task_switch(cpustate,desc.selector,1); i386_task_switch(cpustate,desc.selector,1);
@ -1611,17 +1611,17 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of
if(DPL < CPL) if(DPL < CPL)
{ {
logerror("CALL: Call gate DPL %i is less than CPL %i.\n",DPL,CPL); logerror("CALL: Call gate DPL %i is less than CPL %i.\n",DPL,CPL);
FAULT(FAULT_GP,desc.selector & ~0x07) // #GP(selector) FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector)
} }
if(DPL < RPL) if(DPL < RPL)
{ {
logerror("CALL: Call gate DPL %i is less than RPL %i.\n",DPL,RPL); logerror("CALL: Call gate DPL %i is less than RPL %i.\n",DPL,RPL);
FAULT(FAULT_GP,desc.selector & ~0x07) // #GP(selector) FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector)
} }
if(gate.present == 0) if(gate.present == 0)
{ {
logerror("CALL: Call gate is not present.\n"); logerror("CALL: Call gate is not present.\n");
FAULT(FAULT_NP,desc.selector & ~0x07) // #GP(selector) FAULT(FAULT_NP,desc.selector & ~0x03) // #GP(selector)
} }
desc.selector = gate.selector; desc.selector = gate.selector;
if((gate.selector & ~0x07) == 0) if((gate.selector & ~0x07) == 0)
@ -1634,7 +1634,7 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of
if((desc.selector & ~0x07) > cpustate->ldtr.limit) if((desc.selector & ~0x07) > cpustate->ldtr.limit)
{ {
logerror("CALL: Call gate: Segment is past LDT limit\n"); logerror("CALL: Call gate: Segment is past LDT limit\n");
FAULT(FAULT_GP,desc.selector & ~0x07) // #GP(selector) FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector)
} }
} }
else else
@ -1642,20 +1642,20 @@ static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 of
if((desc.selector & ~0x07) > cpustate->gdtr.limit) if((desc.selector & ~0x07) > cpustate->gdtr.limit)
{ {
logerror("CALL: Call gate: Segment is past GDT limit\n"); logerror("CALL: Call gate: Segment is past GDT limit\n");
FAULT(FAULT_GP,desc.selector & ~0x07) // #GP(selector) FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector)
} }
} }
i386_load_protected_mode_segment(cpustate,&desc); i386_load_protected_mode_segment(cpustate,&desc);
if((desc.flags & 0x0018) != 0x18) if((desc.flags & 0x0018) != 0x18)
{ {
logerror("CALL: Call gate: Segment is not a code segment.\n"); logerror("CALL: Call gate: Segment is not a code segment.\n");
FAULT(FAULT_GP,desc.selector & ~0x07) // #GP(selector) FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector)
} }
DPL = ((desc.flags >> 5) & 0x03); DPL = ((desc.flags >> 5) & 0x03);
if(DPL > CPL) if(DPL > CPL)
{ {
logerror("CALL: Call gate: Segment DPL %i is greater than CPL %i.\n",DPL,CPL); logerror("CALL: Call gate: Segment DPL %i is greater than CPL %i.\n",DPL,CPL);
FAULT(FAULT_GP,desc.selector & ~0x07) // #GP(selector) FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector)
} }
if(DPL < CPL && (desc.flags & 0x0004) == 0) if(DPL < CPL && (desc.flags & 0x0004) == 0)
{ {
@ -1936,7 +1936,7 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op
if(RPL < CPL) if(RPL < CPL)
{ {
logerror("RETF (%08x): Return segment RPL is less than CPL.\n",cpustate->pc); logerror("RETF (%08x): Return segment RPL is less than CPL.\n",cpustate->pc);
FAULT(FAULT_GP,newCS & ~0x07) FAULT(FAULT_GP,newCS & ~0x03)
} }
if(RPL == CPL) if(RPL == CPL)
@ -1952,7 +1952,7 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op
if((newCS & ~0x07) > cpustate->ldtr.limit) if((newCS & ~0x07) > cpustate->ldtr.limit)
{ {
logerror("RETF: Return segment is past LDT limit.\n"); logerror("RETF: Return segment is past LDT limit.\n");
FAULT(FAULT_GP,newCS & ~0x07) FAULT(FAULT_GP,newCS & ~0x03)
} }
} }
else else
@ -1960,20 +1960,20 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op
if((newCS & ~0x07) > cpustate->gdtr.limit) if((newCS & ~0x07) > cpustate->gdtr.limit)
{ {
logerror("RETF: Return segment is past GDT limit.\n"); logerror("RETF: Return segment is past GDT limit.\n");
FAULT(FAULT_GP,newCS & ~0x07) FAULT(FAULT_GP,newCS & ~0x03)
} }
} }
if((desc.flags & 0x0018) != 0x0018) if((desc.flags & 0x0018) != 0x0018)
{ {
logerror("RETF: Return segment is not a code segment.\n"); logerror("RETF: Return segment is not a code segment.\n");
FAULT(FAULT_GP,newCS & ~0x07) FAULT(FAULT_GP,newCS & ~0x03)
} }
if(desc.flags & 0x0004) if(desc.flags & 0x0004)
{ {
if(DPL > CPL) if(DPL > CPL)
{ {
logerror("RETF: Conforming code segment DPL is greater than CPL.\n"); logerror("RETF: Conforming code segment DPL is greater than CPL.\n");
FAULT(FAULT_GP,newCS & ~0x07) FAULT(FAULT_GP,newCS & ~0x03)
} }
} }
else else
@ -1981,13 +1981,13 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op
if(DPL != CPL) if(DPL != CPL)
{ {
logerror("RETF: Non-conforming code segment DPL does not equal CPL.\n"); logerror("RETF: Non-conforming code segment DPL does not equal CPL.\n");
FAULT(FAULT_GP,newCS & ~0x07) FAULT(FAULT_GP,newCS & ~0x03)
} }
} }
if((desc.flags & 0x0080) == 0) if((desc.flags & 0x0080) == 0)
{ {
logerror("RETF: Code segment is not present.\n"); logerror("RETF (%08x): Code segment is not present.\n",cpustate->pc);
FAULT(FAULT_NP,newCS & ~0x07) FAULT(FAULT_NP,newCS & ~0x03)
} }
if(newEIP > desc.limit) if(newEIP > desc.limit)
{ {
@ -1996,7 +1996,7 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op
} }
if(operand32 == 0) if(operand32 == 0)
{ {
if(REG16(SP) > (cpustate->sreg[SS].limit & 0xffff)) if(REG16(SP) > (cpustate->sreg[SS].limit & 0xffff)+1)
{ {
logerror("RETF (%08x): SP is past stack segment limit.\n",cpustate->pc); logerror("RETF (%08x): SP is past stack segment limit.\n",cpustate->pc);
FAULT(FAULT_SS,0) FAULT(FAULT_SS,0)
@ -2004,7 +2004,7 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op
} }
else else
{ {
if(REG32(ESP) > cpustate->sreg[SS].limit) if(REG32(ESP) > cpustate->sreg[SS].limit+1)
{ {
logerror("RETF: ESP is past stack segment limit.\n"); logerror("RETF: ESP is past stack segment limit.\n");
FAULT(FAULT_SS,0) FAULT(FAULT_SS,0)
@ -2020,7 +2020,7 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op
/* outer privilege level */ /* outer privilege level */
if(operand32 == 0) if(operand32 == 0)
{ {
if(REG16(SP)+8+count > cpustate->sreg[SS].limit) if(REG16(SP)+8+count > cpustate->sreg[SS].limit+1)
{ {
logerror("RETF (%08x): SP is past stack segment limit.\n",cpustate->pc); logerror("RETF (%08x): SP is past stack segment limit.\n",cpustate->pc);
FAULT(FAULT_SS,0) FAULT(FAULT_SS,0)
@ -2028,7 +2028,7 @@ static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 op
} }
else else
{ {
if(REG32(ESP)+16+count > cpustate->sreg[SS].limit) if(REG32(ESP)+16+count > cpustate->sreg[SS].limit+1)
{ {
logerror("RETF: ESP is past stack segment limit.\n"); logerror("RETF: ESP is past stack segment limit.\n");
FAULT(FAULT_SS,0) FAULT(FAULT_SS,0)
@ -2408,7 +2408,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
{ {
if(operand32 == 0) if(operand32 == 0)
{ {
if(REG16(SP)+4 > cpustate->sreg[SS].limit) if(REG16(SP)+4 > cpustate->sreg[SS].limit+1)
{ {
logerror("IRET: Data on stack is past SS limit.\n"); logerror("IRET: Data on stack is past SS limit.\n");
FAULT(FAULT_SS,0) FAULT(FAULT_SS,0)
@ -2416,7 +2416,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
} }
else else
{ {
if(REG32(ESP)+6 > cpustate->sreg[SS].limit) if(REG32(ESP)+6 > cpustate->sreg[SS].limit+1)
{ {
logerror("IRET: Data on stack is past SS limit.\n"); logerror("IRET: Data on stack is past SS limit.\n");
FAULT(FAULT_SS,0) FAULT(FAULT_SS,0)
@ -2433,17 +2433,17 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
/* return to same privilege level */ /* return to same privilege level */
if(operand32 == 0) if(operand32 == 0)
{ {
if(REG16(SP)+6 > cpustate->sreg[SS].limit) if(REG16(SP)+6 > cpustate->sreg[SS].limit+1)
{ {
logerror("IRET: Data on stack is past SS limit.\n"); logerror("IRET (%08x): Data on stack is past SS limit.\n",cpustate->pc);
FAULT(FAULT_SS,0) FAULT(FAULT_SS,0)
} }
} }
else else
{ {
if(REG32(ESP)+12 > cpustate->sreg[SS].limit) if(REG32(ESP)+12 > cpustate->sreg[SS].limit+1)
{ {
logerror("IRET: Data on stack is past SS limit.\n"); logerror("IRET (%08x): Data on stack is past SS limit.\n",cpustate->pc);
FAULT(FAULT_SS,0) FAULT(FAULT_SS,0)
} }
} }
@ -2533,14 +2533,14 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
i386_load_protected_mode_segment(cpustate,&stack); i386_load_protected_mode_segment(cpustate,&stack);
if(operand32 == 0) if(operand32 == 0)
{ {
if(REG16(SP)+10 > cpustate->sreg[SS].limit) if(REG16(SP)+10 > cpustate->sreg[SS].limit+1)
{ {
logerror("IRET: SP is past SS limit.\n"); logerror("IRET: SP is past SS limit.\n");
FAULT(FAULT_SS,0) } FAULT(FAULT_SS,0) }
} }
else else
{ {
if(REG32(ESP)+20 > cpustate->sreg[SS].limit) if(REG32(ESP)+20 > cpustate->sreg[SS].limit+1)
{ {
logerror("IRET: ESP is past SS limit.\n"); logerror("IRET: ESP is past SS limit.\n");
FAULT(FAULT_SS,0) FAULT(FAULT_SS,0)

View File

@ -1072,7 +1072,8 @@ static void I386OP(jz_rel16)(i386_state *cpustate) // Opcode 0x0f 84
static void I386OP(jcxz16)(i386_state *cpustate) // Opcode 0xe3 static void I386OP(jcxz16)(i386_state *cpustate) // Opcode 0xe3
{ {
INT8 disp = FETCH(cpustate); INT8 disp = FETCH(cpustate);
if( REG16(CX) == 0 ) { int val = (cpustate->address_size)?(REG32(ECX) == 0):(REG16(CX) == 0);
if( val ) {
if (cpustate->sreg[CS].d) if (cpustate->sreg[CS].d)
{ {
cpustate->eip += disp; cpustate->eip += disp;
@ -3472,14 +3473,21 @@ static void I386OP(xlat16)(i386_state *cpustate) // Opcode 0xd7
static void I386OP(load_far_pointer16)(i386_state *cpustate, int s) static void I386OP(load_far_pointer16)(i386_state *cpustate, int s)
{ {
UINT8 modrm = FETCH(cpustate); UINT8 modrm = FETCH(cpustate);
UINT16 selector;
if( modrm >= 0xc0 ) { if( modrm >= 0xc0 ) {
fatalerror("i386: load_far_pointer16 NYI"); fatalerror("i386: load_far_pointer16 NYI");
} else { } else {
UINT32 ea = GetEA(cpustate,modrm); UINT32 ea = GetEA(cpustate,modrm);
STORE_REG16(modrm, READ16(cpustate,ea + 0)); STORE_REG16(modrm, READ16(cpustate,ea + 0));
cpustate->sreg[s].selector = READ16(cpustate,ea + 2); selector = READ16(cpustate,ea + 2);
i386_load_segment_descriptor(cpustate, s ); if(PROTECTED_MODE && !(V8086_MODE))
i386_protected_mode_sreg_load(cpustate,selector,s);
else
{
cpustate->sreg[s].selector = selector;
i386_load_segment_descriptor(cpustate, s );
}
} }
} }

View File

@ -952,7 +952,8 @@ static void I386OP(jz_rel32)(i386_state *cpustate) // Opcode 0x0f 84
static void I386OP(jcxz32)(i386_state *cpustate) // Opcode 0xe3 static void I386OP(jcxz32)(i386_state *cpustate) // Opcode 0xe3
{ {
INT8 disp = FETCH(cpustate); INT8 disp = FETCH(cpustate);
if( REG32(ECX) == 0 ) { int val = (cpustate->address_size)?(REG32(ECX) == 0):(REG16(CX) == 0);
if( val ) {
cpustate->eip += disp; cpustate->eip += disp;
CHANGE_PC(cpustate,cpustate->eip); CHANGE_PC(cpustate,cpustate->eip);
CYCLES(cpustate,CYCLES_JCXZ); /* TODO: Timing = 9 + m */ CYCLES(cpustate,CYCLES_JCXZ); /* TODO: Timing = 9 + m */
@ -3289,14 +3290,21 @@ static void I386OP(xlat32)(i386_state *cpustate) // Opcode 0xd7
static void I386OP(load_far_pointer32)(i386_state *cpustate, int s) static void I386OP(load_far_pointer32)(i386_state *cpustate, int s)
{ {
UINT8 modrm = FETCH(cpustate); UINT8 modrm = FETCH(cpustate);
UINT16 selector;
if( modrm >= 0xc0 ) { if( modrm >= 0xc0 ) {
fatalerror("i386: load_far_pointer32 NYI"); fatalerror("i386: load_far_pointer32 NYI");
} else { } else {
UINT32 ea = GetEA(cpustate,modrm); UINT32 ea = GetEA(cpustate,modrm);
STORE_REG32(modrm, READ32(cpustate,ea + 0)); STORE_REG32(modrm, READ32(cpustate,ea + 0));
cpustate->sreg[s].selector = READ16(cpustate,ea + 4); selector = READ16(cpustate,ea + 4);
i386_load_segment_descriptor(cpustate, s ); if(PROTECTED_MODE && !(V8086_MODE))
i386_protected_mode_sreg_load(cpustate,selector,s);
else
{
cpustate->sreg[s].selector = selector;
i386_load_segment_descriptor(cpustate, s );
}
} }
} }