emul: build from "cvm" instead of from itself

The C VM now runs the show.
This commit is contained in:
Virgil Dupras 2020-06-26 22:08:45 -04:00
parent 1312817117
commit a65f674c74
7 changed files with 68 additions and 118 deletions

View File

@ -24,9 +24,10 @@ tools.
## Getting started
Usage documentation is in-system, so access to documentation requires you to
run Collapse OS. Fortunately, doing so in an emulator is easy.
run Collapse OS. Fortunately, building and running Collapse OS on a POSIX
environment is easy.
See `/emul/README.md` for getting an emulated system running.
See `/cvm/README.md` for instructions.
Then, run `0 LIST` for an introduction, follow instructions from there.

47
cvm/README.md Normal file
View File

@ -0,0 +1,47 @@
# C VM
This is a C implementation of Collapse OS' native words. It allows Collapse OS
to run natively on any POSIX environment.
## Requirements
You need `ncurses` to build the `forth` executable. In debian-based distros,
it's `libncurses5-dev`.
## Build
Running `make` will yield `forth` and `stage` executables.
## Usage
To play around Collapse OS, you'll want to run `./forth`. Type `0 LIST` for
help.
The program is a curses interface with a limited, fixed size so that it can
provide a AT-XY interface.
You can get a REPL by launching the program with [`rlwrap(1)`][rlwrap] like
this:
rlwrap -e '' -m -S '> ' ./forth /dev/stdin
## Problems?
If the `forth` executable works badly (hangs, spew garbage, etc.),
it's probably because you've broken your bootstrap binary. It's easy to
mistakenly break. To verify if you've done that, look at your git status. If
`forth.bin` is modified, try resetting it and then run `make clean all`. Things
should go better afterwards.
A modified `blkfs` can also break things (although even with a completely broken
blkfs, you should still get to prompt), you might want to run `make pack` to
ensure that the `blkfs` file is in sync with the contents of the `blk/` folder.
If that doesn't work, there's also the nuclear option of `git reset --hard`
and `git clean -fxd`.
If that still doesn't work, it might be because the current commit you're on
is broken, but that is rather rare: the repo on Github is plugged on Travis
and it checks that everything is smooth.
[rlwrap]: https://linux.die.net/man/1/rlwrap

4
emul/.gitignore vendored
View File

@ -1,4 +1,2 @@
/stage
/forth
/*-bin.h
/blkfs
/forth.bin

View File

@ -1,47 +1,30 @@
TARGETS = forth stage
TARGETS = forth
OBJS = emul.o libz80/libz80.o
BLKPACK = ../tools/blkpack
BLKUNPACK = ../tools/blkunpack
CDIR = ../cvm
STAGE = $(CDIR)/stage
BLKFS = $(CDIR)/blkfs
.PHONY: all
all: $(TARGETS)
$(BLKPACK):
$(MAKE) -C ../tools
.PHONY: $(BLKUNPACK)
$(BLKUNPACK): $(BLKPACK)
stage: stage.c $(OBJS) blkfs
$(CC) stage.c $(OBJS) -o $@
blkfs: $(BLKPACK)
$(BLKPACK) ../blk > $@
forth: forth.c $(OBJS) blkfs
forth: forth.c $(OBJS) $(CDIR)/blkfs
$(CC) forth.c $(OBJS) -lncurses -o $@
libz80/libz80.o: libz80/z80.c
$(MAKE) -C libz80/codegen opcodes
$(CC) -Wall -ansi -g -c -o libz80/libz80.o libz80/z80.c
emul.o: emul.c
$(CC) -DFBIN_PATH=\"`pwd`/forth.bin\" -DBLKFS_PATH=\"`pwd`/blkfs\" -c -o emul.o emul.c
emul.o: emul.c forth.bin $(BLKFS)
$(CC) -DFBIN_PATH=\"`pwd`/forth.bin\" -DBLKFS_PATH=\"`pwd`/$(BLKFS)\" -c -o emul.o emul.c
forth.bin: xcomp.fs $(STAGE)
$(CDIR)/stage < xcomp.fs > $@
.PHONY: updatebootstrap
updatebootstrap: stage xcomp.fs pack
./stage < xcomp.fs > new.bin
mv new.bin forth.bin
$(BLKFS): $(STAGE)
.PHONY: pack
pack:
rm blkfs && $(MAKE) blkfs
.PHONY: unpack
unpack:
$(BLKUNPACK) ../blk < blkfs
$(STAGE):
$(MAKE) -C $(CDIR) all
.PHONY: clean
clean:
rm -f $(TARGETS) emul.o *-bin.h blkfs libz80/libz80.o
rm -f $(TARGETS) emul.o *.bin libz80/libz80.o

Binary file not shown.

View File

@ -1,80 +0,0 @@
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include "emul.h"
/* Staging binaries
The role of a stage executable is to compile definitions in a dictionary and
then spit the difference between the starting binary and the new binary.
That binary can then be grafted to an exiting Forth binary to augment its
dictionary.
We could, if we wanted, run only with the bootstrap binary and compile core
defs at runtime, but that would mean that those defs live in RAM. In may system,
RAM is much more constrained than ROM, so it's worth it to give ourselves the
trouble of compiling defs to binary.
*/
#define RAMSTART 0
#define STDIO_PORT 0x00
// To know which part of RAM to dump, we listen to port 2, which at the end of
// its compilation process, spits its HERE addr to port 2 (MSB first)
#define HERE_PORT 0x02
static int running;
// We support double-pokes, that is, a first poke to tell where to start the
// dump and a second one to tell where to stop. If there is only one poke, it's
// then ending HERE and we start at sizeof(KERNEL).
static uint16_t start_here = 0;
static uint16_t end_here = 0;
static uint8_t iord_stdio()
{
int c = getc(stdin);
if (c == EOF) {
running = 0;
}
return (uint8_t)c;
}
static void iowr_stdio(uint8_t val)
{
// comment if you don't like verbose staging output
putc(val, stderr);
}
static void iowr_here(uint8_t val)
{
start_here <<=8;
start_here |= (end_here >> 8);
end_here <<= 8;
end_here |= val;
}
int main(int argc, char *argv[])
{
Machine *m = emul_init();
if (m == NULL) {
return 1;
}
m->ramstart = RAMSTART;
m->iord[STDIO_PORT] = iord_stdio;
m->iowr[STDIO_PORT] = iowr_stdio;
m->iowr[HERE_PORT] = iowr_here;
// Run!
running = 1;
while (running && emul_step());
// We're done, now let's spit dict data
for (int i=start_here; i<end_here; i++) {
putchar(m->mem[i]);
}
emul_deinit();
emul_printdebug();
return 0;
}

View File

@ -4,11 +4,12 @@ git submodule init
git submodule update
git clean -fxd
make -C cvm
make -C emul
make -C tests
# verify that forth.bin is stable
cp emul/forth.bin ref.bin
make -C emul updatebootstrap
cmp emul/forth.bin ref.bin
cp cvm/forth.bin ref.bin
make -C cvm updatebootstrap
cmp cvm/forth.bin ref.bin
rm ref.bin