summary refs log tree commit diff
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@irenes.space>2025-11-06 05:31:30 -0800
committerIrene Knapp <ireneista@irenes.space>2025-11-06 05:31:30 -0800
commit082852f882c7dd64f18fe81193771f4d15dc48da (patch)
tree2385a95d3473f7097b691af9a3a817ab6b03877c
parent2af1e9004620d5c3e95c3fcaf5d3809cd552c2a4 (diff)
implement a bunch of assembly-in-Forth
Force-Push: yes
Change-Id: Ia9844da8f6e5d59ed77348b85200c28a7113bd1f
-rw-r--r--quine.asm220
1 files changed, 197 insertions, 23 deletions
diff --git a/quine.asm b/quine.asm
index 228025f..13c28a1 100644
--- a/quine.asm
+++ b/quine.asm
@@ -2995,6 +2995,11 @@ defword cld, 0
 
 ; Stack:
 ;   output point
+defword std, 0
+  dq docol, lit, 0xFD, pack8, exit
+
+; Stack:
+;   output point
 ;   immediate value
 ;   register name
 defword mov_reg64_imm64, 0
@@ -3071,6 +3076,53 @@ defword lea_reg64_disp8_reg64, 0
 
 ; Stack:
 ;   output point
+;   source register name
+defword push_reg64, 0
+  dq docol, reg64, lit, 0x50, opcodereg, exit
+
+; Stack:
+;   output point
+;   target register name
+defword pop_reg64, 0
+  dq docol, reg64, lit, 0x58, opcodereg, exit
+
+; Stack:
+;   output point
+defword lodsq, 0
+  dq docol, rex_w, lit, 0xAD, pack8, exit
+
+; Stack:
+;   output point
+;   source register name
+;   target register name
+defword add_reg64_reg64, 0
+  dq docol
+  dq roll3, rex_w, lit, 0x01, pack8, unroll3
+  dq swap, reg64, swap, modrm_reg64
+  dq exit
+
+; Stack:
+;   output point
+;   source register name
+;   target register name
+defword add_indirect_reg64_reg64, 0
+  dq docol
+  dq roll3, rex_w, lit, 0x01, pack8, unroll3
+  dq swap, reg64, swap, modrm_indirect_reg64
+  dq exit
+
+; Stack:
+;   output point
+;   source register name
+;   target register name
+defword add_reg64_indirect_reg64, 0
+  dq docol
+  dq roll3, rex_w, lit, 0x03, pack8, unroll3
+  dq reg64, swap, modrm_indirect_reg64
+  dq exit
+
+; Stack:
+;   output point
 ;   source value
 ;   target register name
 defword add_reg64_imm8, 0
@@ -3082,17 +3134,156 @@ defword add_reg64_imm8, 0
 ; Stack:
 ;   output point
 ;   source register name
-defword push_reg64, 0
-  dq docol, reg64, lit, 0x50, opcodereg, exit
+;   target register name
+defword sub_reg64_reg64, 0
+  dq docol
+  dq roll3, rex_w, lit, 0x2B, pack8, unroll3
+  dq swap, reg64, swap, modrm_reg64
 
