summary refs log tree commit diff
path: root/quine.asm
diff options
context:
space:
mode:
Diffstat (limited to 'quine.asm')
-rw-r--r--quine.asm429
1 files changed, 222 insertions, 207 deletions
diff --git a/quine.asm b/quine.asm
index 7568b37..9be965d 100644
--- a/quine.asm
+++ b/quine.asm
@@ -2555,6 +2555,226 @@ zbranch_after_jmp:
   next
 
 
+;;;;;;;;;;;;;;;;;;;;;;
+;;; Ouptut helpers ;;;
+;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;;   These routines are for building up data structures in-memory. Sometimes
+;;; they're used for structures that are meant to stay in memory; other times
+;;; it's a buffer that will become output.
+;;;
+;;;   The general pattern is that each routine takes an output address and
+;;; some specific datum, and returns the output address adjusted to point
+;;; after the new datum. That makes them easy to chain together.
+
+; In: base address, value
+; Out: new base address
+defword pack64, 0
+  dq docol
+  dq swap, dup, unroll3, store, lit, 8, add
+  dq exit
+defword pack32, 0
+  dq docol
+  dq swap, dup, unroll3, store32, lit, 4, add
+  dq exit
+defword pack16, 0
+  dq docol
+  dq swap, dup, unroll3, store16, lit, 2, add
+  dq exit
+defword pack8, 0
+  dq docol
+  dq swap, dup, unroll3, store8, lit, 1, add
+  dq exit
+
+;   This works on C-style strings, which are characters followed by a null
+; terminator. The packed data includes the null terminator.
+;
+; Stack in:
+;   base address, string pointer
+; Stack out:
+;   new base address
+defword packstring, 0
+  dq docol
+  dq dup, stringlen, dup
+  ; base/destination, source, length, length
+  dq lit, 4, roll, dup, lit, 5, unroll
+  ; destination, source, length, length, base/destination
+  dq add, lit, 4, unroll
+  ; new base, destination, source, length
+  dq ccopy
+  dq exit
+
+; Stack in:
+;   base address
+;   byte size
+; Stack out:
+;   new base address
+defword packalign, 0
+  dq docol
+  dq dup2, divmod, drop, zbranch, 8*8
+  dq swap, lit, 0, pack8, swap
+  dq branch, -11*8
+  dq drop, exit
+
+; In the interests of reducing our executable's size, since a lot of it goes
+; to pack* invocations, we define words that combine lit with pack*. This
+; shaves roughly 700 bytes as of when it was added.
+defword litpack64, 0
+  dq $ + 8
+  lodsq
+  push.qreg rax
+  beforenext pack64
+defword litpack32, 0
+  dq $ + 8
+  lodsq
+  push.qreg rax
+  beforenext pack32
+defword litpack16, 0
+  dq $ + 8
+  lodsq
+  push.qreg rax
+  beforenext pack16
+defword litpack8, 0
+  dq $ + 8
+  lodsq
+  push.qreg rax
+  beforenext pack8
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Assembly language, but in Forth ;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;;   It's all backwards and stuff.
+;;;
+;;;   These routines use the output helpers, defined above.  They're called in
+;;; the same way: an output address, followed by data items specific to what's
+;;; being output.
+
+; We define a bunch of keywords, which evaluate to their own codeword
+; addresses.
+defword rax, 0
+  dq docol, lit, rax, exit
+defword rcx, 0
+  dq docol, lit, rcx, exit
+defword rdx, 0
+  dq docol, lit, rdx, exit
+defword rbx, 0
+  dq docol, lit, rbx, exit
+defword rsp, 0
+  dq docol, lit, rsp, exit
+defword rbp, 0
+  dq docol, lit, rbp, exit
+defword rsi, 0
+  dq docol, lit, rsi, exit
+defword rdi, 0
+  dq docol, lit, rdi, exit
+defword r8, 0
+  dq docol, lit, r8, exit
+defword r9, 0
+  dq docol, lit, r9, exit
+defword r10, 0
+  dq docol, lit, r10, exit
+defword r11, 0
+  dq docol, lit, r11, exit
+defword r12, 0
+  dq docol, lit, r12, exit
+defword r13, 0
+  dq docol, lit, r13, exit
+defword r14, 0
+  dq docol, lit, r14, exit
+defword r15, 0
+  dq docol, lit, r15, exit
+
+; Stack in:
+;   register name
+; Stack out:
+;   3-bit encoded value for register
+defword reg64, 0
+  dq docol
+  dq dup, rax, eq, zbranch, 5*8, drop, lit, 0, exit
+  dq dup, rcx, eq, zbranch, 5*8, drop, lit, 1, exit
+  dq dup, rdx, eq, zbranch, 5*8, drop, lit, 2, exit
+  dq dup, rbx, eq, zbranch, 5*8, drop, lit, 3, exit
+  dq dup, rsp, eq, zbranch, 5*8, drop, lit, 4, exit
+  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
+
+; Stack in:
+;   register name
+; Stack out:
+;   3-bit encoded value for register
+defword extrareg64, 0
+  dq docol
+  dq dup, r8, eq, zbranch, 5*8, drop, lit, 0, exit
+  dq dup, r9, eq, zbranch, 5*8, drop, lit, 1, exit
+  dq dup, r10, eq, zbranch, 5*8, drop, lit, 2, exit
+  dq dup, r11, eq, zbranch, 5*8, drop, lit, 3, exit
+  dq dup, r12, eq, zbranch, 5*8, drop, lit, 4, exit
+  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
+
+; Stack:
+;   output point
+defword rex_w, 0
+  dq docol, lit, 0x48, pack8, exit
+defword rex_wb, 0
+  dq docol, lit, 0x49, pack8, exit
+
+; Stack:
+;   output point
+;   3-bit encoded value for register
+;   opcode byte
+defword opcodereg, 0
+  dq docol, or, pack8, exit
+
+; Stack
+;   output point
+;   mode ("mod") field
+;   register/opcode field
+;   register/memory ("RM") field
+defword modrm, 0
+  dq docol, swap, lit, 8, mul, or, swap, lit, 64, mul, or, pack8, exit
+
+; Stack:
+;   output point
+defword cld, 0
+  dq docol, lit, 0xFC, pack8, exit
+
+; Stack:
+;   output point
+;   immediate value
+;   register name
+defword mov_reg64_imm64, 0
+  dq docol
+  dq roll3, rex_w, swap, reg64, lit, 0xB8, opcodereg, swap, pack64
+  dq exit
+defword mov_extrareg64_imm64, 0
+  dq docol
+  dq roll3, rex_wb, swap, extrareg64, lit, 0xB8, opcodereg, swap, pack64
+  dq exit
+
+; Stack:
+;   output point
+;   source register name
+;   target register name
+defword mov_reg64_reg64, 0
+  dq docol
+  dq roll3, rex_w, lit, 0x89, pack8, unroll3
+  dq reg64, swap, reg64, swap, lit, 3, unroll3, modrm
+  dq exit
+
+; Stack:
+;   output point
+defword syscall, 0
+  dq docol, lit, 0x0F, pack8, lit, 0x05, pack8, exit
+
+
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Runtime word definition ;;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -2675,6 +2895,7 @@ defword early_self_codeword, 0
 defword early_here_store, 0
   dq docol, swap, early_here, swap, unroll3, store, exit
 
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Now.... what was our original goal, again? ;;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -2767,83 +2988,6 @@ defword sys_write, 0
   next
 
 
