[SOFT386]
authorAleksandar Andrejevic <aandrejevic@reactos.org>
Fri, 11 Oct 2013 23:45:42 +0000 (23:45 +0000)
committerAleksandar Andrejevic <aandrejevic@reactos.org>
Fri, 11 Oct 2013 23:45:42 +0000 (23:45 +0000)
- Fix calculation of the AF flag in opcode groups 0xFE and 0xFF (INC/DEC).
- Fix a bug in the REP prefix by simulating the wrap-around of DI which
  can occur when the current address size is 16-bit.
- Exception error codes are only pushed on the stack in protected mode.

svn path=/branches/ntvdm/; revision=60625

lib/soft386/common.c
lib/soft386/opcodes.c
lib/soft386/opgroups.c

index f7547f6..569c1cf 100644 (file)
@@ -494,7 +494,8 @@ Soft386ExceptionWithErrorCode(PSOFT386_STATE State,
         return;
     }
 
-    if (EXCEPTION_HAS_ERROR_CODE(ExceptionCode))
+    if (EXCEPTION_HAS_ERROR_CODE(ExceptionCode)
+        && (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE))
     {
         /* Push the error code */
         Soft386StackPush(State, ErrorCode);
index c0907cc..6324262 100644 (file)
@@ -6168,6 +6168,15 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeStos)
         {
             ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize);
 
+            /* Simulate the 16-bit wrap-around of DI in 16-bit address mode */
+            if (!AddressSize)
+            {
+                ULONG MaxBytes = 0x10000 - (ULONG)State->GeneralRegs[SOFT386_REG_EDI].LowWord;
+
+                Processed = min(Processed, MaxBytes / DataSize);
+                if (Processed == 0) Processed = 1;
+            }
+
             if (State->Flags.Df)
             {
                 /* Reduce EDI by the number of bytes to transfer */
@@ -6437,6 +6446,15 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeIns)
         {
             ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize);
 
+            /* Simulate the 16-bit wrap-around of DI in 16-bit address mode */
+            if (!AddressSize)
+            {
+                ULONG MaxBytes = 0x10000 - (ULONG)State->GeneralRegs[SOFT386_REG_EDI].LowWord;
+
+                Processed = min(Processed, MaxBytes / DataSize);
+                if (Processed == 0) Processed = 1;
+            }
+
             /* Read from the I/O port */
             State->IoReadCallback(State,
                                   State->GeneralRegs[SOFT386_REG_EDX].LowWord,
@@ -6574,6 +6592,15 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeOuts)
         {
             ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize);
 
+            /* Simulate the 16-bit wrap-around of DI in 16-bit address mode */
+            if (!AddressSize)
+            {
+                ULONG MaxBytes = 0x10000 - (ULONG)State->GeneralRegs[SOFT386_REG_EDI].LowWord;
+
+                Processed = min(Processed, MaxBytes / DataSize);
+                if (Processed == 0) Processed = 1;
+            }
+
             /* Read from memory */
             if (!Soft386ReadMemory(State,
                                    SOFT386_REG_ES,
index 2822305..d55ad87 100644 (file)
@@ -1414,21 +1414,22 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupFE)
 
     if (ModRegRm.Register == 0)
     {
-        /* Increment and update OF */
+        /* Increment and update OF and AF */
         Value++;
         State->Flags.Of = (Value == SIGN_FLAG_BYTE) ? TRUE : FALSE;
+        State->Flags.Af = ((Value & 0x0F) == 0);
     }
     else
     {
-        /* Decrement and update OF */
+        /* Decrement and update OF and AF */
         State->Flags.Of = (Value == SIGN_FLAG_BYTE) ? TRUE : FALSE;
         Value--;
+        State->Flags.Af = ((Value & 0x0F) == 0x0F);
     }
 
     /* Update flags */
     State->Flags.Sf = (Value & SIGN_FLAG_BYTE) ? TRUE : FALSE;
     State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
-    State->Flags.Af = ((Value & 0x0F) == 0) ? TRUE : FALSE;
     State->Flags.Pf = Soft386CalculateParity(Value);
 
     /* Write back the result */
@@ -1483,15 +1484,17 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupFF)
 
         if (ModRegRm.Register == 0)
         {
-            /* Increment and update OF */
+            /* Increment and update OF and AF */
             Value++;
             State->Flags.Of = (Value == SIGN_FLAG_LONG) ? TRUE : FALSE;
+            State->Flags.Af = ((Value & 0x0F) == 0);
         }
         else if (ModRegRm.Register == 1)
         {
-            /* Decrement and update OF */
+            /* Decrement and update OF and AF */
             State->Flags.Of = (Value == SIGN_FLAG_LONG) ? TRUE : FALSE;
             Value--;
+            State->Flags.Af = ((Value & 0x0F) == 0x0F);
         }
 
         if (ModRegRm.Register <= 1)
@@ -1499,7 +1502,6 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupFF)
             /* Update flags */
             State->Flags.Sf = (Value & SIGN_FLAG_LONG) ? TRUE : FALSE;
             State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
-            State->Flags.Af = ((Value & 0x0F) == 0) ? TRUE : FALSE;
             State->Flags.Pf = Soft386CalculateParity(Value);
 
             /* Write back the result */
@@ -1524,12 +1526,14 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupFF)
             /* Increment and update OF */
             Value++;
             State->Flags.Of = (Value == SIGN_FLAG_WORD) ? TRUE : FALSE;
+            State->Flags.Af = ((Value & 0x0F) == 0);
         }
         else if (ModRegRm.Register == 1)
         {
             /* Decrement and update OF */
             State->Flags.Of = (Value == SIGN_FLAG_WORD) ? TRUE : FALSE;
             Value--;
+            State->Flags.Af = ((Value & 0x0F) == 0x0F);
         }
 
         if (ModRegRm.Register <= 1)
@@ -1537,7 +1541,6 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupFF)
             /* Update flags */
             State->Flags.Sf = (Value & SIGN_FLAG_WORD) ? TRUE : FALSE;
             State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
-            State->Flags.Af = ((Value & 0x0F) == 0) ? TRUE : FALSE;
             State->Flags.Pf = Soft386CalculateParity(Value);
 
             /* Write back the result */