home *** CD-ROM | disk | FTP | other *** search
-
- ;
- ;
- ; Copyright (C) Microsoft Corporation, 1987-90
- ;
- ; This Module contains Proprietary Information of Microsoft
- ; Corporation and should be treated as Confidential.
- ;
- title emoem.asm - OEM dependent code for 80x87
-
- ;--------------------------------------------------------------------
- ;
- ; OEM customization routines for 8087/80287/80387 coprocessor
- ;
- ; This module is designed to work with the following
- ; Microsoft language releases:
- ;
- ; Microsoft C 3.00 and later
- ; Microsoft FORTRAN 77 3.30 and later
- ; Microsoft Pascal 3.30 and later
- ;
- ; This module supersedes the OEMR7.ASM module used in earlier
- ; versions of Microsoft FORTRAN 77 and Pascal. The documentation
- ; provided with the FORTRAN and Pascal releases refers to the old
- ; OEMR7.ASM module and is only slightly relevant to this module.
- ;
- ; The following routines need to be written to properly handle the
- ; 8087/808287/80387 installation, termination, and interrupt handler
- ;
- ; __FPINSTALL87 install 80x87 interrupt handler
- ; __FPTERMINATE87 deinstall 80x87 interrupt handler
- ; __fpintreset reset OEM hardware if an 80x87 interrupt
- ;
- ; ***** NEW INSTRUCTIONS *****
- ;
- ; If you want a PC clone version, do nothing. The libraries are
- ; setup for working on IBM PC's and clones.
- ;
- ; These instructions only need to be followed if a non-IBM PC
- ; clone version is desired.
- ;
- ; This module should be assembled with the
- ; Microsoft Macro Assembler Version 4.00 or later as follows:
- ;
- ; masm -DOEM -r emoem.asm;
- ;
- ; Most hardware handles the 8087/80287/80387 in one of the following
- ; three ways -
- ;
- ; 1. NMI - IBM PC and clones all handle the interrupt this way
- ; 2. single 8259
- ; 3. master/slave 8259
- ;
- ; Manufacturer specific initialization is supported for these 3
- ; machine configurations either by modifying this file and replacing
- ; the existing EMOEM module in the math libraries or by patching
- ; the .LIB and .EXE files directly.
- ;
- ; LIB 87-+EMOEM;
- ; LIB EM-+EMOEM;
- ;
- ;--------------------------------------------------------------------
-
- ifdef OEM
- if1
- %out OEM version for non-clone support
- endif
- endif
-
- ;---------------------------------------------------------------------
- ; Assembly constants.
- ;---------------------------------------------------------------------
-
- ; MS-DOS OS calls
-
- OPSYS EQU 21H
- SETVECOP EQU 25H
- GETVECOP EQU 35H
- DOSVERSION EQU 30h
- CTLCVEC EQU 23h
-
- EMULATOR_DATA segment para public 'FAR_DATA'
- assume ds:EMULATOR_DATA
-
- ; User may place data here if DS is setup properly.
- ; Recommend keeping the data items in the code segment.
-
- EMULATOR_DATA ends
-
-
-
- EMULATOR_TEXT segment para public 'CODE'
- assume cs:EMULATOR_TEXT
-
- public __FPINSTALL87 ; DO NOT CHANGE THE CASE ON
- public __FPTERMINATE87 ; THESE PUBLIC DEFINITIONS
-
- extrn __FPEXCEPTION87:near ; DO NOT CHANGE CASE
-
-
-
-
- ifdef OEM
-
- ;***********************************************************************
- ;
- ; Hardware dependent parameters in the 80x87 exception handler.
- ;
- ; For machines using 2 8259's to handle the 80x87 exception, be sure that
- ; the slave 8259 is the 1st below and the master is the 2nd.
- ;
- ; The last 4 fields allow you to enable extra interrupt lines into the
- ; 8259s. It should only be necessary to use these fields if the 80x87
- ; interrupt is being masked out by the 8259 PIC.
- ;
- ; The ocw2's (EOI commands) can be either non-specific (20H) or
- ; specific (6xH where x=0 to 7). If you do not know which interrupt
- ; request line on the 8259 the 80x87 exception uses, then you should issue
- ; the non-specific EOI (20H). Interrupts are off at this point in the
- ; interrupt handler so a higher priority interrupt will not be seen.
-
- oeminfo struc
- oemnum db 0 ; MS-DOS OEM number (IBM is 00h)
- intnum db 2 ; IBM PC clone interrupt number
- share db 0 ; nonzero if original vector should be taken
- a8259 dw 0 ; 1st 8259 (A0=0) port #
- aocw2 db 0 ; 1st 8259 (A0=0) EOI command
- b8259 dw 0 ; 2nd 8259 (A0=0) port #
- bocw2 db 0 ; 2nd 8259 (A0=0) EOI command
- a8259m dw 0 ; 1st 8259 (A0=1) port #
- aocw1m db 0 ; 1st 8259 (A0=1) value to mask against IMR
- b8259m dw 0 ; 2nd 8259 (A0=1) port #
- bocw1m db 0 ; 2nd 8259 (A0=1) value to mask against IMR
- oeminfo ends
-
- ;-----------------------------------------------------------------------
- ; OEM specific 80x87 information
- ;
- ; If the OEM number returned from the DOS version call matches,
- ; this information is automatically moved into the oem struc below.
-
- oemtab label byte ; Table of OEM specific values for 80x87
-
- ; OEM#, int, shr, a59, acw2,b59, bcw2,a59m,acw1,b59m,bcw1
-
- ;TI Professional Computer
- TI_prof oeminfo <028h,047h,000h,018h,020h,0000,0000,0000,0000,0000,0000>
-
- db 0 ; end of table
-
- ; Unique pattern that can be searched for with the debugger so that
- ; .LIB or .EXE files can be patched with the correct values.
- ; If new values are patched into .LIB or .EXE files, care must be
- ; taken in insure the values are correct. In particular, words and
- ; bytes are intermixed in oeminfo structure. Remember words are
- ; stored low byte - high byte in memory on the 8086 family.
-
- db '<<8087>>' ; older versions used '<8087>'
-
- ; Some manufacturer's machines can not be differentiated by the
- ; OEM number returned by the MS-DOS version check system call.
- ; For these machines it is necessary to replace the line below
-
- oem1 oeminfo <> ; default values for IBM PC & clones
-
- ; with one of the following. If your machine has an 80x87 capability
- ; and it is not in the list below, you should contact your hardware
- ; manufacturer for the necessary information.
-
- ;ACT Apricot
- ;oem1 oeminfo <000h,055h,000h,000h,020h,000h,000h,000h,000h,000h,000h>
-
- ;NEC APC3 and PC-9801 (OEM number returned by NEC MS-DOS's is different)
- ;oem1 oeminfo <000h,016h,000h,008h,066h,000h,067h,00Ah,0BFh,002h,07Fh>
-
- ;---------------------------------------------------------------------
-
- aoldIMR db 0 ; 1st 8259 original IMR value
- boldIMR db 0 ; 2nd 8259 original IMR value
-
- endif ;OEM
-
- statwd dw 0 ; Temporary for status word
- oldvec dd 0 ; Old value in 80x87 exception interrupt vector
- ctlc dd 0 ; Old value of Control-C vector (INT 23h)
-
- page
-
- ;---------------------------------------------------------------------
- ;
- ; Perform OEM specific initialization of the 80x87.
- ;
-
- __FPINSTALL87:
- push ds ; DS = EMULATOR_DATA
-
- push cs ; Move current CS to DS for opsys calls.
- pop ds
- assume ds:EMULATOR_TEXT
-
- ifdef OEM
- push ds
- pop es ; CS = DS = ES
- mov ah,DOSVERSION
- int OPSYS ; bh = OEM#
- cld
- mov si,offset oemtab ; start of OEM 80x87 info table
- mov di,offset oem1+1
- mov cx,(size oem1)-1
- OEMloop:
- lodsb ; get OEM#
- or al,al
- jz OEMdone ; OEM# = 0 - did not find OEM
- cmp al,bh ; correct OEM#
- je OEMfound
- add si,cx ; skip over OEM information
- jmp OEMloop
-
- OEMfound:
- rep movsb ; move the information
-
- OEMdone: ; done with automatic customization
- endif ;OEM
-
- ; Save old interrupt vector.
- ; Ask operating system for vector.
-
- ifdef OEM
- mov al,[oem1].intnum ; Interrupt vector number.
- mov ah,GETVECOP ; Operating system call interrupt.
- else
- mov ax,GETVECOP shl 8 + 2 ; get interrupt vector 2
- endif ;OEM
- int OPSYS ; Call operating system.
-
- mov word ptr [oldvec],bx ; Squirrel away old vector.
- mov word ptr [oldvec+2],es
-
- ; Have operating system install interrupt vectors.
-
- SetVector:
- mov dx,offset __fpinterrupt87 ; Load DX with 80x87 interrupt handler.
- ifdef OEM
- mov ah,SETVECOP ; Set interrupt vector code in AH.
- mov al,[oem1].intnum ; Set vector number.
- else
- mov ax,SETVECOP shl 8 + 2 ; set interrupt vector 2
- endif ;OEM
- int OPSYS ; Install vector.
-
- ; Intercept Control-C vector to guarentee cleanup
-
- mov ax,GETVECOP shl 8 + CTLCVEC
- int OPSYS
- mov word ptr [ctlc],bx
- mov word ptr [ctlc+2],es
- mov dx,offset ctlcexit
- mov ax,SETVECOP shl 8 + CTLCVEC
- int OPSYS
-
- ifdef OEM
-
- ; set up 8259's so that 80x87 interrupts are enabled
-
- mov ah,[oem1].aocw1m ; get mask for 1st 8259 IMR
- or ah,ah ; if 0, don't need to do this
- jz installdone ; and only 1 8259
- mov dx,[oem1].a8259m ; get port number for 1st 8259 (A0=1)
- in al,dx ; read old IMR value
- mov [aoldIMR],al ; save it to restore at termination
- and al,ah ; mask to enable interrupt
- jmp short $+2 ; for 286's
- out dx,al ; write out new mask value
-
- mov ah,[oem1].bocw1m ; get mask for 2nd 8259 IMR
- or ah,ah ; if 0, don't need to do this
- jz installdone ;
- mov dx,[oem1].b8259m ; get port number for 2nd 8259 (A0=1)
- in al,dx ; read old IMR value
- mov [boldIMR],al ; save it to restore at termination
- and al,ah ; mask to enable interrupt
- jmp short $+2 ; for 286's
- out dx,al ; write out new mask value
-
- installdone:
-
- endif ;OEM
-
- assume ds:EMULATOR_DATA
- pop ds
- ret
-
-
- page
- ; __FPTERMINATE87
- ;
- ; This routine should do the OEM 80x87 cleanup. This routine is called
- ; before the program exits.
- ;
- ; DS = EMULATOR_DATA
-
- __FPTERMINATE87:
- push ds
- push ax
- push dx
-
- ifdef OEM
- mov ah,SETVECOP
- mov al,[oem1].intnum
- else
- mov ax,SETVECOP shl 8 + 2
- endif ;OEM
- lds dx,[oldvec]
- int OPSYS
-
- ifdef OEM
-
- ; reset 8259 IMR's to original state
-
- push cs
- pop ds ; DS = CS
- assume ds:EMULATOR_TEXT
- cmp [oem1].aocw1m,0 ; did we have to change 1st 8259 IMR
- je term2nd8259 ; no - check 2nd 8259
- mov al,[aoldIMR] ; get old IMR
- mov dx,[oem1].a8259m ; get 1st 8259 (A0=1) port #
- out dx,al ; restore IMR
-
- term2nd8259:
- cmp [oem1].bocw1m,0 ; did we have to change 2nd 8259 IMR
- je terminatedone ; no
- mov al,[boldIMR] ; get old IMR
- mov dx,[oem1].b8259m ; get 2nd 8259 (A0=1) port #
- out dx,al ; restore IMR
-
- terminatedone:
-
- endif ;OEM
-
- pop dx
- pop ax
- pop ds
- assume ds:EMULATOR_DATA
- ret
-
-
- ; Forced cleanup of 80x87 exception handling on Control-C
-
- ctlcexit:
- push ax
- push dx
- push ds
- call __FPTERMINATE87 ; forced cleanup of exception handler
- lds dx,[ctlc] ; load old control C vector
- mov ax,SETVECOP shl 8 + CTLCVEC
- int OPSYS
- pop ds
- pop dx
- pop ax
- jmp [ctlc] ; go through old vector
-
- page
- ; __fpinterrupt87
- ;
- ; This is the 80x87 exception interrupt routine.
- ;
- ; All OEM specific interrupt and harware handling should be done in
- ; __fpintreset because __FPEXCEPTION87 (the OEM independent 80x87
- ; exception handler) may not return. __FPEXCEPTION87 also turns
- ; interrupts back on.
- ;
-
- PENDINGBIT= 80h ; Bit in status word for interrupt pending
-
- __fpinterrupt87:
- assume ds:nothing
- nop
- fnstsw [statwd] ; Store out exceptions
- push cx ; waste time
- mov cx,3
- self:
- loop self
- pop cx
- test byte ptr [statwd],PENDINGBIT ; Test for 80x87 interrupt
- jz not87int ; Not an 80x87 interrupt.
-
- ifdef OEM
- call __fpintreset ; OEM interrupt reset routine
- endif ;OEM
-
- call __FPEXCEPTION87 ; 80x87 error handling - may not return
- ; this routine turns interrupts back on
-
- ifdef OEM
- cmp [oem1].share,0 ; Should we execute the old interrupt routine?
- jnz not87int ; if so then do it
- ; else return from interrupt
-
- ; If you fall through here to do further hardware resetting, things
- ; may not always work because __FPEXCEPTION87 does not always return
- ; This only happens when the 80x87 handler gets an exception that is
- ; a fatal error in the language runtimes. I.e., divide by zero
- ; is a fatal error in all the languages, unless the control word has
- ; set to mask out divide by zero errors.
-
- endif ;OEM
-
- done8087:
- iret
-
- not87int:
- jmp [oldvec] ; We should never return from here.
-
-
- ifdef OEM
-
-
- __fpintreset:
- push ax
- push dx
- mov al,[oem1].aocw2 ; Load up EOI instruction.
- or al,al ; Is there at least one 8259 to be reset?
- jz Reset8259ret ; no
- mov dx,[oem1].a8259
- out dx,al ; Reset (master) 8259 interrupt controller.
- mov al,[oem1].bocw2 ; Load up EOI instruction.
- or al,al ; Is there a slave 8259 to be reset?
- jz Reset8259ret
- mov dx,[oem1].b8259
- out dx,al ; Reset slave 8259 interrupt controller.
-
- Reset8259ret:
- pop dx
- pop ax
- ret
-
- endif ;OEM
-
-
- EMULATOR_TEXT ends
-
- end
-