}
;; pushr and popr work on the return stack, whose location is stored in the
-;; register RBP.
+;; register RBP. Always allocates an extra 8 bytes as "local frame"
macro pushr x {
sub rbp, 8
mov qword [rbp], x
cmp rax, 0 ; Compare top of stack to see if we should branch
jnz .dont_branch
.do_branch:
- jmp BRANCH.start
+ add rsi,[rsi]
+ next
.dont_branch:
add rsi, 8 ; We need to skip over the next word, which contains
; the offset.
next
+;; Push the return stack pointer. "grows" negatively
+forth_asm RSPGET, 'R='
+ push rbp
+ next
+
+;; The return stack "grows" negatively, and rbp is the address of the top
+;; Move rbp by n (from stack) bytes
+forth_asm RSPADD, 'R+'
+ pop rax
+ sub rbp, rax
+ next
+
+;; Push top of the stack.
+forth_asm TOP_, 'TOP'
+ push rsp
+ next
+
;; Duplicate the top of the stack.
forth_asm DUP_, 'DUP'
push qword [rsp]
pop rax
jmp qword [rax]
+;; This word skips a word without exectuing, but pushes its address
+forth_asm SKIP_, 'SKIP'
+ push rsi
+ add rsi, 8 ; We need to skip over the next word, which contains
+ ; the offset.
+ next
+
;; Expects a character on the stack and prints it to standard output.
forth_asm EMIT, 'EMIT'
pushr rsi
.skip_whitespace:
;; Read characters until one of them is not whitespace.
call KEY.impl
- ;; We consider newlines and spaces to be whitespace.
+ ;; We consider newlines, tabs and spaces to be whitespace.
cmp al, ' '
je .skip_whitespace
+ cmp al, $9
+ je .skip_whitespace
cmp al, $A
je .skip_whitespace
cmp al, ' '
je .end
+ cmp al, 9
+ je .end
cmp al, $A
jne .read_alpha
add rsp, 8
next
+;; Takes a value and an address, and stores the value at the given address.
+forth_asm AND_, '&'
+ pop rbx ; a
+ pop rax ; b
+ and rax, rbx
+ push rax
+ next
+
forth_asm NOT_, 'NOT'
pop rax
cmp rax, 0
push rbx
next
-;; Given two integers a and b on the stack, pushes the quotient and remainder of
-;; division of a by b.
+;; Multiply two integers on the stack ignoring overflow
+forth_asm MULT, '*'
+ pop rax
+ pop rbx
+ mul rbx
+ push rax
+ next
+
+;; Given two integers a and b on the stack, pushes the quotient and
+;; remainder of division of a by b.
forth_asm TIMESMOD, '/MOD'
pop rbx ; b
pop rax ; a
pop rax
pop rbx
pop rdx
+ push rbx
push rax
push rdx
- push rbx
next
forth_asm PICK, 'PICK'
push rax
next
+forth_asm OVER, 'OVER'
+ push qword [rsp + 8]
+ next
+
forth_asm EQL, '='
pop rax
pop rbx
push 1
next
+forth_asm LT_, '<'
+ pop rax
+ pop rbx
+ cmp rax, rbx
+ jle .le
+.notle:
+ push 1
+ next
+.le:
+ push 0
+ next
+
+forth_asm GT_, '>'
+ pop rax
+ pop rbx
+ cmp rax, rbx
+ jge .ge
+.notge:
+ push 1
+ next
+.ge:
+ push 0
+ next
+
forth MAIN, 'MAIN'
dq SYSCODE
dq INTERPRET_STRING
forth_asm EFICALL1, 'EFICALL1'
pop rax ; function pointer
pop rcx ; 1st argument
-
sub rsp, 32
call rax
add rsp, 32
-
next
forth_asm EFICALL2, 'EFICALL2'
pop rax ; function pointer
pop rdx ; 2nd argument
pop rcx ; 1st argument
-
sub rsp, 32
call rax
add rsp, 32
-
next
forth_asm EFICALL3, 'EFICALL3'
pop r8 ; 3rd argument
pop rdx ; 2nd argument
pop rcx ; 1st argument
-
sub rsp, 32
call rax
add rsp, 32
+ push rax
+ next
+forth_asm EFICALL4, 'EFICALL4'
+ pop rax ; function pointer
+ pop r9 ; 4th argument
+ pop r8 ; 3rd argument
+ pop rdx ; 2nd argument
+ pop rcx ; 1st argument
+ sub rsp, 32
+ call rax
+ add rsp, 32
push rax
+ next
+forth_asm EFICALL5, 'EFICALL5'
+ pop rax ; function pointer
+ pop r10 ; 5th argument
+ pop r9 ; 4th argument
+ pop r8 ; 3rd argument
+ pop rdx ; 2nd argument
+ pop rcx ; 1st argument
+ push r10 ; restore as stack argument
+ sub rsp, 32
+ call rax
+ add rsp, 32 + 8
+ push rax
next
forth_asm EFICALL10, 'EFICALL10'
pop rax ; function pointer
-
- mov rcx, [rsp + 8 * 9]
- mov rdx, [rsp + 8 * 8]
+ mov rcx, [rsp + 8 * 9] ; 1st
+ mov rdx, [rsp + 8 * 8] ; 2nd
mov r8, [rsp + 8 * 7]
mov r9, [rsp + 8 * 6]
-
;; Reverse order of stack arguments
mov r10, [rsp + 8 * 5]
mov r11, [rsp + 8 * 0]
mov [rsp + 8 * 5], r11
mov [rsp + 8 * 0], r10
-
mov r10, [rsp + 8 * 4]
mov r11, [rsp + 8 * 1]
mov [rsp + 8 * 4], r11
mov [rsp + 8 * 1], r10
-
mov r10, [rsp + 8 * 3]
mov r11, [rsp + 8 * 2]
mov [rsp + 8 * 3], r11
mov [rsp + 8 * 2], r10
-
sub rsp, 32
call rax
add rsp, 32 + 8 * 10
-
push rax
-
next
;; Built-in variables:
READ_STRING.buffer rb $FF
READ_STRING.length dq ?
-DOTU.chars db '0123456789ABCDEF'
+DOTU.chars db '0123456789abcdef'
DOTU.buffer rq 16 ; 64-bit number has no more than 16 digits in hex
DOTU.rbuffer rq 16
DOTU.length dq ?
sysf:
file '../init/sys.f'
file '../init/uefi.f'
+file '../init/blurb.f'
sysf.len = $ - sysf
-