[FAST486][NTVDM]
authorAleksandar Andrejevic <aandrejevic@reactos.org>
Tue, 27 May 2014 21:10:45 +0000 (21:10 +0000)
committerAleksandar Andrejevic <aandrejevic@reactos.org>
Tue, 27 May 2014 21:10:45 +0000 (21:10 +0000)
Several fixes in fast486 and ntvdm:
DosCopyEnvironmentBlock - prepend the program name tag (0x0001) to the program name.
Fast486OpcodePushByteImm, Fast486OpcodePushImm - sign-extend instead of zero-extending.
Fast486InterruptInternal - The parameter is supposed to be the type of the gate, not a boolean.
GET_SEGMENT_RPL will not work on real-mode selectors, use a special field for the RPL.
Loading a data segment with the NULL selector should never generate an exception.
Mask out the highest-order byte of the physical address when loading a descriptor table in 16-bit mode.
Fast486InterruptInternal - The interrupt gate type determines the size.
CORE-8257 #resolve #comment Fixed in revision r63482.

svn path=/trunk/; revision=63482

reactos/include/reactos/libs/fast486/fast486.h
reactos/lib/fast486/common.c
reactos/lib/fast486/common.h
reactos/lib/fast486/common.inl
reactos/lib/fast486/opcodes.c
reactos/lib/fast486/opgroups.c
reactos/subsystems/ntvdm/dos/dos32krnl/dos.c
reactos/subsystems/ntvdm/dos/dos32krnl/dos.h

index 5fa7291..434f06c 100644 (file)
@@ -251,6 +251,7 @@ typedef struct _FAST486_SEG_REG
     ULONG DirConf       : 1;
     ULONG Executable    : 1;
     ULONG SystemType    : 1;
+    ULONG Rpl           : 2;
     ULONG Dpl           : 2;
     ULONG Present       : 1;
     ULONG Size          : 1;
index 36f026e..4babb2d 100644 (file)
@@ -65,7 +65,7 @@ Fast486ReadMemory(PFAST486_STATE State,
             return FALSE;
         }
 
