mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 15:11:31 +01: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 __SaveInt75 | ||||||
| 
 | 
 | ||||||
|         extern __fpu_status |         extern __fpu_status | ||||||
|         extern __fpu_control |  | ||||||
| 
 | 
 | ||||||
|         extern FPC_HANDLE_I8086_ERROR |         extern FPC_HANDLE_I8086_ERROR | ||||||
| 
 | 
 | ||||||
| @ -283,7 +282,8 @@ error_msg: | |||||||
| 
 | 
 | ||||||
|         global FPC_INT00_HANDLER |         global FPC_INT00_HANDLER | ||||||
| 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 cx | ||||||
|         push ds |         push ds | ||||||
| @ -310,7 +310,7 @@ FPC_INT00_HANDLER: | |||||||
| %ifndef __FAR_CODE__ | %ifndef __FAR_CODE__ | ||||||
|         ; check whether we're coming from the same code segment |         ; check whether we're coming from the same code segment | ||||||
|         mov bp, sp |         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 |         mov bp, cs | ||||||
|         cmp bp, cx |         cmp bp, cx | ||||||
|         jne .call_previous_handler00 |         jne .call_previous_handler00 | ||||||
| @ -318,12 +318,12 @@ FPC_INT00_HANDLER: | |||||||
| 
 | 
 | ||||||
|         ; Call Fpc_Handle_I8086_Error, with err=0 |         ; Call Fpc_Handle_I8086_Error, with err=0 | ||||||
|         mov bp, sp |         mov bp, sp | ||||||
|         mov cx, [bp + 3*2 + 4]  ; get caller offset |         mov cx, [bp + 3*2 + 6]  ; get caller offset | ||||||
| %ifdef __FAR_CODE__ | %ifdef __FAR_CODE__ | ||||||
|         mov dx, [bp + 3*2 + 6]  ; get caller segment |         mov dx, [bp + 3*2 + 6 + 2]  ; get caller segment | ||||||
| %endif | %endif | ||||||
|         pop bp |         pop bp | ||||||
|         add sp, 2*2 + 4 + 6 |         add sp, 2*2 + 6 + 6 | ||||||
|         xor ax, ax |         xor ax, ax | ||||||
|         push ax |         push ax | ||||||
|         mov ax, 0 |         mov ax, 0 | ||||||
| @ -333,6 +333,7 @@ FPC_INT00_HANDLER: | |||||||
| %endif | %endif | ||||||
|         push cx |         push cx | ||||||
|         cld |         cld | ||||||
|  |         sti | ||||||
| %ifdef __FAR_CODE__ | %ifdef __FAR_CODE__ | ||||||
|         jmp far FPC_HANDLE_I8086_ERROR |         jmp far FPC_HANDLE_I8086_ERROR | ||||||
| %else | %else | ||||||
| @ -348,11 +349,12 @@ FPC_INT00_HANDLER: | |||||||
|         pop bp |         pop bp | ||||||
|         pop ds |         pop ds | ||||||
|         pop cx |         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 |         global FPC_INT10_HANDLER | ||||||
| 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 cx | ||||||
|         push ds |         push ds | ||||||
| @ -368,21 +370,8 @@ FPC_INT10_HANDLER: | |||||||
| %endif | %endif | ||||||
|         mov ds, bp |         mov ds, bp | ||||||
|         ; Check that an unmasked exception is indeed set |         ; 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] |         fnstsw word [__fpu_status] | ||||||
|         ; Only the exception part is useful, clear other parts |         test byte [__fpu_status], 80h ; really just this bit is enough, see i8087 datasheet | ||||||
|         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 |  | ||||||
|         je  .call_previous_handler10 |         je  .call_previous_handler10 | ||||||
| 
 | 
 | ||||||
| %ifdef __NEAR_DATA__ | %ifdef __NEAR_DATA__ | ||||||
| @ -396,7 +385,7 @@ FPC_INT10_HANDLER: | |||||||
| %ifndef __FAR_CODE__ | %ifndef __FAR_CODE__ | ||||||
|         ; check whether we're coming from the same code segment |         ; check whether we're coming from the same code segment | ||||||
|         mov bp, sp |         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 |         mov bp, cs | ||||||
|         cmp bp, cx |         cmp bp, cx | ||||||
|         jne .call_previous_handler10 |         jne .call_previous_handler10 | ||||||
| @ -404,12 +393,12 @@ FPC_INT10_HANDLER: | |||||||
| 
 | 
 | ||||||
