tpexcept.pas 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 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. interface
  20. {$ifndef LINUX}
  21. {$S-}
  22. {$endif}
  23. {$ifdef Delphi}
  24. {$undef TP}
  25. {$endif Delphi}
  26. type
  27. jmp_buf = record
  28. {$ifdef TP}
  29. _ax,_bx,_cx,_dx,_si,_di,_bp,_sp,_ip,flags : word;
  30. _cs,_ds,_es,_ss : word;
  31. {$else}
  32. {$ifdef Delphi} { must preserve: ebx, esi, edi, ebp, esp, eip only }
  33. _ebx,_esi,_edi,_ebp,_esp,_eip : longint;
  34. {$else}
  35. eax,ebx,ecx,edx,esi,edi,ebp,esp,eip,flags : longint;
  36. cs,ds,es,fs,gs,ss : word;
  37. {$endif Delphi}
  38. {$endif TP}
  39. end;
  40. pjmp_buf = ^jmp_buf;
  41. {$ifdef TP}
  42. function setjmp(var rec : jmp_buf) : integer;
  43. procedure longjmp(const rec : jmp_buf;return_value : integer);
  44. {$else}
  45. function setjmp(var rec : jmp_buf) : longint;
  46. {$ifdef Delphi}stdcall;{$endif}
  47. procedure longjmp(const rec : jmp_buf;return_value : longint);
  48. {$ifdef Delphi}stdcall;{$endif}
  49. {$endif TP}
  50. const
  51. recoverpospointer : pjmp_buf = nil;
  52. longjump_used : boolean = false;
  53. implementation
  54. {*****************************************************************************
  55. Exception Helpers
  56. *****************************************************************************}
  57. {$ifdef TP}
  58. function setjmp(var rec : jmp_buf) : integer;
  59. begin
  60. asm
  61. push di
  62. push es
  63. les di,rec
  64. mov es:[di].jmp_buf._ax,ax
  65. mov es:[di].jmp_buf._bx,bx
  66. mov es:[di].jmp_buf._cx,cx
  67. mov es:[di].jmp_buf._dx,dx
  68. mov es:[di].jmp_buf._si,si
  69. { load di }
  70. mov ax,[bp-4]
  71. { ... and store it }
  72. mov es:[di].jmp_buf._di,ax
  73. { load es }
  74. mov ax,[bp-6]
  75. { ... and store it }
  76. mov es:[di].jmp_buf._es,ax
  77. { bp ... }
  78. mov ax,[bp]
  79. mov es:[di].jmp_buf._bp,ax
  80. { sp ... }
  81. mov ax,bp
  82. add ax,10
  83. mov es:[di].jmp_buf._sp,ax
  84. { the return address }
  85. mov ax,[bp+2]
  86. mov es:[di].jmp_buf._ip,ax
  87. mov ax,[bp+4]
  88. mov es:[di].jmp_buf._cs,ax
  89. { flags ... }
  90. pushf
  91. pop word ptr es:[di].jmp_buf.flags
  92. mov es:[di].jmp_buf._ds,ds
  93. mov es:[di].jmp_buf._ss,ss
  94. { restore es:di }
  95. pop es
  96. pop di
  97. { we come from the initial call }
  98. xor ax,ax
  99. leave
  100. retf 4
  101. end;
  102. end;
  103. procedure longjmp(const rec : jmp_buf;return_value : integer);
  104. begin
  105. asm
  106. { this is the address of rec }
  107. lds di,rec
  108. { save return value }
  109. mov ax,return_value
  110. mov ds:[di].jmp_buf._ax,ax
  111. { restore compiler shit }
  112. pop bp
  113. { restore some registers }
  114. mov bx,ds:[di].jmp_buf._bx
  115. mov cx,ds:[di].jmp_buf._cx
  116. mov dx,ds:[di].jmp_buf._dx
  117. mov bp,ds:[di].jmp_buf._bp
  118. { create a stack frame for the return }
  119. mov es,ds:[di].jmp_buf._ss
  120. mov si,ds:[di].jmp_buf._sp
  121. sub si,12
  122. { store ds }
  123. mov ax,ds:[di].jmp_buf._ds
  124. mov es:[si],ax
  125. { store di }
  126. mov ax,ds:[di].jmp_buf._di
  127. mov es:[si+2],ax
  128. { store si }
  129. mov ax,ds:[di].jmp_buf._si
  130. mov es:[si+4],ax
  131. { store flags }
  132. mov ax,ds:[di].jmp_buf.flags
  133. mov es:[si+6],ax
  134. { store ip }
  135. mov ax,ds:[di].jmp_buf._ip
  136. mov es:[si+8],ax
  137. { store cs }
  138. mov ax,ds:[di].jmp_buf._cs
  139. mov es:[si+10],ax
  140. { load stack }
  141. mov ax,es
  142. mov ss,ax
  143. mov sp,si
  144. { load return value }
  145. mov ax,ds:[di].jmp_buf._ax
  146. { load old ES }
  147. mov es,ds:[di].jmp_buf._es
  148. pop ds
  149. pop di
  150. pop si
  151. popf
  152. retf
  153. end;
  154. end;
  155. {$else}
  156. {$ifdef Delphi}
  157. {$STACKFRAMES ON}
  158. function setjmp(var rec : jmp_buf) : longint; assembler;
  159. { [ebp+12]: [ebp+8]:@rec, [ebp+4]:eip', [ebp+0]:ebp' }
  160. asm // free: eax, ecx, edx
  161. { push ebp; mov ebp,esp }
  162. mov edx,rec
  163. mov [edx].jmp_buf._ebx,ebx { ebx }
  164. mov [edx].jmp_buf._esi,esi { esi }
  165. mov [edx].jmp_buf._edi,edi { edi }
  166. mov eax,[ebp] { ebp (caller stack frame) }
  167. mov [edx].jmp_buf._ebp,eax
  168. lea eax,[ebp+12] { esp [12]: [8]:@rec, [4]:eip, [0]:ebp }
  169. mov [edx].jmp_buf._esp,eax
  170. mov eax,[ebp+4]
  171. mov [edx].jmp_buf._eip,eax
  172. xor eax,eax
  173. { leave }
  174. { ret 4 }
  175. end;
  176. procedure longjmp(const rec : jmp_buf; return_value : longint);assembler;
  177. { [ebp+12]: return_value [ebp+8]:@rec, [ebp+4]:eip', [ebp+0]:ebp' }
  178. asm
  179. { push ebp, mov ebp,esp }
  180. mov edx,rec
  181. mov ecx,return_value
  182. mov ebx,[edx].jmp_buf._ebx { ebx }
  183. mov esi,[edx].jmp_buf._esi { esi }
  184. mov edi,[edx].jmp_buf._edi { edi }
  185. mov ebp,[edx].jmp_buf._ebp { ebp }
  186. mov esp,[edx].jmp_buf._esp { esp }
  187. mov eax,[edx].jmp_buf._eip { eip }
  188. push eax
  189. mov eax,ecx
  190. ret 0
  191. end;
  192. {$else Delphi}
  193. {$asmmode ATT}
  194. function setjmp(var rec : jmp_buf) : longint;
  195. begin
  196. asm
  197. pushl %edi
  198. movl rec,%edi
  199. movl %eax,(%edi)
  200. movl %ebx,4(%edi)
  201. movl %ecx,8(%edi)
  202. movl %edx,12(%edi)
  203. movl %esi,16(%edi)
  204. { load edi }
  205. movl -4(%ebp),%eax
  206. { ... and store it }
  207. movl %eax,20(%edi)
  208. { ebp ... }
  209. movl (%ebp),%eax
  210. movl %eax,24(%edi)
  211. { esp ... }
  212. leal 12(%ebp),%eax
  213. movl %eax,28(%edi)
  214. { the return address }
  215. movl 4(%ebp),%eax
  216. movl %eax,32(%edi)
  217. { flags ... }
  218. pushfl
  219. popl 36(%edi)
  220. { !!!!! the segment registers, not yet needed }
  221. { you need them if the exception comes from
  222. an interrupt or a seg_move }
  223. movw %cs,40(%edi)
  224. movw %ds,42(%edi)
  225. movw %es,44(%edi)
  226. movw %fs,46(%edi)
  227. movw %gs,48(%edi)
  228. movw %ss,50(%edi)
  229. { restore EDI }
  230. pop %edi
  231. { we come from the initial call }
  232. xorl %eax,%eax
  233. leave
  234. ret $4
  235. end;
  236. end;
  237. procedure longjmp(const rec : jmp_buf;return_value : longint);
  238. begin
  239. asm
  240. { restore compiler shit }
  241. popl %ebp
  242. { this is the address of rec }
  243. movl 4(%esp),%edi
  244. { save return value }
  245. movl 8(%esp),%eax
  246. movl %eax,0(%edi)
  247. { !!!!! load segment registers }
  248. movw 46(%edi),%fs
  249. movw 48(%edi),%gs
  250. { ... and some other registers }
  251. movl 4(%edi),%ebx
  252. movl 8(%edi),%ecx
  253. movl 12(%edi),%edx
  254. movl 24(%edi),%ebp
  255. { !!!!! movw 50(%edi),%es }
  256. movl 28(%edi),%esi
  257. { create a stack frame for the return }
  258. subl $16,%esi
  259. {
  260. movzwl 42(%edi),%eax
  261. !!!!! es
  262. movl %eax,(%esi)
  263. }
  264. { edi }
  265. movl 20(%edi),%eax
  266. { !!!!! es }
  267. movl %eax,(%esi)
  268. { esi }
  269. movl 16(%edi),%eax
  270. { !!!!! es }
  271. movl %eax,4(%esi)
  272. { eip }
  273. movl 32(%edi),%eax
  274. { !!!!! es }
  275. movl %eax,12(%esi)
  276. { !!!!! cs
  277. movl 40(%edi),%eax
  278. es
  279. movl %eax,16(%esi)
  280. }
  281. { load and store flags }
  282. movl 36(%edi),%eax
  283. { !!!!!
  284. es
  285. }
  286. movl %eax,8(%esi)
  287. { load return value }
  288. movl 0(%edi),%eax
  289. { load old ES
  290. !!!!! movw 44(%edi),%es
  291. }
  292. { load stack
  293. !!!!! movw 50(%edi),%ss }
  294. movl %esi,%esp
  295. { !!!!
  296. popl %ds
  297. }
  298. popl %edi
  299. popl %esi
  300. popfl
  301. ret
  302. end;
  303. end;
  304. {$endif Delphi}
  305. {$endif TP}
  306. end.
  307. {
  308. $Log$
  309. Revision 1.13 2000-05-11 09:36:22 pierre
  310. * Delphi implementation by Kovacs Attila Zoltan
  311. Revision 1.12 2000/02/24 18:41:39 peter
  312. * removed warnings/notes
  313. Revision 1.11 2000/02/11 23:59:35 jonas
  314. + $asmmode att for people with -Rintel in their ppc386.cfg
  315. Revision 1.10 2000/02/09 13:23:08 peter
  316. * log truncated
  317. Revision 1.9 2000/01/07 01:14:48 peter
  318. * updated copyright to 2000
  319. Revision 1.8 1999/08/18 11:35:59 pierre
  320. * esp loading corrected
  321. }