Commit Diff


commit - /dev/null
commit + b0948a2196988cb5c4976fdeeb1ff5cc71123941
blob - /dev/null
blob + dbf861a3070de488b056c45153698bfa93902227 (mode 644)
--- /dev/null
+++ .gdbinit
@@ -0,0 +1,2 @@
+layout regs
+
blob - /dev/null
blob + a4d6393d61b9bb9153c030681edae17571a95516 (mode 644)
--- /dev/null
+++ Makefile
@@ -0,0 +1,20 @@
+.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
@@ -0,0 +1,705 @@
+// 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