Author: aandrejevic
Date: Mon Sep 23 14:10:14 2013
New Revision: 60341
URL:
http://svn.reactos.org/svn/reactos?rev=60341&view=rev
Log:
[SOFT386]
Implement the POPF instruction.
Modified:
branches/ntvdm/include/reactos/libs/soft386/soft386.h
branches/ntvdm/lib/soft386/opcodes.c
Modified: branches/ntvdm/include/reactos/libs/soft386/soft386.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/include/reactos/libs/soft…
==============================================================================
--- branches/ntvdm/include/reactos/libs/soft386/soft386.h [iso-8859-1] (original)
+++ branches/ntvdm/include/reactos/libs/soft386/soft386.h [iso-8859-1] Mon Sep 23 14:10:14
2013
@@ -227,7 +227,9 @@
typedef union _SOFT386_FLAGS_REG
{
+ USHORT LowWord;
ULONG Long;
+
struct
{
ULONG Cf : 1;
Modified: branches/ntvdm/lib/soft386/opcodes.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/soft386/opcodes.c?rev…
==============================================================================
--- branches/ntvdm/lib/soft386/opcodes.c [iso-8859-1] (original)
+++ branches/ntvdm/lib/soft386/opcodes.c [iso-8859-1] Mon Sep 23 14:10:14 2013
@@ -4162,10 +4162,135 @@
SOFT386_OPCODE_HANDLER(Soft386OpcodePopFlags)
{
- // TODO: NOT IMPLEMENTED
- UNIMPLEMENTED;
-
- return FALSE;
+ BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
+ INT Cpl = Soft386GetCurrentPrivLevel(State);
+ ULONG NewFlags;
+
+ if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
+ {
+ /* Invalid prefix */
+ Soft386Exception(State, SOFT386_EXCEPTION_UD);
+ return FALSE;
+ }
+
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
+ {
+ /* This OPSIZE prefix toggles the size */
+ Size = !Size;
+ }
+
+ /* Pop the new flags */
+ if (!Soft386StackPop(State, &NewFlags))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ if (!State->Flags.Vm)
+ {
+ /* Check the current privilege level */
+ if (Cpl == 0)
+ {
+ /* Supervisor */
+
+ /* Set the flags */
+ if (Size)
+ {
+ /* Memorize the old state of RF */
+ BOOLEAN OldRf = State->Flags.Rf;
+
+ State->Flags.Long = NewFlags;
+
+ /* Restore VM and RF */
+ State->Flags.Vm = FALSE;
+ State->Flags.Rf = OldRf;
+
+ /* Clear VIF and VIP */
+ State->Flags.Vif = State->Flags.Vip = FALSE;
+ }
+ else State->Flags.LowWord = LOWORD(NewFlags);
+
+ /* Restore the reserved bits */
+ State->Flags.AlwaysSet = TRUE;
+ State->Flags.Reserved0 = FALSE;
+ State->Flags.Reserved1 = FALSE;
+ }
+ else
+ {
+ /* User */
+
+ /* Memorize the old state of IF and IOPL */
+ BOOLEAN OldIf = State->Flags.If;
+ UINT OldIopl = State->Flags.Iopl;
+
+ /* Set the flags */
+ if (Size)
+ {
+ /* Memorize the old state of RF */
+ BOOLEAN OldRf = State->Flags.Rf;
+
+ State->Flags.Long = NewFlags;
+
+ /* Restore VM and RF */
+ State->Flags.Vm = FALSE;
+ State->Flags.Rf = OldRf;
+
+ /* Clear VIF and VIP */
+ State->Flags.Vif = State->Flags.Vip = FALSE;
+ }
+ else State->Flags.LowWord = LOWORD(NewFlags);
+
+ /* Restore the reserved bits and IOPL */
+ State->Flags.AlwaysSet = TRUE;
+ State->Flags.Reserved0 = FALSE;
+ State->Flags.Reserved1 = FALSE;
+ State->Flags.Iopl = OldIopl;
+
+ /* Check if the user doesn't have the privilege to change IF */
+ if (Cpl > State->Flags.Iopl)
+ {
+ /* Restore IF */
+ State->Flags.If = OldIf;
+ }
+ }
+ }
+ else
+ {
+ /* Check the IOPL */
+ if (State->Flags.Iopl == 3)
+ {
+ if (Size)
+ {
+ /* Memorize the old state of RF, VIF and VIP */
+ BOOLEAN OldRf = State->Flags.Rf;
+ BOOLEAN OldVif = State->Flags.Vif;
+ BOOLEAN OldVip = State->Flags.Vip;
+
+ State->Flags.Long = NewFlags;
+
+ /* Restore VM, RF, VIF and VIP */
+ State->Flags.Vm = TRUE;
+ State->Flags.Rf = OldRf;
+ State->Flags.Vif = OldVif;
+ State->Flags.Vip = OldVip;
+ }
+ else State->Flags.LowWord = LOWORD(NewFlags);
+
+ /* Restore the reserved bits and IOPL */
+ State->Flags.AlwaysSet = TRUE;
+ State->Flags.Reserved0 = FALSE;
+ State->Flags.Reserved1 = FALSE;
+ State->Flags.Iopl = 3;
+ }
+ else
+ {
+ /* Call the VM86 monitor */
+ Soft386ExceptionWithErrorCode(State, SOFT386_EXCEPTION_GP, 0);
+ }
+
+ }
+
+ return TRUE;
}
SOFT386_OPCODE_HANDLER(Soft386OpcodeSahf)