diff options
| author | Irene Knapp <ireneista@irenes.space> | 2026-05-16 13:53:08 -0700 |
|---|---|---|
| committer | Irene Knapp <ireneista@irenes.space> | 2026-05-16 13:53:08 -0700 |
| commit | fe3de0772dac094b94f8de89efbb815a62b1a2fa (patch) | |
| tree | cf5fca8004005f5015a6dcfc7c25fd8ff2879d3d | |
| parent | f4112a05de8bf4c69a7abb9817c7ca70be9f7fb5 (diff) | |
implement more internal words
Force-Push: yes Change-Id: I273879e9d05260db0603bc5a36970e240f3e366a
| -rw-r--r-- | interpret.e | 108 | ||||
| -rw-r--r-- | linux.e | 69 |
2 files changed, 166 insertions, 11 deletions
diff --git a/interpret.e b/interpret.e index f1efd4d..147eeac 100644 --- a/interpret.e +++ b/interpret.e @@ -159,17 +159,99 @@ : unhide-entry dup entry-flags@ 0x80 invert & entry-flags! ; +~ (pointer to buffer metadata -- pointer to buffer "physical-start" field) +: buffer-physical-start ; + ~ The physical-start field happens to be the first thing in the metadata, so + ~ this is an nop, but it still exists as a word because having it reduces + ~ confusion. +~ (pointer to buffer metadata -- pointer to buffer "physical-length" field) +: buffer-physical-start 8 + ; +~ (pointer to buffer metadata -- pointer to buffer "logical-start" field) +: buffer-logical-start 2 8 * + ; +~ (pointer to buffer metadata -- pointer to buffer "logical-length" field) +: buffer-logical-length 3 8 * + ; +~ (pointer to input buffer metadata -- pointer to input buffer "refill" field) +: input-buffer-refill 4 8 * + ; +~ (pointer to input buffer metadata +~ -- pointer to input buffer "next-source" field) +: input-buffer-next-source 5 8 * + ; + +~ Given an initialized buffer (input or otherwise), sets its logical-start +~ and logical-length fields to indicate the buffer is empty. This relies on +~ the buffer having a backing store attached, but does not alter the backing +~ store or its contents. +~ +~ (pointer to buffer metadata --) +: clear-buffer + dup buffer-physical-start @ swap + ~ (address of backing store, metadata pointer) + dup 3unroll + ~ (metadata pointer, address of backing store, metadata pointer) + buffer-logical-start ! + buffer-logical-length 0 swap ! ; + + +~ Sets all fields in an input buffer metadata structure to zero, +~ effectively detaching and leaking any backing store that had been attached +~ to it. Suitable for use during initialization. +~ +~ (pointer to input buffer metadata --) +: zero-input-buffer-metadata + dup buffer-physical-start 0 swap ! + dup buffer-physical-length 0 swap ! + dup buffer-logical-start 0 swap ! + dup buffer-logical-length 0 swap ! + dup input-buffer-refill 0 swap ! + ~ Notice the absence of a dup this time. + input-buffer-next-source 0 swap ! ; + + +~ Allocates input-buffer metadata, with no backing store attached. +~ Initializes the metadata to all zeroes. +~ +~ (-- pointer to input buffer metadata) +: allocate-input-buffer-metadata + 6 8 * allocate + dup zero-input-buffer-metadata ; + + +~ Allocates input buffer metadata and a backing store, in one operation. +~ Points the metadata to the backing store. +~ +~ (buffer capacity in bytes -- pointer to input buffer metadata) +: allocate-input-buffer + dup 6 8 * + allocate + dup zero-input-buffer-metadata + ~ (capacity in bytes, metadata pointer) + dup dup 6 8 * + + ~ (capacity in bytes, metadata pointer, metadata pointer, physical start) + swap buffer-physical-start ! + ~ (capacity in bytes, metadata pointer) + dup 3unroll buffer-physical-length ! + ~ (metadata pointer) + dup clear-buffer ; + + +~ Sets the backing store of an input buffer to point at a null-teriminated +~ string and read from it. +~ +~ TODO are these backwards +~ (string pointer, pointer to buffer metadata --) +: attach-string-to-input-buffer + swap + ~ (string pointer, metadata pointer) + 2dup buffer-physical-start ! + ~ (string pointer, metadata pointer) + 2dup buffer-logical-start ! + ~ (string pointer, metadata pointer) + swap stringlen swap + ~ (string length, metadata pointer) + 2dup buffer-physical-length ! + ~ (string length, metadata pointer) + buffer-logical-length ! ; + + ~ TODO -~ buffer-physical-start 0000001000018240 -~ buffer-physical-length 0000001000018270 -~ buffer-logical-start 00000010000182c0 -~ buffer-logical-length 0000001000018308 -~ input-buffer-refill 0000001000018350 -~ clear-buffer 0000001000018398 -~ zero-input-buffer-metadata 0000001000018428 -~ allocate-input-buffer-metadata 0000001000018548 -~ allocate-input-buffer 00000010000185b0 -~ attach-string-to-input-buffer 0000001000018688 ~ main-input-buffer-metadata 0000001000018738 I raw ~ main-input-buffer 0000001000018788 asm ~ consume-from 00000010000187c0 @@ -185,7 +267,11 @@ ~ dropstring-with-result 0000001000018f80 ~ accumulate-string 0000001000018fc8 ~ word 00000010000194a0 -~ find 00000010000195f0 + + +~ (string pointer -- entry pointer or 0) +: find latest swap find-in ; + ~ (character -- 1 for true or 0 for false) : is-alphanumeric diff --git a/linux.e b/linux.e new file mode 100644 index 0000000..ce0b9b7 --- /dev/null +++ b/linux.e @@ -0,0 +1,69 @@ +~ ~~~~~~~~~~~~~~~~~~ +~ ~~ System calls ~~ +~ ~~~~~~~~~~~~~~~~~~ +~ +~ The kernel preserves every register except rax, rcx, and r11. The system +~ call number goes in rax, as does the return value. Parameters go in rdi, +~ rsi, rdx, r10, r8, and r9, in that order. [SysV] A.2.1. +~ +~ Notice that rsi is our control stack, so we have to save it (for +~ syscalls with at least two parameters). We can use the value stack to do +~ that, since rsp is preserved. We don't save other registers because our +~ caller should do that, if it cares. +~ + +~ This does the Linux exit() system call, passing it an exit code taken +~ from the stack. It does not return. +~ +~ (exit code -- *) +: sys-exit + [ here @ + 60 :rax mov-reg64-imm64 ~ syscall number + :rdi pop-reg64 ~ exit code + syscall + + ~ In the event we're still here, let's minimize confusion. + hlt + + ~ This one, uniquely, doesn't need to be followed by the "next" macro. It + ~ is, though, since ;asm does that anyway. + here ! ] ;asm + + +~ This does the Linux write() system call, passing it an address from the +~ top of the stack and a length from the second position on the stack. It +~ writes to file descriptor 1, which is stdout. +~ +~ For our length parameter, we can pop directly from the stack into rdx, +~ which directly becomes the syscall parameter. For our address parameter, +~ the syscall wants it in rsi, which we also care about, so we have to do a +~ little juggling. +~ +~ (length to write, base address -- *) +: sys-write + [ here @ + :rcx pop-reg64 ~ address from stack + :rdx pop-reg64 ~ length from stack, passed directly + :rsi push-reg64 ~ save rsi + 1 :rax mov-reg64-imm64 ~ syscall number + 1 :rdi mov-reg64-imm64 ~ file descriptor + :rcx :rsi mov-reg64-reg64 ~ pass address + syscall + :rsi pop-reg64 ~ restore rsi + here ! ] ;asm + + +~ (length to read, base address -- *) +: sys-read + [ here @ + :rcx pop-reg64 ~ address from stack + :rdx pop-reg64 ~ length from stack, passed directly + :rsi push-reg64 ~ save rsi + 0 :rax mov-reg64-imm64 ~ syscall number + 0 :rdi mov-reg64-imm64 ~ file descriptor + :rcx :rsi mov-reg64-reg64 ~ pass address + syscall + :rsi pop-reg64 ~ restore rsi + :rax push-reg64 ~ return length + here ! ] ;asm + |