emu387.pp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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, strings;
  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,i : longint;
  100. begin
  101. _envvar:=upcase(envvar);
  102. hp:=environ;
  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.3 1998-03-31 10:18:55 florian
  188. * exit message removed
  189. Revision 1.2 1998/03/26 12:23:17 peter
  190. * emu387 doesn't uses dos anymore (getenv copied local)
  191. * makefile compilation order changed
  192. Revision 1.1.1.1 1998/03/25 11:18:42 root
  193. * Restored version
  194. Revision 1.6 1998/03/18 15:34:46 pierre
  195. + fpu state is restaured in excep_exit
  196. less risk of problems
  197. Revision 1.5 1998/02/05 17:24:09 pierre
  198. * bug in assembler code
  199. * changed default name to wmemu387.dxe
  200. Revision 1.4 1998/02/05 17:04:59 pierre
  201. * emulation is working with wmemu387.dxe
  202. Revision 1.3 1998/01/26 11:57:34 michael
  203. + Added log at the end
  204. Revision 1.2 1998/01/19 17:04:40 pierre
  205. * bug in dxe loading corrected, emu still does not work !!
  206. Revision 1.1 1998/01/16 16:53:15 pierre
  207. emu387 is a program based on npxset from DJGPP
  208. that loads the emu387.dxe if no FPU is present
  209. or if the env var 387 is set to N
  210. }
  211. {
  212. $Log$
  213. Revision 1.3 1998-03-31 10:18:55 florian
  214. * exit message removed
  215. Revision 1.2 1998/03/26 12:23:17 peter
  216. * emu387 doesn't uses dos anymore (getenv copied local)
  217. * makefile compilation order changed
  218. Revision 1.1.1.1 1998/03/25 11:18:42 root
  219. * Restored version
  220. Revision 1.6 1998/03/18 15:34:46 pierre
  221. + fpu state is restaured in excep_exit
  222. less risk of problems
  223. Revision 1.5 1998/02/05 17:24:09 pierre
  224. * bug in assembler code
  225. * changed default name to wmemu387.dxe
  226. Revision 1.4 1998/02/05 17:04:59 pierre
  227. * emulation is working with wmemu387.dxe
  228. Revision 1.3 1998/01/26 11:57:34 michael
  229. + Added log at the end
  230. Working file: rtl/dos/go32v2/emu387.pp
  231. description:
  232. ----------------------------
  233. revision 1.2
  234. date: 1998/01/19 17:04:40; author: pierre; state: Exp; lines: +11 -2
  235. * bug in dxe loading corrected, emu still does not work !!
  236. ----------------------------
  237. revision 1.1
  238. date: 1998/01/16 16:53:15; author: pierre; state: Exp;
  239. emu387 is a program based on npxset from DJGPP
  240. that loads the emu387.dxe if no FPU is present
  241. or if the env var 387 is set to N
  242. =============================================================================
  243. }