|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.