mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-25 12:41:40 +02:00 
			
		
		
		
	Fix for FPU generated exception as interrupt 0x10, contributed by Max Nazhalov
git-svn-id: trunk@36813 -
This commit is contained in:
		
							parent
							
								
									301fc9af70
								
							
						
					
					
						commit
						ba7586a5c8
					
				| @ -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 | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 pierre
						pierre