|         ; Call Fpc_Handle_I8086_Error, with err=$10 |         ; Call Fpc_Handle_I8086_Error, with err=$10 | ||||||
|         mov bp, sp |         mov bp, sp | ||||||
|         mov cx, [bp + 3*2 + 4]  ; get caller offset |         mov cx, [bp + 3*2 + 6]  ; get caller offset | ||||||
| %ifdef __FAR_CODE__ | %ifdef __FAR_CODE__ | ||||||
|         mov dx, [bp + 3*2 + 6]  ; get caller segment |         mov dx, [bp + 3*2 + 6 + 2]  ; get caller segment | ||||||
| %endif | %endif | ||||||
|         pop bp |         pop bp | ||||||
|         add sp, 2*2 + 4 + 6 |         add sp, 2*2 + 6 + 6 | ||||||
|         xor ax, ax |         xor ax, ax | ||||||
|         push ax |         push ax | ||||||
|         mov ax, 10h |         mov ax, 10h | ||||||
| @ -419,6 +408,7 @@ FPC_INT10_HANDLER: | |||||||
| %endif | %endif | ||||||
|         push cx |         push cx | ||||||
|         cld |         cld | ||||||
|  |         sti | ||||||
| %ifdef __FAR_CODE__ | %ifdef __FAR_CODE__ | ||||||
|         jmp far FPC_HANDLE_I8086_ERROR |         jmp far FPC_HANDLE_I8086_ERROR | ||||||
| %else | %else | ||||||
| @ -434,11 +424,12 @@ FPC_INT10_HANDLER: | |||||||
|         pop bp |         pop bp | ||||||
|         pop ds |         pop ds | ||||||
|         pop cx |         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 |         global FPC_INT75_HANDLER | ||||||
| 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 cx | ||||||
|         push ds |         push ds | ||||||
| @ -465,7 +456,7 @@ FPC_INT75_HANDLER: | |||||||
| %ifndef __FAR_CODE__ | %ifndef __FAR_CODE__ | ||||||
|         ; check whether we're coming from the same code segment |         ; check whether we're coming from the same code segment | ||||||
|         mov bp, sp |         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 |         mov bp, cs | ||||||
|         cmp bp, cx |         cmp bp, cx | ||||||
|         jne .call_previous_handler75 |         jne .call_previous_handler75 | ||||||
| @ -473,12 +464,12 @@ FPC_INT75_HANDLER: | |||||||
| 
 | 
 | ||||||
|         ; Call Fpc_Handle_I8086_Error, with err=$75 |         ; Call Fpc_Handle_I8086_Error, with err=$75 | ||||||
|         mov bp, sp |         mov bp, sp | ||||||
|         mov cx, [bp + 3*2 + 4]  ; get caller offset |         mov cx, [bp + 3*2 + 6]  ; get caller offset | ||||||
| %ifdef __FAR_CODE__ | %ifdef __FAR_CODE__ | ||||||
|         mov dx, [bp + 3*2 + 6]  ; get caller segment |         mov dx, [bp + 3*2 + 6 + 2]  ; get caller segment | ||||||
| %endif | %endif | ||||||
|         pop bp |         pop bp | ||||||
|         add sp, 2*2 + 4 + 6 |         add sp, 2*2 + 6 + 6 | ||||||
|         xor ax, ax |         xor ax, ax | ||||||
|         push ax |         push ax | ||||||
|         mov ax, 75h |         mov ax, 75h | ||||||
| @ -488,6 +479,14 @@ FPC_INT75_HANDLER: | |||||||
| %endif | %endif | ||||||
|         push cx |         push cx | ||||||
|         cld |         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__ | %ifdef __FAR_CODE__ | ||||||
|         jmp far FPC_HANDLE_I8086_ERROR |         jmp far FPC_HANDLE_I8086_ERROR | ||||||
| %else | %else | ||||||
| @ -509,9 +508,9 @@ FPC_INT75_HANDLER: | |||||||
| 
 | 
 | ||||||
|         global FPC_INSTALL_INTERRUPT_HANDLERS |         global FPC_INSTALL_INTERRUPT_HANDLERS | ||||||
| FPC_INSTALL_INTERRUPT_HANDLERS: | FPC_INSTALL_INTERRUPT_HANDLERS: | ||||||
|         push ds |  | ||||||
| 
 | 
 | ||||||