-defword lodsq, 0
-  dq docol, rex_w, lit, 0xAD, pack8, exit
+; Stack:
+;   output point
+;   source register name
+;   target register name
+defword sub_indirect_reg64_reg64, 0
+  dq docol
+  dq roll3, rex_w, lit, 0x2B, pack8, unroll3
+  dq swap, reg64, swap, modrm_indirect_reg64
+
+; Stack:
+;   output point
+;   source register name
+;   target register name
+defword mul_reg64_reg64, 0
+  dq docol
+  dq roll3, rex_w, lit, 0xF7, pack8, unroll3
+  dq swap, reg64, swap, modrm_reg64
+  dq exit
+
+;   The dividend is 128 bits, and is formed from rdx as the high half and rax
+; as the low half. The divisor is a specified register. The quotient is
+; returned in rax, truncated towards zero. The remainder is in rdx. This
+; entire process is unsigned.
+;
+;   The official mnemonic for this is "div", but divmod is what it does.
+;
+; Stack:
+;   output point
+;   divisor register name
+defword divmod_reg64, 0
+  dq docol
+  dq swap, rex_w, lit, 0xF7, pack8, swap
+  dq lit, 6, swap, modrm_reg64
+
+; Same as divmod, but signed.
+;
+; Stack:
+;   output point
+;   divisor register name
+defword idivmod_reg64, 0
+  dq docol
+  dq swap, rex_w, lit, 0xF7, pack8, swap
+  dq lit, 7, swap, modrm_reg64
+
+; Stack:
+;   output point
+;   target register name
+defword inc_reg64, 0
+  dq docol, swap, rex_w, lit, 0xFF, pack8, swap, lit, 0, swap, modrm_reg64
+
+; Stack:
+;   output point
+;   target register name
+defword dec_reg64, 0
+  dq docol, swap, rex_w, lit, 0xFF, pack8, swap, lit, 1, swap, modrm_reg64
+
+; Stack:
+;   output point
+;   source register name
+;   target register name
+defword and_reg64_reg64, 0
+  dq docol
+  dq roll3, rex_w, lit, 0x23, pack8, unroll3
+  dq reg64, swap, modrm_reg64
+  dq exit
+
+; Stack:
+;   output point
+;   source value
+;   target register name
+defword and_reg64_imm8, 0
+  dq docol
+  dq roll3, rex_w, lit, 0x83, pack8, swap
+  dq lit, 4, swap, modrm_reg64
+  dq swap, pack8
+  dq exit
+
+; Stack:
+;   output point
+;   source register name
+;   target register name
+defword or_reg64_reg64, 0
+  dq docol
+  dq roll3, rex_w, lit, 0x0B, pack8, unroll3
+  dq reg64, swap, modrm_reg64
+  dq exit
+
+; Stack:
+;   output point
+;   source value
+;   target register name
+defword or_reg64_imm8, 0
+  dq docol
+  dq roll3, rex_w, lit, 0x83, pack8, swap
+  dq lit, 1, swap, modrm_reg64
+  dq swap, pack8
+  dq exit
+
+; Stack:
+;   output point
+;   source register name
+;   target register name
+defword xor_reg64_reg64, 0
+  dq docol
+  dq roll3, rex_w, lit, 0x33, pack8, unroll3
+  dq reg64, swap, modrm_reg64
+  dq exit
 
+; Stack:
+;   output point
+;   target register name
+defword not_reg64, 0
+  dq docol
+  dq swap, rex_w, lit, 0xF7, pack8
+  dq swap, lit, 2, swap, modrm_reg64
+  dq exit
+
+; Stack:
+;   output point
+;   left register name
+;   right register name
+defword cmp_reg64_reg64, 0
+  dq docol
+  dq roll3, rex_w, 0x3B, pack8, unroll3
+  dq swap, reg64, swap, modrm_reg64
+  dq exit
+
+; Stack:
+;   output point
+;   left register name
+;   right register name
+defword test_reg64_reg64, 0
+  dq docol
+  dq roll3, rex_w, 0x85, pack8, unroll3
+  dq swap, reg64, swap, modrm_reg64
+  dq exit
+
+; Stack:
+;   output point
+;   register name
 defword jmp_abs_indirect_reg64, 0
   dq docol
   dq swap, lit, 0xFF, pack8, swap
-  ; TODO use modrm_indirect_reg64 instead
-  dq reg64, lit, 0, lit, 4, roll3, modrm
+  dq lit, 4, swap, modrm_indirect_reg64
   dq exit
 
 ; Stack:
@@ -3100,8 +3291,6 @@ defword jmp_abs_indirect_reg64, 0
 defword syscall, 0
   dq docol, lit, 0x0F, pack8, lit, 0x05, pack8, exit
 
-; TODO pop_reg64
-; TODO dec_reg64
 ; TODO mov_reg64_indexed_reg64
 ; TODO mov_indirect_reg64_reg8
 ; TODO mov_reg8_indirect_qreg
@@ -3111,26 +3300,11 @@ defword syscall, 0
 ; TODO mov_reg32_indirect_reg64
 ; TODO lea_reg64_indexed_reg64
 ; TODO lea_reg64_disp8_indexed_reg64
-; TODO std
 ; TODO rep movsb
 ; TODO rep movsq
 ; TODO repnz scasb
-; TODO add_reg64_reg64
-; TODO add_indirect_reg64_reg64
-; TODO add_reg64_indirect_reg64
-; TODO sub_reg64_reg64
-; TODO sub_indirect_reg64_reg64
-; TODO mul_reg64_reg64
-; TODO divmod_reg64
-; TODO cmp_reg64_reg64
-; TODO test_reg64_reg64
 ; TODO set_reg8_cc
 ;   (and condition codes)
-; TODO and_reg64_imm8
-; TODO and_reg64_reg64
-; TODO or_reg64_reg64
-; TODO xor_reg64_reg64
-; TODO not_reg64
 ; TODO jmp_cc_rel_imm8
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;