summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--quine.asm77
1 files changed, 66 insertions, 11 deletions
diff --git a/quine.asm b/quine.asm
index 9be965d..5ecc29e 100644
--- a/quine.asm
+++ b/quine.asm
@@ -1900,12 +1900,15 @@ cold_start:
   ;;; on the stack
   ;;;   Start defining some words that are allocated at runtime on the heap,
   ;;; beginning with the minimal set of words needed to define more words.
-  dq litstring, "heap", early_create
-  dq lit, 0x42, early_comma
-  dq litstring, "s0", early_create
-  dq litstring, "r0", early_create
-  dq litstring, "latest", early_create
-  dq litstring, "here", early_create
+  ;;; The first few are our variables, which hardcode the addresses they will
+  ;;; return - but since we're doing this at runtime, "hardcoding" can reflect
+  ;;; where our heap is. This is the fundamental trick that makes the heap
+  ;;; usable.
+  dq early_heap, litstring, "heap", early_defvar
+  dq early_s0, litstring, "s0", early_defvar
+  dq early_r0, litstring, "r0", early_defvar
+  dq early_latest, litstring, "latest", early_defvar
+  dq early_here, litstring, "here", early_defvar
   dq quit
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -2700,7 +2703,8 @@ defword reg64, 0
   dq dup, rbp, eq, zbranch, 5*8, drop, lit, 5, exit
   dq dup, rsi, eq, zbranch, 5*8, drop, lit, 6, exit
   dq dup, rdi, eq, zbranch, 5*8, drop, lit, 7, exit
-  dq sys_exit
+  dq litstring, "Parameter to reg64 is not a reg64.", emitstring
+  dq lit, 1, sys_exit
 
 ; Stack in:
 ;   register name
@@ -2716,7 +2720,8 @@ defword extrareg64, 0
   dq dup, r13, eq, zbranch, 5*8, drop, lit, 5, exit
   dq dup, r14, eq, zbranch, 5*8, drop, lit, 6, exit
   dq dup, r15, eq, zbranch, 5*8, drop, lit, 7, exit
-  dq sys_exit
+  dq litstring, "Parameter to extrareg64 is not an extrareg64.", emitstring
+  dq lit, 1, sys_exit
 
 ; Stack:
 ;   output point
@@ -2770,6 +2775,21 @@ defword mov_reg64_reg64, 0
 
 ; Stack:
 ;   output point
+;   source register name
+defword push_reg64, 0
+  dq docol, reg64, lit, 0x50, opcodereg, exit
+
+defword lodsq, 0
+  dq docol, rex_w, lit, 0xAD, pack8, exit
+
+defword jmp_abs_indirect_qreg, 0
+  dq docol
+  dq swap, lit, 0xFF, pack8, swap
+  dq reg64, lit, 0, lit, 4, roll3, modrm
+  dq exit
+
+; Stack:
+;   output point
 defword syscall, 0
   dq docol, lit, 0x0F, pack8, lit, 0x05, pack8, exit
 
@@ -2895,6 +2915,32 @@ defword early_self_codeword, 0
 defword early_here_store, 0
   dq docol, swap, early_here, swap, unroll3, store, exit
 
+;   Notice that we've switched over to stuff that follows the pack* idioms.
+;
+; Stack in:
+;   base address
+; Stack out:
+;   new base address
+defword pack_next, 0
+  dq docol, lodsq, rax, jmp_abs_indirect_qreg, exit
+
+; Stack in:
+;   heap address
+;   address for new variable word to return
+;   name string
+; Stack out:
+;   heap address
+defword early_defvar, 0
+  dq docol
+  dq swap, unroll3, early_create, early_self_codeword
+  ; (address to return, heap address)
+  dq early_here, fetch, swap, unroll3, swap
+  ; (heap address, modified "here" value, address to return)
+  dq rax, mov_reg64_imm64, rax, push_reg64
+  ; (heap address, modified "here" value)
+  dq pack_next, lit, 8, packalign, early_here_store
+  dq exit
+
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Now.... what was our original goal, again? ;;;
@@ -2934,7 +2980,7 @@ defword quit, 0
   ;;; If the repl ever exits, do it all again.
   ;;;
   ;dq branch, quit - $
-  dq sys_exit
+  dq lit, 0, sys_exit
 
 
 ;;;;;;;;;;;;;;;;;;;;
@@ -2952,13 +2998,14 @@ defword quit, 0
 ;;;
 
 ;;;
-;;;   This does the Linux exit() system call, passing it exit code zero.
+;;;   This does the Linux exit() system call, passing it an exit code taken
+;;; from the stack.
 ;;;
 defword sys_exit, 0
   dq $ + 8
 
   mov.qreg.qimm rax, 60          ; syscall number
-  mov.qreg.qimm rdi, 0           ; exit code
+  pop.qreg rdi                   ; exit code
   syscall
 
   ; In the event we're still here, let's minimize confusion.
@@ -2988,6 +3035,14 @@ defword sys_write, 0
   next
 
 
+;;;;;;;;;;;;;;;;;;;;;;;;
+;;; I/O conveniences ;;;
+;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+defword emitstring, 0
+  dq docol, dup, stringlen, swap, sys_write, exit
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; (new) Implementation strategy ;;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;