tpexcept.pas 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  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. {$ifndef UNIX}
  22. {$S-}
  23. {$endif}
  24. type
  25. jmp_buf = record
  26. {$ifdef Delphi} { must preserve: ebx, esi, edi, ebp, esp, eip only }
  27. _ebx,_esi,_edi,_ebp,_esp,_eip : longint;
  28. {$else}
  29. eax,ebx,ecx,edx,esi,edi,ebp,esp,eip,flags : longint;
  30. cs,ds,es,fs,gs,ss : word;
  31. {$endif Delphi}
  32. end;
  33. pjmp_buf = ^jmp_buf;
  34. function setjmp(var rec : jmp_buf) : longint;{$ifdef Delphi}stdcall;{$endif}
  35. procedure longjmp(const rec : jmp_buf;return_value : longint);{$ifdef Delphi}stdcall;{$endif}
  36. const
  37. recoverpospointer : pjmp_buf = nil;
  38. longjump_used : boolean = false;
  39. implementation
  40. {*****************************************************************************
  41. Exception Helpers
  42. *****************************************************************************}
  43. {$ifdef DELPHI}
  44. {$STACKFRAMES ON}
  45. function setjmp(var rec : jmp_buf) : longint; assembler;
  46. { [ebp+12]: [ebp+8]:@rec, [ebp+4]:eip', [ebp+0]:ebp' }
  47. asm // free: eax, ecx, edx
  48. { push ebp; mov ebp,esp }
  49. mov edx,rec
  50. mov [edx].jmp_buf._ebx,ebx { ebx }
  51. mov [edx].jmp_buf._esi,esi { esi }
  52. mov [edx].jmp_buf._edi,edi { edi }
  53. mov eax,[ebp] { ebp (caller stack frame) }
  54. mov [edx].jmp_buf._ebp,eax
  55. lea eax,[ebp+12] { esp [12]: [8]:@rec, [4]:eip, [0]:ebp }
  56. mov [edx].jmp_buf._esp,eax
  57. mov eax,[ebp+4]
  58. mov [edx].jmp_buf._eip,eax
  59. xor eax,eax
  60. { leave }
  61. { ret 4 }
  62. end;
  63. procedure longjmp(const rec : jmp_buf; return_value : longint);assembler;
  64. { [ebp+12]: return_value [ebp+8]:@rec, [ebp+4]:eip', [ebp+0]:ebp' }
  65. asm
  66. { push ebp, mov ebp,esp }
  67. mov edx,rec
  68. mov ecx,return_value
  69. mov ebx,[edx].jmp_buf._ebx { ebx }
  70. mov esi,[edx].jmp_buf._esi { esi }
  71. mov edi,[edx].jmp_buf._edi { edi }
  72. mov ebp,[edx].jmp_buf._ebp { ebp }
  73. mov esp,[edx].jmp_buf._esp { esp }
  74. mov eax,[edx].jmp_buf._eip { eip }
  75. push eax
  76. mov eax,ecx
  77. ret 0
  78. end;
  79. {$else not DELPHI}
  80. {$asmmode ATT}
  81. function setjmp(var rec : jmp_buf) : longint;
  82. begin
  83. asm
  84. pushl %edi
  85. movl rec,%edi
  86. movl %eax,(%edi)
  87. movl %ebx,4(%edi)
  88. movl %ecx,8(%edi)
  89. movl %edx,12(%edi)
  90. movl %esi,16(%edi)
  91. { load edi }
  92. movl -4(%ebp),%eax
  93. { ... and store it }
  94. movl %eax,20(%edi)
  95. { ebp ... }
  96. movl (%ebp),%eax
  97. movl %eax,24(%edi)
  98. { esp ... }
  99. leal 12(%ebp),%eax
  100. movl %eax,28(%edi)
  101. { the return address }
  102. movl 4(%ebp),%eax
  103. movl %eax,32(%edi)
  104. { flags ... }
  105. pushfl
  106. popl 36(%edi)
  107. { !!!!! the segment registers, not yet needed }
  108. { you need them if the exception comes from
  109. an interrupt or a seg_move }
  110. movw %cs,40(%edi)
  111. movw %ds,42(%edi)
  112. movw %es,44(%edi)
  113. movw %fs,46(%edi)
  114. movw %gs,48(%edi)
  115. movw %ss,50(%edi)
  116. { restore EDI }
  117. pop %edi
  118. { we come from the initial call }
  119. xorl %eax,%eax
  120. leave
  121. ret $4
  122. end;
  123. end;
  124. procedure longjmp(const rec : jmp_buf;return_value : longint);
  125. begin
  126. asm
  127. { restore compiler shit }
  128. popl %ebp
  129. { this is the address of rec }
  130. movl 4(%esp),%edi
  131. { save return value }
  132. movl 8(%esp),%eax
  133. movl %eax,0(%edi)
  134. { !!!!! load segment registers }
  135. movw 46(%edi),%fs
  136. movw 48(%edi),%gs
  137. { ... and some other registers }
  138. movl 4(%edi),%ebx
  139. movl 8(%edi),%ecx
  140. movl 12(%edi),%edx
  141. movl 24(%edi),%ebp
  142. { !!!!! movw 50(%edi),%es }
  143. movl 28(%edi),%esi
  144. { create a stack frame for the return }
  145. subl $16,%esi
  146. {
  147. movzwl 42(%edi),%eax
  148. !!!!! es
  149. movl %eax,(%esi)
  150. }
  151. { edi }
  152. movl 20(%edi),%eax
  153. { !!!!! es }
  154. movl %eax,(%esi)
  155. { esi }
  156. movl 16(%edi),%eax
  157. { !!!!! es }
  158. movl %eax,4(%esi)
  159. { eip }
  160. movl 32(%edi),%eax
  161. { !!!!! es }
  162. movl %eax,12(%esi)
  163. { !!!!! cs
  164. movl 40(%edi),%eax
  165. es
  166. movl %eax,16(%esi)
  167. }
  168. { load and store flags }
  169. movl 36(%edi),%eax
  170. { !!!!!
  171. es
  172. }
  173. movl %eax,8(%esi)
  174. { load return value }
  175. movl 0(%edi),%eax
  176. { load old ES
  177. !!!!! movw 44(%edi),%es
  178. }
  179. { load stack
  180. !!!!! movw 50(%edi),%ss }
  181. movl %esi,%esp
  182. { !!!!
  183. popl %ds
  184. }
  185. popl %edi
  186. popl %esi
  187. popfl
  188. ret
  189. end;
  190. end;
  191. {$endif DELPHI}
  192. end.
  193. {
  194. $Log$
  195. Revision 1.8 2002-05-18 13:34:21 peter
  196. * readded missing revisions
  197. Revision 1.7 2002/05/16 19:46:46 carl
  198. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  199. + try to fix temp allocation (still in ifdef)
  200. + generic constructor calls
  201. + start of tassembler / tmodulebase class cleanup
  202. }