| %ifdef __HUGE__ | %ifdef __HUGE__ | ||||||
|  |         push ds | ||||||
|         mov ax, SYSTEM_DATA |         mov ax, SYSTEM_DATA | ||||||
|         mov ds, ax |         mov ds, ax | ||||||
| %endif | %endif | ||||||
| @ -525,14 +524,16 @@ FPC_INSTALL_INTERRUPT_HANDLERS: | |||||||
| 
 | 
 | ||||||
|         ; install the new int 00 handler |         ; install the new int 00 handler | ||||||
| %ifndef __TINY__ | %ifndef __TINY__ | ||||||
|  |         push ds | ||||||
|         push cs |         push cs | ||||||
|         pop ds |         pop ds | ||||||
| %endif | %endif | ||||||
|         mov dx, FPC_INT00_HANDLER |         mov dx, FPC_INT00_HANDLER | ||||||
|         pop ds |  | ||||||
|         push ds |  | ||||||
|         mov ax, 2500h |         mov ax, 2500h | ||||||
|         int 21h |         int 21h | ||||||
|  | %ifndef __TINY__ | ||||||
|  |         pop ds | ||||||
|  | %endif | ||||||
| 
 | 
 | ||||||
|         ; save old int $10 handler |         ; save old int $10 handler | ||||||
|         mov ax, 3510h |         mov ax, 3510h | ||||||
| @ -543,14 +544,16 @@ FPC_INSTALL_INTERRUPT_HANDLERS: | |||||||
| 
 | 
 | ||||||
|         ; install the new int $10 handler |         ; install the new int $10 handler | ||||||
| %ifndef __TINY__ | %ifndef __TINY__ | ||||||
|  |         push ds | ||||||
|         push cs |         push cs | ||||||
|         pop ds |         pop ds | ||||||
| %endif | %endif | ||||||
|         mov dx, FPC_INT10_HANDLER |         mov dx, FPC_INT10_HANDLER | ||||||
|         mov ax, 2510h |         mov ax, 2510h | ||||||
|         int 21h |         int 21h | ||||||
|  | %ifndef __TINY__ | ||||||
|         pop ds |         pop ds | ||||||
|         push ds | %endif | ||||||
| 
 | 
 | ||||||
|         ; save old int $75 handler |         ; save old int $75 handler | ||||||
|         mov ax, 3575h |         mov ax, 3575h | ||||||
| @ -561,15 +564,21 @@ FPC_INSTALL_INTERRUPT_HANDLERS: | |||||||
| 
 | 
 | ||||||
|         ; install the new int $75 handler |         ; install the new int $75 handler | ||||||
| %ifndef __TINY__ | %ifndef __TINY__ | ||||||
|  |         push ds | ||||||
|         push cs |         push cs | ||||||
|         pop ds |         pop ds | ||||||
| %endif | %endif | ||||||
|         mov dx, FPC_INT75_HANDLER |         mov dx, FPC_INT75_HANDLER | ||||||
|         mov ax, 2575h |         mov ax, 2575h | ||||||
|         int 21h |         int 21h | ||||||
| 
 | %ifndef __TINY__ | ||||||
| 
 |  | ||||||
|         pop ds |         pop ds | ||||||
|  | %endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %ifdef __HUGE__ | ||||||
|  |         pop ds | ||||||
|  | %endif | ||||||
| %ifdef __FAR_CODE__ | %ifdef __FAR_CODE__ | ||||||
|         retf |         retf | ||||||
| %else | %else | ||||||
| @ -579,26 +588,33 @@ FPC_INSTALL_INTERRUPT_HANDLERS: | |||||||
| 
 | 
 | ||||||
|         global FPC_RESTORE_INTERRUPT_HANDLERS |         global FPC_RESTORE_INTERRUPT_HANDLERS | ||||||
| FPC_RESTORE_INTERRUPT_HANDLERS: | FPC_RESTORE_INTERRUPT_HANDLERS: | ||||||
|         push ds |  | ||||||
| 
 | 
 | ||||||
| %ifdef __HUGE__ | %ifdef __HUGE__ | ||||||
|  |         push ds | ||||||
|         mov ax, SYSTEM_DATA |         mov ax, SYSTEM_DATA | ||||||
|         mov ds, ax |         mov ds, ax | ||||||
| %endif | %endif | ||||||
| 
 |         push ds | ||||||
