mlibc: GNU Gcc support: setjmp, longjmp.

* stage0/x86.M1 (jmp____*%ebx): New macro.
  (mov____0x8(%ebp),%ebp): New macro.
  (mov____0x8(%ebp),%esp): New macro.
* include/setjmp.h (jmp_buf): Redefine as struct.
* lib/libc-mes+tcc.c (longjmp, setjmp): Implement.
* scaffold/tests/80-setjmp.c: Test it.
* make.scm ("80-setjmp"): Build it.
* .gitignore: Ignore *.tcc-guile.
This commit is contained in:
Jan Nieuwenhuizen 2017-11-26 13:10:46 +01:00
parent 83f2a55c2c
commit e8884d83e1
6 changed files with 136 additions and 4 deletions

2
.gitignore vendored
View file

@ -18,6 +18,7 @@
*.mini-hex2
*.mlibc-gcc
*.mlibc-o
*.tcc-guile
!/stage0/*
!/stage0/*.c
/stage0/exit-42.*
@ -48,3 +49,4 @@
/doc/fosdem/fosdem.tex
/doc/fosdem/fosdem.toc
/doc/fosdem/fosdem.*vrb

View file

@ -25,7 +25,20 @@
#include_next <setjmp.h>
#else // ! (__GNUC__ && POSIX)
typedef int jmp_buf;
typedef struct
{
int __bp;
int __pc;
int __sp;
} __jmp_buf;
typedef __jmp_buf jmp_buf[1];
#if __MESC__
__jmp_buf buf[1];
#else
jmp_buf buf;
#endif
void longjmp (jmp_buf env, int val);
int setjmp (jmp_buf env);

View file

@ -184,7 +184,27 @@ localtime (time_t const *timep)
void
longjmp (jmp_buf env, int val)
{
eputs ("longjmp stub\n");
val = val == 0 ? 1 : val;
#if __MESC__
asm ("mov____0x8(%ebp),%eax !0x0c"); // val
asm ("mov____0x8(%ebp),%ebp !0x08"); // env*
asm ("mov____0x8(%ebp),%ebx !0x4"); // env.__pc
asm ("mov____0x8(%ebp),%esp !0x8"); // env.__sp
asm ("mov____0x8(%ebp),%ebp !0x0"); // env.__bp
asm ("jmp____*%ebx");
#else
asm ("mov 0xc(%ebp),%eax\n\t" // val
"mov 0x8(%ebp),%ebp\n\t" // env*
"mov 0x4(%ebp),%ebx\n\t" // env->__pc
"mov 0x8(%ebp),%esp\n\t" // env->__sp
"mov 0x0(%ebp),%ebp\n\t" // env->__bp
"jmp *%ebx\n\t" // jmp *PC
);
#endif
// not reached
exit (42);
}
void *
@ -235,10 +255,36 @@ remove (char const *file_name)
return 0;
}
#if 0
int
setjmp_debug (jmp_buf env, int val)
{
int i;
#if 1
i = env->__bp;
i = env->__pc;
i = env->__sp;
#else
i = env[0].__bp;
i = env[0].__pc;
i = env[0].__sp;
#endif
return val == 0 ? 1 : val;
}
#endif
#if __MESC__
int
setjmp (__jmp_buf *env)
#else
int
setjmp (jmp_buf env)
#endif
{
eputs ("setjmp stub\n");
int *p = (int*)&env;
env[0].__bp = p[-2];
env[0].__pc = p[-1];
env[0].__sp = (int)&env;
return 0;
}

View file

@ -128,6 +128,7 @@ exec ${GUILE-guile} --no-auto-compile -L . -L guile -C . -C guile -s "$0" ${1+"$
(add-target (bin.mescc (string-append "scaffold/tests/" name ".c") #:libc libc #:includes includes))
(add-target (check (string-append "scaffold/tests/" name "." (cond ((not libc) "0-")
((eq? libc mini-libc-mes.hex2) "mini-")
((eq? libc libc-mes+tcc.hex2) "tcc-")
(else "")) "guile") #:exit exit)))
(add-target (compile.gcc "lib/crt1.c" #:libc #f))
@ -253,6 +254,15 @@ exec ${GUILE-guile} --no-auto-compile -L . -L guile -C . -C guile -s "$0" ${1+"$
(add-target (group "check-scaffold-tests" #:dependencies (filter (target-prefix? "check-scaffold/tests") %targets)))
;; tests/80: and beyond tinycc; building GNU GCC and dependencies
(for-each
(cut add-scaffold-test <> #:libc libc-mes+tcc.hex2 #:libc-gcc libc-gcc+tcc.mlibc-o)
'("80-setjmp"))
(add-target (group "check-scaffold-tests/8" #:dependencies (filter (target-prefix? "check-scaffold/tests/8") %targets)))
(add-target (group "check-scaffold-tests" #:dependencies (filter (target-prefix? "check-scaffold/tests") %targets)))
(add-target (cpp.mescc "lib/libc-mes+tcc.c"))
(add-target (compile.mescc "lib/libc-mes+tcc.c"))

View file

@ -0,0 +1,58 @@
/* -*-comment-start: "//";comment-end:""-*-
* Mes --- Maxwell Equations of Software
* Copyright © 2017 Jan Nieuwenhuizen <janneke@gnu.org>
*
* This file is part of Mes.
*
* 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.
*
* 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 Mes. If not, see <http://www.gnu.org/licenses/>.
*/
#include "30-test.i"
#include <stdlib.h>
#include <stdio.h>
#include <setjmp.h>
int foo;
void
second()
{
if (foo++) exit (1);
printf ("second\n"); // prints
longjmp (buf,1); // jumps back to where setjmp was called - making setjmp now return 1
exit (1);
}
void
first ()
{
second ();
printf ("first\n"); // does not print
exit (2);
}
int
test ()
{
if (!setjmp (buf))
first (); // when executed, setjmp returned 0
else // when longjmp jumps back, setjmp returns 1
{
printf ("main\n"); // prints
return 0;
}
return 3;
}

View file

@ -51,8 +51,8 @@ DEFINE cmp____%al,%dl 38c2
DEFINE cmp____%edx,%eax 39d0
DEFINE hlt f4
DEFINE idiv___%ebx f7fb
DEFINE int____$0x80 cd80
DEFINE int cd
DEFINE int____$0x80 cd80
DEFINE je32 0f84
DEFINE je8 74
DEFINE jg32 0f8f
@ -60,6 +60,7 @@ DEFINE jge32 0f8d
DEFINE jl32 0f8c
DEFINE jle32 0f8e
DEFINE jmp32 e9
DEFINE jmp____*%ebx ffe3
DEFINE jne32 0f85
DEFINE lahf 9f
DEFINE lea____0x32(%ebp),%eax 8d85
@ -128,9 +129,11 @@ DEFINE mov____0x8(%eax),%eax 8b40
DEFINE mov____0x8(%eax),%ebx 8b58
DEFINE mov____0x8(%eax),%ecx 8b48
DEFINE mov____0x8(%ebp),%eax 8b45
DEFINE mov____0x8(%ebp),%ebp 8b6d
DEFINE mov____0x8(%ebp),%ebx 8b5d
DEFINE mov____0x8(%ebp),%ecx 8b4d
DEFINE mov____0x8(%ebp),%edx 8b55
DEFINE mov____0x8(%ebp),%esp 8b65
DEFINE movzbl_%al,%eax 0fb6c0
DEFINE movzbl_%dl,%edx 0fb6d2
DEFINE movzbl_(%eax),%eax 0fb600