summaryrefslogtreecommitdiff
path: root/readme.md
blob: 51a8f1ce99b69a9e67b3a0960b1014b1fc030872 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# jewelforth

its a forth for linux x86\_64. mostly made for personal stuff.
if you use it and it breaks, too bad

public domain

the plan right now is that this will be an STC forth.
if this proves Too Complicated To Deal With the plan may be changed
to a DTC forth instead.

## dictionary
the dictionary follows a fairly standard format.

| field | size | forth name |
| :---- | :--- | :--------- |
| link to previous | 8 bytes | LFA (link field address) |
| flag | 1 byte | FFA (flag field address) |
| string length | 2 bytes | NFA (name field address) |
| string | variable length | still NFA |
| null byte | 1 byte |
| code | variable length | CFA (code field address) |

probably, some bitmask antics could be done to store the string length
and flags together. but alternatively: no.

the stored string is a counted string but also has a
null byte at the end. bit of a waste of space but i can use
x86's `repz` for it. maybe there is a counted string version
though, i don't know

## forth registers
there are a set of 'virtual registers' (see moving forth part 1)

- W, the working register, is r11.
- X, the secondary working register, is r12.
- Y, the tertiary working register, is r13.
- SP, the working stack pointer, is r14.
- RSP, the return stack pointer, is rsp.

## miscellaneous notes and stuff

### COMPILE,
this is an STC forth so when we compile a call we have to
write the bytes of a `call` in manually.
x86\_64 does not allow absolute jumps from an immediate address,
so a wonky but hopefully not too slow solution is to compile
`literal address → W` and then `call W`. It'll Be Fine?

- `mov r11, [cfa]` = `94 BB [CFA]`
- `call r11` = `41 FF D3`

### words to bootstrap from
i want to make the kernel reasonably small,
especially if i add an assembler.
but obviously we need *something* to bootstrap from.
(this list is Inspired by [miniforth](https://github.com/meithecatte/miniforth)'s builtins)

- `!` (`val addr -- `): store a 64 bit word
- `@` (`addr -- val`): fetch a 64 bit word
- `c!` (`byte addr -- `): store a byte
- `c@` (`addr -- byte`): fetch a byte
- `:` (` -- `): compile a word from the current input source
- `;` (` -- `): stop compiling the current word
- `parse` (` -- c-addr u`): parse a word from the *forth init* (see footnote)
- `find` (`c-addr u -- ?lfa flag`)
- `interpret`: the stage 1 interpreter
- `latest`: a variable, the latest defined word
- `state`: a variable, determines current mode (interp./compiling)
- `>in`: a variable, offset from start of forth init

on `parse`: i don't want to deal with file access and stuff from the kernel.
so this word will be Upgraded in the forth init to read from a file.

### Some Links

- starting forth part 1: http://www.bradrodriguez.com/papers/moving1.htm
- a forum thread about determining empty stack with TOS register: http://forum.6502.org/viewtopic.php?t=8424

## silly little plans

### in-forth assembler
this would reap the most benefits from STC.
probably look at dusk's assemblers for how it should look like
or liek something liek dusk's lib/bm?
idk something to do stuff Fast if u need. would be fun