summary refs log tree commit diff
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
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
-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