diff --git a/reactos/lib/fast486/common.c b/reactos/lib/fast486/common.c index 03ba743eb09..36c69d457d2 100644 --- a/reactos/lib/fast486/common.c +++ b/reactos/lib/fast486/common.c @@ -67,7 +67,7 @@ Fast486ReadMemory(PFAST486_STATE State, } /* Check for protected mode */ - if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) + if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && !State->Flags.Vm) { /* Privilege checks */ @@ -189,7 +189,7 @@ Fast486WriteMemory(PFAST486_STATE State, } /* Check for protected mode */ - if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) + if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && !State->Flags.Vm) { /* Privilege checks */ @@ -304,6 +304,7 @@ Fast486InterruptInternal(PFAST486_STATE State, { USHORT OldSs = State->SegmentRegs[FAST486_REG_SS].Selector; ULONG OldEsp = State->GeneralRegs[FAST486_REG_ESP].Long; + BOOLEAN OldVm = State->Flags.Vm; if (IdtEntry->Type == FAST486_TASK_GATE_SIGNATURE) { @@ -398,6 +399,12 @@ Fast486InterruptInternal(PFAST486_STATE State, } State->GeneralRegs[FAST486_REG_ESP].Long = NewEsp; + + if (State->Flags.Vm) + { + /* Clear the VM flag */ + State->Flags.Vm = FALSE; + } } /* Load new CS */ @@ -418,27 +425,44 @@ Fast486InterruptInternal(PFAST486_STATE State, State->InstPtr.LowWord = IdtEntry->Offset; } - /* Check if the interrupt handler is more privileged or we're in VM86 mode (again) */ - if ((OldCpl > GET_SEGMENT_RPL(IdtEntry->Selector)) || State->Flags.Vm) + if (OldVm) { - if (State->Flags.Vm) + /* Push GS, FS, DS and ES */ + if (!Fast486StackPushInternal(State, + GateSize, + State->SegmentRegs[FAST486_REG_GS].Selector)) { - /* Clear the VM flag */ - State->Flags.Vm = FALSE; - - /* Push GS, FS, DS and ES */ - if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_GS].Selector)) return FALSE; - if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_FS].Selector)) return FALSE; - if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_DS].Selector)) return FALSE; - if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_ES].Selector)) return FALSE; - - /* Now load them with NULL selectors, since they are useless in protected mode */ - if (!Fast486LoadSegment(State, FAST486_REG_GS, 0)) return FALSE; - if (!Fast486LoadSegment(State, FAST486_REG_FS, 0)) return FALSE; - if (!Fast486LoadSegment(State, FAST486_REG_DS, 0)) return FALSE; - if (!Fast486LoadSegment(State, FAST486_REG_ES, 0)) return FALSE; + return FALSE; + } + if (!Fast486StackPushInternal(State, + GateSize, + State->SegmentRegs[FAST486_REG_FS].Selector)) + { + return FALSE; + } + if (!Fast486StackPushInternal(State, + GateSize, + State->SegmentRegs[FAST486_REG_DS].Selector)) + { + return FALSE; + } + if (!Fast486StackPushInternal(State, + GateSize, + State->SegmentRegs[FAST486_REG_ES].Selector)) + { + return FALSE; } + /* Now load them with NULL selectors, since they are useless in protected mode */ + if (!Fast486LoadSegment(State, FAST486_REG_GS, 0)) return FALSE; + if (!Fast486LoadSegment(State, FAST486_REG_FS, 0)) return FALSE; + if (!Fast486LoadSegment(State, FAST486_REG_DS, 0)) return FALSE; + if (!Fast486LoadSegment(State, FAST486_REG_ES, 0)) return FALSE; + } + + /* Check if the interrupt handler is more privileged or we're in VM86 mode (again) */ + if ((OldCpl > GET_SEGMENT_RPL(IdtEntry->Selector)) || OldVm) + { /* Push SS selector */ if (!Fast486StackPushInternal(State, GateSize, OldSs)) return FALSE; diff --git a/reactos/lib/fast486/common.inl b/reactos/lib/fast486/common.inl index e2527c68021..fed138650f8 100644 --- a/reactos/lib/fast486/common.inl +++ b/reactos/lib/fast486/common.inl @@ -554,8 +554,24 @@ Fast486LoadSegmentInternal(PFAST486_STATE State, CachedDescriptor = &State->SegmentRegs[Segment]; /* Check for protected mode */ - if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && !State->Flags.Vm) + if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) { + /* Check for VM86 mode */ + if (State->Flags.Vm) + { + /* Update the cached descriptor with VM86 values */ + CachedDescriptor->Selector = Selector; + CachedDescriptor->Base = Selector << 4; + CachedDescriptor->Limit = 0xFFFF; + CachedDescriptor->ReadWrite = TRUE; + CachedDescriptor->DirConf = FALSE; + CachedDescriptor->SystemType = TRUE; + CachedDescriptor->Dpl = CachedDescriptor->Rpl = 3; + CachedDescriptor->Present = TRUE; + CachedDescriptor->Size = FALSE; + return TRUE; + } + if (!Fast486ReadDescriptorEntry(State, Selector, &Valid, &GdtEntry)) { /* Exception occurred */ diff --git a/reactos/lib/fast486/opcodes.c b/reactos/lib/fast486/opcodes.c index d9ced5e339a..ed2c8863fa4 100644 --- a/reactos/lib/fast486/opcodes.c +++ b/reactos/lib/fast486/opcodes.c @@ -3727,7 +3727,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodePushByteImm) FAST486_OPCODE_HANDLER(Fast486OpcodeMovByteModrm) { - UCHAR FirstValue, SecondValue, Result; + UCHAR Result; FAST486_MOD_REG_RM ModRegRm; BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; @@ -3743,24 +3743,28 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeMovByteModrm) return; } - if (!Fast486ReadModrmByteOperands(State, - &ModRegRm, - &FirstValue, - &SecondValue)) + if (Opcode & FAST486_OPCODE_WRITE_REG) { - /* Exception occurred */ - return; + if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Result)) + { + /* Exception occurred */ + return; + } + } + else + { + if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Result, NULL)) + { + /* Exception occurred */ + return; + } } - - if (Opcode & FAST486_OPCODE_WRITE_REG) Result = SecondValue; - else Result = FirstValue; /* Write back the result */ Fast486WriteModrmByteOperands(State, &ModRegRm, Opcode & FAST486_OPCODE_WRITE_REG, Result); - } FAST486_OPCODE_HANDLER(Fast486OpcodeMovModrm) @@ -3786,19 +3790,26 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeMovModrm) /* Check the operand size */ if (OperandSize) { - ULONG FirstValue, SecondValue, Result; + ULONG Result; - if (!Fast486ReadModrmDwordOperands(State, - &ModRegRm, - &FirstValue, - &SecondValue)) + + + if (Opcode & FAST486_OPCODE_WRITE_REG) { - /* Exception occurred */ - return; + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Result)) + { + /* Exception occurred */ + return; + } + } + else + { + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Result, NULL)) + { + /* Exception occurred */ + return; + } } - - if (Opcode & FAST486_OPCODE_WRITE_REG) Result = SecondValue; - else Result = FirstValue; /* Write back the result */ Fast486WriteModrmDwordOperands(State, @@ -3808,19 +3819,24 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeMovModrm) } else { - USHORT FirstValue, SecondValue, Result; + USHORT Result; - if (!Fast486ReadModrmWordOperands(State, - &ModRegRm, - &FirstValue, - &SecondValue)) + if (Opcode & FAST486_OPCODE_WRITE_REG) { - /* Exception occurred */ - return; + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Result)) + { + /* Exception occurred */ + return; + } + } + else + { + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Result, NULL)) + { + /* Exception occurred */ + return; + } } - - if (Opcode & FAST486_OPCODE_WRITE_REG) Result = SecondValue; - else Result = FirstValue; /* Write back the result */ Fast486WriteModrmWordOperands(State, @@ -4696,11 +4712,17 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIret) /* Set the new IP */ State->InstPtr.Long = LOWORD(InstPtr); + /* Set the new SP */ + State->GeneralRegs[FAST486_REG_ESP].Long = StackPtr; + /* Set the new flags */ if (Size) State->Flags.Long = NewFlags.Long & REAL_MODE_FLAGS_MASK; else State->Flags.LowWord = NewFlags.LowWord & REAL_MODE_FLAGS_MASK; State->Flags.AlwaysSet = State->Flags.Vm = TRUE; + /* Switch to CPL 3 */ + State->Cpl = 3; + /* Load the new segments */ if (!Fast486LoadSegment(State, FAST486_REG_CS, CodeSel)) return; if (!Fast486LoadSegment(State, FAST486_REG_SS, StackSel)) return;