Merge remote-tracking branch 'upstream/main' into d6/subprocess-feb2024
This commit is contained in:
commit
b9e953a490
|
@ -0,0 +1,79 @@
|
||||||
|
( test file )
|
||||||
|
|
||||||
|
|0100 @program
|
||||||
|
|
||||||
|
#01 ?{ ( skip ) #ffff }
|
||||||
|
!{ ( skip ) #ffff }
|
||||||
|
{ ( skip ) #ffff } POP2r
|
||||||
|
|
||||||
|
( nested lambda )
|
||||||
|
{ { "hello 0a $1 } STH2r !print-str } STH2r JSR2
|
||||||
|
|
||||||
|
( function application )
|
||||||
|
{ 01 02 03 04 05 } STH2r { LIT "0 ADD #18 DEO #0a18 DEO JMP2r } STH2r foreach
|
||||||
|
|
||||||
|
( get lambda length )
|
||||||
|
{ "Dindeldums $1 } STH2r get-lambda-length <print-dec> #0a18 DEO
|
||||||
|
|
||||||
|
( allocated string )
|
||||||
|
;hello-word print-str
|
||||||
|
|
||||||
|
#800f DEO
|
||||||
|
|
||||||
|
BRK
|
||||||
|
|
||||||
|
(
|
||||||
|
@| test label inheritance )
|
||||||
|
|
||||||
|
@Object &x $1 &y $1
|
||||||
|
|
||||||
|
&get-x ( -- x )
|
||||||
|
,&x LDR
|
||||||
|
JMP2r
|
||||||
|
|
||||||
|
@Object/get-y ( -- y )
|
||||||
|
,&y LDR
|
||||||
|
JMP2r
|
||||||
|
|
||||||
|
@Object/get-both ( -- x y )
|
||||||
|
/get-x /get-y
|
||||||
|
JMP2r
|
||||||
|
|
||||||
|
( raw lambda length )
|
||||||
|
_{ 01 02 03 }
|
||||||
|
|
||||||
|
@get-lambda-length ( lambda* -- length* )
|
||||||
|
#0002 SUB2 LDA2
|
||||||
|
JMP2r
|
||||||
|
|
||||||
|
@print-str ( str* -- )
|
||||||
|
&while ( -- )
|
||||||
|
( send ) LDAk #18 DEO
|
||||||
|
( loop ) INC2 LDAk ?&while
|
||||||
|
POP2
|
||||||
|
|
||||||
|
JMP2r
|
||||||
|
|
||||||
|
@foreach ( arr* fn* -- )
|
||||||
|
STH2
|
||||||
|
DUP2
|
||||||
|
DUP2 #0002 SUB2 LDA2 ADD2
|
||||||
|
SWP2
|
||||||
|
&l
|
||||||
|
LDAk STH2kr JSR2
|
||||||
|
INC2 NEQ2k ?&l
|
||||||
|
POP2 POP2 POP2r
|
||||||
|
JMP2r
|
||||||
|
|
||||||
|
@<print-dec> ( short* -- )
|
||||||
|
#2710 [ LIT2r 00fb ]
|
||||||
|
&w ( -- )
|
||||||
|
DIV2k #000a DIV2k MUL2 SUB2 SWPr EQUk OVR STHkr EQU AND ?&>skip
|
||||||
|
DUP [ LIT "0 ] ADD #19 DEO
|
||||||
|
INCr &>skip
|
||||||
|
POP2 #000a DIV2 SWPr INCr STHkr ?&w
|
||||||
|
POP2r POP2 POP2 JMP2r
|
||||||
|
|
||||||
|
$20 @label2
|
||||||
|
|
||||||
|
@hello-word "Hello 20 "World! 0a $1
|
14
makefile
14
makefile
|
@ -5,28 +5,26 @@ EMU_src=${CLI_src} src/devices/screen.c src/devices/controller.c src/devices/mou
|
||||||
RELEASE_flags=-DNDEBUG -O2 -g0 -s
|
RELEASE_flags=-DNDEBUG -O2 -g0 -s
|
||||||
DEBUG_flags=-std=c89 -D_POSIX_C_SOURCE=199309L -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined
|
DEBUG_flags=-std=c89 -D_POSIX_C_SOURCE=199309L -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined
|
||||||
|
|
||||||
.PHONY: all debug dest rom run test install uninstall format clean
|
.PHONY: all debug dest run test install uninstall format clean
|
||||||
|
|
||||||
all: dest bin/uxnasm bin/uxncli bin/uxn11
|
all: dest bin/uxnasm bin/uxncli bin/uxn11
|
||||||
|
|
||||||
dest:
|
dest:
|
||||||
@ mkdir -p bin
|
@ mkdir -p bin
|
||||||
rom:
|
run: all bin/uxnasm bin/uxncli bin/uxn11
|
||||||
@ ./bin/uxnasm etc/screen.bounds.tal bin/res.rom
|
@ ./bin/uxn11
|
||||||
run: all bin/uxnasm bin/uxncli bin/uxn11 rom
|
|
||||||
@ ./bin/uxn11 bin/res.rom
|
|
||||||
test: bin/uxnasm bin/uxncli bin/uxn11
|
test: bin/uxnasm bin/uxncli bin/uxn11
|
||||||
@ ./bin/uxnasm && ./bin/uxncli && ./bin/uxn11 && ./bin/uxnasm -v && ./bin/uxncli -v && ./bin/uxn11 -v
|
@ ./bin/uxnasm -v && ./bin/uxncli -v && ./bin/uxn11 -v
|
||||||
@ ./bin/uxnasm etc/opctest.tal bin/opctest.rom
|
@ ./bin/uxnasm etc/opctest.tal bin/opctest.rom
|
||||||
@ ./bin/uxncli bin/opctest.rom
|
@ ./bin/uxncli bin/opctest.rom
|
||||||
install: bin/uxnasm bin/uxncli bin/uxn11
|
install: all bin/uxnasm bin/uxncli bin/uxn11
|
||||||
@ cp bin/uxn11 bin/uxnasm bin/uxncli ~/bin/
|
@ cp bin/uxn11 bin/uxnasm bin/uxncli ~/bin/
|
||||||
uninstall:
|
uninstall:
|
||||||
@ rm -f ~/bin/uxn11 ~/bin/uxnasm ~/bin/uxncli
|
@ rm -f ~/bin/uxn11 ~/bin/uxnasm ~/bin/uxncli
|
||||||
format:
|
format:
|
||||||
@ clang-format -i src/uxnasm.c src/uxncli.c src/uxn11.c src/devices/*
|
@ clang-format -i src/uxnasm.c src/uxncli.c src/uxn11.c src/devices/*
|
||||||
clean:
|
clean:
|
||||||
@ rm -f bin/uxnasm bin/uxncli bin/uxn11 bin/polycat.rom bin/polycat.rom.sym
|
@ rm -fr bin
|
||||||
|
|
||||||
bin/uxnasm: src/uxnasm.c
|
bin/uxnasm: src/uxnasm.c
|
||||||
@ cc ${RELEASE_flags} ${CFLAGS} src/uxnasm.c -o bin/uxnasm
|
@ cc ${RELEASE_flags} ${CFLAGS} src/uxnasm.c -o bin/uxnasm
|
||||||
|
|
14
src/uxn11.c
14
src/uxn11.c
|
@ -296,16 +296,14 @@ main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
Uxn u = {0};
|
Uxn u = {0};
|
||||||
int i = 1;
|
int i = 1;
|
||||||
if(i == argc) {
|
char *rom;
|
||||||
fprintf(stdout, "usage: %s [-v] file.rom [args..]\n", argv[0]);
|
if(i != argc && argv[i][0] == '-' && argv[i][1] == 'v') {
|
||||||
return 0;
|
fprintf(stdout, "Uxn11 - Varvara Emulator, 22 Feb 2023.\n");
|
||||||
}
|
|
||||||
if(argv[i][0] == '-' && argv[i][1] == 'v') {
|
|
||||||
fprintf(stdout, "Uxn11 - Varvara Emulator, 14 Feb 2023.\n");
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if(!system_boot(&u, (Uint8 *)calloc(0x10000 * RAM_PAGES, sizeof(Uint8)), argv[i++])) {
|
rom = i == argc ? "boot.rom" : argv[i++];
|
||||||
fprintf(stdout, "Could not boot.\n");
|
if(!system_boot(&u, (Uint8 *)calloc(0x10000 * RAM_PAGES, sizeof(Uint8)), rom)) {
|
||||||
|
fprintf(stdout, "usage: %s [-v] file.rom [args..]\n", argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(!display_init()) {
|
if(!display_init()) {
|
||||||
|
|
28
src/uxnasm.c
28
src/uxnasm.c
|
@ -55,6 +55,8 @@ static char ops[][4] = {
|
||||||
"ADD", "SUB", "MUL", "DIV", "AND", "ORA", "EOR", "SFT"
|
"ADD", "SUB", "MUL", "DIV", "AND", "ORA", "EOR", "SFT"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static char *runes = "|$@&,_.-;=!?#\"%~";
|
||||||
|
|
||||||
static int scmp(char *a, char *b, int len) { int i = 0; while(a[i] == b[i]) if(!a[i] || ++i >= len) return 1; return 0; } /* string compare */
|
static int scmp(char *a, char *b, int len) { int i = 0; while(a[i] == b[i]) if(!a[i] || ++i >= len) return 1; return 0; } /* string compare */
|
||||||
static int sihx(char *s) { int i = 0; char c; while((c = s[i++])) if(!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f')) return 0; return i > 1; } /* string is hexadecimal */
|
static int sihx(char *s) { int i = 0; char c; while((c = s[i++])) if(!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f')) return 0; return i > 1; } /* string is hexadecimal */
|
||||||
static int shex(char *s) { int n = 0, i = 0; char c; while((c = s[i++])) if(c >= '0' && c <= '9') n = n * 16 + (c - '0'); else if(c >= 'a' && c <= 'f') n = n * 16 + 10 + (c - 'a'); return n; } /* string to num */
|
static int shex(char *s) { int n = 0, i = 0; char c; while((c = s[i++])) if(c >= '0' && c <= '9') n = n * 16 + (c - '0'); else if(c >= 'a' && c <= 'f') n = n * 16 + 10 + (c - 'a'); return n; } /* string to num */
|
||||||
|
@ -156,6 +158,15 @@ makemacro(char *name, FILE *f)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
isrune(char c)
|
||||||
|
{
|
||||||
|
char cc, *r = runes;
|
||||||
|
while((cc = *r++))
|
||||||
|
if(c == cc) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
makelabel(char *name)
|
makelabel(char *name)
|
||||||
{
|
{
|
||||||
|
@ -166,6 +177,8 @@ makelabel(char *name)
|
||||||
return error("Label name is hex number", name);
|
return error("Label name is hex number", name);
|
||||||
if(findopcode(name) || scmp(name, "BRK", 4) || !slen(name))
|
if(findopcode(name) || scmp(name, "BRK", 4) || !slen(name))
|
||||||
return error("Label name is invalid", name);
|
return error("Label name is invalid", name);
|
||||||
|
if(isrune(name[0]))
|
||||||
|
return error("Label name is runic", name);
|
||||||
if(p.label_len == 0x400)
|
if(p.label_len == 0x400)
|
||||||
return error("Labels limit exceeded", name);
|
return error("Labels limit exceeded", name);
|
||||||
l = &p.labels[p.label_len++];
|
l = &p.labels[p.label_len++];
|
||||||
|
@ -195,7 +208,7 @@ makereference(char *scope, char *label, char rune, Uint16 addr)
|
||||||
if(label[0] == '{') {
|
if(label[0] == '{') {
|
||||||
p.lambda_stack[p.lambda_ptr++] = p.lambda_count;
|
p.lambda_stack[p.lambda_ptr++] = p.lambda_count;
|
||||||
scpy(makelambda(p.lambda_count++), r->name, 0x40);
|
scpy(makelambda(p.lambda_count++), r->name, 0x40);
|
||||||
} else if(label[0] == '&') {
|
} else if(label[0] == '&' || label[0] == '/') {
|
||||||
if(!sublabel(subw, scope, label + 1))
|
if(!sublabel(subw, scope, label + 1))
|
||||||
return error("Invalid sublabel", label);
|
return error("Invalid sublabel", label);
|
||||||
scpy(subw, r->name, 0x40);
|
scpy(subw, r->name, 0x40);
|
||||||
|
@ -320,7 +333,10 @@ parse(char *w, FILE *f)
|
||||||
case '@': /* label */
|
case '@': /* label */
|
||||||
if(!makelabel(w + 1))
|
if(!makelabel(w + 1))
|
||||||
return error("Invalid label", w);
|
return error("Invalid label", w);
|
||||||
scpy(w + 1, p.scope, 0x40);
|
i = 0;
|
||||||
|
while(w[i + 1] != '/' && i < 0x3e && (p.scope[i] = w[i + 1]))
|
||||||
|
i++;
|
||||||
|
p.scope[i] = '\0';
|
||||||
break;
|
break;
|
||||||
case '&': /* sublabel */
|
case '&': /* sublabel */
|
||||||
if(!sublabel(subw, p.scope, w + 1) || !makelabel(subw))
|
if(!sublabel(subw, p.scope, w + 1) || !makelabel(subw))
|
||||||
|
@ -346,7 +362,6 @@ parse(char *w, FILE *f)
|
||||||
case '.': /* literal byte zero-page */
|
case '.': /* literal byte zero-page */
|
||||||
makereference(p.scope, w + 1, w[0], p.ptr + 1);
|
makereference(p.scope, w + 1, w[0], p.ptr + 1);
|
||||||
return writelitbyte(0xff);
|
return writelitbyte(0xff);
|
||||||
case ':':
|
|
||||||
case '=': /* raw short absolute */
|
case '=': /* raw short absolute */
|
||||||
makereference(p.scope, w + 1, w[0], p.ptr);
|
makereference(p.scope, w + 1, w[0], p.ptr);
|
||||||
return writeshort(0xffff, 0);
|
return writeshort(0xffff, 0);
|
||||||
|
@ -420,7 +435,6 @@ resolve(void)
|
||||||
p.data[r->addr] = l->addr & 0xff;
|
p.data[r->addr] = l->addr & 0xff;
|
||||||
l->refs++;
|
l->refs++;
|
||||||
break;
|
break;
|
||||||
case ':':
|
|
||||||
case '=':
|
case '=':
|
||||||
case ';':
|
case ';':
|
||||||
if(!(l = findlabel(r->name)))
|
if(!(l = findlabel(r->name)))
|
||||||
|
@ -501,14 +515,12 @@ main(int argc, char *argv[])
|
||||||
if(argc == 1)
|
if(argc == 1)
|
||||||
return error("usage", "uxnasm [-v] input.tal output.rom");
|
return error("usage", "uxnasm [-v] input.tal output.rom");
|
||||||
if(argv[1][0] == '-' && argv[1][1] == 'v')
|
if(argv[1][0] == '-' && argv[1][1] == 'v')
|
||||||
return !fprintf(stdout, "Uxnasm - Uxntal Assembler, 27 Oct 2023.\n");
|
return !fprintf(stdout, "Uxnasm - Uxntal Assembler, 25 Feb 2024.\n");
|
||||||
if(!(src = fopen(argv[1], "r")))
|
if(!(src = fopen(argv[1], "r")))
|
||||||
return !error("Invalid input", argv[1]);
|
return !error("Invalid input", argv[1]);
|
||||||
if(!assemble(src))
|
if(!assemble(src))
|
||||||
return !error("Assembly", "Failed to assemble rom.");
|
return !error("Assembly", "Failed to assemble rom.");
|
||||||
if(scmp(argv[2], "-", 2))
|
if(!(dst = fopen(argv[2], "wb")))
|
||||||
dst = stdout;
|
|
||||||
else if(!(dst = fopen(argv[2], "wb")))
|
|
||||||
return !error("Invalid Output", argv[2]);
|
return !error("Invalid Output", argv[2]);
|
||||||
if(p.length <= TRIM)
|
if(p.length <= TRIM)
|
||||||
return !error("Assembly", "Output rom is empty.");
|
return !error("Assembly", "Output rom is empty.");
|
||||||
|
|
Loading…
Reference in New Issue