Forráskód Böngészése

Fix for FPU generated exception as interrupt 0x10, contributed by Max Nazhalov

git-svn-id: trunk@36813 -
pierre 8 éve
szülő
commit
ba7586a5c8
2 módosított fájl, 61 hozzáadás és 50 törlés
  1. 54 38
      rtl/msdos/prt0comn.asm
  2. 7 12
      rtl/msdos/system.pp

+ 54 - 38
rtl/msdos/prt0comn.asm

@@ -73,7 +73,6 @@
         extern __SaveInt75
 
         extern __fpu_status
-        extern __fpu_control
 
         extern FPC_HANDLE_I8086_ERROR
 
@@ -283,7 +282,8 @@ error_msg:
 
         global FPC_INT00_HANDLER
 FPC_INT00_HANDLER:
-        sub sp, 4  ; reserve space on the stack for the retf
+        pushf
+        sub sp, 4  ; reserve space on the stack for the iret
 
         push cx
         push ds
@@ -310,7 +310,7 @@ FPC_INT00_HANDLER:
 %ifndef __FAR_CODE__
         ; check whether we're coming from the same code segment
         mov bp, sp
-        mov cx, [bp + 3*2 + 6]  ; get caller segment
+        mov cx, [bp + 3*2 + 6 + 2]  ; get caller segment
         mov bp, cs
         cmp bp, cx
         jne .call_previous_handler00
@@ -318,12 +318,12 @@ FPC_INT00_HANDLER:
 
         ; Call Fpc_Handle_I8086_Error, with err=0
         mov bp, sp
-        mov cx, [bp + 3*2 + 4]  ; get caller offset
+        mov cx, [bp + 3*2 + 6]  ; get caller offset
 %ifdef __FAR_CODE__
-        mov dx, [bp + 3*2 + 6]  ; get caller segment
+        mov dx, [bp + 3*2 + 6 + 2]  ; get caller segment
 %endif
         pop bp
-        add sp, 2*2 + 4 + 6
+        add sp, 2*2 + 6 + 6
         xor ax, ax
         push ax
         mov ax, 0
@@ -333,6 +333,7 @@ FPC_INT00_HANDLER:
 %endif
         push cx
         cld
+        sti
 %ifdef __FAR_CODE__
         jmp far FPC_HANDLE_I8086_ERROR
 %else
@@ -348,11 +349,12 @@ FPC_INT00_HANDLER:
         pop bp
         pop ds
         pop cx
-        retf  ; jumps to the previous handler with all registers and stack intact
+        iret  ; jumps to the previous handler with all registers and stack intact
 
         global FPC_INT10_HANDLER
 FPC_INT10_HANDLER:
-        sub sp, 4  ; reserve space on the stack for the retf
+        pushf
+        sub sp, 4  ; reserve space on the stack for the iret
 
         push cx
         push ds
@@ -368,21 +370,8 @@ FPC_INT10_HANDLER:
 %endif
         mov ds, bp
         ; Check that an unmasked exception is indeed set
-        ; First load FPU control register to __fpu_control
-        fnstcw word [__fpu_control]
-        ; Move control register value to bx register
-        mov bx,word [__fpu_control]
-        ; Now load status register to ax
         fnstsw word [__fpu_status]
-        ; Only the exception part is useful, clear other parts
-        and bx,3fh
-        ; at least one same bit must also be set in bx
-        ; in that case with a bit set in status register
-        ; which means an exception has been generated by the FPU
-        ; and the exeception is not masked, as the same
-        ; bit is set in control register
-        mov ax,word [__fpu_status]
-        and ax,bx
+        test byte [__fpu_status], 80h ; really just this bit is enough, see i8087 datasheet
         je  .call_previous_handler10
 
 %ifdef __NEAR_DATA__
@@ -396,7 +385,7 @@ FPC_INT10_HANDLER:
 %ifndef __FAR_CODE__
         ; check whether we're coming from the same code segment
         mov bp, sp
-        mov cx, [bp + 3*2 + 6]  ; get caller segment
+        mov cx, [bp + 3*2 + 6 + 2]  ; get caller segment
         mov bp, cs
         cmp bp, cx
         jne .call_previous_handler10
@@ -404,12 +393,12 @@ FPC_INT10_HANDLER:
 
         ; Call Fpc_Handle_I8086_Error, with err=$10
         mov bp, sp
-        mov cx, [bp + 3*2 + 4]  ; get caller offset
+        mov cx, [bp + 3*2 + 6]  ; get caller offset
 %ifdef __FAR_CODE__
-        mov dx, [bp + 3*2 + 6]  ; get caller segment
+        mov dx, [bp + 3*2 + 6 + 2]  ; get caller segment
 %endif
         pop bp
-        add sp, 2*2 + 4 + 6
+        add sp, 2*2 + 6 + 6
         xor ax, ax
         push ax
         mov ax, 10h
@@ -419,6 +408,7 @@ FPC_INT10_HANDLER:
 %endif
         push cx
         cld
+        sti
 %ifdef __FAR_CODE__
         jmp far FPC_HANDLE_I8086_ERROR
 %else
@@ -434,11 +424,12 @@ FPC_INT10_HANDLER:
         pop bp
         pop ds
         pop cx
-        retf  ; jumps to the previous handler with all registers and stack intact
+        iret  ; jumps to the previous handler with all registers and stack intact
 
         global FPC_INT75_HANDLER
 FPC_INT75_HANDLER:
-        sub sp, 4  ; reserve space on the stack for the retf
+        pushf
+        sub sp, 4  ; reserve space on the stack for the iret
 
         push cx
         push ds
@@ -465,7 +456,7 @@ FPC_INT75_HANDLER:
 %ifndef __FAR_CODE__
         ; check whether we're coming from the same code segment
         mov bp, sp