-        if ((!InstFetch && (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl))
+        if ((!InstFetch && (CachedDescriptor->Rpl > CachedDescriptor->Dpl))
             || (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl))
         {
             Fast486Exception(State, FAST486_EXCEPTION_GP);
@@ -132,7 +132,7 @@ Fast486WriteMemory(PFAST486_STATE State,
             return FALSE;
         }
 
-        if ((GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
+        if ((CachedDescriptor->Rpl > CachedDescriptor->Dpl)
             || (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl))
         {
             Fast486Exception(State, FAST486_EXCEPTION_GP);
@@ -164,14 +164,26 @@ BOOLEAN
 Fast486InterruptInternal(PFAST486_STATE State,
                          USHORT SegmentSelector,
                          ULONG Offset,
-                         BOOLEAN InterruptGate)
+                         ULONG GateType)
 {
+    BOOLEAN GateSize = (GateType == FAST486_IDT_INT_GATE_32)
+                       || (GateType == FAST486_IDT_TRAP_GATE_32);
+
     /* Check for protected mode */
     if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
     {
         FAST486_TSS Tss;
         USHORT OldSs = State->SegmentRegs[FAST486_REG_SS].Selector;
         ULONG OldEsp = State->GeneralRegs[FAST486_REG_ESP].Long;
+        
+        if (GateSize != (State->SegmentRegs[FAST486_REG_CS].Size))
+        {
+            /*
+             * The gate size doesn't match the current operand size, so toggle
+             * the OPSIZE flag.
+             */
+            State->PrefixFlags ^= FAST486_PREFIX_OPSIZE;
+        }
 
         /* Check if the interrupt handler is more privileged */
         if (Fast486GetCurrentPrivLevel(State) > GET_SEGMENT_RPL(SegmentSelector))
@@ -257,7 +269,7 @@ Fast486InterruptInternal(PFAST486_STATE State,
     /* Push the instruction pointer */
     if (!Fast486StackPush(State, State->InstPtr.Long)) return FALSE;
 
-    if (InterruptGate)
+    if ((GateType == FAST486_IDT_INT_GATE) || (GateType == FAST486_IDT_INT_GATE_32))
     {
         /* Disable interrupts after a jump to an interrupt gate handler */
         State->Flags.If = FALSE;
@@ -270,7 +282,7 @@ Fast486InterruptInternal(PFAST486_STATE State,
         return FALSE;
     }
 
-    if (State->SegmentRegs[FAST486_REG_CS].Size)
+    if (GateSize)
     {
         /* 32-bit code segment, use EIP */
         State->InstPtr.Long = Offset;
index 1bfdb31..677bd19 100644 (file)
@@ -159,7 +159,7 @@ Fast486InterruptInternal
     PFAST486_STATE State,
     USHORT SegmentSelector,
     ULONG Offset,
-    BOOLEAN InterruptGate
+    ULONG GateType
 );
 
 VOID
index fff8fc0..a558ed4 100644 (file)
@@ -542,24 +542,32 @@ Fast486LoadSegment(PFAST486_STATE State,
         {
             /* Loading a data segment */
 
-            if (!GdtEntry.SystemType)
+            if (GET_SEGMENT_INDEX(Selector) != 0)
             {
-                /* This is a special descriptor */
-                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
-                return FALSE;
-            }
+                if (!GdtEntry.SystemType)
+                {
+                    /* This is a special descriptor */
+                    Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                    return FALSE;
+                }
 
-            if ((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl)
-                || (Fast486GetCurrentPrivLevel(State) > GdtEntry.Dpl))
-            {
-                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
-                return FALSE;
-            }
+                if ((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl)
+                    || (Fast486GetCurrentPrivLevel(State) > GdtEntry.Dpl))
+                {
+                    Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                    return FALSE;
+                }
 
-            if (!GdtEntry.Present)
+                if (!GdtEntry.Present)
+                {
+                    Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector);
+                    return FALSE;
+                }
+            }
+            else
             {
-                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector);
-                return FALSE;
+                /* This is a NULL selector */
+                RtlZeroMemory(&GdtEntry, sizeof(GdtEntry));
             }
         }
 
@@ -572,6 +580,7 @@ Fast486LoadSegment(PFAST486_STATE State,
         CachedDescriptor->DirConf = GdtEntry.DirConf;
         CachedDescriptor->Executable = GdtEntry.Executable;
         CachedDescriptor->SystemType = GdtEntry.SystemType;
+        CachedDescriptor->Rpl = GET_SEGMENT_RPL(Selector);
         CachedDescriptor->Dpl = GdtEntry.Dpl;
         CachedDescriptor->Present = GdtEntry.Present;
         CachedDescriptor->Size = GdtEntry.Size;
index 1a8f126..e6f91a9 100644 (file)
@@ -3702,9 +3702,9 @@ FAST486_OPCODE_HANDLER(Fast486OpcodePushImm)
     }
     else
     {
-        USHORT Data;
+        SHORT Data;
 
-        if (!Fast486FetchWord(State, &Data))
+        if (!Fast486FetchWord(State, (PUSHORT)&Data))
         {
             /* Exception occurred */
             return FALSE;
@@ -3837,12 +3837,12 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeImulModrmImm)
 
 FAST486_OPCODE_HANDLER(Fast486OpcodePushByteImm)
 {
-    UCHAR Data;
+    CHAR Data;
 
     /* Make sure this is the right instruction */
     ASSERT(Opcode == 0x6A);
 
-    if (!Fast486FetchByte(State, &Data))
+    if (!Fast486FetchByte(State, (PUCHAR)&Data))
     {
         /* Exception occurred */
         return FALSE;
index 264fa66..efcaa16 100644 (file)
@@ -2018,10 +2018,13 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
 {
     UCHAR TableReg[6];
     FAST486_MOD_REG_RM ModRegRm;
-    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    BOOLEAN OperandSize, AddressSize;
     FAST486_SEG_REGS Segment = FAST486_REG_DS;
 
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
     NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(OperandSize);
     TOGGLE_ADSIZE(AddressSize);
 
     if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
@@ -2117,6 +2120,9 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
             State->Gdtr.Size = *((PUSHORT)TableReg);
             State->Gdtr.Address = *((PULONG)&TableReg[sizeof(USHORT)]);
 
+            /* In 16-bit mode the highest byte is masked out */
+            if (!OperandSize) State->Gdtr.Address &= 0x00FFFFFF;
+
             return TRUE;
         }
 
@@ -2153,6 +2159,9 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
             State->Idtr.Size = *((PUSHORT)TableReg);
             State->Idtr.Address = *((PULONG)&TableReg[sizeof(USHORT)]);
 
+            /* In 16-bit mode the highest byte is masked out */
+            if (!OperandSize) State->Idtr.Address &= 0x00FFFFFF;
+
             return TRUE;
         }
 
index 353fa6d..ad218f1 100644 (file)
@@ -442,6 +442,10 @@ static WORD DosCopyEnvironmentBlock(LPCVOID Environment, LPCSTR ProgramName)
     /* Set the final zero */
     *(DestBuffer++) = 0;
 
+    /* Store the special program name tag */
+    *(DestBuffer++) = LOWORD(DOS_PROGRAM_NAME_TAG);
+    *(DestBuffer++) = HIWORD(DOS_PROGRAM_NAME_TAG);
+
     /* Copy the program name after the environment block */
     strcpy(DestBuffer, ProgramName);
 
index e2f0cef..abbef7e 100644 (file)
@@ -47,6 +47,7 @@
 #define DOS_DIR_LENGTH 64
 #define NUM_DRIVES ('Z' - 'A' + 1)
 #define DOS_CHAR_ATTRIBUTE 0x07
+#define DOS_PROGRAM_NAME_TAG 0x0001
 
 enum DOS_ALLOC_STRATEGY
 {