diff --git a/ueforth/Makefile b/ueforth/Makefile index 6a3a561..ddfbb68 100644 --- a/ueforth/Makefile +++ b/ueforth/Makefile @@ -7,11 +7,13 @@ WINDOWS = $(OUT)/windows ARDUINO = $(OUT)/arduino DEPLOY = $(OUT)/deploy -CFLAGS_COMMON = -Wall -Werror \ - -O2 \ +CFLAGS_COMMON = -O2 -I ./ -I $(OUT) + +CFLAGS_MINIMIZE = \ -s \ - -ffreestanding \ + -DUEFORTH_MINIMAL \ -fno-exceptions \ + -ffreestanding \ -fno-stack-check \ -fno-stack-protector \ -fno-stack-protector \ @@ -19,9 +21,10 @@ CFLAGS_COMMON = -Wall -Werror \ -mno-stack-arg-probe \ -fno-ident -Wl,--build-id=none \ -ffunction-sections -fdata-sections \ - -fmerge-all-constants \ - -I ./ -I $(OUT) + -fmerge-all-constants CFLAGS = $(CFLAGS_COMMON) \ + -Wall \ + -Werror \ -Wl,--gc-sections STRIP_ARGS = -S \ --strip-unneeded \ @@ -32,39 +35,57 @@ STRIP_ARGS = -S \ --remove-section=.note.ABI-tag LIBS=-ldl -WIN_CFLAGS = $(CFLAGS_COMMON) -mwindows -nostdlib \ +WIN_CFLAGS = $(CFLAGS_COMMON) \ + -I "c:/Program Files (x86)/Microsoft SDKs/Windows/v7.1A/Include" \ + -I "c:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.28.29333/include" \ + -I "c:/Program Files (x86)/Windows Kits/10/Include/10.0.19041.0/ucrt" -WIN_LIBS = -lkernel32 +WIN_LFLAGS32 = /LIBPATH:"c:/Program Files (x86)/Microsoft SDKs/Windows/v7.1A/Lib" \ + /LIBPATH:"c:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.28.29333/lib/x86" \ + /LIBPATH:"c:/Program Files (x86)/Windows Kits/10/Lib/10.0.19041.0/ucrt/x86" + +WIN_LFLAGS64 = /LIBPATH:"c:/Program Files (x86)/Microsoft SDKs/Windows/v7.1A/Lib/x64" \ + /LIBPATH:"c:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.28.29333/lib/x64" \ + /LIBPATH:"c:/Program Files (x86)/Windows Kits/10/Lib/10.0.19041.0/ucrt/x64" \ TARGETS = $(WEB)/terminal.html \ $(WEB)/ueforth.js \ $(POSIX)/ueforth \ $(ARDUINO)/ueforth/ueforth.ino +PROGFILES = /mnt/c/Program Files (x86) +CL32 = "$(shell find "${PROGFILES}/Microsoft Visual Studio" -name cl.exe | grep /Hostx86/x86/ | head -n 1)" +CL64 = "$(shell find "${PROGFILES}/Microsoft Visual Studio" -name cl.exe | grep /Hostx86/x64/ | head -n 1)" +LINK32 = "$(shell find "${PROGFILES}/Microsoft Visual Studio" -name link.exe | grep /Hostx86/x86/ | head -n 1)" +LINK64 = "$(shell find "${PROGFILES}/Microsoft Visual Studio" -name link.exe | grep /Hostx86/x64/ | head -n 1)" +RC32 = "$(shell find "${PROGFILES}/Windows Kits" -name rc.exe | grep /x86/ | head -n 1)" +RC64 = "$(shell find "${PROGFILES}/Windows Kits" -name rc.exe | grep /x64/ | head -n 1)" + # Selectively enable windows if tools available DEPLOYABLE = 1 -ifneq (, $(shell which i686-w64-mingw32-windres)) - ifneq (, $(shell which i686-w64-mingw32-gcc)) +ifneq (, $(CL32)) + ifneq (, $(RC32)) TARGETS += $(WINDOWS)/uEforth32.exe else - $(warning "Missing i686-w64-mingw32-gcc skipping 32-bit Windows.") + $(warning "Missing Visual Studio rc.exe skipping 32-bit Windows.") DEPLOYABLE := 0 endif else - $(warning "Missing i686-w64-mingw32-windres skipping 32-bit Windows.") + $(warning "Missing Visual Studio cl.exe skipping 32-bit Windows.") DEPLOYABLE := 0 endif -ifneq (, $(shell which x86_64-w64-mingw32-windres)) - ifneq (, $(shell which x86_64-w64-mingw32-gcc)) +ifneq (, $(CL64)) + ifneq (, $(RC64)) TARGETS += $(WINDOWS)/uEforth64.exe else - $(warning "Missing x86_64-w64-mingw32-gcc skipping 64-bit Windows.") + $(warning "Missing Visual Studio rc.exe skipping 64-bit Windows.") DEPLOYABLE := 0 endif else - $(warning "Missing x86_64-w64-mingw32-windres skipping 64-bit Windows.") + $(warning "Missing Visual Studio cl.exe skipping 64-bit Windows.") DEPLOYABLE := 0 endif + # Decide if we can deploy. DEPLOY_TARGETS = ifeq (1, $(DEPLOYABLE)) @@ -145,11 +166,11 @@ ICON_SIZES = $(RES)/eforth256x256.png \ $(RES)/eforth.ico: $(ICON_SIZES) convert $^ $< $@ -$(RES)/ueforth_res32.o: windows/ueforth.rc $(RES)/eforth.ico - i686-w64-mingw32-windres $< $@ +$(RES)/ueforth_res32.res: windows/ueforth.rc $(RES)/eforth.ico + $(RC32) /fo $@ $< -$(RES)/ueforth_res64.o: windows/ueforth.rc $(RES)/eforth.ico - x86_64-w64-mingw32-windres $< $@ +$(RES)/ueforth_res64.res: windows/ueforth.rc $(RES)/eforth.ico + $(RC64) /fo $@ $< # ---- WEB ---- @@ -175,6 +196,7 @@ $(POSIX): $(POSIX)/ueforth: \ posix/posix_main.c \ common/opcodes.h \ + common/interp.h \ common/core.h \ $(GEN)/posix_boot.h | $(POSIX) $(CC) $(CFLAGS) $< -o $@ $(LIBS) @@ -185,23 +207,31 @@ $(POSIX)/ueforth: \ $(WINDOWS): mkdir -p $@ -$(WINDOWS)/uEforth32.exe: \ +$(WINDOWS)/uEforth32.obj: \ windows/windows_main.c \ common/opcodes.h \ common/core.h \ - $(GEN)/windows_boot.h \ - $(RES)/ueforth_res32.o | $(WINDOWS) - i686-w64-mingw32-gcc \ - $(WIN_CFLAGS) $< $(RES)/ueforth_res32.o -o $@ $(WIN_LIBS) + windows/windows_interp.h \ + $(GEN)/windows_boot.h | $(WINDOWS) + $(CL32) /c /Fo$@ $(WIN_CFLAGS) $< + +$(WINDOWS)/uEforth32.exe: \ + $(WINDOWS)/uEforth32.obj \ + $(RES)/ueforth_res32.res | $(WINDOWS) + $(LINK32) /OUT:$@ $(WIN_LFLAGS32) $^ + +$(WINDOWS)/uEforth64.obj: \ + windows/windows_main.c \ + common/opcodes.h \ + common/core.h \ + windows/windows_interp.h \ + $(GEN)/windows_boot.h | $(WINDOWS) + $(CL64) /c /Fo$@ $(WIN_CFLAGS) $< $(WINDOWS)/uEforth64.exe: \ - windows/windows_main.c \ - common/opcodes.h \ - common/core.h \ - $(GEN)/windows_boot.h \ - $(RES)/ueforth_res64.o | $(WINDOWS) - x86_64-w64-mingw32-gcc \ - $(WIN_CFLAGS) $< $(RES)/ueforth_res64.o -o $@ $(WIN_LIBS) + $(WINDOWS)/uEforth64.obj \ + $(RES)/ueforth_res64.res | $(WINDOWS) + $(LINK64) /OUT:$@ $(WIN_LFLAGS64) $^ # ---- ARDUINO ---- @@ -213,6 +243,7 @@ $(ARDUINO)/ueforth/ueforth.ino: \ arduino/arduino.template.ino \ common/opcodes.h \ common/core.h \ + common/interp.h \ $(GEN)/arduino_boot.h | $(ARDUINO)/ueforth $^ >$@ diff --git a/ueforth/arduino/arduino.template.ino b/ueforth/arduino/arduino.template.ino index dc100cc..a64775a 100644 --- a/ueforth/arduino/arduino.template.ino +++ b/ueforth/arduino/arduino.template.ino @@ -214,6 +214,7 @@ static char filename[PATH_MAX]; static String string_value; {{core}} +{{interp}} {{boot}} static IPAddress ToIP(cell_t ip) { diff --git a/ueforth/arduino/fuse_ino.js b/ueforth/arduino/fuse_ino.js index 6d41445..057abeb 100755 --- a/ueforth/arduino/fuse_ino.js +++ b/ueforth/arduino/fuse_ino.js @@ -5,10 +5,12 @@ var fs = require('fs'); var code = fs.readFileSync(process.argv[2]).toString(); var opcodes = fs.readFileSync(process.argv[3]).toString(); var core = fs.readFileSync(process.argv[4]).toString(); -var boot = fs.readFileSync(process.argv[5]).toString(); +var interp = fs.readFileSync(process.argv[5]).toString(); +var boot = fs.readFileSync(process.argv[6]).toString(); code = code.replace('{{opcodes}}', function() { return opcodes; }); code = code.replace('{{boot}}', function() { return boot; }); code = code.replace('{{core}}', function() { return core; }); +code = code.replace('{{interp}}', function() { return interp; }); process.stdout.write(code); diff --git a/ueforth/common/calling.h b/ueforth/common/calling.h index b357029..03dc267 100644 --- a/ueforth/common/calling.h +++ b/ueforth/common/calling.h @@ -1,7 +1,7 @@ #ifndef CALLTYPE # define CALLTYPE #endif -typedef CALLTYPE cell_t (*call_t)(); +typedef cell_t (CALLTYPE *call_t)(); #define CALLING_OPCODE_LIST \ X("CALL0", OP_CALL0, tos = ((call_t) tos)()) \ diff --git a/ueforth/common/core.h b/ueforth/common/core.h index a9ac434..83043cf 100644 --- a/ueforth/common/core.h +++ b/ueforth/common/core.h @@ -1,6 +1,5 @@ #define PRINT_ERRORS 0 -#define NEXT w = *ip++; goto **(void **) w #define CELL_LEN(n) (((n) + sizeof(cell_t) - 1) / sizeof(cell_t)) #define FIND(name) find(name, sizeof(name) - 1) #define LOWER(ch) ((ch) & 0x5F) @@ -120,25 +119,7 @@ static cell_t *evaluate1(cell_t *sp) { return sp; } -static void ueforth_run() { - if (!g_sys.ip) { -#define X(name, op, code) create(name, sizeof(name) - 1, name[0] == ';', && OP_ ## op); - PLATFORM_OPCODE_LIST - OPCODE_LIST -#undef X - return; - } - register cell_t *ip = g_sys.ip, *rp = g_sys.rp, *sp = g_sys.sp, tos, w; - DROP; NEXT; -#define X(name, op, code) OP_ ## op: { code; } NEXT; - PLATFORM_OPCODE_LIST - OPCODE_LIST -#undef X - OP_DOCOLON: ++rp; *rp = (cell_t) ip; ip = (cell_t *) (w + sizeof(cell_t)); NEXT; - OP_DOCREATE: DUP; tos = w + sizeof(cell_t) * 2; NEXT; - OP_DODOES: DUP; tos = w + sizeof(cell_t) * 2; - ++rp; *rp = (cell_t) ip; ip = (cell_t *) *(cell_t *) (w + sizeof(cell_t)); NEXT; -} +static void ueforth_run(void); static void ueforth(int argc, char *argv[], void *heap, const char *src, cell_t src_len) { diff --git a/ueforth/common/interp.h b/ueforth/common/interp.h new file mode 100644 index 0000000..4f9a933 --- /dev/null +++ b/ueforth/common/interp.h @@ -0,0 +1,25 @@ +#define JMPW goto **(void **) w +#define NEXT w = *ip++; JMPW +#define ADDR_DOCOLON && OP_DOCOLON +#define ADDR_DOCREATE && OP_DOCREATE +#define ADDR_DODOES && OP_DODOES + +static void ueforth_run(void) { + if (!g_sys.ip) { +#define X(name, op, code) create(name, sizeof(name) - 1, name[0] == ';', && OP_ ## op); + PLATFORM_OPCODE_LIST + OPCODE_LIST +#undef X + return; + } + register cell_t *ip = g_sys.ip, *rp = g_sys.rp, *sp = g_sys.sp, tos, w; + DROP; NEXT; +#define X(name, op, code) OP_ ## op: { code; } NEXT; + PLATFORM_OPCODE_LIST + OPCODE_LIST +#undef X + OP_DOCOLON: ++rp; *rp = (cell_t) ip; ip = (cell_t *) (w + sizeof(cell_t)); NEXT; + OP_DOCREATE: DUP; tos = w + sizeof(cell_t) * 2; NEXT; + OP_DODOES: DUP; tos = w + sizeof(cell_t) * 2; + ++rp; *rp = (cell_t) ip; ip = (cell_t *) *(cell_t *) (w + sizeof(cell_t)); NEXT; +} diff --git a/ueforth/common/opcodes.h b/ueforth/common/opcodes.h index 5ef9e54..0cc3acf 100644 --- a/ueforth/common/opcodes.h +++ b/ueforth/common/opcodes.h @@ -5,28 +5,29 @@ typedef intptr_t cell_t; typedef uintptr_t ucell_t; -#if __SIZEOF_POINTER__ == 8 -typedef __int128_t dcell_t; -typedef __uint128_t udcell_t; -#elif __SIZEOF_POINTER__ == 4 -typedef int64_t dcell_t; -typedef uint64_t udcell_t; -#else -# error "unsupported cell size" -#endif #define DUP *++sp = tos #define DROP tos = *sp-- #define COMMA(n) *g_sys.heap++ = (n) #define IMMEDIATE() g_sys.last[-1] |= 1 -#define DOES(ip) *g_sys.last = (cell_t) && OP_DODOES; g_sys.last[1] = (cell_t) ip -#ifndef SSMOD_FUNC -#define SSMOD_FUNC dcell_t d = (dcell_t) *sp * (dcell_t) sp[-1]; \ - --sp; *sp = (cell_t) (((udcell_t) d) % tos); \ - tos = (cell_t) (d < 0 ? ~(~d / tos) : d / tos) -#endif +#define DOES(ip) *g_sys.last = (cell_t) ADDR_DODOES; g_sys.last[1] = (cell_t) ip #define PARK DUP; g_sys.ip = ip; g_sys.rp = rp; g_sys.sp = sp +#ifndef SSMOD_FUNC +# if __SIZEOF_POINTER__ == 8 +typedef __int128_t dcell_t; +typedef __uint128_t udcell_t; +# elif __SIZEOF_POINTER__ == 4 || defined(_M_IX86) +typedef int64_t dcell_t; +typedef uint64_t udcell_t; +# else +# error "unsupported cell size" +# endif +# define SSMOD_FUNC dcell_t d = (dcell_t) *sp * (dcell_t) sp[-1]; \ + --sp; *sp = (cell_t) (((udcell_t) d) % tos); \ + tos = (cell_t) (d < 0 ? ~(~d / tos) : d / tos) +#endif + #define OPCODE_LIST \ X("0=", ZEQUAL, tos = !tos ? -1 : 0) \ X("0<", ZLESS, tos = (tos|0) < 0 ? -1 : 0) \ @@ -54,7 +55,7 @@ typedef uint64_t udcell_t; X(">R", TOR, *++rp = tos; DROP) \ X("R>", FROMR, DUP; tos = *rp; --rp) \ X("R@", RAT, DUP; tos = *rp) \ - X("EXECUTE", EXECUTE, w = tos; DROP; goto **(void **) w) \ + X("EXECUTE", EXECUTE, w = tos; DROP; JMPW) \ X("BRANCH", BRANCH, ip = (cell_t *) *ip) \ X("0BRANCH", ZBRANCH, if (!tos) ip = (cell_t *) *ip; else ++ip; DROP) \ X("DONEXT", DONEXT, *rp = *rp - 1; \ @@ -67,17 +68,17 @@ typedef uint64_t udcell_t; X("S>NUMBER?", CONVERT, tos = convert((const char *) *sp, tos, sp); \ if (!tos) --sp) \ X("CREATE", CREATE, DUP; DUP; tos = parse(32, sp); \ - create((const char *) *sp, tos, 0, && OP_DOCREATE); \ + create((const char *) *sp, tos, 0, ADDR_DOCREATE); \ COMMA(0); --sp; DROP) \ X("DOES>", DOES, DOES(ip); ip = (cell_t *) *rp; --rp) \ X("IMMEDIATE", IMMEDIATE, IMMEDIATE()) \ X("'SYS", SYS, DUP; tos = (cell_t) &g_sys) \ X("YIELD", YIELD, PARK; return) \ X(":", COLON, DUP; DUP; tos = parse(32, sp); \ - create((const char *) *sp, tos, 0, && OP_DOCOLON); \ + create((const char *) *sp, tos, 0, ADDR_DOCOLON); \ g_sys.state = -1; --sp; DROP) \ X("EVALUATE1", EVALUATE1, DUP; sp = evaluate1(sp); w = *sp--; DROP; \ - if (w) goto **(void **) w) \ + if (w) JMPW) \ X("EXIT", EXIT, ip = (cell_t *) *rp--) \ X(";", SEMICOLON, COMMA(g_sys.DOEXIT_XT); g_sys.state = 0) \ diff --git a/ueforth/posix/posix_main.c b/ueforth/posix/posix_main.c index d60217e..674c5a0 100644 --- a/ueforth/posix/posix_main.c +++ b/ueforth/posix/posix_main.c @@ -12,6 +12,7 @@ CALLING_OPCODE_LIST \ #include "common/core.h" +#include "common/interp.h" #include "gen/posix_boot.h" diff --git a/ueforth/windows/windows_interp.h b/ueforth/windows/windows_interp.h new file mode 100644 index 0000000..562a1e8 --- /dev/null +++ b/ueforth/windows/windows_interp.h @@ -0,0 +1,44 @@ +#define NEXT goto next +#define JMPW goto work +#define ADDR_DOCOLON ((void *) OP_DOCOLON) +#define ADDR_DOCREATE ((void *) OP_DOCREATE) +#define ADDR_DODOES ((void *) OP_DODOES) + +enum { + OP_DOCOLON = 0, + OP_DOCREATE, + OP_DODOES, +#define X(name, op, code) OP_ ## op, + PLATFORM_OPCODE_LIST + OPCODE_LIST +#undef X +}; + +static void ueforth_run(void) { + if (!g_sys.ip) { +#define X(name, op, code) \ + create(name, sizeof(name) - 1, name[0] == ';', (void *) OP_ ## op); + PLATFORM_OPCODE_LIST + OPCODE_LIST +#undef X + return; + } + register cell_t *ip = g_sys.ip, *rp = g_sys.rp, *sp = g_sys.sp, tos, w; + DROP; + for (;;) { +next: + w = *ip++; +work: + switch (*(cell_t *) w & 0xff) { +#define X(name, op, code) case OP_ ## op: { code; } NEXT; + PLATFORM_OPCODE_LIST + OPCODE_LIST +#undef X + case OP_DOCOLON: ++rp; *rp = (cell_t) ip; ip = (cell_t *) (w + sizeof(cell_t)); NEXT; + case OP_DOCREATE: DUP; tos = w + sizeof(cell_t) * 2; NEXT; + case OP_DODOES: DUP; tos = w + sizeof(cell_t) * 2; + ++rp; *rp = (cell_t) ip; + ip = (cell_t *) *(cell_t *) (w + sizeof(cell_t)); NEXT; + } + } +} diff --git a/ueforth/windows/windows_main.c b/ueforth/windows/windows_main.c index 086c8e7..201b0ce 100644 --- a/ueforth/windows/windows_main.c +++ b/ueforth/windows/windows_main.c @@ -1,12 +1,13 @@ +#define _USING_V110_SDK71_ 1 #include "windows.h" +#include #define CALLTYPE WINAPI - -# define SSMOD_FUNC \ - w = tos; asm("imul %4\n\t" \ - "idiv %2" \ - : "=a" (tos), "=d" (sp[-1]) \ - : "r" (w), "a" (sp[-1]), "d" (*sp)); --sp; if (*sp < 0) { *sp += w; --tos; } +#if defined(_M_X64) +# define SSMOD_FUNC --sp; cell_t b, a = _mul128(*sp, sp[1], &b); tos = _div128(b, a, tos, sp) +#elif defined(_M_IX86) +# define SSMOD_FUNC --sp; __int64 a = (__int64) *sp * (__int64) sp[1]; tos = _div64(a, tos, sp) +#endif #include "common/opcodes.h" #include "common/calling.h" @@ -22,13 +23,17 @@ CALLING_OPCODE_LIST \ #include "common/core.h" +#include "windows/windows_interp.h" #include "gen/windows_boot.h" +#ifdef UEFORTH_MINIMAL int WINAPI WinMainCRTStartup(void) { +#else +int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmd, int show) { +#endif void *heap = VirtualAlloc( NULL, HEAP_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); ueforth(0, 0, heap, boot, sizeof(boot)); - return 1; }