-;;;;;;;;;;;;;;;;;;;;;;
-;;; Ouptut helpers ;;;
-;;;;;;;;;;;;;;;;;;;;;;
-
-; In: base address, value
-; Out: new base address
-defword pack64, 0
-  dq docol
-  dq swap, dup, unroll3, store, lit, 8, add
-  dq exit
-defword pack32, 0
-  dq docol
-  dq swap, dup, unroll3, store32, lit, 4, add
-  dq exit
-defword pack16, 0
-  dq docol
-  dq swap, dup, unroll3, store16, lit, 2, add
-  dq exit
-defword pack8, 0
-  dq docol
-  dq swap, dup, unroll3, store8, lit, 1, add
-  dq exit
-
-; Includes the null terminator.
-;
-; Stack in:
-;   base address, string pointer
-; Stack out:
-;   new base address
-defword packstring, 0
-  dq docol
-  dq dup, stringlen, dup
-  ; base/destination, source, length, length
-  dq lit, 4, roll, dup, lit, 5, unroll
-  ; destination, source, length, length, base/destination
-  dq add, lit, 4, unroll
-  ; new base, destination, source, length
-  dq ccopy
-  dq exit
-
-; Stack in:
-;   base address
-;   byte size
-; Stack out:
-;   new base address
-defword packalign, 0
-  dq docol
-  dq dup2, divmod, drop, zbranch, 8*8
-  dq swap, lit, 0, pack8, swap
-  dq branch, -11*8
-  dq drop, exit
-
-; In the interests of reducing our executable's size, since a lot of it goes
-; to PACK* invocations, we define words that combine lit with PACK*. This
-; shaves roughly 700 bytes as of when it was added.
-defword litpack64, 0
-  dq $ + 8
-  lodsq
-  push.qreg rax
-  beforenext pack64
-defword litpack32, 0
-  dq $ + 8
-  lodsq
-  push.qreg rax
-  beforenext pack32
-defword litpack16, 0
-  dq $ + 8
-  lodsq
-  push.qreg rax
-  beforenext pack16
-defword litpack8, 0
-  dq $ + 8
-  lodsq
-  push.qreg rax
-  beforenext pack8
-
-
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; (new) Implementation strategy ;;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -3092,136 +3236,7 @@ defword self_raw, 0
   dq exit
 
 
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Assembly language, but in Forth ;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;
-;;; It's all backwards and stuff.
-
-; We define a bunch of keywords, which evaluate to their own codeword
-; addresses.
-defword rax, 0
-  dq docol, lit, rax, exit
-defword rcx, 0
-  dq docol, lit, rcx, exit
-defword rdx, 0
-  dq docol, lit, rdx, exit
-defword rbx, 0
-  dq docol, lit, rbx, exit
-defword rsp, 0
-  dq docol, lit, rsp, exit
-defword rbp, 0
-  dq docol, lit, rbp, exit
-defword rsi, 0
-  dq docol, lit, rsi, exit
-defword rdi, 0
-  dq docol, lit, rdi, exit
-defword r8, 0
-  dq docol, lit, r8, exit
-defword r9, 0
-  dq docol, lit, r9, exit
-defword r10, 0
-  dq docol, lit, r10, exit
-defword r11, 0
-  dq docol, lit, r11, exit
-defword r12, 0
-  dq docol, lit, r12, exit
-defword r13, 0
-  dq docol, lit, r13, exit
-defword r14, 0
-  dq docol, lit, r14, exit
-defword r15, 0
-  dq docol, lit, r15, exit
-
-; Stack in:
-;   register name
-; Stack out:
-;   3-bit encoded value for register
-defword reg64, 0
-  dq docol
-  dq dup, rax, eq, zbranch, 5*8, drop, lit, 0, exit
-  dq dup, rcx, eq, zbranch, 5*8, drop, lit, 1, exit
-  dq dup, rdx, eq, zbranch, 5*8, drop, lit, 2, exit
-  dq dup, rbx, eq, zbranch, 5*8, drop, lit, 3, exit
-  dq dup, rsp, eq, zbranch, 5*8, drop, lit, 4, exit
-  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
-
-; Stack in:
-;   register name
-; Stack out:
-;   3-bit encoded value for register
-defword extrareg64, 0
-  dq docol
-  dq dup, r8, eq, zbranch, 5*8, drop, lit, 0, exit
-  dq dup, r9, eq, zbranch, 5*8, drop, lit, 1, exit
-  dq dup, r10, eq, zbranch, 5*8, drop, lit, 2, exit
-  dq dup, r11, eq, zbranch, 5*8, drop, lit, 3, exit
-  dq dup, r12, eq, zbranch, 5*8, drop, lit, 4, exit
-  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
-
-; Stack:
-;   output point
-defword rex_w, 0
-  dq docol, lit, 0x48, pack8, exit
-defword rex_wb, 0
-  dq docol, lit, 0x49, pack8, exit
-
-; Stack:
-;   output point
-;   3-bit encoded value for register
-;   opcode byte
-defword opcodereg, 0
-  dq docol, or, pack8, exit
-
-; Stack
-;   output point
-;   mode ("mod") field
-;   register/opcode field
-;   register/memory ("RM") field
-defword modrm, 0
-  dq docol, swap, lit, 8, mul, or, swap, lit, 64, mul, or, pack8, exit
-
-; Stack:
-;   output point
-defword cld, 0
-  dq docol, lit, 0xFC, pack8, exit
-
-; Stack:
-;   output point
-;   immediate value
-;   register name
-defword mov_reg64_imm64, 0
-  dq docol
-  dq roll3, rex_w, swap, reg64, lit, 0xB8, opcodereg, swap, pack64
-  dq exit
-defword mov_extrareg64_imm64, 0
-  dq docol
-  dq roll3, rex_wb, swap, extrareg64, lit, 0xB8, opcodereg, swap, pack64
-  dq exit
-
-; Stack:
-;   output point
-;   source register name
-;   target register name
-defword mov_reg64_reg64, 0
-  dq docol
-  dq roll3, rex_w, lit, 0x89, pack8, unroll3
-  dq reg64, swap, reg64, swap, lit, 3, unroll3, modrm
-  dq exit
-
-; Stack:
-;   output point
-defword syscall, 0
-  dq docol, lit, 0x0F, pack8, lit, 0x05, pack8, exit
-
-
-final_word_name = syscall_name
+final_word_name = self_raw
 code_size = $ - code_start
 file_size = $ - $$