duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit d6d3dc1f15c9f52c01fe19d37e61138512032ce2
parent a3e95d2d208c8ed76c9774dcfbeb2a5d4e4fa168
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Wed,  1 Jun 2022 13:51:41 -0400

Seriously, I'm really getting there...

Diffstat:
MMakefile | 4++--
Dasm.py | 244-------------------------------------------------------------------------------
Mboot2.fs | 2+-
Mdusk.asm | 9++++++---
Ddusk.c | 205-------------------------------------------------------------------------------
Dops.txt | 6------
Mxcomp.txt | 90++++++++++++++------------------------------------------------------------------
Dxcomp2.txt | 90-------------------------------------------------------------------------------
8 files changed, 24 insertions(+), 626 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,10 +1,10 @@ TARGETS = dusk all: $(TARGETS) -xcomp.asm: dusk.asm xcomp2.txt f2asm.py aliases.txt +xcomp.asm: dusk.asm xcomp.txt f2asm.py aliases.txt echo "; This file is autogenerated" > $@ cat dusk.asm >> $@ - ./f2asm.py xcomp2.txt >> $@ + ./f2asm.py xcomp.txt >> $@ dusk: xcomp.asm boot2.fs nasm -f elf32 xcomp.asm -o dusk.o diff --git a/asm.py b/asm.py @@ -1,244 +0,0 @@ -#!/usr/bin/env python3 -# ad hoc assembler for forth.bin -# temporary crutch until we're self-hosting. -import sys -import struct - -ops = open('ops.txt', 'rb').read().split(b',') -ops = [s.strip() for s in ops] -ops = {name:i for i, name in enumerate(ops)} -fp = open(sys.argv[1], 'rb') -outbuf = bytearray() -prevword = 0 -words = {} # name:pc -labels = {} # name:pc -fwlabels = [] # (name, pc) label forward references -ps = [] # PS for immediate words - -aliases = [ - ('p2r', '>r'), - ('r2p', 'r>'), - ('rget', 'r@'), - ('rdrop', 'r~'), - ('a2r', 'A>r'), - ('r2a', 'r>A'), -] -for a, b in aliases: - opcode = ops[a.encode()] - del ops[a.encode()] - ops[b.encode()] = opcode - -def out(fmt, *args): - outbuf.extend(struct.pack(fmt, *args)) - -def opwr(name): - if isinstance(name, str): - name = name.encode() - out('<b', ops[name]) - -def intwr(n): - out('<i', n) - -def intset(offset, n): - outbuf[offset:offset+4] = struct.pack('<i', n) - -def litwr(n): - opwr('_i_') - intwr(n) - -def callwr(addr): - opwr('_call_') - intwr(addr) - -def pc(): - return len(outbuf) - -def litparse(s): - try: - if len(s) == 3 and s[0] == ord("'") and s[2] == ord("'"): - return s[1] - elif s.startswith(b'$'): - return int(s[1:], 16) - else: - return int(s) - except ValueError: - pass - return None - -def nextt(): - r = bytearray() - c = fp.read(1) - while c and c[0] <= 0x20: - c = fp.read(1) - while c and c[0] > 0x20: - r.append(c[0]) - c = fp.read(1) - return bytes(r) - -def labelwr(t): - if t.endswith(b':'): - t = t[:-1] - for name, off in fwlabels: - if name == t: - intset(off, pc()) - labels[t] = pc() - else: - if t in labels: - intwr(labels[t]) - else: - fwlabels.append((t, pc())) - intwr(0) - -def newword(name=None): - global prevword - if not name: - name = nextt() - count = len(name) - out(f'<{count}sib', name, prevword, count) - prevword = pc() - words[name] = prevword - -def _comment_(): - c = fp.read(1) - while c and c != b')': - c = fp.read(1) - -def _lcomment_(): - c = fp.read(1) - while c and c != b'\n': - c = fp.read(1) - -def _if_(): - opwr('_cbr_') - ps.append(pc()) - intwr(0) - -def _then_(): - intset(ps.pop(), pc()) - -def _else_(): - x = ps.pop() - opwr('_br_') - ps.append(pc()) - intwr(0) - intset(x, pc()) - -def _begin_(): - ps.append(pc()) - -def _again_(): - opwr('_br_') - intwr(ps.pop()) - -def _until_(): - opwr('_cbr_') - intwr(ps.pop()) - -def _next_(): - opwr('_next_') - intwr(ps.pop()) - -def exitwr(): - opwr('exit') - -def strwr(): - s = bytearray() - c = fp.read(1) - while c and c != b'"': - s.append(c[0]) - c = fp.read(1) - outbuf.extend(s) - return s - -def slitwr(): - opwr('_br_') - ps.append(pc()) - intwr(0) - spc = pc() - s = strwr() - _then_() - litwr(spc) - litwr(len(s)) - -def _create_(): - newword() - callwr(labels[b'lblcell']) - -def _value_(): - newword() - callwr(labels[b'lblval']) - n = litparse(nextt()) - intwr(n) - -def _alias_(): - newword() - callwr(labels[b'lblalias']) - off = words[nextt()] - intwr(off) - -def _immediate_(): - outbuf[prevword-1] |= 0x80 # immediate - -def _opwriter_(): - newword() - _immediate_() - opcode = ops[nextt()] - litwr(opcode) - callwr(words[b'c,']) - exitwr() - -def _callop_(): - intwr(ops[b'_call_']) - -def _pspushop_(): - intwr(ops[b'_i_']) - -def _exitop_(): - intwr(ops[b'exit']) - -special = { - b':': newword, - b'(': _comment_, - b'\\': _lcomment_, - b';': exitwr, - b',"': strwr, - b'S"': slitwr, - b'if': _if_, - b'then': _then_, - b'else': _else_, - b'begin': _begin_, - b'again': _again_, - b'until': _until_, - b'next': _next_, - b'create': _create_, - b'value': _value_, - b'alias': _alias_, - b'opwriter': _opwriter_, - b'callop': _callop_, - b'pspushop': _pspushop_, - b'exitop': _exitop_, - b'immediate': _immediate_, -} - -t = nextt() -while t: - if t in special: - special[t]() - elif t in words: - callwr(words[t]) - elif t in ops: - opwr(t) - elif t.startswith(b'lbl'): - labelwr(t) - else: - n = litparse(t) - if n is None: - t = t.decode() - print(f"invalid token {t}", file=sys.stderr) - sys.exit(1) - else: - litwr(n) - t = nextt() - -fp.close() -sys.stdout.buffer.write(outbuf) diff --git a/boot2.fs b/boot2.fs @@ -1 +1 @@ -'X' emit bye +: foo 'X' emit ; foo bye diff --git a/dusk.asm b/dusk.asm @@ -381,20 +381,23 @@ litncode: litncode_end: defword 'litn', 4, word_litn, word_shrc pspush litncode ; src - pspush litncode_end-litncode ; len + pspush litncode_end-litncode-4 ; len_of_code-len-of-imm call word_movewrite call word_write ret defword 'call,', 5, word_callwrite, word_litn - pspop eax ; absolute addr + mov eax, [ebp] ; absolute addr sub eax, [here] ; displacement - add eax, 5 ; ... from *after* call op + sub eax, 5 ; ... from *after* call op + mov [ebp], eax pspush 0xe8 ; call opcode call word_cwrite call word_write + ret defword 'exit,', 5, word_exitwrite, word_callwrite word_asmlast: pspush 0xc3 ; ret opcode call word_cwrite + ret diff --git a/dusk.c b/dusk.c @@ -1,205 +0,0 @@ -#include <unistd.h> -#include <inttypes.h> -#include <stdio.h> -#include <termios.h> - -#define CELLSIZE 4 -#define MEMSIZE 0x10000 -#define STACKSIZE 0x100 - -typedef uint32_t cell; -typedef uint8_t byte; -struct stack { - cell data[STACKSIZE]; - cell ptr; -}; -static cell stack_peek(struct stack *s) { - return s->data[s->ptr&(STACKSIZE-1)]; -} -static cell stack_pop(struct stack *s) { - cell n = stack_peek(s); - s->ptr++; - return n; -} -static void stack_push(struct stack *s, cell x) { - s->ptr--; - s->data[s->ptr&(STACKSIZE-1)] = x; -} - -byte mem[MEMSIZE]; -struct stack ps, rs; -cell pc; -byte running; -byte toflag; -cell areg; - -/* Utilities */ -static void checka(cell *addr) { - if (*addr >= MEMSIZE) { - fprintf(stderr, "Illegal mem addr %08x at PC %08x. Halting.\n", addr, pc); - running = 0; - *addr = 0; - } -} -static cell gc(cell addr) { - checka(&addr); - return mem[addr+3] << 24 | mem[addr+2] << 16 | mem[addr+1] << 8 | mem[addr]; -} -static void sc(cell addr, cell val) { - checka(&addr); - mem[addr] = val; - mem[addr+1] = val >> 8; - mem[addr+2] = val >> 16; - mem[addr+3] = val >> 24; -} -static cell peek() { return stack_peek(&ps); } -static cell pop() { return stack_pop(&ps); } -static void push(cell x) { stack_push(&ps, x); } -static cell peekRS() { return stack_peek(&rs); } -static cell popRS() { return stack_pop(&rs); } -static void pushRS(cell x) { stack_push(&rs, x); } -static cell pc32() { cell n = gc(pc); pc+=CELLSIZE; return n; } - -/* Native words */ -/* stack */ -static void _i_() { push(pc32()); } -static void _drop() { pop(); } -static void _dup() { push(peek()); } -static void cdup() { if (peek()) push(peek()); } -static void _swap() { cell a = pop(); cell b = pop(); push(a); push(b); } -static void _over() { cell a = pop(); cell b = peek(); push(a); push(b); } -static void _rot() { - cell c = pop(); cell b = pop(); cell a = pop(); - push(b); push(c); push(a); } -static void p2r() { pushRS(pop()); } -static void r2p() { push(popRS()); } -static void rget() { push(peekRS()); } -static void rdrop() { popRS(); } -static void _scnt() { push(STACKSIZE-ps.ptr); } -static void _rcnt() { push(STACKSIZE-rs.ptr); } - -/* flow */ -static void _rs0() { rs.ptr = STACKSIZE; } -static void _ps0() { ps.ptr = STACKSIZE; } -static void _br_() { pc = gc(pc); } -static void _cbr_() { if (pop()) { pc+=CELLSIZE; } else { _br_(); } } -static void _next_() { - cell n = popRS()-1; - if (n) { pushRS(n); _br_(); } - else { pc+=CELLSIZE; } -} -static void _call_() { pushRS(pc+CELLSIZE); _br_(); } -static void exit() { pc = popRS(); } -static void execute() { pushRS(pc); pc = pop(); } -static void _bye() { running = 0; } - -/* memory */ -static void cfetch() { cell a = pop(); checka(&a); push(mem[a]); } -static void cstore() { cell a = pop(); checka(&a); mem[a] = pop(); } -static void fetch() { cell a = pop(); push(gc(a)); } -static void store() { cell a = pop(); sc(a, pop()); } -static void _to() { toflag = 1; } -static void isto() { push(toflag); toflag = 0; } - -/* arithmetic */ -static void inc() { push(pop()+1); } -static void dec() { push(pop()-1); } -static void shl() { cell n = pop(); push(n<<1); push(n>>31); } -static void shr() { cell n = pop(); push(n>>1); push(n&1); } -static void _and() { cell b = pop(); cell a = pop(); push(a&b); } -static void _or() { cell b = pop(); cell a = pop(); push(a|b); } -static void _xor() { cell b = pop(); cell a = pop(); push(a^b); } -static void add() { cell b = pop(); cell a = pop(); push(a+b); } -static void sub() { cell b = pop(); cell a = pop(); push(a-b); } -static void mul() { cell b = pop(); cell a = pop(); push(a*b); } -static void lt() { cell b = pop(); cell a = pop(); push(a<b); } -static void _not() { push(pop() ? 0 : 1); } - -/* A register */ -static void a2p() { push(areg); } -static void p2a() { areg = pop(); } -static void a2r() { pushRS(areg); } -static void r2a() { areg = popRS(); } -static void ainc() { areg++; } -static void adec() { areg--; } -static void acfetch() { checka(&areg); push(mem[areg]); } -static void acstore() { checka(&areg); mem[areg] = pop(); } - -/* I/O */ -static void _emit() { putchar(pop()); } -static void _key() { push(getchar()); } - -static void (*ops[50])() = { -#include "ops.txt" -}; - -static void opexec(byte op) { - if (op < sizeof(ops)/sizeof(void*)) { - ops[op](); - } else { - fprintf(stderr, "Out of bounds op %02x. PC: %08x\n", op, pc); - running = 0; - } -} - -byte step() { - if (!running) { - fprintf(stderr, "machine halted!\n"); - return 0; - } - checka(&pc); - opexec(mem[pc++]); - return running; -} - -static void memdump() { - fprintf(stderr, "Dumping memory to memdump. PC %08x\n", pc); - FILE *fp = fopen("memdump", "w"); - fwrite(mem, MEMSIZE, 1, fp); - fclose(fp); -} - -static void printstack(struct stack *s) { - for (cell i=s->ptr; i<STACKSIZE; i++) { - fprintf(stderr, "%08x ", s->data[i]); - } - putc('\n', stderr); -} -static void printdbg() { - fprintf(stderr, "PC %08x PS %04x:\n", pc, STACKSIZE-ps.ptr); - printstack(&ps); - fprintf(stderr, "RS %04x:\n", STACKSIZE-rs.ptr); - printstack(&rs); -} - -int main() { - struct termios bkptio, tio; - FILE *fp = fopen("forth.bin", "r"); - if (!fp) { - fprintf(stderr, "Can't open forth bin\n"); - return 1; - } - int i = 0; - int c = getc(fp); - while (c != EOF) { - mem[i++] = c; - c = getc(fp); - } - fclose(fp); - ps.ptr = rs.ptr = STACKSIZE; - pc = toflag = 0; - running = 1; - if (isatty(STDIN_FILENO)) { - tcgetattr(STDIN_FILENO, &tio); - bkptio = tio; - tio.c_lflag &=(~ICANON & ~ECHO); /* no echo, unbuffered */ - tcsetattr(STDIN_FILENO, TCSANOW, &tio); - } - while (step()); - if (isatty(STDIN_FILENO)) { - tcsetattr(STDIN_FILENO, TCSANOW, &bkptio); - } - printdbg(); - memdump(); - return 0; -} diff --git a/ops.txt b/ops.txt @@ -1,6 +0,0 @@ -_i_, _drop, _dup, cdup, _swap, _over, _rot, p2r, r2p, rget, rdrop, _scnt, _rcnt, -_rs0, _ps0, _br_, _cbr_, _next_, _call_, exit, execute, _bye, -cfetch, cstore, fetch, store, _to, isto, -inc, dec, shl, shr, _and, _or, _xor, add, sub, mul, lt, _not, -a2p, p2a, a2r, r2a, ainc, adec, acfetch, acstore, -_emit, _key diff --git a/xcomp.txt b/xcomp.txt @@ -1,57 +1,10 @@ -_br_ lblmain -\ native words -: drop _drop ; -: dup _dup ; -: ?dup cdup ; -: swap _swap ; -: over _over ; -: rot _rot ; -: scnt _scnt ; -: rcnt _rcnt ; -: bye _bye ; -: c@ cfetch ; -: c! cstore ; -: @ fetch ; -: ! store ; -: to _to ; -: to? isto ; -: 1+ inc ; -: 1- dec ; -: <<c shl ; -: >>c shr ; -: and _and ; -: or _or ; -: xor _xor ; -: + add ; -: - sub ; -: * mul ; -: < lt ; -: not _not ; -: A> a2p ; -: >A p2a ; -: A+ ainc ; -: A- adec ; -: Ac@ acfetch ; -: Ac! acstore ; -: emit _emit ; -: key _key ; +sysval current +sysval here +sysval compiling +const SPC $20 const CR $0d const LF $0a const BS $08 +sysval in> +syscell 'curword curword -\ core labels -lblcell: r> ; -lblval: r> to? if ! else @ then ; -lblalias: r> to? if ! else @ >r then ; - -\ variables -: current _call_ lblval lblcurrent -: here _call_ lblval lblhere -value compiling 0 -value SPC $20 value CR $0d value LF $0a value BS $08 -value in> 6144 \ where boot.fs starts -create 'curword ," xxxxxx" - -\ words -: quit _rs0 _br_ lblmain -: abort _ps0 quit : 2drop drop drop ; : 2dup over over ; : nip swap drop ; @@ -109,43 +62,30 @@ create tbl-0-f ," 0123456789abcdef" ?dup not if 2drop 1 exit then A>r >r >A ( a1 ) begin Ac@+ over c@ = not if r~ r>A drop 0 exit then 1+ next drop r>A 1 ; +: wordlen ( w -- len ) 1- c@ $7f and ; +: wordname ( w -- sa sl ) dup wordlen swap 5 - over - swap ; +: prevword ( w -- w ) dup if 5 - @ then ; +: immediate? ( w -- f ) 1- c@ $80 and ; : find ( sa sl -- w? f ) \ Guards A A>r >r >A current begin ( w R:sl ) - dup 1- c@ $7f and ( wlen ) r@ = if ( w ) - dup r@ - 5 - A> r@ ( w a1 a2 u ) + dup wordlen r@ = if ( w ) + A> over wordname ( w a1 a2 u ) []= if ( w ) r~ 1 r>A exit then then - 5 - ( prev field ) @ ?dup not until r~ 0 r>A ( not found ) ; + prevword ?dup not until r~ 0 r>A ( not found ) ; : (wnf) curword stype S" word not found" stype abort ; : ' word find not if (wnf) then ; -: litn ( n -- ) _i_ pspushop c, , ; -: call, ( n -- ) _i_ callop c, , ; : entry word tuck move, ( len ) current , c, here to current ; : xtcomp 1 to compiling begin word parse if litn else curword find if - dup 1- c@ $80 and ( imm? ) if execute else call, then + dup immediate? if execute else call, then else (wnf) then then compiling not until exit, ; :imm ; 0 to compiling ; : : entry xtcomp ; -: create entry _i_ lblcell call, ; -: value entry _i_ lblval call, , ; : stack? scnt 0< if S" stack underflow" stype abort then ; : run1 ( -- ) \ interpret next word word parse not if curword find not if (wnf) then execute stack? then ; -opwriter r> r> -opwriter >r >r -opwriter r@ r@ -opwriter r~ r~ -opwriter A>r A>r -opwriter r>A r>A -opwriter exit exit -opwriter execute execute -opwriter (br) _br_ -opwriter (?br) _cbr_ -opwriter (next) _next_ -lblmain: 0 'curword 5 + c! begin run1 again -: _ lblcurrent: ; -lblhere: +: mainloop 0 'curword 5 + c! begin run1 again ; diff --git a/xcomp2.txt b/xcomp2.txt @@ -1,90 +0,0 @@ -sysval current -sysval here -sysval compiling -const SPC $20 const CR $0d const LF $0a const BS $08 -sysval in> -syscell 'curword curword - -: 2drop drop drop ; -: 2dup over over ; -: nip swap drop ; -: tuck swap over ; -: rot> rot rot ; -: leave r> r~ 1 >r >r ; -: Ac@+ Ac@ A+ ; -: Ac!+ Ac! A+ ; -: c@+ dup 1+ swap c@ ; -: c!+ tuck c! 1+ ; -: allot here + to here ; -: , here ! 4 allot ; -: c, here c! 1 allot ; -: = - not ; -: > swap < ; -: 0< <<c nip ; : 0>= 0< not ; : >= < not ; : <= > not ; -: -^ swap - ; -: << <<c drop ; -: >> >>c drop ; -: move ( src dst u -- ) ?dup if - >r >A begin ( src ) c@+ Ac!+ next drop then ; -: move, ( a u -- ) here over allot swap move ; -: stype >r begin c@+ emit next drop ; -: ws? SPC <= ; -: boot< in> c@+ swap to in> ; -alias in<? boot< -alias in< boot< -: toword ( -- ) begin in< ws? not until ; -: curword ( -- sa sl ) 'curword 1+ @ 'curword c@ ; -: _ ( f sa sl -- ) 'curword c!+ tuck ! 4 + c! ; -: word ( -- sa sl ) - 'curword 5 + c@ if curword else - toword in> 1- 0 ( sa sl ) begin 1+ in<? ws? until then - ( sa sl ) 2dup 0 rot> _ ; -: word! 1 rot> _ ; -: [c]? ( c a u -- i ) \ Guards A - ?dup not if 2drop -1 exit then A>r over >r >r >A ( c ) - begin dup Ac@+ = if leave then next ( c ) - A- Ac@ = if A> r> - ( i ) else r~ -1 then r>A ; -: _ ( sl -- n? f ) \ parse unsigned decimal - >r 0 begin ( r ) - 10 * Ac@+ ( r c ) '0' - dup 9 > if - 2drop r~ 0 exit then + next ( r ) 1 ; -create tbl-0-f ," 0123456789abcdef" -: parse ( sa sl -- n? f ) \ *A* - over c@ ''' = if ( sa sl ) - 3 = if 1+ dup 1+ c@ ''' = if c@ 1 exit then then - drop 0 exit then ( sa sl ) - over c@ '$' = if ( sa sl ) 1- >r 1+ >A 0 begin ( r ) - 16 * Ac@+ ( r c ) $20 or tbl-0-f $10 [c]? - dup 0< if 2drop r~ 0 exit then + next ( r ) 1 exit then - swap >A dup 1 > Ac@ '-' = and if ( sl ) - A+ 1- _ if 0 -^ 1 else 0 then else _ then ; -: []= ( a1 a2 u -- f ) \ Guards A - ?dup not if 2drop 1 exit then A>r >r >A ( a1 ) - begin Ac@+ over c@ = not if r~ r>A drop 0 exit then 1+ next - drop r>A 1 ; -: wordlen ( w -- len ) 1- c@ $7f and ; -: wordname ( w -- sa sl ) dup wordlen swap 5 - over - swap ; -: prevword ( w -- w ) dup if 5 - @ then ; -: find ( sa sl -- w? f ) \ Guards A - A>r >r >A current begin ( w R:sl ) - dup wordlen r@ = if ( w ) - A> over wordname ( w a1 a2 u ) - []= if ( w ) r~ 1 r>A exit then then - prevword ?dup not until r~ 0 r>A ( not found ) ; -: (wnf) curword stype S" word not found" stype abort ; -: ' word find not if (wnf) then ; -: entry word tuck move, ( len ) - current , c, here to current ; -: xtcomp 1 to compiling begin - word parse if litn else curword find if - dup 1- c@ $80 and ( imm? ) if execute else call, then - else (wnf) then then - compiling not until - exit, ; -:imm ; 0 to compiling ; -: : entry xtcomp ; -: stack? scnt 0< if S" stack underflow" stype abort then ; -: run1 ( -- ) \ interpret next word - word parse not if - curword find not if (wnf) then execute stack? then ; -: mainloop 0 'curword 5 + c! begin run1 again ;