summary refs log tree commit diff
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@irenes.space>2025-11-02 16:33:32 -0800
committerIrene Knapp <ireneista@irenes.space>2025-11-02 16:33:32 -0800
commitd563b5a0c414015a0e52d3addb59d30e949baefd (patch)
treeb26a6a3961da59cc2cd438176fb28030d331ec80
parent311c4bd6ba2a5e9e38eb4f2ad6b3866df05c11de (diff)
output a whole bunch of assembly from Forth
and begin to grow the Forth-styled assembly language

it needs runtime word definition next, in our view, so we're checkpointing it here so as to work on that

Force-Push: yes
Change-Id: I08927581f6b6fdc69f6543936e46fe9ff83c8d48
-rw-r--r--quine.asm152
1 files changed, 149 insertions, 3 deletions
diff --git a/quine.asm b/quine.asm
index dc7eb51..52460e4 100644
--- a/quine.asm
+++ b/quine.asm
@@ -2727,7 +2727,9 @@ defword HLT, 0
 ; It also makes use of label stuff, further back on the stack.
 defword ALL_CONTENTS, 0
   dq DOCOL                       ; codeword
-  dq ELF_FILE_HEADER, ELF_PROGRAM_HEADER, SELF_RAW
+  dq ELF_FILE_HEADER, ELF_PROGRAM_HEADER
+  dq OUTPUT_START_ROUTINE
+  dq SELF_RAW
   dq SET_LABEL
   dq EXIT
 
@@ -2797,13 +2799,28 @@ defword ELF_PROGRAM_HEADER, 0
   dq EXIT
 
 
+defword OUTPUT_START_ROUTINE, 0
+  dq DOCOL
+  dq cld
+  dq LIT, 9, rax, mov_reg64_imm64
+  dq LIT, heap_requested_address, rdi, mov_reg64_imm64
+  dq LIT, heap_size, rsi, mov_reg64_imm64
+  dq LIT, 0x03, rdx, mov_reg64_imm64
+  dq LIT, 0x22, r10, mov_extrareg64_imm64
+  dq LIT, 0, r8, mov_extrareg64_imm64
+  dq LIT, 0, r9, mov_extrareg64_imm64
+  dq syscall
+  dq rax, rdi, mov_reg64_reg64
+  dq EXIT
+
+
 ; write() the machine code by using self-reference
 ; TODO do this in a "real" quine way
 defword SELF_RAW, 0
   dq DOCOL                       ; codeword
   dq DUP
-  dq LIT, elf_header + 0x78      ; source
-  dq LIT, file_size - 0x78       ; length
+  dq LIT, elf_header + 0xc4      ; source
+  dq LIT, file_size - 0xc4       ; length
   ; destination destination source length
   dq DUP, LIT, 4, ROLL, ADD, LIT, 4, UNROLL
   ; result destination source length
@@ -2811,6 +2828,135 @@ 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
+
+
 code_size = $ - code_start
 file_size = $ - $$