diff options
Diffstat (limited to 'quine.asm')
| -rw-r--r-- | quine.asm | 185 |
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". ;;; |