commit b0948a2196988cb5c4976fdeeb1ff5cc71123941 from: Benjamin Stürz date: Mon Apr 29 15:04:27 2024 UTC Initial commit 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