setjmp.c 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. /* -*-comment-start: "//";comment-end:""-*-
  2. * GNU Mes --- Maxwell Equations of Software
  3. * Copyright © 2017,2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
  4. * Copyright © 2020 Danny Milosavljevic <dannym@scratchpost.org>
  5. *
  6. * This file is part of GNU Mes.
  7. *
  8. * GNU Mes is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 3 of the License, or (at
  11. * your option) any later version.
  12. *
  13. * GNU Mes is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #include <setjmp.h>
  22. #include <stdlib.h>
  23. void
  24. longjmp (jmp_buf env, int val)
  25. {
  26. val = val == 0 ? 1 : val;
  27. asm ("!0xc ldr____%r0,(%fp,+#$i8)"); // val
  28. asm ("!0x8 ldr____%fp,(%fp,+#$i8)"); // env
  29. asm ("!0x8 ldr____%sp,(%fp,+#$i8)"); // env.__sp
  30. /* setjmp's ENV argument is missing in setjmp caller's frame. Re-add it. */
  31. asm ("pop____%lr"); // junk
  32. asm ("push___%ebp");
  33. asm ("!0x4 ldr____%lr,(%fp,+#$i8)"); // env.__lr
  34. asm ("!0x0 ldr____%fp,(%fp,+#$i8)"); // env.__fp
  35. asm ("push___%lr");
  36. /* Avoid function epilogue */
  37. asm ("ret");
  38. }
  39. int
  40. setjmp (__jmp_buf * env)
  41. {
  42. /* Function prelude emitter emits: push %lr; push %fp; %fp := %sp */
  43. long *p = (long*)&env; // location of parameter on stack
  44. env[0].__fp = p[-2]; // frame of caller of setjmp
  45. env[0].__lr = p[-1]; // caller of setjmp
  46. env[0].__sp = p; // stack of caller of setjmp (location of ENV value)
  47. /* Function epilogue emitter emits: %sp := %fp; pop %fp; pop %lr; %pc := %lr.
  48. That means that all of the setjmp state is gone after we return from setjmp.
  49. Once we enter longjmp, we can't use setjmp state and have to reconstruct
  50. the state of setjmp's call site instead. */
  51. return 0;
  52. }