-        mov cx, [bp + 3*2 + 6]  ; get caller segment
+        mov cx, [bp + 3*2 + 6 + 2]  ; get caller segment
         mov bp, cs
         cmp bp, cx
         jne .call_previous_handler75
@@ -473,12 +464,12 @@ FPC_INT75_HANDLER:
 
         ; Call Fpc_Handle_I8086_Error, with err=$75
         mov bp, sp
-        mov cx, [bp + 3*2 + 4]  ; get caller offset
+        mov cx, [bp + 3*2 + 6]  ; get caller offset
 %ifdef __FAR_CODE__
-        mov dx, [bp + 3*2 + 6]  ; get caller segment
+        mov dx, [bp + 3*2 + 6 + 2]  ; get caller segment
 %endif
         pop bp
-        add sp, 2*2 + 4 + 6
+        add sp, 2*2 + 6 + 6
         xor ax, ax
         push ax
         mov ax, 75h
@@ -488,6 +479,14 @@ FPC_INT75_HANDLER:
 %endif
         push cx
         cld
+
+        ; Reset IRQ/#IGNNE latch; signal EOI; enable interrupts
+        mov al,20h
+        out 0F0h,al ; al=any
+        out 0A0h,al
+        out 020h,al
+        sti
+
 %ifdef __FAR_CODE__
         jmp far FPC_HANDLE_I8086_ERROR
 %else
@@ -509,9 +508,9 @@ FPC_INT75_HANDLER:
 
         global FPC_INSTALL_INTERRUPT_HANDLERS
 FPC_INSTALL_INTERRUPT_HANDLERS:
-        push ds
 
 %ifdef __HUGE__
+        push ds
         mov ax, SYSTEM_DATA
         mov ds, ax
 %endif
@@ -525,14 +524,16 @@ FPC_INSTALL_INTERRUPT_HANDLERS:
 
         ; install the new int 00 handler
 %ifndef __TINY__
+        push ds
         push cs
         pop ds
 %endif
         mov dx, FPC_INT00_HANDLER
-        pop ds
-        push ds
         mov ax, 2500h
         int 21h
+%ifndef __TINY__
+        pop ds
+%endif
 
         ; save old int $10 handler
         mov ax, 3510h
@@ -543,14 +544,16 @@ FPC_INSTALL_INTERRUPT_HANDLERS:
 
         ; install the new int $10 handler
 %ifndef __TINY__
+        push ds
         push cs
         pop ds
 %endif
         mov dx, FPC_INT10_HANDLER
         mov ax, 2510h
         int 21h
+%ifndef __TINY__
         pop ds
-        push ds
+%endif
 
         ; save old int $75 handler
         mov ax, 3575h
@@ -561,15 +564,21 @@ FPC_INSTALL_INTERRUPT_HANDLERS:
 
         ; install the new int $75 handler
 %ifndef __TINY__
+        push ds
         push cs
         pop ds
 %endif
         mov dx, FPC_INT75_HANDLER
         mov ax, 2575h
         int 21h
+%ifndef __TINY__
+        pop ds
+%endif
 
 
+%ifdef __HUGE__
         pop ds
+%endif
 %ifdef __FAR_CODE__
         retf
 %else
@@ -579,26 +588,33 @@ FPC_INSTALL_INTERRUPT_HANDLERS:
 
         global FPC_RESTORE_INTERRUPT_HANDLERS
 FPC_RESTORE_INTERRUPT_HANDLERS:
-        push ds
 
 %ifdef __HUGE__
+        push ds
         mov ax, SYSTEM_DATA
         mov ds, ax
 %endif
-
+        push ds
         mov ax, 2500h
         lds dx, [__SaveInt00]
         int 21h
+        pop ds
 
+        push ds
         mov ax, 2510h
         lds dx, [__SaveInt10]
         int 21h
+        pop ds
 
+        push ds
         mov ax, 2575h
         lds dx, [__SaveInt75]
         int 21h
+        pop ds
 
+%ifdef __HUGE__
         pop ds
+%endif
 %ifdef __FAR_CODE__
         retf
 %else

+ 7 - 12
rtl/msdos/system.pp

@@ -84,7 +84,6 @@ var
   SaveInt10: FarPointer;public name '__SaveInt10';
   SaveInt75: FarPointer;public name '__SaveInt75';
   fpu_status: word;public name '__fpu_status';
-  fpu_control: word;public name '__fpu_control';
 
 
   AllFilesMask: string [3];
@@ -182,7 +181,7 @@ Procedure SysInitFPU;
       fldcw   localfpucw
       fwait
     end;
-    if Test8087 < 2 then
+    if Test8087 < 3 then { i8087/i80287 do not have "native" exception mode (CR0:NE) }
       begin
         restore_old_int10:=true;
       end
@@ -239,13 +238,11 @@ Procedure SysInitFPU;
           end;
         { Restore previous interrupt 06 handler }
         asm
-          push es
-          mov bx,word [prevInt06]
-          mov dx,word [prevInt06+2]
-          mov es,dx
+          push ds
           mov ax, $2506
+          lds dx,[prevInt06]
           int $21
-          pop es
+          pop ds
         end;
       end;
       { Special handler of interrupt $10
@@ -254,13 +251,11 @@ Procedure SysInitFPU;
       {$ifndef TEST_FPU_INT10}
       if restore_old_int10 then
         asm
-          push es
-          mov bx,word [SaveInt10]
-          mov dx,word [SaveInt10+2]
-          mov es,dx
+          push ds
           mov ax, $2510
+          lds dx,[SaveInt10]
           int $21
-          pop es
+          pop ds
         end;
       {$endif ndef TEST_FPU_INT10}
   end;