[FAST486]
[reactos.git] / lib / fast486 / common.c
index db38487..36f026e 100644 (file)
 #include <fast486.h>
 #include "common.h"
 
-/* PRIVATE FUNCTIONS **********************************************************/
-
-static inline
-ULONG
-Fast486GetPageTableEntry(PFAST486_STATE State,
-                         ULONG VirtualAddress)
-{
-    // TODO: NOT IMPLEMENTED
-    UNIMPLEMENTED;
-
-    return 0;
-}
-
 /* PUBLIC FUNCTIONS ***********************************************************/
 
 BOOLEAN
@@ -54,7 +41,6 @@ Fast486ReadMemory(PFAST486_STATE State,
 {
     ULONG LinearAddress;
     PFAST486_SEG_REG CachedDescriptor;
-    INT Cpl = Fast486GetCurrentPrivLevel(State);
 
     ASSERT(SegmentReg < FAST486_NUM_SEG_REGS);
 
@@ -79,7 +65,8 @@ Fast486ReadMemory(PFAST486_STATE State,
             return FALSE;
         }
 
-        if (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
+        if ((!InstFetch && (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl))
+            || (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl))
         {
             Fast486Exception(State, FAST486_EXCEPTION_GP);
             return FALSE;
@@ -108,58 +95,8 @@ Fast486ReadMemory(PFAST486_STATE State,
     /* Find the linear address */
     LinearAddress = CachedDescriptor->Base + Offset;
 
-    /* Check if paging is enabled */
-    if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PG)
-    {
-        ULONG Page;
-        FAST486_PAGE_TABLE TableEntry;
-
-        for (Page = PAGE_ALIGN(LinearAddress);
-             Page <= PAGE_ALIGN(LinearAddress + Size - 1);
-             Page += PAGE_SIZE)
-        {
-            ULONG PageOffset = 0, PageLength = PAGE_SIZE;
-
-            /* Get the table entry */
-            TableEntry.Value = Fast486GetPageTableEntry(State, Page);
-
-            if (!TableEntry.Present || (!TableEntry.Usermode && (Cpl > 0)))
-            {
-                /* Exception */
-                Fast486ExceptionWithErrorCode(State,
-                                              FAST486_EXCEPTION_PF,
-                                              TableEntry.Value & 0x07);
-                return FALSE;
-            }
-
-            /* Check if this is the first page */
-            if (Page == PAGE_ALIGN(LinearAddress))
-            {
-                /* Start copying from the offset from the beginning of the page */
-                PageOffset = PAGE_OFFSET(LinearAddress);
-            }
-
-            /* Check if this is the last page */
-            if (Page == PAGE_ALIGN(LinearAddress + Size - 1))
-            {   
-                /* Copy only a part of the page */
-                PageLength = PAGE_OFFSET(LinearAddress + Size);
-            }
-
-            /* Read the entry */
-            State->MemReadCallback(State,
-                                   (TableEntry.Address << 12) | PageOffset,
-                                   Buffer,
-                                   PageLength);
-        }
-    }
-    else
-    {
-        /* Read the entry */
-        State->MemReadCallback(State, LinearAddress, Buffer, Size);
-    }
-
-    return TRUE;
+    /* Read from the linear address */
+    return Fast486ReadLinearMemory(State, LinearAddress, Buffer, Size);
 }
 
 BOOLEAN
@@ -171,7 +108,6 @@ Fast486WriteMemory(PFAST486_STATE State,
 {
     ULONG LinearAddress;
     PFAST486_SEG_REG CachedDescriptor;
-    INT Cpl = Fast486GetCurrentPrivLevel(State);
 
     ASSERT(SegmentReg < FAST486_NUM_SEG_REGS);
 
@@ -182,7 +118,6 @@ Fast486WriteMemory(PFAST486_STATE State,
     {
         /* Write beyond limit */
         Fast486Exception(State, FAST486_EXCEPTION_GP);
-
         return FALSE;
     }
 
@@ -197,7 +132,8 @@ Fast486WriteMemory(PFAST486_STATE State,
             return FALSE;
         }
 
-        if (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
+        if ((GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
+            || (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl))
         {
             Fast486Exception(State, FAST486_EXCEPTION_GP);
             return FALSE;
@@ -220,60 +156,8 @@ Fast486WriteMemory(PFAST486_STATE State,
     /* Find the linear address */
     LinearAddress = CachedDescriptor->Base + Offset;
 
-    /* Check if paging is enabled */
-    if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PG)
-    {
-        ULONG Page;
-        FAST486_PAGE_TABLE TableEntry;
-
-        for (Page = PAGE_ALIGN(LinearAddress);
-             Page <= PAGE_ALIGN(LinearAddress + Size - 1);
-             Page += PAGE_SIZE)
-        {
-            ULONG PageOffset = 0, PageLength = PAGE_SIZE;
-
-            /* Get the table entry */
-            TableEntry.Value = Fast486GetPageTableEntry(State, Page);
-
-            if ((!TableEntry.Present || (!TableEntry.Usermode && (Cpl > 0)))
-                || ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_WP)
-                && !TableEntry.Writeable))
-            {
-                /* Exception */
-                Fast486ExceptionWithErrorCode(State,
-                                              FAST486_EXCEPTION_PF,
-                                              TableEntry.Value & 0x07);
-                return FALSE;
-            }
-
-            /* Check if this is the first page */
-            if (Page == PAGE_ALIGN(LinearAddress))
-            {
-                /* Start copying from the offset from the beginning of the page */
-                PageOffset = PAGE_OFFSET(LinearAddress);
-            }
-
-            /* Check if this is the last page */
-            if (Page == PAGE_ALIGN(LinearAddress + Size - 1))
-            {   
-                /* Copy only a part of the page */
-                PageLength = PAGE_OFFSET(LinearAddress + Size);
-            }
-
-            /* Write the entry */
-            State->MemWriteCallback(State,
-                                    (TableEntry.Address << 12) | PageOffset,
-                                    Buffer,
-                                    PageLength);
-        }
-    }
-    else
-    {
-        /* Write the entry */
-        State->MemWriteCallback(State, LinearAddress, Buffer, Size);
-    }
-
-    return TRUE;
+    /* Write to the linear address */
+    return Fast486WriteLinearMemory(State, LinearAddress, Buffer, Size);
 }
 
 BOOLEAN
@@ -293,11 +177,14 @@ Fast486InterruptInternal(PFAST486_STATE State,
         if (Fast486GetCurrentPrivLevel(State) > GET_SEGMENT_RPL(SegmentSelector))
         {
             /* Read the TSS */
-            // FIXME: This code is only correct when paging is disabled!!!
-            State->MemReadCallback(State,
-                                   State->Tss.Address,
-                                   &Tss,
-                                   sizeof(Tss));
+            if (!Fast486ReadLinearMemory(State,
+                                         State->TaskReg.Base,
+                                         &Tss,
+                                         sizeof(Tss)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
 
             /* Check the new (higher) privilege level */
             switch (GET_SEGMENT_RPL(SegmentSelector))
@@ -352,6 +239,14 @@ Fast486InterruptInternal(PFAST486_STATE State,
             if (!Fast486StackPush(State, OldEsp)) return FALSE;
         }
     }
+    else
+    {
+        if (State->SegmentRegs[FAST486_REG_CS].Size)
+        {
+            /* Set OPSIZE, because INT always pushes 16-bit values in real mode */
+            State->PrefixFlags |= FAST486_PREFIX_OPSIZE;
+        }
+    }
 
     /* Push EFLAGS */
     if (!Fast486StackPush(State, State->Flags.Long)) return FALSE;
@@ -444,8 +339,18 @@ Fast486ExceptionWithErrorCode(PFAST486_STATE State,
         && (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE))
     {
         /* Push the error code */
-        Fast486StackPush(State, ErrorCode);
+        if (!Fast486StackPush(State, ErrorCode))
+        {
+            /*
+             * If this function failed, that means Fast486Exception
+             * was called again, so just return in this case.
+             */
+            return;
+        }
     }
+
+    /* Reset the exception count */
+    State->ExceptionCount = 0;
 }
 
 /* EOF */