emu387.pp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993,97 by Pierre Muller,
  5. member of the Free Pascal development team.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. { Translated to FPK pascal by Pierre Muller,
  13. without changing the fpu.s file }
  14. {
  15. /* Copyright (C) 1994, 1995 Charles Sandmann ([email protected])
  16. * FPU setup and emulation hooks for DJGPP V2.0
  17. * This file maybe freely distributed, no warranty. */
  18. this file has been translated from
  19. npxsetup.c }
  20. unit emu387;
  21. interface
  22. procedure npxsetup(prog_name : string);
  23. implementation
  24. uses dxeload, dpmiexcp;
  25. type
  26. emu_entry_type = function(exc : pexception_state) : longint;
  27. var
  28. _emu_entry : emu_entry_type;
  29. procedure _control87(mask1,mask2 : word);
  30. begin
  31. {/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */}
  32. { from file cntrl87.s in src/libc/pc_hw/fpu }
  33. asm
  34. { make room on stack }
  35. pushl %eax
  36. fstcw (%esp)
  37. fwait
  38. popl %eax
  39. andl $0xffff, %eax
  40. { OK; we have the old value ready }
  41. movl mask2, %ecx
  42. notl %ecx
  43. andl %eax, %ecx /* the bits we want to keep */
  44. movl mask2, %edx
  45. andl mask1, %edx /* the bits we want to change */
  46. orl %ecx, %edx /* the new value */
  47. pushl %edx
  48. fldcw (%esp)
  49. popl %edx
  50. end;
  51. end;
  52. { the problem with the stack that is not cleared }
  53. function emu_entry(exc : pexception_state) : longint;
  54. begin
  55. emu_entry:=_emu_entry(exc);
  56. end;
  57. function nofpsig( sig : longint) : longint;
  58. var res : longint;
  59. const
  60. last_eip : longint = 0;
  61. begin
  62. {if last_eip=djgpp_exception_state^.__eip then
  63. begin
  64. writeln('emu call two times at same address');
  65. dpmi_set_coprocessor_emulation(1);
  66. _raise(SIGFPE);
  67. exit(0);
  68. end; }
  69. last_eip:=djgpp_exception_state^.__eip;
  70. res:=emu_entry(djgpp_exception_state);
  71. if res<>0 then
  72. begin
  73. writeln('emu call failed. res = ',res);
  74. dpmi_set_coprocessor_emulation(1);
  75. _raise(SIGFPE);
  76. exit(0);
  77. end;
  78. longjmp(pjmprec(djgpp_exception_state)^, djgpp_exception_state^.__eax);
  79. nofpsig:=0;
  80. end;
  81. var
  82. prev_exit : pointer;
  83. procedure restore_DPMI_fpu_state;
  84. begin
  85. exitproc:=prev_exit;
  86. dpmi_set_coprocessor_emulation(1);
  87. { writeln('Coprocessor restored '); }
  88. {/* Enable Coprocessor, no exceptions */}
  89. end;
  90. { function _detect_80387 : boolean;[C];
  91. not used because of the underscore problem }
  92. {$L fpu.o }
  93. function getenv(const envvar:string):string;
  94. { Copied here, preserves uses Dos (PFV) }
  95. var
  96. hp : ppchar;
  97. hs,
  98. _envvar : string;
  99. eqpos : longint;
  100. begin
  101. _envvar:=upcase(envvar);
  102. hp:=envp;
  103. getenv:='';
  104. while assigned(hp^) do
  105. begin
  106. hs:=strpas(hp^);
  107. eqpos:=pos('=',hs);
  108. if copy(hs,1,eqpos-1)=_envvar then
  109. begin
  110. getenv:=copy(hs,eqpos+1,255);
  111. exit;
  112. end;
  113. hp:=hp+4;
  114. end;
  115. end;
  116. procedure npxsetup(prog_name : string);
  117. var
  118. cp : string;
  119. i : byte;
  120. have_80387 : boolean;
  121. emu_p : pointer;
  122. const
  123. veryfirst : boolean = True;
  124. begin
  125. cp:=getenv('387');
  126. if (length(cp)>0) and (upcase(cp[1])='N') then
  127. have_80387:=False
  128. else
  129. begin
  130. dpmi_set_coprocessor_emulation(1);
  131. asm
  132. call __detect_80387
  133. movb %al,have_80387
  134. end;
  135. end;
  136. if (length(cp)>0) and (upcase(cp[1])='Q') then
  137. begin
  138. if not have_80387 then
  139. write(stderr,'No ');
  140. writeln(stderr,'80387 detected.');
  141. end;
  142. if have_80387 then
  143. {/* mask all exceptions, except invalid operation */}
  144. _control87($033e, $ffff)
  145. else
  146. begin
  147. {/* Flags value 3 means coprocessor emulation, exceptions to us */}
  148. if (dpmi_set_coprocessor_emulation(3)<>0) then
  149. begin
  150. writeln(stderr,'Warning: Coprocessor not present and DPMI setup failed!');
  151. writeln(stderr,' If application attempts floating operations system may hang!');
  152. end
  153. else
  154. begin
  155. cp:=getenv('EMU387');
  156. if length(cp)=0 then
  157. begin
  158. for i:=length(prog_name) downto 1 do
  159. if (prog_name[i]='\') or (prog_name[i]='/') then
  160. break;
  161. if i>1 then
  162. cp:=copy(prog_name,1,i);
  163. cp:=cp+'wmemu387.dxe';
  164. end;
  165. emu_p:=dxe_load(cp);
  166. _emu_entry:=emu_entry_type(emu_p);
  167. if (emu_p=nil) then
  168. begin
  169. writeln(cp+' load failed !');
  170. halt;
  171. end;
  172. if veryfirst then
  173. begin
  174. veryfirst:=false;
  175. prev_exit:=exitproc;
  176. exitproc:=@restore_DPMI_fpu_state;
  177. end;
  178. signal(SIGNOFP,@nofpsig);
  179. end;
  180. end;
  181. end;
  182. begin
  183. npxsetup(paramstr(0));
  184. end.
  185. {
  186. $Log$
  187. Revision 1.4 1998-05-21 19:30:51 peter
  188. * objects compiles for linux
  189. + assign(pchar), assign(char), rename(pchar), rename(char)
  190. * fixed read_text_as_array
  191. + read_text_as_pchar which was not yet in the rtl
  192. Revision 1.3 1998/03/31 10:18:55 florian
  193. * exit message removed
  194. Revision 1.2 1998/03/26 12:23:17 peter
  195. * emu387 doesn't uses dos anymore (getenv copied local)
  196. * makefile compilation order changed
  197. Revision 1.1.1.1 1998/03/25 11:18:42 root
  198. * Restored version
  199. Revision 1.6 1998/03/18 15:34:46 pierre
  200. + fpu state is restaured in excep_exit
  201. less risk of problems
  202. Revision 1.5 1998/02/05 17:24:09 pierre
  203. * bug in assembler code
  204. * changed default name to wmemu387.dxe
  205. Revision 1.4 1998/02/05 17:04:59 pierre
  206. * emulation is working with wmemu387.dxe
  207. Revision 1.3 1998/01/26 11:57:34 michael
  208. + Added log at the end
  209. Revision 1.2 1998/01/19 17:04:40 pierre
  210. * bug in dxe loading corrected, emu still does not work !!
  211. Revision 1.1 1998/01/16 16:53:15 pierre
  212. emu387 is a program based on npxset from DJGPP
  213. that loads the emu387.dxe if no FPU is present
  214. or if the env var 387 is set to N
  215. }
  216. {
  217. $Log$
  218. Revision 1.4 1998-05-21 19:30:51 peter
  219. * objects compiles for linux
  220. + assign(pchar), assign(char), rename(pchar), rename(char)
  221. * fixed read_text_as_array
  222. + read_text_as_pchar which was not yet in the rtl
  223. Revision 1.3 1998/03/31 10:18:55 florian
  224. * exit message removed
  225. Revision 1.2 1998/03/26 12:23:17 peter
  226. * emu387 doesn't uses dos anymore (getenv copied local)
  227. * makefile compilation order changed
  228. Revision 1.1.1.1 1998/03/25 11:18:42 root
  229. * Restored version
  230. Revision 1.6 1998/03/18 15:34:46 pierre
  231. + fpu state is restaured in excep_exit
  232. less risk of problems
  233. Revision 1.5 1998/02/05 17:24:09 pierre
  234. * bug in assembler code
  235. * changed default name to wmemu387.dxe
  236. Revision 1.4 1998/02/05 17:04:59 pierre
  237. * emulation is working with wmemu387.dxe
  238. Revision 1.3 1998/01/26 11:57:34 michael
  239. + Added log at the end
  240. Working file: rtl/dos/go32v2/emu387.pp
  241. description:
  242. ----------------------------
  243. revision 1.2
  244. date: 1998/01/19 17:04:40; author: pierre; state: Exp; lines: +11 -2
  245. * bug in dxe loading corrected, emu still does not work !!
  246. ----------------------------
  247. revision 1.1
  248. date: 1998/01/16 16:53:15; author: pierre; state: Exp;
  249. emu387 is a program based on npxset from DJGPP
  250. that loads the emu387.dxe if no FPU is present
  251. or if the env var 387 is set to N
  252. =============================================================================
  253. }