R_EMUL.A 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. (* Release 3.10 *)
  2. (*-------------------------------------------------------------------------*
  3. * *
  4. * R_EMUL.A - real-mode emulator support *
  5. * *
  6. * COPYRIGHT (C) 1989..1992 Clarion Software Corporation. *
  7. * All Rights Reserved *
  8. * *
  9. *--------------------------------------------------------------------------*)
  10. module r_emul
  11. auto_select = 1 (* use 8087 if one is present at run time *)
  12. emInt = 34H
  13. public FIDRQQ = 05C32H
  14. public FIWRQQ = 0A23DH
  15. public FIERQQ = 01632H
  16. public FIARQQ = 0FE32H
  17. public FISRQQ = 00632H
  18. public FICRQQ = 00E32H
  19. public FJERQQ = 00000H
  20. public FJARQQ = 04000H
  21. public FJSRQQ = 08000H
  22. public FJCRQQ = 0C000H
  23. public FIXRQQ = 0
  24. segment EMU_INITSTATE(FAR_DATA,68H)
  25. originalVectors : org 4*10
  26. temp87 : org 2
  27. entryChoice : org 4
  28. currentInt : org 1
  29. segment _BSS(BSS, 28H)
  30. ExecFloatState : org 94
  31. segment EMU_TEXT (EMU_CODE,28H)
  32. (*%T auto_select*)
  33. (*INCLUDE E087ENTR.ASM*)
  34. (* We arrive here due to any one of nine emulation interrupts, 34H..3Ch.*)
  35. (* save registers*)
  36. (* { Obtain the instruction.*)
  37. (* Int-op - NPX instruction one of 8 different interrupts*)
  38. (* modrm - mode register/memory specifies what kind of operand*)
  39. (* { optional }*)
  40. (* offset - byte/word if modrm requires an offset*)
  41. (* The total can be from 3 to 5 bytes. Upon arrival the old cs:IP points to*)
  42. (* the third byte.*)
  43. emInt = 34H
  44. (*callFrame STRUC*) (* caller's stack top at time of stack swap*)
  45. callBP = 0
  46. callCSIP = 2
  47. callFL = 6
  48. WaitEscCode = 0D89BH (* Wait, ESC ..*)
  49. emIntCode = 034CDH (* Int 34H ..*)
  50. waitCode = 09BH
  51. segfixCode = 026H (* es:*)
  52. escCode = 0D8H
  53. nopWait = 09B90H (* nop, Wait*)
  54. e087_Entry :
  55. push bp
  56. mov bp, sp
  57. push ax
  58. push si
  59. push ds
  60. (*Not worth enabling interrupts*)
  61. (*test [bp].callFL[by1], 02 ; interrupts enabled ?*)
  62. (*jz sameInterrupts*)
  63. (* sti ; interrupt enable same as caller had*)
  64. (*sameInterrupts:*)
  65. lds si, [bp][callCSIP]
  66. mov ax, [si][-1] (* "nn" byte of Int + next byte*)
  67. sub al, emInt
  68. cmp al, 8
  69. jnb ninthFormat
  70. sub si, 2
  71. add word [si], WaitEscCode - emIntCode
  72. retryExit:
  73. mov [bp][callCSIP], si (* retry the instruction*)
  74. jmp e087_exit
  75. (* supplement byte will be*)
  76. (* - mod/r/m byte if one of the 8 default (no-segfix) interrupts*)
  77. (* - segfix + opcode if 9th interrupt AND supplement.bit5*)
  78. (* - function number if 9th AND NOT supplement.bit5*)
  79. ninthFormat:
  80. ja maybeTenth
  81. test ah, 20H
  82. jnz unknownFunction1
  83. (* we need to patch to create <wait, segfix, ESCnn>*)
  84. sub si, 2
  85. mov [bp][callCSIP], si (* retry begins at Wait*)
  86. mov byte [si], waitCode
  87. inc si
  88. mov al, ah
  89. and ax, 07C0H (* ESC number in AH, seg number in AL*)
  90. shr al, 1
  91. shr al, 1 (* align the segment number*)
  92. shr al, 1
  93. xor al, 18H (* fix the peculiar Microsoft order*)
  94. add ax, segfixCode + (escCode * 256)
  95. mov [si], ax
  96. e087_exit:
  97. pop ds
  98. pop si
  99. pop ax
  100. pop bp
  101. iret
  102. maybeTenth:
  103. cmp al, 9
  104. ja unknownFunction1
  105. sub si, 2
  106. mov word [si], nopWait
  107. jmp retryExit
  108. unknownFunction1:
  109. (* your choice of code to go here !*)
  110. jmp e087_exit
  111. (*%E*)
  112. extrn emulate8087
  113. oldFlags = 22
  114. oldCS = 20
  115. oldIP = 18
  116. oldAX = 16
  117. oldBX = 14
  118. oldBX = 12
  119. oldDX = 10
  120. oldSI = 8
  121. oldDI = 6
  122. oldDS = 4
  123. oldES = 2
  124. oldBP = 0
  125. e086_entry :
  126. sti
  127. push ax
  128. push bx
  129. push cx
  130. push dx
  131. push si
  132. push di
  133. push ds
  134. push es
  135. push bp
  136. mov bp,sp
  137. cld (* forward string direction *)
  138. lds si, [bp][oldIP]
  139. dec si (* move back to inspect Int nn instruction *)
  140. mov cx, si (* remember original IP *)
  141. sub dl, dl (* records whether there was a segment override *)
  142. lodsw
  143. sub al, emInt
  144. cmp al, 8
  145. jae unusual
  146. decoded:
  147. jmp emulate8087
  148. resume:
  149. (* ggfb: check for another float instruction *)
  150. lds si, [bp][oldIP]
  151. cmp byte ds:[si], 0CDH
  152. jne notanother
  153. inc si
  154. sub dl, dl (* records whether there was a segment override *)
  155. cld (* !! it may not be clear! *)
  156. lodsw
  157. sub al, emInt
  158. cmp al, 8
  159. jb decoded (* ax,dl,bp,si must all be valid *)
  160. je override
  161. notanother:
  162. mov sp, bp
  163. pop bp
  164. pop es
  165. pop ds
  166. pop di
  167. pop si
  168. pop dx
  169. pop cx
  170. pop bx
  171. pop ax
  172. iret
  173. unusual:
  174. ja iswait
  175. override:
  176. mov al, ah
  177. and al, 0C0H
  178. jz DSfix
  179. cmp al, 0C0H
  180. je ESfix
  181. cmp al, 080H
  182. je CSfix
  183. (*jmp SSfix*)
  184. SSfix: mov di, ss; jmp segfix
  185. CSfix: mov di, ds; jmp segfix
  186. ESfix: mov di, [bp][oldES]; jmp segfix
  187. DSfix: mov di, [bp][oldDS]; (*jmp segfix*)
  188. segfix:
  189. mov es, di
  190. lodsb (* advance to pick up mod/r/m byte *)
  191. xchg ah, al
  192. and al, 7
  193. inc dl
  194. jmp decoded
  195. iswait:
  196. mov word [si][-3], 9090H (* patch with no-ops *)
  197. jmp resume
  198. EmuInit: db 0
  199. public __FloatInit:
  200. (* Initialise EMU_INITSTATE *)
  201. push bp
  202. mov bp, sp
  203. sub sp, 2
  204. extrn __fp_1
  205. call far __fp_1
  206. push ds
  207. mov ax,EMU_INITSTATE
  208. mov ds,ax
  209. (* First check to see if a real 8087/287 is available. That allows us to*)
  210. (* select which version of NDP support is to remain resident.*)
  211. db 0DBH, 0E3H (*finit*)
  212. mov word ds:[temp87], -1
  213. mov cx,400H
  214. here2:
  215. loop here2 (*FWAIT*)
  216. db 0DDH,03EH; dw temp87; (*FSTSW temp87*)
  217. mov cx,400H
  218. here:
  219. loop here (*FWAIT*)
  220. cmp byte ds:[temp87], 0
  221. (*%T auto_select*)
  222. mov ax, e087_Entry
  223. jz installSupporter (* --- disable this for debugging ---*)
  224. (*%E*)
  225. extrn @Save8087
  226. mov ax, seg @Save8087
  227. mov es, ax
  228. mov byte es:[@Save8087], 0
  229. mov ax, e086_entry
  230. installSupporter:
  231. mov word ds:[entryChoice], ax
  232. mov word ds:[entryChoice][2], EMU_TEXT
  233. (* Set the emulation interrupt vectors to point to their handlers.*)
  234. doCapture:
  235. mov byte ds:[currentInt], emInt
  236. mov cx, 10 (* there are 10 vectors*)
  237. mov di, originalVectors
  238. rememberLoop:
  239. (* Remember earlier use of vector. They must be replaced when the program*)
  240. (* terminates.*)
  241. mov al, ds:[currentInt]
  242. mov ah, 35H (* read interrupt vector*)
  243. int 21H (* results in es:bx*)
  244. mov ds:[di][0], bx
  245. mov ds:[di][2], es
  246. add di, 4
  247. inc byte ds:[currentInt]
  248. loop rememberLoop
  249. (* Now take over the vectors.*)
  250. mov byte ds:[currentInt], emInt
  251. mov cx, 10 (* there are 10 vectors*)
  252. mov di, ds:[entryChoice][2]
  253. captureLoop:
  254. push ds
  255. mov dx, ds:[entryChoice]
  256. mov al, ds:[currentInt]
  257. mov ds, di
  258. mov ah, 25H (* set interrupt vector*)
  259. int 21H (* with value in ds:dx*)
  260. pop ds
  261. inc byte ds:[currentInt]
  262. loop captureLoop
  263. mov byte cs:[EmuInit], 1
  264. pop ds
  265. mov bx, ss
  266. jmp misProlog
  267. (*call __FloatInitInstance*)
  268. (*ret far 0*)
  269. public __FloatInitInstance:
  270. push bp
  271. mov bp, sp
  272. sub sp, 2
  273. misProlog:
  274. push ax
  275. mov ax, resume
  276. extrn __EmulInitInstance
  277. call __EmulInitInstance
  278. pop ax
  279. cmp byte cs:[EmuInit], 1
  280. jne abort
  281. finit
  282. fstcw [bp][-2]
  283. fwait
  284. or word [bp][-2], 0C00H
  285. and word [bp][-2],~001DH (* enable invalid op/underflow/overflow/divide by zero exception *)
  286. fldcw [bp][-2]
  287. extrn __FloatInitStack
  288. call far __FloatInitStack
  289. mov sp,bp
  290. pop bp
  291. abort:
  292. ret far 0
  293. public __FloatFinish:
  294. push bp
  295. mov bp, sp
  296. mov ax,EMU_INITSTATE
  297. mov ds,ax
  298. mov byte ds:[currentInt], emInt
  299. mov cx, 10 (* there are 10 vectors*)
  300. mov bx, originalVectors
  301. restoreLoop:
  302. push ds
  303. mov dx, [bx]
  304. mov al, ds:[currentInt]
  305. mov ds, [bx][2]
  306. mov ah, 25H (* set interrupt vector*)
  307. int 21H (* with value in ds:dx*)
  308. pop ds
  309. add bx, 4
  310. inc byte ds:[currentInt]
  311. loop restoreLoop
  312. pop bp
  313. ret far 0
  314. public __FloatEmulNMI:
  315. extrn __sigFp
  316. jmp far __sigFp
  317. public __FloatMathExcepDos :
  318. (*
  319. the stack contains a FAR return address to signal handler, then
  320. the far address of the point of exception, then the iret flags
  321. *)
  322. push ax (* make room for status word *)
  323. push bp
  324. mov bp,sp
  325. push ax
  326. mov ax,[bp][4] (* return ip *)
  327. mov [bp][2],ax
  328. mov ax,[bp][6] (* return cs *)
  329. mov [bp][4],ax
  330. fstsw [bp][6] (* will bring in emulator ! *)
  331. pop ax
  332. pop bp
  333. fclex
  334. extrn __math_excep
  335. jmp far __math_excep
  336. public __FloatJmpSave :
  337. st1_reg = 20
  338. st2_reg = 30
  339. push bp
  340. mov bp, sp
  341. fld st(0), st(1)
  342. fstp tbyte es:[di][st1_reg], st(0)
  343. fld st(0), st(2)
  344. fstp tbyte es:[di][st2_reg], st(0)
  345. fwait
  346. pop bp
  347. ret far 0
  348. public __FloatJmpRestore :
  349. push bp
  350. mov bp, sp
  351. fld tbyte st(0), ds:[si][st1_reg]
  352. fstp st(2), st(0)
  353. fld tbyte st(0), ds:[si][st2_reg]
  354. fstp st(3), st(0)
  355. pop bp
  356. ret far 0
  357. public __FloatExecSave :
  358. push bp
  359. mov bp, sp
  360. push ax
  361. mov ax, _BSS
  362. mov es, ax
  363. fsave es:[ExecFloatState]
  364. pop ax
  365. fwait
  366. pop bp
  367. ret far 0
  368. public __FloatExecRestore :
  369. push bp
  370. mov bp, sp
  371. push ax
  372. mov ax, _BSS
  373. mov es, ax
  374. frstor es:[ExecFloatState]
  375. pop ax
  376. fwait
  377. pop bp
  378. ret far 0
  379. ProcessFloat = 14
  380. public __FloatSave :
  381. push bp
  382. mov bp, sp
  383. fsave es:[ProcessFloat]
  384. fwait
  385. pop bp
  386. ret far 0
  387. public __FloatRestore :
  388. push bp
  389. mov bp, sp
  390. frstor ds:[ProcessFloat]
  391. fwait
  392. pop bp
  393. ret far 0
  394. segment EMU_STATE(DATA,68H)
  395. emuRecSize = 490
  396. select EMU_STATE
  397. public emuBuffer:
  398. db 0
  399. org emuRecSize-1
  400. end (*R_EMUL.A*)
  401.