Annotation of os2sdk/lib/emoem.asm, revision 1.1.1.1

1.1       root        1: 
                      2: ;
                      3: ;
                      4: ;      Copyright (C) Microsoft Corporation, 1987
                      5: ;
                      6: ;      This Module contains Proprietary Information of Microsoft
                      7: ;      Corporation and should be treated as Confidential.
                      8: ;
                      9: title  emoem.asm - OEM dependent code for 8087
                     10: 
                     11: ;--------------------------------------------------------------------
                     12: ;
                     13: ;      OEM customization routines for 8087/80287 coprocessor
                     14: ;
                     15: ;      This module is designed to work with the following
                     16: ;      Microsoft language releases:
                     17: ;
                     18: ;              Microsoft C 3.00 and later
                     19: ;              Microsoft FORTRAN 77 3.30 and later
                     20: ;              Microsoft Pascal 3.30 and later
                     21: ;
                     22: ;      This module supersedes the OEMR7.ASM module used in earlier
                     23: ;      versions of Microsoft FORTRAN 77 and Pascal.  The documentation
                     24: ;      provided with the FORTRAN and Pascal releases refers to the old
                     25: ;      OEMR7.ASM module and is only slightly relevant to this module.
                     26: ;
                     27: ;      The following routines need to be written to properly handle the
                     28: ;      8087/808287 installation, termination, and interrupt handler
                     29: ;
                     30: ;      __FPINSTALL87           install 8087 interrupt handler
                     31: ;      __FPTERMINATE87         deinstall 8087 interrupt handler
                     32: ;      __fpintreset            reset OEM hardware if an 8087 interrupt
                     33: ;
                     34: ;      *****  NEW INSTRUCTIONS  *****
                     35: ;
                     36: ;      If you want a PC clone version, do nothing.  The libraries are
                     37: ;      setup for working on IBM PC's and clones.
                     38: ;
                     39: ;      These instructions only need to be followed if a non-IBM PC
                     40: ;      clone version is desired.
                     41: ;
                     42: ;      This module should be assembled with the
                     43: ;      Microsoft Macro Assembler Version 4.00 or later as follows:
                     44: ;
                     45: ;              masm -DOEM -r emoem.asm;
                     46: ;
                     47: ;      Most hardware handles the 8087/80287 in one of the following
                     48: ;      three ways -
                     49: ;
                     50: ;      1.      NMI - IBM PC and clones all handle the interrupt this way
                     51: ;      2.      single 8259
                     52: ;      3.      master/slave 8259
                     53: ;
                     54: ;      Manufacturer specific initialization is supported for these 3
                     55: ;      machine configurations either by modifying this file and replacing
                     56: ;      the existing EMOEM module in the math libraries or by patching
                     57: ;      the .LIB and .EXE files directly.
                     58: ;
                     59: ;              LIB 87-+EMOEM;
                     60: ;              LIB EM-+EMOEM;
                     61: ;
                     62: ;--------------------------------------------------------------------
                     63: 
                     64: ifdef  OEM
                     65: if1
                     66:        %out    OEM version for non-clone support
                     67: endif
                     68: endif
                     69: 
                     70: ;---------------------------------------------------------------------
                     71: ;      Assembly constants.
                     72: ;---------------------------------------------------------------------
                     73: 
                     74: ; MS-DOS OS calls
                     75: 
                     76:    OPSYS       EQU     21H
                     77:    SETVECOP    EQU     25H
                     78:    GETVECOP    EQU     35H
                     79:    DOSVERSION  EQU     30h
                     80:    CTLCVEC     EQU     23h
                     81: 
                     82: EMULATOR_DATA  segment public 'FAR_DATA'
                     83: assume ds:EMULATOR_DATA
                     84: 
                     85: ;      User may place data here if DS is setup properly.
                     86: ;      Recommend keeping the data items in the code segment.
                     87: 
                     88: EMULATOR_DATA  ends
                     89: 
                     90: 
                     91: 
                     92: EMULATOR_TEXT  segment public 'CODE'
                     93: assume cs:EMULATOR_TEXT
                     94: 
                     95:        public  __FPINSTALL87           ; DO NOT CHANGE THE CASE ON
                     96:        public  __FPTERMINATE87         ; THESE PUBLIC DEFINITIONS
                     97: 
                     98:        extrn   __FPEXCEPTION87:near    ; DO NOT CHANGE CASE
                     99: 
                    100: 
                    101: ifdef  OEM
                    102: 
                    103: ;***********************************************************************
                    104: ;
                    105: ; Hardware dependent parameters in the 8087 exception handler.
                    106: ;
                    107: ; For machines using 2 8259's to handle the 8087 exception, be sure that
                    108: ; the slave 8259 is the 1st below and the master is the 2nd.
                    109: ;
                    110: ; The last 4 fields allow you to enable extra interrupt lines into the
                    111: ; 8259s.  It should only be necessary to use these fields if the 8087
                    112: ; interrupt is being masked out by the 8259 PIC.
                    113: ;
                    114: ; The ocw2's (EOI commands) can be either non-specific (20H) or
                    115: ; specific (6xH where x=0 to 7).  If you do not know which interrupt
                    116: ; request line on the 8259 the 8087 exception uses, then you should issue
                    117: ; the non-specific EOI (20H).  Interrupts are off at this point in the
                    118: ; interrupt handler so a higher priority interrupt will not be seen.
                    119: 
                    120: oeminfo struc
                    121: oemnum db      0               ; MS-DOS OEM number (IBM is 00h)
                    122: intnum db      2               ; IBM PC clone interrupt number
                    123: share  db      0               ; nonzero if original vector should be taken
                    124: a8259  dw      0               ; 1st 8259 (A0=0) port #
                    125: aocw2  db      0               ; 1st 8259 (A0=0) EOI command
                    126: b8259  dw      0               ; 2nd 8259 (A0=0) port #
                    127: bocw2  db      0               ; 2nd 8259 (A0=0) EOI command
                    128: a8259m dw      0               ; 1st 8259 (A0=1) port #
                    129: aocw1m db      0               ; 1st 8259 (A0=1) value to mask against IMR
                    130: b8259m dw      0               ; 2nd 8259 (A0=1) port #
                    131: bocw1m db      0               ; 2nd 8259 (A0=1) value to mask against IMR
                    132: oeminfo ends
                    133: 
                    134: ;-----------------------------------------------------------------------
                    135: ;      OEM specific 8087 information
                    136: ;
                    137: ;      If the OEM number returned from the DOS version call matches,
                    138: ;      this information is automatically moved into the oem struc below.
                    139: 
                    140: oemtab label   byte    ; Table of OEM specific values for 8087
                    141: 
                    142: ;              OEM#, int, shr, a59, acw2,b59, bcw2,a59m,acw1,b59m,bcw1
                    143: 
                    144: ;TI Professional Computer
                    145: TI_prof oeminfo <028h,047h,000h,018h,020h,0000,0000,0000,0000,0000,0000>
                    146: 
                    147:        db      0       ; end of table
                    148: 
                    149: ;      Unique pattern that can be searched for with the debugger so that
                    150: ;      .LIB or .EXE files can be patched with the correct values.
                    151: ;      If new values are patched into .LIB or .EXE files, care must be
                    152: ;      taken in insure the values are correct.  In particular, words and
                    153: ;      bytes are intermixed in oeminfo structure.  Remember words are
                    154: ;      stored low byte - high byte in memory on the 8086 family.
                    155: 
                    156:        db      '<<8087>>'      ; older versions used '<8087>'
                    157: 
                    158: ;      Some manufacturer's machines can not be differentiated by the
                    159: ;      OEM number returned by the MS-DOS version check system call.
                    160: ;      For these machines it is necessary to replace the line below
                    161: 
                    162: oem1   oeminfo <>              ; default values for IBM PC & clones
                    163: 
                    164: ;      with one of the following.  If your machine has an 8087 capability
                    165: ;      and it is not in the list below, you should contact your hardware
                    166: ;      manufacturer for the necessary information.
                    167: 
                    168: ;ACT Apricot
                    169: ;oem1   oeminfo <000h,055h,000h,000h,020h,000h,000h,000h,000h,000h,000h>
                    170: 
                    171: ;NEC APC3 and PC-9801  (OEM number returned by NEC MS-DOS's is different)
                    172: ;oem1   oeminfo <000h,016h,000h,008h,066h,000h,067h,00Ah,0BFh,002h,07Fh>
                    173: 
                    174: ;---------------------------------------------------------------------
                    175: 
                    176: aoldIMR        db      0       ; 1st 8259 original IMR value
                    177: boldIMR        db      0       ; 2nd 8259 original IMR value
                    178: 
                    179: endif  ;OEM
                    180: 
                    181: statwd         dw      0       ; Temporary for status word
                    182: oldvec         dd      0       ; Old value in 8087 exception interrupt vector
                    183: ctlc           dd      0       ; Old value of Control-C vector (INT 23h)
                    184: 
                    185: page
                    186: 
                    187: ;---------------------------------------------------------------------
                    188: ;
                    189: ;      Perform OEM specific initialization of the 8087.
                    190: ;
                    191: 
                    192: __FPINSTALL87:
                    193:        push    ds                      ; DS = EMULATOR_DATA
                    194: 
                    195:        push    cs                      ; Move current CS to DS for opsys calls.
                    196:        pop     ds
                    197: assume ds:EMULATOR_TEXT
                    198: 
                    199: ifdef  OEM
                    200:        push    ds
                    201:        pop     es                      ; CS = DS = ES
                    202:        mov     ah,DOSVERSION
                    203:        int     OPSYS                   ; bh = OEM#
                    204:        cld
                    205:        mov     si,offset oemtab        ; start of OEM 8087 info table
                    206:        mov     di,offset oem1+1
                    207:        mov     cx,(size oem1)-1
                    208: OEMloop:
                    209:        lodsb                           ; get OEM#
                    210:        or      al,al
                    211:        jz      OEMdone                 ; OEM# = 0 - did not find OEM
                    212:        cmp     al,bh                   ; correct OEM#
                    213:        je      OEMfound
                    214:        add     si,cx                   ; skip over OEM information
                    215:        jmp     OEMloop
                    216: 
                    217: OEMfound:
                    218:        rep     movsb                   ; move the information
                    219: 
                    220: OEMdone:                               ; done with automatic customization
                    221: endif  ;OEM
                    222: 
                    223: ; Save old interrupt vector.
                    224: ; Ask operating system for vector.
                    225: 
                    226: ifdef  OEM
                    227:        mov     al,[oem1].intnum        ; Interrupt vector number.
                    228:        mov     ah,GETVECOP             ; Operating system call interrupt.
                    229: else
                    230:        mov     ax,GETVECOP shl 8 + 2   ; get interrupt vector 2
                    231: endif  ;OEM
                    232:        int     OPSYS                   ; Call operating system.
                    233:        mov     word ptr [oldvec],bx    ; Squirrel away old vector.
                    234:        mov     word ptr [oldvec+2],es
                    235: 
                    236: ; Have operating system install interrupt vectors.
                    237: 
                    238:        mov     dx,offset __fpinterrupt87 ; Load DX with 8087 interrupt handler.
                    239: ifdef  OEM
                    240:        mov     ah,SETVECOP             ; Set interrupt vector code in AH.
                    241:        mov     al,[oem1].intnum        ; Set vector number.
                    242: else
                    243:        mov     ax,SETVECOP shl 8 + 2   ; set interrupt vector 2
                    244: endif  ;OEM
                    245:        int     OPSYS                   ; Install vector.
                    246: 
                    247: ; Intercept Control-C vector to guarentee cleanup
                    248: 
                    249:        mov     ax,GETVECOP shl 8 + CTLCVEC
                    250:        int     OPSYS
                    251:        mov     word ptr [ctlc],bx
                    252:        mov     word ptr [ctlc+2],es
                    253:        mov     dx,offset ctlcexit
                    254:        mov     ax,SETVECOP shl 8 + CTLCVEC
                    255:        int     OPSYS
                    256: 
                    257: ifdef  OEM
                    258: 
                    259: ;      set up 8259's so that 8087 interrupts are enabled
                    260: 
                    261:        mov     ah,[oem1].aocw1m        ; get mask for 1st 8259 IMR
                    262:        or      ah,ah                   ;   if 0, don't need to do this
                    263:        jz      installdone             ;   and only 1 8259
                    264:        mov     dx,[oem1].a8259m        ; get port number for 1st 8259 (A0=1)
                    265:        in      al,dx                   ; read old IMR value
                    266:        mov     [aoldIMR],al            ; save it to restore at termination
                    267:        and     al,ah                   ; mask to enable interrupt
                    268:        jmp     short $+2               ; for 286's
                    269:        out     dx,al                   ; write out new mask value
                    270: 
                    271:        mov     ah,[oem1].bocw1m        ; get mask for 2nd 8259 IMR
                    272:        or      ah,ah                   ;   if 0, don't need to do this
                    273:        jz      installdone             ;
                    274:        mov     dx,[oem1].b8259m        ; get port number for 2nd 8259 (A0=1)
                    275:        in      al,dx                   ; read old IMR value
                    276:        mov     [boldIMR],al            ; save it to restore at termination
                    277:        and     al,ah                   ; mask to enable interrupt
                    278:        jmp     short $+2               ; for 286's
                    279:        out     dx,al                   ; write out new mask value
                    280: 
                    281: installdone:
                    282: 
                    283: endif  ;OEM
                    284: 
                    285: assume ds:EMULATOR_DATA
                    286:        pop     ds
                    287:        ret
                    288: 
                    289: 
                    290: page
                    291: ;      __FPTERMINATE87
                    292: ;
                    293: ;      This routine should do the OEM 8087 cleanup.  This routine is called
                    294: ;      before the program exits.
                    295: ;
                    296: ;      DS = EMULATOR_DATA
                    297: 
                    298: __FPTERMINATE87:
                    299:        push    ds
                    300:        push    ax
                    301:        push    dx
                    302: 
                    303: ifdef  OEM
                    304:        mov     ah,SETVECOP
                    305:        mov     al,[oem1].intnum
                    306: else
                    307:        mov     ax,SETVECOP shl 8 + 2
                    308: endif  ;OEM
                    309:        lds     dx,[oldvec]
                    310:        int     OPSYS
                    311: 
                    312: ifdef  OEM
                    313: 
                    314: ;      reset 8259 IMR's to original state
                    315: 
                    316:        push    cs
                    317:        pop     ds                      ; DS = CS
                    318: assume ds:EMULATOR_TEXT
                    319:        cmp     [oem1].aocw1m,0         ; did we have to change 1st 8259 IMR
                    320:        je      term2nd8259             ;   no - check 2nd 8259
                    321:        mov     al,[aoldIMR]            ; get old IMR
                    322:        mov     dx,[oem1].a8259m        ; get 1st 8259 (A0=1) port #
                    323:        out     dx,al                   ; restore IMR
                    324: 
                    325: term2nd8259:
                    326:        cmp     [oem1].bocw1m,0         ; did we have to change 2nd 8259 IMR
                    327:        je      terminatedone           ;   no
                    328:        mov     al,[boldIMR]            ; get old IMR
                    329:        mov     dx,[oem1].b8259m        ; get 2nd 8259 (A0=1) port #
                    330:        out     dx,al                   ; restore IMR
                    331: 
                    332: terminatedone:
                    333: 
                    334: endif  ;OEM
                    335: 
                    336:        pop     dx
                    337:        pop     ax
                    338:        pop     ds
                    339: assume ds:EMULATOR_DATA
                    340:        ret
                    341: 
                    342: 
                    343: ;      Forced cleanup of 8087 exception handling on Control-C
                    344: 
                    345: ctlcexit:
                    346:        push    ax
                    347:        push    dx
                    348:        push    ds
                    349:        call    __FPTERMINATE87         ; forced cleanup of exception handler
                    350:        lds     dx,[ctlc]               ; load old control C vector
                    351:        mov     ax,SETVECOP shl 8 + CTLCVEC
                    352:        int     OPSYS
                    353:        pop     ds
                    354:        pop     dx
                    355:        pop     ax
                    356:        jmp     [ctlc]                  ; go through old vector
                    357: 
                    358: page
                    359: ;      __fpinterrupt87
                    360: ;
                    361: ;      This is the 8087 exception interrupt routine.
                    362: ;
                    363: ;      All OEM specific interrupt and harware handling should be done in
                    364: ;      __fpintreset because __FPEXCEPTION87 (the OEM independent 8087
                    365: ;      exception handler) may not return.  __FPEXCEPTION87 also turns
                    366: ;      interrupts back on.
                    367: ;
                    368: 
                    369: PENDINGBIT=    80h             ; Bit in status word for interrupt pending
                    370: 
                    371: __fpinterrupt87:
                    372: assume ds:nothing
                    373:        nop
                    374:        fnstsw  [statwd]        ; Store out exceptions
                    375:        push    cx              ; waste time
                    376:        mov     cx,3
                    377: self:
                    378:        loop    self
                    379:        pop     cx
                    380:        test    byte ptr [statwd],PENDINGBIT    ; Test for 8087 interrupt
                    381:        jz      not87int        ; Not an 8087 interrupt.
                    382: 
                    383: ifdef  OEM
                    384:        call    __fpintreset    ; OEM interrupt reset routine
                    385: endif  ;OEM
                    386: 
                    387:        call    __FPEXCEPTION87 ; 8087 error handling - may not return
                    388:                                ; this routine turns interrupts back on
                    389: 
                    390: ifdef  OEM
                    391:        cmp     [oem1].share,0  ; Should we execute the old interrupt routine?
                    392:        jnz     not87int        ;    if so then do it
                    393:                                ;    else return from interrupt
                    394: 
                    395: ;      If you fall through here to do further hardware resetting, things
                    396: ;      may not always work because __FPEXCEPTION87 does not always return
                    397: ;      This only happens when the 8087 handler gets an exception that is
                    398: ;      a fatal error in the language runtimes.  I.e., divide by zero
                    399: ;      is a fatal error in all the languages, unless the control word has
                    400: ;      set to mask out divide by zero errors.
                    401: 
                    402: endif  ;OEM
                    403: 
                    404: done8087:
                    405:        iret
                    406: 
                    407: not87int:
                    408:        jmp     [oldvec]        ; We should never return from here.
                    409: 
                    410: 
                    411: ifdef  OEM
                    412: 
                    413: 
                    414: __fpintreset:
                    415:        push    ax
                    416:        push    dx
                    417:        mov     al,[oem1].aocw2 ; Load up EOI instruction.
                    418:        or      al,al           ; Is there at least one 8259 to be reset?
                    419:        jz      Reset8259ret    ; no
                    420:        mov     dx,[oem1].a8259
                    421:        out     dx,al           ; Reset (master) 8259 interrupt controller.
                    422:        mov     al,[oem1].bocw2 ; Load up EOI instruction.
                    423:        or      al,al           ; Is there a slave 8259 to be reset?
                    424:        jz      Reset8259ret
                    425:        mov     dx,[oem1].b8259
                    426:        out     dx,al           ; Reset slave 8259 interrupt controller.
                    427: 
                    428: Reset8259ret:
                    429:        pop     dx
                    430:        pop     ax
                    431:        ret
                    432: 
                    433: endif  ;OEM
                    434: 
                    435: 
                    436: EMULATOR_TEXT  ends
                    437: 
                    438:        end

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.