summary refs log tree commit diff
path: root/quine.asm
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@irenes.space>2025-11-06 18:07:24 -0800
committerIrene Knapp <ireneista@irenes.space>2025-11-06 18:07:24 -0800
commit71e5dbbc3c8f720dae0ccac531fe49c15af62b63 (patch)
treeff9e9ef122a722bbea0d2ec5fa66462e15da977d /quine.asm
parent7c0227c5b6466b911add5afec0accaca368131a5 (diff)
did all the pending instructions that use indexed addressing modes
we're starting to feel vaguely proficient in stack juggling, but it will still be quite a thing if these don't need fixing later

Force-Push: yes
Change-Id: Ic1285d01cc42c6e8a30d36fc53e67135d8d9e175
Diffstat (limited to 'quine.asm')
-rw-r--r--quine.asm91
1 files changed, 86 insertions, 5 deletions
diff --git a/quine.asm b/quine.asm
index 9dedc18..77360f8 100644
--- a/quine.asm
+++ b/quine.asm
@@ -2893,6 +2893,19 @@ defword extrareg64, 0
   dq litstring, "Parameter to extrareg64 is not an extrareg64.", emitstring
   dq lit, 1, sys_exit
 
+; Stack in:
+;   scale factor, as a count of bytes
+; Stack out:
+;   2-bit encoded value for scale field in SIB byte
+defword scalefield, 0
+  dq docol
+  dq dup, 1, eq, zbranch, 5*8, drop, lit, 0, exit
+  dq dup, 2, eq, zbranch, 5*8, drop, lit, 1, exit
+  dq dup, 4, eq, zbranch, 5*8, drop, lit, 2, exit
+  dq dup, 8, eq, zbranch, 5*8, drop, lit, 3, exit
+  dq litstring, "Parameter to scalefield is not 1, 2, 4, or 8.", emitstring
+  dq lit, 1, sys_exit
+
 ; Stack:
 ;   output point
 defword rex_w, 0
@@ -2971,8 +2984,6 @@ defword addressing_indirect_reg64, 0
   dq emitstring
   dq lit, 1, sys_exit
 
-;   This mode can do rbp fine, rsp is the only unusual case.
-;
 ; Stack:
 ;   output point
 ;   reg/op field value (raw number)
@@ -2980,6 +2991,7 @@ defword addressing_indirect_reg64, 0
 ;   displacement value
 defword addressing_disp8_reg64, 0
   dq docol
+  ; This mode can do rbp fine, so no need to check for that.
   ; Check whether the R/M register is rsp; save the test result for later.
   dq swap, dup, rsp, eq, lit, 5, unroll, swap
   ; Stash the displacement value out of the way, too.
@@ -2993,6 +3005,40 @@ defword addressing_disp8_reg64, 0
 
 ; Stack:
 ;   output point
+;   reg/op field value (raw number)
+;   scale factor, as a count of bytes
+;   index register name
+;   base field register name
+defword addressing_indexed_reg64, 0
+  dq docol
+  ; Exit with an error if the base register is rbp.
+  dq dup, rbp, ne, zbranch, 17*8
+  ; Reg/mem value 4 means to use an SIB byte (at least, with this mode).
+  dq lit, 5, roll, lit, 0, lit, 6, roll, lit, 4, modrm, lit, 4, unroll
+  dq reg64, unroll3, reg64, unroll3, scalefield, unroll3, sib
+  dq exit
+  dq litstring, "Base parameter to addressing_indexed_reg64 is rbp."
+  dq emitstring
+  dq lit, 1, sys_exit
+
+; Stack:
+;   output point
+;   reg/op field value (raw number)
+;   scale factor, as a count of bytes
+;   index register name
+;   base field register name
+;   displacement value
+defword addressing_disp8_indexed_reg64, 0
+  dq docol
+  ; This mode can do rbp fine, so no need to check for that.
+  ; Reg/mem value 4 means to use an SIB byte (at least, with this mode).
+  dq lit, 6, roll, lit, 1, lit, 7, roll, lit, 4, modrm, lit, 5, unroll
+  dq lit, 5, unroll, reg64, unroll3, reg64, unroll3, scalefield, unroll3, sib
+  dq swap, pack8
+  dq exit
+
+; Stack:
+;   output point
 defword cld, 0
   dq docol, lit, 0xFC, pack8, exit
 
@@ -3069,6 +3115,18 @@ defword mov_reg64_disp8_reg64, 0
 ; Stack:
 ;   output point
 ;   source register name
+;   source index register name
+;   source index scale factor, as a count of bytes
+;   target register name
+defword mov_reg64_indexed_reg64, 0
+  dq docol
+  dq lit, 5, roll, rex_w, lit, 0x8B, pack8, lit, 5, unroll
+  dq reg64, lit, 4, unroll, unroll3, swap, addressing_indexed_reg64
+  dq exit
+
+; Stack:
+;   output point
+;   source register name
 ;   source displacement value
 ;   target register name
 defword lea_reg64_disp8_reg64, 0
@@ -3080,6 +3138,32 @@ defword lea_reg64_disp8_reg64, 0
 ; Stack:
 ;   output point
 ;   source register name
+;   source index register name
+;   source index scale factor, as a count of bytes
+;   target register name
+defword lea_reg64_indexed_reg64, 0
+  dq docol
+  dq lit, 5, roll, rex_w, lit, 0x8D, pack8, lit, 5, unroll
+  dq reg64, lit, 4, unroll, unroll3, swap, addressing_indexed_reg64
+  dq exit
+
+; Stack:
+;   output point
+;   source register name
+;   source index register name
+;   source index scale factor, as a count of bytes
+;   source displacement value
+;   target register name
+defword lea_reg64_disp8_indexed_reg64, 0
+  dq docol
+  dq lit, 6, roll, rex_w, lit, 0x8D, pack8, lit, 6, unroll
+  dq reg64, lit, 5, unroll, lit, 3, roll, lit, 4, roll, lit, 3, roll
+  dq addressing_disp8_indexed_reg64
+  dq exit
+
+; Stack:
+;   output point
+;   source register name
 defword push_reg64, 0
   dq docol, reg64, lit, 0x50, opcodereg, exit
 
@@ -3298,15 +3382,12 @@ defword jmp_abs_indirect_reg64, 0
 defword syscall, 0
   dq docol, lit, 0x0F, pack8, lit, 0x05, pack8, exit
 
-; TODO mov_reg64_indexed_reg64
 ; TODO mov_indirect_reg64_reg8
 ; TODO mov_reg8_indirect_qreg
 ; TODO mov_indirect_reg64_reg16
 ; TODO mov_reg16_indirect_reg64
 ; TODO mov_indirect_reg64_reg32
 ; TODO mov_reg32_indirect_reg64
-; TODO lea_reg64_indexed_reg64
-; TODO lea_reg64_disp8_indexed_reg64
 ; TODO rep movsb
 ; TODO rep movsq
 ; TODO repnz scasb