Implement setjmp for ARM mescc.

* include/setjmp.h: Add ARM case.
* lib/arm-mes-mescc/setjmp.c: New file.
This commit is contained in:
Danny Milosavljevic 2020-06-04 23:00:10 +02:00
parent 48ecb2f29e
commit 6478476ed7
No known key found for this signature in database
GPG key ID: E71A35542C30BAA5
2 changed files with 70 additions and 0 deletions

View file

@ -1,6 +1,7 @@
/* -*-comment-start: "//";comment-end:""-*-
* GNU Mes --- Maxwell Equations of Software
* Copyright © 2017 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
* Copyright © 2020 Danny Milosavljevic <dannym@scratchpost.org>
*
* This file is part of GNU Mes.
*
@ -25,12 +26,21 @@
#include_next <setjmp.h>
#else // ! SYSTEM_LIBC
#if __arm__
typedef struct
{
long __fp;
long __lr;
long __sp;
} __jmp_buf;
#else
typedef struct
{
long __bp;
long __pc;
long __sp;
} __jmp_buf;
#endif
typedef __jmp_buf jmp_buf[1];
#if __MESC__

View file

@ -0,0 +1,60 @@
/* -*-comment-start: "//";comment-end:""-*-
* GNU Mes --- Maxwell Equations of Software
* Copyright © 2017,2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
* Copyright © 2020 Danny Milosavljevic <dannym@scratchpost.org>
*
* This file is part of GNU Mes.
*
* GNU Mes is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* GNU Mes is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
*/
#include <setjmp.h>
#include <stdlib.h>
void
longjmp (jmp_buf env, int val)
{
val = val == 0 ? 1 : val;
asm ("!0xc ldr____%r0,(%fp,+#$i8)"); // val
asm ("!0x8 ldr____%fp,(%fp,+#$i8)"); // env
asm ("!0x8 ldr____%sp,(%fp,+#$i8)"); // env.__sp
/* setjmp's ENV argument is missing in setjmp caller's frame. Re-add it. */
asm ("pop____%lr"); // junk
asm ("push___%ebp");
asm ("!0x4 ldr____%lr,(%fp,+#$i8)"); // env.__lr
asm ("!0x0 ldr____%fp,(%fp,+#$i8)"); // env.__fp
asm ("push___%lr");
/* Avoid function epilogue */
asm ("ret");
}
int
setjmp (__jmp_buf * env)
{
/* Function prelude emitter emits: push %lr; push %fp; %fp := %sp */
long *p = (long*)&env; // location of parameter on stack
env[0].__fp = p[-2]; // frame of caller of setjmp
env[0].__lr = p[-1]; // caller of setjmp
env[0].__sp = p; // stack of caller of setjmp (location of ENV value)
/* Function epilogue emitter emits: %sp := %fp; pop %fp; pop %lr; %pc := %lr.
That means that all of the setjmp state is gone after we return from setjmp.
Once we enter longjmp, we can't use setjmp state and have to reconstruct
the state of setjmp's call site instead. */
return 0;
}