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
|
# 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 |
| 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.
## 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.
- IP, the instruction pointer, is r13. (this will only be needed if we switch to DTC, otherwise this can be Y, a third general purpose register)
- 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)
- `latest`: a variable, the latest defined word
- `state`: a variable, determines current mode (interp./compiling)
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
|