commit - /dev/null
commit + b0948a2196988cb5c4976fdeeb1ff5cc71123941
blob - /dev/null
blob + dbf861a3070de488b056c45153698bfa93902227 (mode 644)
--- /dev/null
+++ .gdbinit
+layout regs
+
blob - /dev/null
blob + a4d6393d61b9bb9153c030681edae17571a95516 (mode 644)
--- /dev/null
+++ Makefile
+.POSIX:
+
+LDFLAGS = -g -no-pie
+
+all: rvforth
+
+od: rvforth
+ llvm-objdump -d rvforth | less
+
+gdb: rvforth
+ egdb ./rvforth
+
+run: rvforth
+ ./rvforth
+
+clean:
+ rm -f rvforth *.core
+
+
+
blob - /dev/null
blob + a5e20c33ebfa93d315f75c4e1644e58450c3f376 (mode 644)
--- /dev/null
+++ rvforth.S
+// s5 - data stack pointer
+// s6 - return stack pointer
+// s7 - program counter
+
+#define DSP s5
+#define RSP s6
+#define PC s7
+
+.set F_HIDDEN, 0x80
+.set F_IMMED, 0x40
+.set F_LENMASK, 0x1f
+.set WORDLEN, 32
+.set name_0, 0
+
+.macro def name, namelen, label, prev, flags=0
+.section .rodata
+.align 8
+.global name_\label
+.type name_\label, @object
+name_\label :
+.quad name_\prev
+.byte \flags + \namelen
+.ascii "\name"
+.skip (8 - ((\namelen + 1) & 7)) & 7
+.global \label
+.type \label, @object
+\label:
+.endm
+
+.macro defword name, namelen, label, prev, flags=0
+def "\name", \namelen, \label, \prev, \flags
+.quad DOCOL
+.endm
+
+.macro defcode name, namelen, label, prev, flags=0
+def "\name", \namelen, \label, \prev, \flags
+.quad code_\label
+.section .text
+.align 4
+.global code_\label
+code_\label:
+.endm
+
+.macro defvar name, namelen, label, prev, initial=0, flags=0
+defcode \name, \namelen, \label, \prev, \flags
+ la t0, var_\name
+ PUSH t0
+ NEXT
+
+.section .data
+var_\name:
+ .quad \initial
+.endm
+
+.macro defconst name, namelen, label, prev, value, flags=0
+defcode \name, \namelen, \label, \prev, \flags
+ la t0, \value
+ PUSH t0
+ NEXT
+.endm
+
+.macro NEXT
+ ld t0, 0(PC)
+ addi PC, PC, 8
+ ld t1, 0(t0)
+ jr t1
+.endm
+
+.macro PUSH, reg
+ addi DSP, DSP, -8
+ sd \reg, 0(DSP)
+.endm
+
+.macro POP, reg
+ ld \reg, 0(DSP)
+ addi DSP, DSP, 8
+.endm
+
+.macro PUSHRSP, reg
+ addi RSP, RSP, -8
+ sd \reg, 0(RSP)
+.endm
+
+.macro POPRSP, reg
+ ld \reg, 0(RSP)
+ addi RSP, RSP, 8
+.endm
+
+.section .text
+.global DOCOL
+.type DOCOL, @function
+DOCOL:
+ PUSHRSP PC
+ add t0, t0, 8
+ mv PC, t0
+ NEXT
+
+.global main
+.type main, @function
+main:
+ addi sp, sp, -64
+ sd ra, 0(sp)
+ sd DSP, 8(sp)
+ sd RSP, 16(sp)
+ sd PC, 24(sp)
+ sd s0, 32(sp)
+ sd s1, 40(sp)
+ sd s2, 48(sp)
+ sd s3, 56(sp)
+
+ la DSP, data_stack
+ la RSP, return_stack
+ la PC, cold_start
+ la t0, var_S0
+ sd DSP, 0(t0)
+ NEXT
+.size main, . - main
+
+return:
+ mv a0, zero
+ ld s3, 56(sp)
+ ld s2, 48(sp)
+ ld s1, 40(sp)
+ ld s0, 32(sp)
+ ld PC, 24(sp)
+ ld RSP, 16(sp)
+ ld DSP, 8(sp)
+ ld ra, 0(sp)
+ addi sp, sp, 64
+ jr ra
+.size return, . - return
+
+.section .rodata
+.align 8
+cold_start:
+ .quad QUIT
+
+.section .text
+
+// memeq (s1, s2, n);
+_MEMEQ:
+ beq a2, zero, 1f
+ lbu t0, 0(a0)
+ lbu t1, 0(a1)
+ bne t0, t1, 2f
+ addi a0, a0, 1
+ addi a1, a1, 1
+ addi a2, a2, -1
+ j _MEMEQ
+
+1: // equal
+ li a0, 1
+ jr ra
+
+2: // not equal
+ mv a0, zero
+ jr ra
+.size _MEMEQ, . - _MEMEQ
+
+// a0 - name
+// a1 - namelen
+_FIND:
+ addi sp, sp, -32
+ sd ra, 0(sp)
+ sd s0, 8(sp)
+ sd s1, 16(sp)
+ sd s2, 24(sp)
+
+ mv s0, a0 // name
+ mv s1, a1 // namelen
+ la s2, var_LATEST
+ j 2f
+
+1:
+ lbu a2, 8(s2)
+ andi t0, a2, F_HIDDEN
+ bne t0, zero, 2f
+ andi a2, a2, F_LENMASK
+ bne a2, s1, 2f
+
+ mv a0, s0
+ addi a1, s2, 9
+ jal _MEMEQ
+ beq a0, zero, 2f
+
+ j 3f
+
+2:
+ ld s2, 0(s2)
+ bne s2, zero, 1b
+
+3:
+ mv a0, s2
+
+ ld s2, 24(sp)
+ ld s1, 16(sp)
+ ld s0, 8(sp)
+ ld ra, 0(sp)
+ addi sp, sp, 32
+ jr ra
+.size _FIND, . - _FIND
+
+// return:
+// a0 - word
+// a1 - wordlen
+_WORD:
+ addi sp, sp, -32
+ sd ra, 0(sp)
+ sd s0, 8(sp)
+ sd s1, 16(sp)
+
+ la s0, wordbuf
+ mv s1, zero
+
+1:
+ jal _KEY
+ li t0, ' '
+ beq a0, t0, 1b
+ li t0, '\n'
+ beq a0, t0, 1b
+ li t0, '\r'
+ beq a0, t0, 1b
+ li t0, '\b'
+ beq a0, t0, 1b
+ j 3f
+
+2:
+ li t0, ' '
+ beq a0, t0, nl
+ li t0, '\n'
+ beq a0, t0, nl
+ li t0, '\b'
+ beq a0, t0, bs
+ li t0, '\r'
+ beq a0, t0, 1f
+3:
+ li t0, -1
+ beq a0, t0, nl
+
+ add t0, s0, s1
+ sb a0, 0(t0)
+ addi s1, s1, 1
+
+1:
+ jal _KEY
+ j 2b
+
+nl:
+ add t0, s0, s1
+ sb zero, 0(t0)
+
+ la t0, wordlen
+ sd s1, 0(t0)
+ mv a0, s0
+ mv a1, s1
+
+ ld s1, 16(sp)
+ ld s0, 8(sp)
+ ld ra, 0(sp)
+ addi sp, sp, 32
+ jr ra
+
+bs:
+ beq s1, zero, _WORD
+ jal _EMIT
+ li a0, ' '
+ jal _EMIT
+ li a0, '\b'
+ jal _EMIT
+ addi s1, s1, -1
+ j 1b
+.size _WORD, . - _WORD
+
+_TCFA:
+ addi a0, a0, 9
+ lbu t0, -1(a0)
+ andi t0, t0, F_LENMASK
+ add a0, a0, t0
+ addi a0, a0, 7
+ andi a0, a0, ~7
+ jr ra
+.size _TCFA, . - _TCFA
+
+_EMIT:
+ j putchar
+.size _EMIT, . - _EMIT
+
+_KEY:
+ j getchar
+.size _KEY, . - _KEY
+
+// a0 - str
+// a1 - len
+_NUMBER:
+ mv t0, zero
+ beq a1, zero, 2f
+ li a2, 1
+
+ lbu t1, 0(a0)
+ li t2, '-'
+ bne t1, t2, 1f
+
+ li a2, -1
+ addi a0, a0, 1
+ addi a1, a1, -1
+
+1:
+ lbu t1, 0(a0)
+
+ li t2, '0'
+ bltu t1, t2, 2f
+ li t2, '9'
+ bgt t1, t2, 2f
+
+ li t2, 10
+ mul t0, t0, t2
+ add t0, t0, t1
+ addi t0, t0, -'0'
+
+ addi a0, a0, 1
+ addi a1, a1, -1
+
+3:
+ bne a1, zero, 1b
+ li a0, -1
+ //mv a1, t0
+ mul a1, t0, a2
+ jr ra
+
+2: // not a digit
+ mv a0, zero
+ jr ra
+
+.size _NUMBER, . - _NUMBER
+
+_COMMA:
+ la t0, var_HERE
+ ld t1, 0(t0)
+ sd a0, 0(t1)
+ addi t1, t1, 8
+ sd t1, 0(t0)
+ jr ra
+.size _COMMA, . - _COMMA
+
+defcode "DONE", 4, DONE, 0
+ POP a0
+ jal exit
+
+defcode "EXIT", 4, EXIT, DONE
+ POPRSP PC
+ NEXT
+
+defcode "DROP", 4, DROP, EXIT
+ POP t0
+ NEXT
+
+defcode "SWAP", 4, SWAP, DROP
+ POP t0
+ POP t1
+ PUSH t0
+ PUSH t1
+ NEXT
+
+defcode "DUP", 3, DUP, SWAP
+ POP t0
+ PUSH t0
+ PUSH t0
+ NEXT
+
+defcode "+", 1, ADD, DUP
+ POP t1
+ POP t0
+ add t0, t0, t1
+ PUSH t0
+ NEXT
+
+defcode "-", 1, SUB, ADD
+ POP t1
+ POP t0
+ sub t0, t0, t1
+ PUSH t0
+ NEXT
+
+defcode "*", 1, MUL, SUB
+ POP t1
+ POP t0
+ mul t0, t0, t1
+ PUSH t0
+ NEXT
+
+defcode "AND", 3, AND, MUL
+ POP t1
+ POP t0
+ and t0, t0, t1
+ PUSH t0
+ NEXT
+
+defcode "OR", 2, OR, AND
+ POP t1
+ POP t0
+ or t0, t0, t1
+ PUSH t0
+ NEXT
+
+defcode "XOR", 3, XOR, OR
+ POP t1
+ POP t0
+ xor t0, t0, t1
+ PUSH t0
+ NEXT
+
+defcode "0=", 2, EQZ, XOR
+ POP t0
+ beq t0, zero, 1f
+ PUSH zero
+ NEXT
+
+1:
+ li t0, -1
+ PUSH t0
+ NEXT
+
+defcode "KEY", 3, KEY, EQZ
+ jal _KEY
+ PUSH a0
+ NEXT
+
+defcode "WORD", 4, WORD, KEY
+ jal _WORD
+ PUSH a1
+ PUSH a0
+ NEXT
+
+defcode "FIND", 4, FIND, WORD
+ POP a1
+ POP a0
+ jal _FIND
+ PUSH a0
+ NEXT
+
+defcode "BRANCH", 6, BRANCH, FIND
+ ld t0, 0(PC)
+ add PC, PC, t0
+ NEXT
+
+defcode "0BRANCH", 7, ZBRANCH, BRANCH
+ POP a0
+ beq a0, zero, code_BRANCH
+ addi PC, PC, 8
+ NEXT
+
+defcode "RSP!", 8, RSPSTORE, ZBRANCH
+ POP RSP
+ NEXT
+
+defcode "CREATE", 6, CREATE, RSPSTORE
+ POP a0 // name
+ POP a1 // namelen
+ la t0, var_LATEST
+ la t1, var_HERE
+ ld t2, 0(t0) // LATEST
+ ld t3, 0(t1) // HERE
+ sd t3, 0(t0) // update LATEST
+
+ // store link pointer
+ sd t2, 0(t3)
+
+ // store name length
+ sb a1, 8(t3)
+
+ // store name
+ add t3, t3, 9
+
+1:
+ lbu t0, 0(a0)
+ sb t0, 0(t3)
+ addi a0, a0, 1
+ addi t3, t3, 1
+ addi a1, a1, -1
+ bne a1, zero, 1b
+
+ addi t3, t3, 7
+ andi t3, t3, ~7
+ sd t3, 0(t1)
+ NEXT
+
+defcode "INTERPRET", 9, INTERPRET, CREATE
+ jal _WORD
+ beq a1, zero, return
+ mv s0, a0
+ mv s1, a1
+
+ // check if compiling
+ la t0, var_STATE
+ ld s2, 0(t0)
+
+ jal _FIND
+ beq a0, zero, 1f
+
+ // check if word is immediate
+ lbu t0, 8(a0)
+ andi t0, t0, F_IMMED
+ bne t0, zero, 3f
+
+ // check if compiling
+ beq s2, zero, 3f
+
+ // compile word
+ jal _TCFA
+ jal _COMMA
+ NEXT
+
+3: // execute word
+ jal _TCFA
+ mv t0, a0
+ ld a0, 0(t0)
+ jr a0
+
+1: // not found, maybe number?
+ mv a0, s0
+ mv a1, s1
+ jal _NUMBER
+
+ beq a0, zero, 2f
+
+ beq s2, zero, 4f
+
+ mv s0, a1
+ la a0, LIT
+ jal _COMMA
+
+ mv a0,s0
+ jal _COMMA
+ NEXT
+
+4: // push integer
+ PUSH a1
+ NEXT
+
+2: // not found
+ la a0, .Lerr
+ jal puts
+ la s7, cold_start
+ NEXT
+
+defword "QUIT", 4, QUIT, INTERPRET
+ .quad R0, RSPSTORE
+ .quad INTERPRET
+ .quad BRANCH, -16
+
+defcode "!", 1, STORE, QUIT
+ POP t0
+ POP t1
+ sd t1, 0(t0)
+ NEXT
+
+defcode "@", 1, FETCH, STORE
+ POP t0
+ ld t0, 0(t0)
+ PUSH t0
+ NEXT
+
+defcode "C!", 2, STOREBYTE, FETCH
+ POP t0
+ POP t1
+ sb t1, 0(t0)
+ NEXT
+
+defcode "C@", 2, FETCHBYTE, STOREBYTE
+ POP t0
+ lbu t0, 0(t0)
+ PUSH t0
+ NEXT
+
+defcode ".", 1, PRINT, FETCHBYTE
+ POP a1
+ la a0, .Lfmt
+ jal printf
+ NEXT
+
+defcode ",", 1, COMMA, PRINT
+ POP a0
+ jal _COMMA
+ NEXT
+
+defcode "'", 1, TICK, COMMA
+ ld a0, 0(PC)
+ addi PC, PC, 8
+ PUSH a0
+ NEXT
+
+defword "[", 1, LBRACK, TICK, F_IMMED
+ .quad LIT, 0
+ .quad STATE
+ .quad STORE
+ .quad EXIT
+
+defword "]", 1, RBRACK, LBRACK
+ .quad LIT, 1
+ .quad STATE
+ .quad STORE
+ .quad EXIT
+
+defword "HIDDEN", 6, HIDDEN, RBRACK
+ .quad LIT, 8
+ .quad ADD
+ .quad DUP
+ .quad FETCHBYTE
+ .quad LIT, F_HIDDEN
+ .quad XOR
+ .quad SWAP
+ .quad STOREBYTE
+ .quad EXIT
+
+defword "HIDE", 4, HIDE, HIDDEN
+ .quad LATEST, FETCH
+ .quad HIDDEN
+ .quad EXIT
+
+defword "IMMEDIATE", 9, IMMEDIATE, HIDE
+ .quad LATEST, FETCH
+ .quad LIT, 8
+ .quad ADD
+ .quad DUP
+ .quad FETCHBYTE
+ .quad LIT, F_IMMED
+ .quad XOR
+ .quad SWAP
+ .quad STOREBYTE
+ .quad EXIT
+
+defcode "LIT", 3, LIT, IMMEDIATE
+ ld t0, 0(PC)
+ addi PC, PC, 8
+ PUSH t0
+ NEXT
+
+defword ":", 1, COLON, LIT
+ .quad WORD
+ .quad CREATE
+ .quad LIT, DOCOL, COMMA
+ .quad LATEST, FETCH, HIDDEN
+ .quad RBRACK
+ .quad EXIT
+
+defword ";", 1, SEMICOLON, COLON, F_IMMED
+ .quad LIT, EXIT, COMMA
+ .quad LATEST, FETCH, HIDDEN
+ .quad LBRACK
+ .quad EXIT
+
+defcode "EXECUTE", 7, EXECUTE, SEMICOLON
+ POP a0
+ jr a0
+
+defcode "EMIT", 4, EMIT, EXECUTE
+ POP a0
+ jal _EMIT
+ NEXT
+
+defcode "CHAR", 4, CHAR, EMIT
+ jal _WORD
+ lbu a0, 0(a0)
+ PUSH a0
+ NEXT
+
+defcode "TCFA", 4, TCFA, CHAR
+ POP a0
+ jal _TCFA
+ PUSH a0
+ NEXT
+
+defword "RECURSE", 7, RECURSE, TCFA, F_IMMED
+ .quad LATEST, FETCH
+ .quad TCFA
+ .quad COMMA
+ .quad EXIT
+
+defvar "LATEST", 6, LATEST, RECURSE, name_R0
+defvar "HERE", 4, HERE, LATEST, memory
+defvar "STATE", 5, STATE, HERE
+defvar "S0", 2, S0, STATE
+defconst "R0", 2, R0, S0, return_stack
+
+.section .rodata
+.Lerr:
+ .asciz "not found"
+.Lfmt:
+ .asciz "%d\n"
+.Lhex:
+ .asciz "%#x\n"
+
+.section .bss
+wordlen:
+ .skip 8
+wordbuf:
+ .skip WORDLEN + 1
+
+ .skip 4096
+return_stack:
+ .skip 4096
+data_stack:
+.align 8
+memory:
+ .skip 65536