setjump.inc 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 2002 by Jonas Maebe and other members of the
  5. Free Pascal development team
  6. SetJmp and LongJmp implementation for exception handling
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. {#define ENV(base,reg) [%base + (reg * 4)]
  14. #define ST_FLUSH_WINDOWS 3
  15. #define RW_FP [%fp + 0x48]
  16. }
  17. {$ifdef needsigprocmask}
  18. const
  19. JMPSIG_BLOCK = 1;
  20. JMPSIG_SETMASK = 4;
  21. {$ifdef FPC_USE_LIBC}
  22. function JmpSigProcMask(how:longint;nset : pjmpsigset;oset : pjmpsigset):longint; external name 'sigprocmask';
  23. {$else}
  24. function JmpSigProcMask(how:longint;nset : pjmpsigset;oset : pjmpsigset):longint; external name 'FPC_SYSC_SIGPROCMASK';
  25. {$endif}
  26. procedure savesigmask(var s:jmp_buf);
  27. begin
  28. jmpsigprocmask(JMPSIG_BLOCK,nil,@s.sigmask);
  29. end;
  30. procedure restoresigmask(var s:jmp_buf);
  31. begin
  32. jmpsigprocmask(JMPSIG_SETMASK,@s.sigmask,nil);
  33. end;
  34. {$endif needsigprocmask}
  35. procedure longjmp(var s : jmp_buf;value:longint);assembler;nostackframe;[Public,alias:'FPC_LONGJMP'];
  36. asm
  37. // Store our arguments in global registers so we can still
  38. // use them while unwinding frames and their register windows.
  39. ld [%o0+4], %g3 // Cache target FP in register %g3.
  40. mov %o0, %g1 // s in %g1
  41. orcc %o1, %g0, %g2 // value in %g2
  42. be,a .L0 // Branch if zero; else skip delay slot.
  43. mov 1, %g2 // Delay slot only hit if zero: VAL = 1.
  44. .L0:
  45. xor %fp, %g3, %o0
  46. add %fp, 512, %o1
  47. andncc %o0, 4095, %o0
  48. bne .Lthread
  49. cmp %o1, %g3
  50. bl .Lthread
  51. // Now we will loop, unwinding the register windows up the stack
  52. // until the restored %fp value matches the target value in %g3.
  53. .Lloop:
  54. cmp %fp, %g3 // Have we reached the target frame?
  55. bl,a .Lloop // Loop while current fp is below target.
  56. restore // Unwind register window in delay slot.
  57. be,a .Lfound // Better have hit it exactly.
  58. ld [%g1], %o0 // Delay slot: extract target SP.
  59. .Lthread:
  60. {
  61. * Do a "flush register windows trap". The trap handler in the
  62. * kernel writes all the register windows to their stack slots, and
  63. * marks them all as invalid (needing to be sucked up from the
  64. * stack when used). This ensures that all information needed to
  65. * unwind to these callers is in memory, not in the register
  66. * windows.
  67. }
  68. ta 3
  69. mov %g1,%o1 // use %o1, since %g1 will be destroyed by the call below
  70. ld [%o1], %fp // Set saved SP on restore below.
  71. sub %fp, 64, %sp // Allocate a register frame.
  72. st %g3, [%fp+48] // Set saved FP on restore below.
  73. {$ifdef needsigprocmask}
  74. mov %o1,%o0
  75. call restoresigmask
  76. nop
  77. {$endif needsigprocmask}
  78. ld [%o1+8], %o7 // Set return PC.
  79. retl
  80. restore %g2, 0, %o0 // Restore values from above register frame.
  81. .Lfound:
  82. // We have unwound register windows so %fp matches the target.
  83. mov %o0, %sp // OK, install new SP.
  84. .Lsp_ok:
  85. ld [%g1+8], %o0 // Extract target return PC.
  86. jmp %o0+8 // Return there.
  87. mov %g2, %o0 // Delay slot: set return value.
  88. end;
  89. function setjmp(var S:jmp_buf):longint;assembler;nostackframe;[Public,alias:'FPC_SETJMP'];
  90. asm
  91. // We don't create a stackframe so we can save PC,SP and FP of the caller
  92. st %o7, [%o0+8]
  93. st %sp, [%o0]
  94. st %fp, [%o0+4]
  95. {$ifdef needsigprocmask}
  96. call savesigmask
  97. nop
  98. {$endif needsigprocmask}
  99. ld [%o0+8], %o7
  100. mov %g0, %o0
  101. end;
  102. {
  103. $Log$
  104. Revision 1.11 2005-02-13 20:01:38 peter
  105. * include file cleanup
  106. Revision 1.10 2005/01/20 16:38:28 peter
  107. * restore sigprocmask for linux
  108. Revision 1.9 2004/09/12 12:04:22 peter
  109. * restore traps when returning with longjmp
  110. Revision 1.8 2004/05/31 10:43:00 peter
  111. * don't create stackframes so we can retrieve the info from
  112. the caller
  113. Revision 1.7 2004/05/30 12:08:32 florian
  114. * setjmp on sparc improved
  115. Revision 1.6 2004/05/25 21:38:11 peter
  116. * fixed input registers
  117. Revision 1.5 2004/05/18 19:36:37 florian
  118. * started to fix set/longjmp on sparc
  119. Revision 1.4 2003/01/05 21:32:35 mazen
  120. * fixing several bugs compiling the RTL
  121. Revision 1.3 2002/12/24 21:30:20 mazen
  122. - some writeln(s) removed in compiler
  123. + many files added to RTL
  124. * some errors fixed in RTL
  125. Revision 1.2 2002/11/24 18:19:44 mazen
  126. + setjmp and longjmp
  127. Revision 1.1 2002/11/16 20:10:31 florian
  128. + sparc specific rtl skeleton added
  129. }