diff --git a/.gitignore b/.gitignore index 4ab37c91..ea64ef76 100644 --- a/.gitignore +++ b/.gitignore @@ -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 + diff --git a/include/setjmp.h b/include/setjmp.h index c1c5300c..09ec2c63 100644 --- a/include/setjmp.h +++ b/include/setjmp.h @@ -25,7 +25,20 @@ #include_next #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); diff --git a/lib/libc-mes+tcc.c b/lib/libc-mes+tcc.c index 213448af..01d69ccd 100644 --- a/lib/libc-mes+tcc.c +++ b/lib/libc-mes+tcc.c @@ -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; } diff --git a/make.scm b/make.scm index 8f3651c8..e8419c52 100755 --- a/make.scm +++ b/make.scm @@ -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")) diff --git a/scaffold/tests/80-setjmp.c b/scaffold/tests/80-setjmp.c new file mode 100644 index 00000000..f0524929 --- /dev/null +++ b/scaffold/tests/80-setjmp.c @@ -0,0 +1,58 @@ +/* -*-comment-start: "//";comment-end:""-*- + * Mes --- Maxwell Equations of Software + * Copyright © 2017 Jan Nieuwenhuizen + * + * 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 . + */ + +#include "30-test.i" + +#include +#include +#include + +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; +} diff --git a/stage0/x86.M1 b/stage0/x86.M1 index c3bfd439..cbac03e2 100644 --- a/stage0/x86.M1 +++ b/stage0/x86.M1 @@ -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