diff --git a/Makefile b/Makefile index a97d38c..b039eff 100644 --- a/Makefile +++ b/Makefile @@ -345,8 +345,6 @@ $(WEB)/ueforth.js: \ # ---- POSIX ---- -POSIX_CFLAGS = -DHAS_SIGNALS - posix: posix_target posix_tests posix_target: $(POSIX)/ueforth @@ -355,6 +353,7 @@ $(POSIX): $(POSIX)/ueforth: \ posix/main.c \ + posix/faults.h \ common/tier0_opcodes.h \ common/tier1_opcodes.h \ common/tier2_opcodes.h \ @@ -365,7 +364,7 @@ $(POSIX)/ueforth: \ common/bits.h \ common/core.h \ $(GEN)/posix_boot.h | $(POSIX) - $(CXX) $(CFLAGS) $(POSIX_CFLAGS) $< -o $@ $(LIBS) + $(CXX) $(CFLAGS) $< -o $@ $(LIBS) strip $(STRIP_ARGS) $@ # ---- WINDOWS ---- @@ -434,6 +433,7 @@ $(GEN)/esp32_sim_opcodes.h: $(GEN)/print-esp32-builtins | $(GEN) $(ESP32_SIM)/Esp32forth-sim: \ esp32/sim_main.cpp \ esp32/main.cpp \ + esp32/faults.h \ common/tier0_opcodes.h \ common/tier1_opcodes.h \ common/tier2_opcodes.h \ @@ -468,6 +468,7 @@ ESP32_PARTS = tools/replace.js \ common/bits.h \ common/core.h \ common/interp.h \ + esp32/faults.h \ esp32/options.h \ esp32/builtins.h \ esp32/builtins.cpp \ @@ -487,6 +488,7 @@ $(ESP32)/ESP32forth/ESP32forth.ino: $(ESP32_PARTS) | $(ESP32)/ESP32forth bits=@common/bits.h \ core=@common/core.h \ interp=@common/interp.h \ + faults=@esp32/faults.h \ options=@esp32/options.h \ builtins.h=@esp32/builtins.h \ builtins.cpp=@esp32/builtins.cpp \ diff --git a/common/interp.h b/common/interp.h index 3eb9fd4..fec38e8 100644 --- a/common/interp.h +++ b/common/interp.h @@ -12,43 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if defined(HAS_SIGNALS) || defined(ENABLE_ESP32_FORTH_FAULT_HANDLING) -# include -#endif -#if defined(HAS_SIGNALS) -# include -#endif - #define JMPW goto **(void **) w #define NEXT w = *ip++; JMPW #define ADDROF(x) (&& OP_ ## x) -#if defined(HAS_SIGNALS) || defined(ENABLE_ESP32_FORTH_FAULT_HANDLING) -static __thread jmp_buf g_forth_fault; -static __thread int g_forth_signal; -#endif - -#if defined(HAS_SIGNALS) -static void forth_signal_handler(int sig) { - g_forth_signal = sig; - sigset_t ss; - sigemptyset(&ss); - sigprocmask(SIG_SETMASK, &ss, 0); - longjmp(g_forth_fault, 1); -} -#endif - -#if defined(ENABLE_ESP32_FORTH_FAULT_HANDLING) -# include "soc/soc.h" -# include -static __thread uint32_t g_forth_setlevel; -static void IRAM_ATTR forth_exception_handler(XtExcFrame *frame) { - g_forth_signal = frame->exccause; - XTOS_RESTORE_INTLEVEL(g_forth_setlevel); - longjmp(g_forth_fault, 1); -} -#endif - static cell_t *forth_run(cell_t *init_rp) { static const BUILTIN_WORD builtins[] = { #define Z(flags, name, op, code) \ @@ -65,46 +32,12 @@ static cell_t *forth_run(cell_t *init_rp) { if (!init_rp) { g_sys->DOCREATE_OP = ADDROF(DOCREATE); g_sys->builtins = builtins; -#if defined(HAS_SIGNALS) - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = forth_signal_handler; - sigaction(SIGSEGV, &sa, 0); - sigaction(SIGBUS, &sa, 0); - sigaction(SIGINT, &sa, 0); - sigaction(SIGFPE, &sa, 0); -#endif -#if defined(ENABLE_ESP32_FORTH_FAULT_HANDLING) - xt_set_exception_handler(EXCCAUSE_LOAD_STORE_ERROR, forth_exception_handler); - xt_set_exception_handler(EXCCAUSE_PRIVILEGED, forth_exception_handler); - xt_set_exception_handler(EXCCAUSE_UNALIGNED, forth_exception_handler); - xt_set_exception_handler(EXCCAUSE_DIVIDE_BY_ZERO, forth_exception_handler); - xt_set_exception_handler(EXCCAUSE_INSTR_ERROR, forth_exception_handler); - xt_set_exception_handler(EXCCAUSE_ILLEGAL, forth_exception_handler); - xt_set_exception_handler(EXCCAUSE_LOAD_PROHIBITED, forth_exception_handler); - xt_set_exception_handler(EXCCAUSE_STORE_PROHIBITED, forth_exception_handler); - xt_set_exception_handler(EXCCAUSE_INSTR_PROHIBITED, forth_exception_handler); - uint32_t default_setlevel = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); - XTOS_RESTORE_INTLEVEL(default_setlevel); - g_forth_setlevel = default_setlevel; -#endif + forth_faults_setup(); return 0; } register cell_t *ip, *rp, *sp, tos, w; register float *fp, ft; - rp = init_rp; UNPARK; -#if defined(HAS_SIGNALS) || defined(ENABLE_ESP32_FORTH_FAULT_HANDLING) - if (setjmp(g_forth_fault)) { - rp = *g_sys->throw_handler; - *g_sys->throw_handler = (cell_t *) *rp--; - sp = (cell_t *) *rp--; - fp = (float *) *rp--; - ip = (cell_t *) *rp--; - --sp; - tos = -g_forth_signal; - } -#endif - NEXT; + rp = init_rp; UNPARK; FAULT_ENTRY; NEXT; #define Z(flags, name, op, code) OP_ ## op: { code; } NEXT; PLATFORM_OPCODE_LIST TIER2_OPCODE_LIST diff --git a/common/tier0_opcodes.h b/common/tier0_opcodes.h index 249845e..0dbb2f8 100644 --- a/common/tier0_opcodes.h +++ b/common/tier0_opcodes.h @@ -34,6 +34,9 @@ typedef uintptr_t ucell_t; #define PARK DUP; *++rp = (cell_t) fp; *++rp = (cell_t) sp; *++rp = (cell_t) ip #define UNPARK ip = (cell_t *) *rp--; sp = (cell_t *) *rp--; fp = (float *) *rp--; DROP +#define THROWIT(n) rp = *g_sys->throw_handler; *g_sys->throw_handler = (cell_t *) *rp--; \ + sp = (cell_t *) *rp--; fp = (float *) *rp--; ip = (cell_t *) *rp--; \ + NIP; tos = (n); #define TOFLAGS(xt) ((uint8_t *) (((cell_t *) (xt)) - 1)) #define TONAMELEN(xt) (TOFLAGS(xt) + 1) diff --git a/esp32/builtins.cpp b/esp32/builtins.cpp index f015e04..273b254 100644 --- a/esp32/builtins.cpp +++ b/esp32/builtins.cpp @@ -17,6 +17,7 @@ static char filename2[PATH_MAX]; {{bits}} {{core}} +{{faults}} {{interp}} {{boot}} diff --git a/esp32/faults.h b/esp32/faults.h new file mode 100644 index 0000000..a28e97c --- /dev/null +++ b/esp32/faults.h @@ -0,0 +1,54 @@ +// Copyright 2023 Bradley D. Nelson +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#if defined(ENABLE_ESP32_FORTH_FAULT_HANDLING) + +#include +#include "soc/soc.h" +#include + +static __thread jmp_buf g_forth_fault; +static __thread int g_forth_signal; +static __thread uint32_t g_forth_setlevel; + +#define FAULT_ENTRY \ + if (setjmp(g_forth_fault)) { THROWIT(-g_forth_signal); } + +static void IRAM_ATTR forth_exception_handler(XtExcFrame *frame) { + g_forth_signal = frame->exccause; + XTOS_RESTORE_INTLEVEL(g_forth_setlevel); + longjmp(g_forth_fault, 1); +} + +static void forth_faults_setup(void) { + xt_set_exception_handler(EXCCAUSE_LOAD_STORE_ERROR, forth_exception_handler); + xt_set_exception_handler(EXCCAUSE_PRIVILEGED, forth_exception_handler); + xt_set_exception_handler(EXCCAUSE_UNALIGNED, forth_exception_handler); + xt_set_exception_handler(EXCCAUSE_DIVIDE_BY_ZERO, forth_exception_handler); + xt_set_exception_handler(EXCCAUSE_INSTR_ERROR, forth_exception_handler); + xt_set_exception_handler(EXCCAUSE_ILLEGAL, forth_exception_handler); + xt_set_exception_handler(EXCCAUSE_LOAD_PROHIBITED, forth_exception_handler); + xt_set_exception_handler(EXCCAUSE_STORE_PROHIBITED, forth_exception_handler); + xt_set_exception_handler(EXCCAUSE_INSTR_PROHIBITED, forth_exception_handler); + uint32_t default_setlevel = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); + XTOS_RESTORE_INTLEVEL(default_setlevel); + g_forth_setlevel = default_setlevel; +} + +#else + +#define forth_faults_setup() +#define FAULT_ENTRY + +#endif diff --git a/esp32/sim_main.cpp b/esp32/sim_main.cpp index c979c0e..39c45f3 100644 --- a/esp32/sim_main.cpp +++ b/esp32/sim_main.cpp @@ -42,6 +42,9 @@ PLATFORM_SIMULATED_OPCODE_LIST // Fault handling can't work in the simulator for now. #undef ENABLE_ESP32_FORTH_FAULT_HANDLING +#define forth_faults_setup() +#define FAULT_ENTRY + #include "common/bits.h" #include "common/core.h" #include "common/interp.h" diff --git a/posix/faults.h b/posix/faults.h new file mode 100644 index 0000000..521940f --- /dev/null +++ b/posix/faults.h @@ -0,0 +1,40 @@ +// Copyright 2023 Bradley D. Nelson +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +static __thread jmp_buf g_forth_fault; +static __thread int g_forth_signal; + +#define FAULT_ENTRY \ + if (setjmp(g_forth_fault)) { THROWIT(-g_forth_signal); } + +static void forth_signal_handler(int sig) { + g_forth_signal = sig; + sigset_t ss; + sigemptyset(&ss); + sigprocmask(SIG_SETMASK, &ss, 0); + longjmp(g_forth_fault, 1); +} + +static void forth_faults_setup(void) { + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = forth_signal_handler; + sigaction(SIGSEGV, &sa, 0); + sigaction(SIGBUS, &sa, 0); + sigaction(SIGINT, &sa, 0); + sigaction(SIGFPE, &sa, 0); +} diff --git a/posix/main.c b/posix/main.c index fdd569d..2252ee6 100644 --- a/posix/main.c +++ b/posix/main.c @@ -34,6 +34,7 @@ #include "common/bits.h" #include "common/core.h" +#include "posix/faults.h" #include "common/interp.h" #include "gen/posix_boot.h" diff --git a/windows/interp.h b/windows/interp.h index 2566098..edc9a64 100644 --- a/windows/interp.h +++ b/windows/interp.h @@ -62,13 +62,7 @@ work: } } } __except (1) { - rp = *g_sys->throw_handler; - *g_sys->throw_handler = (cell_t *) *rp--; - sp = (cell_t *) *rp--; - fp = (float *) *rp--; - ip = (cell_t *) *rp--; - --sp; - tos = GetExceptionCode(); + THROWIT(GetExceptionCode()); } } }