cpustate->sreg[ES].selector = 0;
cpustate->VM = 0;
//cpustate->eflags = get_flags(cpustate);
- cpustate->eflags &= ~I386_EFLAGS_VM; // Clear VM flag
- set_flags(cpustate, cpustate->eflags);
+ //cpustate->eflags &= ~I386_EFLAGS_VM; // Clear VM flag
+ //set_flags(cpustate, cpustate->eflags);
i386_load_segment_descriptor(cpustate,GS);
i386_load_segment_descriptor(cpustate,FS);
i386_load_segment_descriptor(cpustate,DS);
UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1);
UINT32 stack_size = 6;
CPL = cpustate->CPL;
- UINT32 ea = i386_translate(cpustate, SS, (STACK_32BIT)?REG32(ESP):REG16(SP), 0, (operand32)?12:6);
+ //UINT32 ea = i386_translate(cpustate, SS, (STACK_32BIT)?REG32(ESP):REG16(SP), 0, (operand32)?12:6);
+ UINT32 ea = i386_translate(cpustate, SS, (STACK_32BIT)?REG32(ESP):REG16(SP), 0, 1);
if(operand32 == 0)
{
newEIP = READ16(cpustate, ea) & 0xffff;
}
if(operand32 == 0)
{
- cpustate->sreg[CS].selector = newCS & 0xffff;
- i386_load_segment_descriptor(cpustate,CS);
- if((newEIP & 0xffff) > cpustate->sreg[CS].limit) {
- FAULT(FAULT_GP, 0);
- }
+ //if((newEIP & 0xffff) > cpustate->sreg[CS].limit) {
+ // FAULT(FAULT_GP, 0);
+ //}
cpustate->eip = newEIP & 0xffff;
+ cpustate->sreg[CS].selector = newCS & 0xffff;
+ //i386_load_segment_descriptor(cpustate,CS);
//newflags &= ~(3<<12);
//newflags |= (((oldflags>>12)&3)<<12); // IOPL cannot be changed in V86 mode
newflags &= ~I386_EFLAGS_IOPL; // IOPL cannot be changed in V86 mode
newflags |= (oldflags & I386_EFLAGS_IOPL);
set_flags(cpustate,(newflags & 0xffff) | (oldflags & ~0xffff));
- if(STACK_32BIT) {
- REG32(ESP) += stack_size;
- } else {
- REG16(SP) += stack_size;
- }
+ //if(STACK_32BIT) {
+ //REG32(ESP) += stack_size;
+ //} else {
+ // REG16(SP) += stack_size;
+ REG16(SP) += 6;
+ //}
}
else
{
cpustate->sreg[CS].selector = newCS & 0xffff;
- i386_load_segment_descriptor(cpustate,CS);
- if(newEIP > cpustate->sreg[CS].limit) {
- FAULT(FAULT_GP, 0);
- }
+ //i386_load_segment_descriptor(cpustate,CS);
+ //if(newEIP > cpustate->sreg[CS].limit) {
+ // FAULT(FAULT_GP, 0);
+ //}
cpustate->eip = newEIP;
//newflags &= ~(3<<12);
//newflags |= 0x20000 | (((oldflags>>12)&3)<<12); // IOPL and VM cannot be changed in V86 mode
newflags &= ~I386_EFLAGS_IOPL; // IOPL and VM cannot be changed in V86 mode
newflags |= (oldflags & I386_EFLAGS_IOPL) | I386_EFLAGS_VM;
set_flags(cpustate,newflags);
- if(STACK_32BIT) {
- REG32(ESP) += stack_size;
- } else {
- REG16(SP) += stack_size;
- }
+ //if(STACK_32BIT) {
+ //REG32(ESP) += stack_size;
+ //} else {
+ // REG16(SP) += stack_size;
+ //}
+ REG32(ESP) += 12;
+
}
}
}
if(newCS & 0x04)
{
- if((newCS & ~0x07) >= cpustate->ldtr.limit)
+ if((newCS & ~0x07) >= (cpustate->ldtr.limit & ~0x07))
{
logerror("IRET: Return CS selector (%04x) is past LDT limit.\n",newCS);
FAULT(FAULT_GP,newCS & ~0x03)
}
else
{
- if((newCS & ~0x07) >= cpustate->gdtr.limit)
+ if((newCS & ~0x07) >= (cpustate->gdtr.limit & ~0x07))
{
- logerror("IRET: Return CS selector is past GDT limit.\n");
+ logerror("IRET: Return CS selector is past GDT limit.GDTR:LIMIT=%04X CS=%04X\n",cpustate->gdtr.limit, newCS);
FAULT(FAULT_GP,newCS & ~0x03)
}
}
offset = REG32(ESP) - 2;
else
offset = (REG16(SP) - 2) & 0xffff;
- if(!PROTECTED_MODE || !V8086_MODE || ((cpustate->IOP1) && (cpustate->IOP2))) {
+ //if(!PROTECTED_MODE || !V8086_MODE || ((cpustate->IOP1) && (cpustate->IOP2))) {
if(i386_limit_check(cpustate,SS,offset,2) == 0)
- PUSH16(cpustate, (get_flags(cpustate) & 0xffff) | 0x0002 );
+ PUSH16(cpustate, (get_flags(cpustate) & 0xffff));
else
FAULT(FAULT_SS,0)
- } else {
- FAULT(FAULT_GP, 0)
- }
+ //} else {
+ // FAULT(FAULT_GP, 0)
+ //}
CYCLES(cpustate,CYCLES_PUSHF);
}
}
case 2: /* LGDT */
{
- //printf("LGDT %08x\n", modrm);
if(PROTECTED_MODE && cpustate->CPL) {
logerror("group0F01_16: LGDT() EXCEPTION(PROTECTED_MODE) / CPL set.\n");
FAULT(FAULT_GP,0)
}
cpustate->gdtr.limit = READ16(cpustate,ea);
cpustate->gdtr.base = READ32(cpustate,ea + 2) & 0xffffff;
+ logerror("LGDT(16) PC=%08X MODRM=%02X BASE=%08X LIMIT=%04X\n", cpustate->prev_pc, modrm, cpustate->gdtr.base, cpustate->gdtr.limit);
CYCLES(cpustate,CYCLES_LGDT);
break;
}
if(i386_limit_check(cpustate,SS,offset,4) == 0)
{
value = POP32(cpustate);
- value = value & expect_flags;
+ value = /*value & expect_flags;*/ value & ~0x00010000; // RF will always return zero
set_flags(cpustate,(current & ~mask) | (value & mask)); // mask out reserved bits
}
else
}
cpustate->gdtr.limit = READ16(cpustate,ea);
cpustate->gdtr.base = READ32(cpustate,ea + 2);
+ logerror("LGDT(32) PC=%08X MODRM=%02X BASE=%08X LIMIT=%04X\n", cpustate->prev_pc, modrm, cpustate->gdtr.base, cpustate->gdtr.limit);
CYCLES(cpustate,CYCLES_LGDT);
break;
}
if(cpustate->CPL > IOPL) {
logerror("Privilege error: I386OP(cli) CPL=%d IOPL=%d PC=%08X\n", cpustate->CPL, IOPL, cpustate->pc);
FAULT(FAULT_GP,0);
- return;
+ //return;
}
}
cpustate->IF = 0;
{
UINT32 oldpc = cpustate->pc;
UINT8 modrm = FETCH(cpustate);
- if(modrm < 0xc0) {
- FAULT(FAULT_UD, 0);
- return;
- }
- if((PROTECTED_MODE && ((V8086_MODE) || (cpustate->CPL != 0)))) {
+ //if(modrm < 0xc0) {
+ // FAULT(FAULT_UD, 0);
+ // return;
+ //}
+ if((PROTECTED_MODE && (/*(V8086_MODE) ||*/ (cpustate->CPL != 0)))) {
logerror("Call from non-supervisor privilege: I386OP(mov_r32_cr) at %08X", oldpc);
FAULT(FAULT_GP, 0);
- return;
+ //return;
}
UINT8 cr = (modrm >> 3) & 0x7;
//logdebug("MOV r32 CR%d VAL=(%08X)\n", cr, cpustate->cr[cr], oldpc);
- if(cr < 5) {
- if(cr == 1) {
- FAULT(FAULT_UD, 0);
- return;
- }
+// if(cr < 5) {
+// if(cr == 1) {
+// FAULT(FAULT_UD, 0);
+// return;
+// }
STORE_RM32(modrm, cpustate->cr[cr]);
CYCLES(cpustate,CYCLES_MOV_CR_REG);
- } else {
- logerror("Index error");
- }
+// } else {
+// logerror("Index error");
+// }
}
if(cpustate->CPL > IOPL) {
logerror("Privilege error: I386OP(sti) CPL=%d IOPL=%d\n", cpustate->CPL, IOPL);
FAULT(FAULT_GP,0);
- return;
+ //return;
}
}
cpustate->delayed_interrupt_enable = 1; // IF is set after the next instruction.
INLINE int i386_limit_check(i386_state *cpustate, int seg, UINT32 offset, UINT32 size)
{
+// size = 1; // TBD
if(PROTECTED_MODE && !V8086_MODE)
{
if((cpustate->sreg[seg].flags & 0x0018) == 0x0010 && cpustate->sreg[seg].flags & 0x0004) // if expand-down data segment
{
// compare if greater then 0xffffffff when we're passed the access size
- if(((offset + size - 1) <= cpustate->sreg[seg].limit) || ((cpustate->sreg[seg].d)?0:((offset + size - 1) > 0xffff)))
+ if(offset < size) size = offset;
+ if(((offset - size) <= cpustate->sreg[seg].limit) || ((cpustate->sreg[seg].d)?0:((offset + size - 1) > 0xffff)))
{
logerror("Limit check at 0x%08x failed. Segment %04x, limit %08x, offset %08x (expand-down)\n",cpustate->pc,cpustate->sreg[seg].selector,cpustate->sreg[seg].limit,offset);
return 1;