summary refs log tree commit diff
path: root/quine.asm
diff options
context:
space:
mode:
Diffstat (limited to 'quine.asm')
-rw-r--r--quine.asm185
1 files changed, 185 insertions, 0 deletions
diff --git a/quine.asm b/quine.asm
index 09f5cfb..b8cf76c 100644
--- a/quine.asm
+++ b/quine.asm
@@ -129,6 +129,16 @@ macro opcodereg opcode, reg
   db opcode or reg
 end macro
 
+;;; On registers
+;;; ------------
+;;;
+;;;   The x86 architecture has been around a while, it has been through
+;;; several transitions from smaller word sizes to larger ones. Therefore it
+;;; has different names for the "same" registers, depending on how much of
+;;; them you're using.
+;;;
+;;; TODO there's more to write here
+
 macro bytereg result, register
   match =al?, register
     result = 0
@@ -361,6 +371,104 @@ macro mov.indirect.qreg.qreg target, source
 end macro
 
 
+; 8-bit source register
+macro mov.indirect.qreg.breg target, source
+  match =rsp, target
+    assert 0
+    ; The SIB case.
+  else match =rbp, target
+    assert 0
+    ; An unrelated addressing mode.
+  else
+    bytereg sreg, source
+    qwordreg treg, target
+    db 0x88
+    modrm 0, sreg, treg
+  end match
+end macro
+
+macro mov.breg.indirect.qreg target, source
+  match =rsp, target
+    assert 0
+    ; The SIB case.
+  else match =rbp, target
+    assert 0
+    ; An unrelated addressing mode.
+  else
+    qwordreg sreg, source
+    bytereg treg, target
+    db 0x8A
+    modrm 0, treg, sreg
+  end match
+end macro
+
+; We use the operand-size prefix to specify 16-bit. No REX.W. Table 3-4.
+macro mov.indirect.qreg.wreg target, source
+  match =rsp, target
+    assert 0
+    ; The SIB case.
+  else match =rbp, target
+    assert 0
+    ; An unrelated addressing mode.
+  else
+    wordreg sreg, source
+    qwordreg treg, target
+    db 0x66
+    db 0x89
+    modrm 0, sreg, treg
+  end match
+end macro
+
+; We use the operand-size prefix to specify 16-bit. No REX.W. Table 3-4.
+macro mov.wreg.indirect.qreg target, source
+  match =rsp, target
+    assert 0
+    ; The SIB case.
+  else match =rbp, target
+    assert 0
+    ; An unrelated addressing mode.
+  else
+    qwordreg sreg, source
+    wordreg treg, target
+    db 0x66
+    db 0x8B
+    modrm 0, treg, sreg
+  end match
+end macro
+
+; It defaults to 32-bit, no prefix needed, also no REX.W. Table 3-4.
+macro mov.indirect.qreg.dreg target, source
+  match =rsp, target
+    assert 0
+    ; The SIB case.
+  else match =rbp, target
+    assert 0
+    ; An unrelated addressing mode.
+  else
+    dwordreg sreg, source
+    qwordreg treg, target
+    db 0x89
+    modrm 0, sreg, treg
+  end match
+end macro
+
+; It defaults to 32-bit, no prefix needed, also no REX.W. Table 3-4.
+macro mov.dreg.indirect.qreg target, source
+  match =rsp, target
+    assert 0
+    ; The SIB case.
+  else match =rbp, target
+    assert 0
+    ; An unrelated addressing mode.
+  else
+    qwordreg sreg, source
+    dwordreg treg, target
+    db 0x8B
+    modrm 0, treg, sreg
+  end match
+end macro
+
+
 ; Take a 64-bit source register, store its value into a high 64-bit target
 ; register (r8-r15).
 ;
@@ -1706,6 +1814,83 @@ defword INVERT, 0
   NEXT
 
 ;;;
+;;; Routine LIT
+;;; ------------
+;;;
+
+defword LIT, 0
+  dq $ + 0x8                     ; codeword
+  lodsq
+  push.qreg rax
+  NEXT
+
+;;;
+;;; Memory access routines
+;;; ----------------------
+;;;
+;;;   We go with Forth names for this stuff. The HP's names for memory and
+;;; storage operations heavily leverage the fact they have an object system
+;;; with type tags and so on; we want to stay close to the bytes.
+;;;
+
+; Address on the top of the stack, value in the second position
+defword STORE, 0
+  dq $ + 0x8                     ; codeword
+  pop.qreg rbx
+  pop.qreg rax
+  mov.indirect.qreg.qreg rbx, rax
+  NEXT
+
+defword FETCH, 0
+  dq $ + 0x8                     ; codeword
+  pop.qreg rax
+  mov.qreg.indirect.qreg rax, rax
+  push.qreg rax
+  NEXT
+
+defword STORE8, 0
+  dq $ + 0x8                     ; codeword
+  pop.qreg rbx
+  pop.qreg rax
+  mov.indirect.qreg.breg rbx, al
+  NEXT
+
+defword FETCH8, 0
+  dq $ + 0x8                     ; codeword
+  pop.qreg rbx
+  xor.qreg.qreg rax, rax
+  mov.breg.indirect.qreg al, rbx
+  NEXT
+
+defword STORE16, 0
+  dq $ + 0x8                     ; codeword
+  pop.qreg rbx
+  pop.qreg rax
+  mov.indirect.qreg.wreg rbx, ax
+  NEXT
+
+defword FETCH16, 0
+  dq $ + 0x8                     ; codeword
+  pop.qreg rbx
+  xor.qreg.qreg rax, rax
+  mov.wreg.indirect.qreg ax, rbx
+  NEXT
+
+defword STORE32, 0
+  dq $ + 0x8                     ; codeword
+  pop.qreg rbx
+  pop.qreg rax
+  mov.indirect.qreg.dreg rbx, eax
+  NEXT
+
+defword FETCH32, 0
+  dq $ + 0x8                     ; codeword
+  pop.qreg rbx
+  xor.qreg.qreg rax, rax
+  mov.dreg.indirect.qreg eax, rbx
+  NEXT
+
+;;;
 ;;;   One of the most charming naming traditions in Forth is that the
 ;;; top-level word that stays running forever, is called "quit".
 ;;;