home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l291 / 5.ddi / EMOEM.AS$ / EMOEM.bin
Encoding:
Text File  |  1990-07-06  |  11.9 KB  |  443 lines

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