tpexcept.pas 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. SetJmp and LongJmp implementation for recovery handling of the
  5. compiler
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************}
  18. unit tpexcept;
  19. {$i fpcdefs.inc}
  20. interface
  21. {$ifdef VER1_0}
  22. {$define HASNOLONGJMP}
  23. {$else}
  24. {$ifdef DELPHI}
  25. {$define HASNOLONGJMP}
  26. {$endif}
  27. {$endif}
  28. {$ifndef UNIX}
  29. {$S-}
  30. {$endif}
  31. {$ifdef HASNOLONGJMP}
  32. type
  33. jmp_buf = record
  34. {$ifdef Delphi} { must preserve: ebx, esi, edi, ebp, esp, eip only }
  35. _ebx,_esi,_edi,_ebp,_esp,_eip : longint;
  36. {$else}
  37. eax,ebx,ecx,edx,esi,edi,ebp,esp,eip,flags : longint;
  38. cs,ds,es,fs,gs,ss : word;
  39. {$endif Delphi}
  40. end;
  41. pjmp_buf = ^jmp_buf;
  42. function setjmp(var rec : jmp_buf) : longint;{$ifndef ver1_0}oldfpccall;{$endif}
  43. procedure longjmp(const rec : jmp_buf;return_value : longint);{$ifndef ver1_0}oldfpccall;{$endif}
  44. {$endif HASNOLONGJMP}
  45. const
  46. recoverpospointer : pjmp_buf = nil;
  47. longjump_used : boolean = false;
  48. implementation
  49. {$ifdef HASNOLONGJMP}
  50. {*****************************************************************************
  51. Exception Helpers
  52. *****************************************************************************}
  53. {$ifdef DELPHI}
  54. {$STACKFRAMES ON}
  55. function setjmp(var rec : jmp_buf) : longint; assembler;
  56. { [ebp+12]: [ebp+8]:@rec, [ebp+4]:eip', [ebp+0]:ebp' }
  57. asm // free: eax, ecx, edx
  58. { push ebp; mov ebp,esp }
  59. mov edx,rec
  60. mov [edx].jmp_buf._ebx,ebx { ebx }
  61. mov [edx].jmp_buf._esi,esi { esi }
  62. mov [edx].jmp_buf._edi,edi { edi }
  63. mov eax,[ebp] { ebp (caller stack frame) }
  64. mov [edx].jmp_buf._ebp,eax
  65. lea eax,[ebp+12] { esp [12]: [8]:@rec, [4]:eip, [0]:ebp }
  66. mov [edx].jmp_buf._esp,eax
  67. mov eax,[ebp+4]
  68. mov [edx].jmp_buf._eip,eax
  69. xor eax,eax
  70. { leave }
  71. { ret 4 }
  72. end;
  73. procedure longjmp(const rec : jmp_buf; return_value : longint);assembler;
  74. { [ebp+12]: return_value [ebp+8]:@rec, [ebp+4]:eip', [ebp+0]:ebp' }
  75. asm
  76. { push ebp, mov ebp,esp }
  77. mov edx,rec
  78. mov ecx,return_value
  79. mov ebx,[edx].jmp_buf._ebx { ebx }
  80. mov esi,[edx].jmp_buf._esi { esi }
  81. mov edi,[edx].jmp_buf._edi { edi }
  82. mov ebp,[edx].jmp_buf._ebp { ebp }
  83. mov esp,[edx].jmp_buf._esp { esp }
  84. mov eax,[edx].jmp_buf._eip { eip }
  85. push eax
  86. mov eax,ecx
  87. ret 0
  88. end;
  89. {$else not DELPHI}
  90. {$asmmode ATT}
  91. function setjmp(var rec : jmp_buf) : longint; {$ifndef ver1_0}oldfpccall;{$endif}
  92. begin
  93. asm
  94. pushl %edi
  95. movl rec,%edi
  96. movl %eax,(%edi)
  97. movl %ebx,4(%edi)
  98. movl %ecx,8(%edi)
  99. movl %edx,12(%edi)
  100. movl %esi,16(%edi)
  101. { load edi }
  102. movl -4(%ebp),%eax
  103. { ... and store it }
  104. movl %eax,20(%edi)
  105. { ebp ... }
  106. movl (%ebp),%eax
  107. movl %eax,24(%edi)
  108. { esp ... }
  109. leal 12(%ebp),%eax
  110. movl %eax,28(%edi)
  111. { the return address }
  112. movl 4(%ebp),%eax
  113. movl %eax,32(%edi)
  114. { flags ... }
  115. pushfl
  116. popl 36(%edi)
  117. { !!!!! the segment registers, not yet needed }
  118. { you need them if the exception comes from
  119. an interrupt or a seg_move }
  120. movw %cs,40(%edi)
  121. movw %ds,42(%edi)
  122. movw %es,44(%edi)
  123. movw %fs,46(%edi)
  124. movw %gs,48(%edi)
  125. movw %ss,50(%edi)
  126. { restore EDI }
  127. pop %edi
  128. { we come from the initial call }
  129. xorl %eax,%eax
  130. leave
  131. ret $4
  132. end;
  133. end;
  134. procedure longjmp(const rec : jmp_buf;return_value : longint); {$ifndef ver1_0}oldfpccall;{$endif}
  135. begin
  136. asm
  137. { restore compiler shit }
  138. popl %ebp
  139. { this is the address of rec }
  140. movl 4(%esp),%edi
  141. { save return value }
  142. movl 8(%esp),%eax
  143. movl %eax,0(%edi)
  144. { !!!!! load segment registers }
  145. movw 46(%edi),%fs
  146. movw 48(%edi),%gs
  147. { ... and some other registers }
  148. movl 4(%edi),%ebx
  149. movl 8(%edi),%ecx
  150. movl 12(%edi),%edx
  151. movl 24(%edi),%ebp
  152. { !!!!! movw 50(%edi),%es }
  153. movl 28(%edi),%esi
  154. { create a stack frame for the return }
  155. subl $16,%esi
  156. {
  157. movzwl 42(%edi),%eax
  158. !!!!! es
  159. movl %eax,(%esi)
  160. }
  161. { edi }
  162. movl 20(%edi),%eax
  163. { !!!!! es }
  164. movl %eax,(%esi)
  165. { esi }
  166. movl 16(%edi),%eax
  167. { !!!!! es }
  168. movl %eax,4(%esi)
  169. { eip }
  170. movl 32(%edi),%eax
  171. { !!!!! es }
  172. movl %eax,12(%esi)
  173. { !!!!! cs
  174. movl 40(%edi),%eax
  175. es
  176. movl %eax,16(%esi)
  177. }
  178. { load and store flags }
  179. movl 36(%edi),%eax
  180. { !!!!!
  181. es
  182. }
  183. movl %eax,8(%esi)
  184. { load return value }
  185. movl 0(%edi),%eax
  186. { load old ES
  187. !!!!! movw 44(%edi),%es
  188. }
  189. { load stack
  190. !!!!! movw 50(%edi),%ss }
  191. movl %esi,%esp
  192. { !!!!
  193. popl %ds
  194. }
  195. popl %edi
  196. popl %esi
  197. popfl
  198. ret
  199. end;
  200. end;
  201. {$endif DELPHI}
  202. {$endif HASNOLONGJMP}
  203. end.
  204. {
  205. $Log$
  206. Revision 1.12 2004-10-15 09:14:17 mazen
  207. - remove $IFDEF DELPHI and related code
  208. - remove $IFDEF FPCPROCVAR and related code
  209. Revision 1.11 2004/06/20 08:55:30 florian
  210. * logs truncated
  211. Revision 1.10 2004/02/12 16:00:39 peter
  212. * don't use the local longjmp for 1.9.x
  213. }