|         mov ax, 2500h |         mov ax, 2500h | ||||||
|         lds dx, [__SaveInt00] |         lds dx, [__SaveInt00] | ||||||
|         int 21h |         int 21h | ||||||
|  |         pop ds | ||||||
| 
 | 
 | ||||||
|  |         push ds | ||||||
|         mov ax, 2510h |         mov ax, 2510h | ||||||
|         lds dx, [__SaveInt10] |         lds dx, [__SaveInt10] | ||||||
|         int 21h |         int 21h | ||||||
|  |         pop ds | ||||||
| 
 | 
 | ||||||
|  |         push ds | ||||||
|         mov ax, 2575h |         mov ax, 2575h | ||||||
|         lds dx, [__SaveInt75] |         lds dx, [__SaveInt75] | ||||||
|         int 21h |         int 21h | ||||||
| 
 |  | ||||||
|         pop ds |         pop ds | ||||||
|  | 
 | ||||||
|  | %ifdef __HUGE__ | ||||||
|  |         pop ds | ||||||
|  | %endif | ||||||
| %ifdef __FAR_CODE__ | %ifdef __FAR_CODE__ | ||||||
|         retf |         retf | ||||||
| %else | %else | ||||||
|  | |||||||
| @ -84,7 +84,6 @@ var | |||||||
|   SaveInt10: FarPointer;public name '__SaveInt10'; |   SaveInt10: FarPointer;public name '__SaveInt10'; | ||||||
|   SaveInt75: FarPointer;public name '__SaveInt75'; |   SaveInt75: FarPointer;public name '__SaveInt75'; | ||||||
|   fpu_status: word;public name '__fpu_status'; |   fpu_status: word;public name '__fpu_status'; | ||||||
|   fpu_control: word;public name '__fpu_control'; |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|   AllFilesMask: string [3]; |   AllFilesMask: string [3]; | ||||||
| @ -182,7 +181,7 @@ Procedure SysInitFPU; | |||||||
|       fldcw   localfpucw |       fldcw   localfpucw | ||||||
|       fwait |       fwait | ||||||
|     end; |     end; | ||||||
|     if Test8087 < 2 then |     if Test8087 < 3 then { i8087/i80287 do not have "native" exception mode (CR0:NE) } | ||||||
|       begin |       begin | ||||||
|         restore_old_int10:=true; |         restore_old_int10:=true; | ||||||
|       end |       end | ||||||
| @ -239,13 +238,11 @@ Procedure SysInitFPU; | |||||||
|           end; |           end; | ||||||
|         { Restore previous interrupt 06 handler } |         { Restore previous interrupt 06 handler } | ||||||
|         asm |         asm | ||||||
|           push es |           push ds | ||||||
|           mov bx,word [prevInt06] |  | ||||||
|           mov dx,word [prevInt06+2] |  | ||||||
|           mov es,dx |  | ||||||
|           mov ax, $2506 |           mov ax, $2506 | ||||||
|  |           lds dx,[prevInt06] | ||||||
|           int $21 |           int $21 | ||||||
|           pop es |           pop ds | ||||||
|         end; |         end; | ||||||
|       end; |       end; | ||||||
|       { Special handler of interrupt $10 |       { Special handler of interrupt $10 | ||||||
| @ -254,13 +251,11 @@ Procedure SysInitFPU; | |||||||
|       {$ifndef TEST_FPU_INT10} |       {$ifndef TEST_FPU_INT10} | ||||||
|       if restore_old_int10 then |       if restore_old_int10 then | ||||||
|         asm |         asm | ||||||
|           push es |           push ds | ||||||
|           mov bx,word [SaveInt10] |  | ||||||
|           mov dx,word [SaveInt10+2] |  | ||||||
|           mov es,dx |  | ||||||
|           mov ax, $2510 |           mov ax, $2510 | ||||||
|  |           lds dx,[SaveInt10] | ||||||
|           int $21 |           int $21 | ||||||
|           pop es |           pop ds | ||||||
|         end; |         end; | ||||||
|       {$endif ndef TEST_FPU_INT10} |       {$endif ndef TEST_FPU_INT10} | ||||||
|   end; |   end; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 pierre
						pierre