2
0

emu387.pp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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 dos, 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. procedure npxsetup(prog_name : string);
  94. var
  95. cp : string;
  96. i : byte;
  97. have_80387 : boolean;
  98. emu_p : pointer;
  99. const
  100. veryfirst : boolean = True;
  101. begin
  102. cp:=getenv('387');
  103. if (length(cp)>0) and (upcase(cp[1])='N') then
  104. have_80387:=False
  105. else
  106. begin
  107. dpmi_set_coprocessor_emulation(1);
  108. asm
  109. call __detect_80387
  110. movb %al,have_80387
  111. end;
  112. end;
  113. if (length(cp)>0) and (upcase(cp[1])='Q') then
  114. begin
  115. if not have_80387 then
  116. write(stderr,'No ');
  117. writeln(stderr,'80387 detected.');
  118. end;
  119. if have_80387 then
  120. {/* mask all exceptions, except invalid operation */}
  121. _control87($033e, $ffff)
  122. else
  123. begin
  124. {/* Flags value 3 means coprocessor emulation, exceptions to us */}
  125. if (dpmi_set_coprocessor_emulation(3)<>0) then
  126. begin
  127. writeln(stderr,'Warning: Coprocessor not present and DPMI setup failed!');
  128. writeln(stderr,' If application attempts floating operations system may hang!');
  129. end
  130. else
  131. begin
  132. cp:=getenv('EMU387');
  133. if length(cp)=0 then
  134. begin
  135. for i:=length(prog_name) downto 1 do
  136. if (prog_name[i]='\') or (prog_name[i]='/') then
  137. break;
  138. if i>1 then
  139. cp:=copy(prog_name,1,i);
  140. cp:=cp+'wmemu387.dxe';
  141. end;
  142. emu_p:=dxe_load(cp);
  143. _emu_entry:=emu_entry_type(emu_p);
  144. if (emu_p=nil) then
  145. begin
  146. writeln(cp+' load failed !');
  147. halt;
  148. end;
  149. if veryfirst then
  150. begin
  151. veryfirst:=false;
  152. prev_exit:=exitproc;
  153. exitproc:=@restore_DPMI_fpu_state;
  154. end;
  155. signal(SIGNOFP,@nofpsig);
  156. end;
  157. end;
  158. end;
  159. begin
  160. npxsetup(paramstr(0));
  161. end.
  162. {
  163. $Log$
  164. Revision 1.1.1.1 1998-03-25 11:18:42 root
  165. * Restored version
  166. Revision 1.6 1998/03/18 15:34:46 pierre
  167. + fpu state is restaured in excep_exit
  168. less risk of problems
  169. Revision 1.5 1998/02/05 17:24:09 pierre
  170. * bug in assembler code
  171. * changed default name to wmemu387.dxe
  172. Revision 1.4 1998/02/05 17:04:59 pierre
  173. * emulation is working with wmemu387.dxe
  174. Revision 1.3 1998/01/26 11:57:34 michael
  175. + Added log at the end
  176. Revision 1.2 1998/01/19 17:04:40 pierre
  177. * bug in dxe loading corrected, emu still does not work !!
  178. Revision 1.1 1998/01/16 16:53:15 pierre
  179. emu387 is a program based on npxset from DJGPP
  180. that loads the emu387.dxe if no FPU is present
  181. or if the env var 387 is set to N
  182. }
  183. {
  184. $Log$
  185. Revision 1.1.1.1 1998-03-25 11:18:42 root
  186. * Restored version
  187. Revision 1.6 1998/03/18 15:34:46 pierre
  188. + fpu state is restaured in excep_exit
  189. less risk of problems
  190. Revision 1.5 1998/02/05 17:24:09 pierre
  191. * bug in assembler code
  192. * changed default name to wmemu387.dxe
  193. Revision 1.4 1998/02/05 17:04:59 pierre
  194. * emulation is working with wmemu387.dxe
  195. Revision 1.3 1998/01/26 11:57:34 michael
  196. + Added log at the end
  197. Working file: rtl/dos/go32v2/emu387.pp
  198. description:
  199. ----------------------------
  200. revision 1.2
  201. date: 1998/01/19 17:04:40; author: pierre; state: Exp; lines: +11 -2
  202. * bug in dxe loading corrected, emu still does not work !!
  203. ----------------------------
  204. revision 1.1
  205. date: 1998/01/16 16:53:15; author: pierre; state: Exp;
  206. emu387 is a program based on npxset from DJGPP
  207. that loads the emu387.dxe if no FPU is present
  208. or if the env var 387 is set to N
  209. =============================================================================
  210. }