X-Git-Url: https://git.rrq.au/?a=blobdiff_plain;f=rrqforth.asm;h=5d360306df30648ac9d94d9d5a9618dd5b85a096;hb=1650b06e609ebb40a1fcd3df54a3147f41f42138;hp=9709fde6df03a0e85259d8ced4bd970d2ffe0bb1;hpb=69125f1514739aa5dcee13a29eb161a229e47eed;p=rrq%2Frrqforth.git diff --git a/rrqforth.asm b/rrqforth.asm index 9709fde..5d36030 100644 --- a/rrqforth.asm +++ b/rrqforth.asm @@ -7,128 +7,245 @@ include 'machine.asm' ;;; ============================================================ segment readable writable executable - - WORD return_stack,'RS',dovariable - ;; The return stack - rb 1048576 ; 1 Mb return stack -RS_TOP: ; The initial rbp - WORD data_stack,'DS',dovariable - ;; The data stack - rb 1048576 ; 1 Mb data stack -DS_TOP: ; The initial rsp - - WORD inline_code,'[ASM]',fasm - ;; ( -- ) - ;; This transitions execution into inline assembler in the - ;; calling word defintion. Note that it stops advancing rsi; - ;; code should use FORTH macro to reenter forth execution, or - ;; exit to the calling definition via "jmp exit". - jmp qword rsi - - WORD p_exit, 'EXIT',fasm - ;; ( -- ) ( R: addr -- ) - ;; Returns execution to the calling definition as per the - ;; return stack. -exit: - popr rsi - next +;;; ======================================== +;;; These are the core "execution semantics" words, which are placed +;;; first so as to remain at the same binary address at successive +;;; compilations, which is helful for declaring special debugging gdb +;;; aliases. +;;; +;;; The DO* words are declared as "variables" to provide their +;;; assembled address when used in FORTH. +;;; +;;; The register context at entry to an "execution semantcs" code +;;; snippets is: +;;; rax = cfa* of word to execute +;;; rsi = cell* in the calling definition, after calling cell +;;; rsp = data stack pointer +;;; rbp = return stack pointer +;;; + +previous_word = 0 ; Used for chaining the words + + WORD p_dofasm,'doFASM',dovariable + ;; Execution semantics for assembly words. +dofasm: + add rax,8 + jmp rax -;;; Execution semantics for FORTH defition word -;;; At entry, rsi points into the calling definition, at the cell -;;; following the cell indicating this word, rax points to the CFA of -;;; this word. + WORD p_doforth,'doFORTH',dovariable ; + ;; Execution semantics for FORTH defition word. doforth: pushr rsi lea rsi, [rax+8] ; rsi = the DFA of the rax word next -;;; Execution semantics for DOES> -;;; The cell at [cfa-8] holds an adjustment offset. + WORD p_dodoes,'doDOES',dovariable + ;; Execution semantics for DOES> + ;; [cfa-8] holds the adjustment offset ("does offset") dodoes: pushr rsi lea rsi, [rax+8] ; rsi = the DFA of the rax word - add rsi,[rax-8] ; adjust rsi to the DOES> part + add rsi,qword [rax-8] ; adjust rsi by the "does offset' next + WORD p_dovariable,'doVARIABLE',dovariable ;; Execution semantics for a variable ( -- addr ) ;; rax points to CFA field dovariable: - add rax,8 + lea rax, [rax+8] ; rsi = the DFA of the rax word push rax next - ;; Execution semantics for a constant ( -- v ) + WORD p_dovalue,'doVALUE',dovariable + ;; Execution semantics for a value constant ( -- v ) ;; rax points to CFA field dovalue: - push qword [rax+8] + lea rax, [rax+8] ; rsi = the DFA of the rax word + push qword [rax] next + WORD p_dostring,'doSTRING',dovariable ;; Execution semantics for a string constant ( -- addr n ) ;; rax points to CFA field dostring: - add rax,8 - xor rbx,rbx - mov bl,[rax] - inc rax - push rax - push rbx + lea rax, [rax+8] ; rsi = the DFA of the rax word + pushpname rax next -include 'wordlists.asm' + WORD p_calltrace,'calltrace',dovalue + ;; Common call point for debugging + ;; rax = cfa of called word + ;; rsi = cell* of next forth word + ;; [$rsp] = from where the call was + ret + include 'syscalls.asm' + +;;; ======================================== +;;; The stacks are placed here. + + ;segment readable writable + + WORD return_stack,'RETURN-STACK',dovariable + ;; The return stack + BLOCK RS_TOP + rb 1048576 ; 1 Mb return stack +RS_TOP: ; The initial rbp + +last_system_word: + WORD data_stack,'DATA-STACK',dovariable + ;; The data stack + BLOCK DS_TOP + rb 1048576 ; 1 Mb data stack +DS_TOP: ; The initial rsp + + +;;; ======================================== +;;; Core execution control words + + ;segment readable executable + +;;; At fasm compilation: reset previous_word to make a new word list +;;; Words above belong to the SYSTEM wordlist, and the following +;;; belong to the FORTH wordlist. +previous_word = 0 + + WORD p_system,'SYSTEM',dovariable + ;; ( -- dfa ) + ;; The SYSTEM word list + dq last_system_word ; tfa of last SYSTEM word + dq p_forth_DFA ; dfa of successor word list + + WORD inline_code,'[ASM]',fasm + ;; ( -- ) + ;; This transitions execution into inline assembler in the + ;; calling word defintion. Note that it stops advancing rsi; + ;; code should use FORTH macro to reenter forth execution, or + ;; exit to the calling definition via "jmp exit". + jmp qword rsi + + WORD p_execute,'EXECUTE',fasm + ;; ( cfa -- ) + ;; Execute the word + pop rax + jmp qword [rax] ; goto code of that FORTH word (64 bit jump) + + WORD p_exit, 'EXIT',fasm + ;; ( -- ) ( R: addr -- ) + ;; Returns execution to the calling definition as per the + ;; return stack. +exit: + popr rsi + next + + ;; TERMINATE0 terminates the program with code 0 + ;; ( -- ) + WORD p_terminate, 'TERMINATE0',fasm + pop rdx +terminate_special: + mov eax,60 + syscall + +;;; ======================================== +;;; Core extension(s) + + ;segment readable writable executable + +include 'control.asm' +include 'wordlists.asm' include 'memory.asm' include 'stack.asm' include 'math.asm' +include 'logic.asm' include 'stdio.asm' +include 'compile.asm' WORD p_program_version,'PROGRAM_VERSION',dostring - STRING 'RRQ Forth version 0.1 - 2021-05-13',10 + STRING 'RRQ Forth version 0.1 - 2021-05-22',10 WORD p_stdin,'STDIN',dovalue ;; Initialised to hold a STREAM for fd 0 dq 0 + + WORD p_args,'ARGS',dostring + ;; Pointer to initial argument block + dq 0 ; *(int argc,(char*[argc]) argv) + + WORD p_lparen,'(',fasm,IMMEDIATE + pushr rsi +p_lparen_loop: + DOFORTH p_stdin, p_read_word + pop rax + pop rbx + cmp rax,0 ; end of stream + je p_lparen_exit + cmp rax,1 + jne p_lparen_loop + push rbx + push qword ')' + push 1 + DOFORTH p_strncmp + pop rax + cmp rax,0 + jne p_lparen_loop +p_lparen_exit: + popr rsi + next +;;; ******** The main entry point. ******** +main: + ;; Initial rsp points to the arguments block of size (64 bits) + ;; followed by the argument pointers. + mov qword [p_args_DFA],rsp + jmp p_quit_DFA ; QUIT + +;;; This word is also the last word before syscalls +last_forth_word: WORD p_quit,'QUIT',fasm ;; QUIT is the program entry point ******************** -main: + mov rsp,DS_TOP mov rbp,RS_TOP - ;; Initialize STREAM STDIN + cmp qword [p_stdin_DFA],0 + jne p_quit_INITIALIZED + ;; Initialize STDIN push 0 push 10000 DOFORTH p_stream - pop qword [p_stdin_DFA] + pop qword [p_stdin_DFA] ; Assign STDIN - ;; read a word - push qword 1 ; ( fd ) =stdout - push qword [p_stdin_DFA] +p_quit_INITIALIZED: + ;; Initial blurb FORTH - dq p_read_word ; ( fd s n ) - dq sys_write + dq p_program_version + dq p_tell + dq p_stdin + dq p_evaluate_stream + BRANCH 0,p_quit_ERROR + dq p_false + dq sys_exit +p_quit_ERROR: + dq p_literal_string + STRING 10,'*** Unknown word: ' + dq p_tell + dq p_this_word + dq p_2get + dq p_tell + dq p_literal_string + STRING 10 + dq p_tell ENDFORTH + mov rbp,RS_TOP ; reset the return stack + jmp main - push qword 1 ; stdout - DOFORTH p_program_version ; version string => ( s n ) - DOFORTH sys_write ; printout - pop rax ; ignore errors - - push 0 - DOFORTH sys_exit - - ;; TERMINATE0 terminates the program with code 0 - ;; ( v -- ) - WORD terminate, 'TERMINATE',fasm - pop rdx -terminate_special: - mov eax,60 - syscall - -last_word: - ;; FORTH is the last word of VOCABULARY FORTH - WORD forth,'FORTH',dovalue - dq forth_TFA - dq 0 +;;; ======================================== + ;segment readable writable heap_start: + rb 1048576 ; +1 Mb heap + rb 1048576 ; +1 Mb heap + rb 1048576 ; +1 Mb heap + rb 1048576 ; +1 Mb heap + rb 1048576 ; +1 Mb heap