Annotation of os2sdk/lib/emoem.asm, revision 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.