From 0860b49f8e326016349e1096ab705dc0efefe3a8 Mon Sep 17 00:00:00 2001 From: Irene Knapp Date: Mon, 21 Sep 2026 00:29:46 -0700 Subject: release version 3.0 this is the first-ever release! wow :33333 have fun y'all!!!! Force-Push: yes Change-Id: Ifc95e4e63e4ee477b4c23d83a82f7a1e050f7925 --- quine.asm | 12376 ------------------------------------------------------------ 1 file changed, 12376 deletions(-) delete mode 100644 quine.asm (limited to 'quine.asm') diff --git a/quine.asm b/quine.asm deleted file mode 100644 index 987c966..0000000 --- a/quine.asm +++ /dev/null @@ -1,12376 +0,0 @@ -;;; QUINE -;;; -;;; This file is formatted to be read at 80-columns or wider. -;;; -;;; There's some tabular information, but diagrams have been avoided, in an -;;; attempt to make this manageable in screen readers. Feedback welcome. -;;; -;;; First the hex -;;; Second the spark -;;; Third the words -;;; Then tie the knot -;;; [draft] - - -;;;;;;;;;;;;;;;;;;;;; -;;; Workflow tips ;;; -;;;;;;;;;;;;;;;;;;;;; -;;; -;;; Currently, this is not yet fully self-hosting; it is based on -;;; flatassembler[1]. A minimal command to build and run it is: -;;; -;;; $ fasmg quine.asm quine && chmod 755 quine && ./quine; echo $? -;;; -;;; A workflow you may wish to use for debugging is: -;;; -;;; $ rm quine2; fasmg quine.asm quine && chmod 755 quine && ./quine > quine2; echo "exit code:" $?; echo; hexdump -C quine; echo; hexdump -C quine2; echo; cmp -l quine quine2 ; echo cmp: $? -;;; -;;; The reason this removes the old one first is that otherwise, there's a -;;; risk the error message will be scrolled off the top of the screen and -;;; you'll see stale output and not realize. -;;; -;;; You may also wish to do: -;;; -;;; $ objdump --disassemble quine -;;; $ ZydisDisasm -64 quine -;;; -;;; This relies on GNU binutils, and on zydis, respectively. -;;; -;;; [1] https://flatassembler.net/ -;;; -;;; -;;; gdb -;;; --- -;;; -;;; You can run gdb on it if you want; there's no symbols, but if you are -;;; familiar with the hex it should be readable. Keep a hexdump of the program -;;; handy to look up what addresses are. -;;; -;;; If you want to see a routine implemented in assembly, look at the hexdump -;;; of the overall file, find it by looking at the ASCII names, skip past the -;;; codeword, and do ie -;;; -;;; (gdb) disassemble/r 0x80007c0,+32 -;;; -;;; If you want to see the value stack, you can do -;;; -;;; (gdb) x/16xg $rsp -;;; -;;; The same will work with $rbp for the control stack, and don't forget that -;;; the "instruction pointer" is rsi. To see all the registers, do -;;; -;;; (gdb) info registers - - -;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Assembly language ;;; -;;;;;;;;;;;;;;;;;;;;;;;;; -;;; -;;; Before doing any actual code, we define macros for writing x86-64 -;;; assembly language. This is built from scratch, relying only on -;;; flatassembler's built-in semantics. No include files of any kind are used -;;; for it. - -macro pad: bytes - if bytes > 0 - db 0x00 - pad (bytes - 1) - end if -end macro - -macro align: bytes - if bytes > 0 - if $ mod bytes <> 0 - db 0x00 - align bytes - end if - end if -end macro - -; The way these are all spelled out like this is slightly ridiculous, there -; must be a better way. -macro rex.0 - db 0x40 -end macro -macro rex.w - db 0x48 -end macro -macro rex.r - db 0x44 -end macro -macro rex.x - db 0x42 -end macro -macro rex.b - db 0x41 -end macro -macro rex.wr - db 0x4C -end macro -macro rex.wx - db 0x4A -end macro -macro rex.wb - db 0x49 -end macro -macro rex.rx - db 0x46 -end macro -macro rex.rb - db 0x45 -end macro -macro rex.xb - db 0x43 -end macro -macro rex.wrx - db 0x4E -end macro -macro rex.wrb - db 0x4D -end macro -macro rex.wxb - db 0x4B -end macro -macro rex.rxb - db 0x47 -end macro -macro rex.wrxb - db 0x4F -end macro - -macro modrm mod, reg, rm - assert mod >= 0 & mod < 4 - assert reg >= 0 & reg < 8 - assert rm >= 0 & rm < 8 - db (mod shl 6) OR (reg shl 3) OR rm -end macro - -macro sib scale, index, base - assert scale >= 0 & scale < 4 - assert index >= 0 & index < 8 - assert base >= 0 & index < 8 - db (scale shl 6) OR (index shl 3) OR base -end macro - -macro opcodereg opcode, reg - assert opcode >= 0 & opcode < 256 & opcode AND 7 = 0 - assert reg >= 0 & reg < 8 - db opcode OR reg -end macro - -macro opcodecc opcode, cc - assert opcode >= 0 & opcode < 256 & opcode AND 15 = 0 - assert cc >= 0 & cc < 16 - db opcode OR cc -end macro - -macro scalefield sfield, scale - if 1 = scale - sfield = 0 - else if 2 = scale - sfield = 1 - else if 4 = scale - sfield = 2 - else if 8 = scale - sfield = 3 - else - assert 0 - end if -end macro - -; Yep, there sure is a lot of duplication in these. This is based on Intel's -; documented mnemonics... -; -; "Above" and "below" are for unsigned comparisons. "Greater" and "less" are -; for signed comparisons. -; -; This is documented on the individual opcode pages, and also in B.1.4.7. -macro conditioncode cc, condition - match =above, condition - cc = 0x07 - else match =above_equal, condition - cc = 0x03 - else match =below, condition - cc = 0x02 - else match =below_equal, condition - cc = 0x06 - else match =carry, condition - cc = 0x02 - else match =equal, condition - cc = 0x04 - else match =greater, condition - cc = 0x0F - else match =greater_equal, condition - cc = 0x0D - else match =less, condition - cc = 0x0C - else match =less_equal, condition - cc = 0x0E - else match =not_above, condition - cc = 0x06 - else match =not_above_equal, condition - cc = 0x02 - else match =not_below, condition - cc = 0x03 - else match =not_below_equal, condition - cc = 0x07 - else match =not_carry, condition - cc = 0x03 - else match =not_equal, condition - cc = 0x05 - else match =not_greater, condition - cc = 0x0E - else match =not_greater_equal, condition - cc = 0x0C - else match =not_less, condition - cc = 0x0D - else match =not_less_equal, condition - cc = 0x0F - else match =not_overflow, condition - cc = 0x01 - else match =not_parity, condition - cc = 0x0B - else match =not_sign, condition - cc = 0x09 - else match =not_zero, condition - cc = 0x05 - else match =overflow, condition - cc = 0x00 - else match =parity, condition - cc = 0x0A - else match =parity_even, condition - cc = 0x0A - else match =parity_odd, condition - cc = 0x0B - else match =sign, condition - cc = 0x08 - else match =zero, condition - cc = 0x04 - else - assert 0 - end match -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 - else match =cl?, register - result = 1 - else match =dl?, register - result = 2 - else match =bl?, register - result = 3 - else match =ah?, register - result = 4 - else match =ch?, register - result = 5 - else match =dh?, register - result = 6 - else match =bh?, register - result = 7 - else - assert 0 - end match -end macro - -macro wordreg result, register - match =ax?, register - result = 0 - else match =cx?, register - result = 1 - else match =dx?, register - result = 2 - else match =bx?, register - result = 3 - else match =sp?, register - result = 4 - else match =bp?, register - result = 5 - else match =si?, register - result = 6 - else match =di?, register - result = 7 - else - assert 0 - end match -end macro - -macro dwordreg result, register - match =eax?, register - result = 0 - else match =ecx?, register - result = 1 - else match =edx?, register - result = 2 - else match =ebx?, register - result = 3 - else match =esp?, register - result = 4 - else match =ebp?, register - result = 5 - else match =esi?, register - result = 6 - else match =edi?, register - result = 7 - else - assert 0 - end match -end macro - -macro qwordreg result, register - match =rax?, register - result = 0 - else match =rcx?, register - result = 1 - else match =rdx?, register - result = 2 - else match =rbx?, register - result = 3 - else match =rsp?, register - result = 4 - else match =rbp?, register - result = 5 - else match =rsi?, register - result = 6 - else match =rdi?, register - result = 7 - else - assert 0 - end match -end macro - -macro owordreg result, register - match =r8?, register - result = 0 - else match =r9?, register - result = 1 - else match =r10?, register - result = 2 - else match =r11?, register - result = 3 - else match =r12?, register - result = 4 - else match =r13?, register - result = 5 - else match =r14?, register - result = 6 - else match =r15?, register - result = 7 - else - assert 0 - end match -end macro - - -;;; Instructions -;;; ------------ - - -macro mov.dreg.dimm target, source - dwordreg treg, target - opcodereg 0xB8, treg - dd source -end macro - - -macro mov.qreg.dimm target, source - qwordreg treg, target - rex.w - db 0xC7 - modrm 3, 0, treg - dd source -end macro - - -macro mov.qreg.qimm target, source - qwordreg treg, target - rex.w - opcodereg 0xB8, treg - dq source -end macro - - -; Notice the use of REX.B here; this instruction puts the register number in -; the opcode field, so it uses Table 3-1. -macro mov.oreg.qimm target, source - owordreg treg, target - rex.wb - opcodereg 0xB8, treg - dq source -end macro - - -macro mov.qreg.qreg target, source - qwordreg treg, target - qwordreg sreg, source - rex.w - db 0x89 - modrm 3, sreg, treg -end macro - - -; Take a 64-bit source register, treat it as an address and look up the 64-bit -; value it points to, store that into a 64-bit target register. -; -; For a source of rbp, the only modes available also have displacement; we -; disallow that. Use mov.qreg.disp8.qreg for that case, and set a displacement -; of 0. -; -; In understanding this, pay close attention to the Op/En column in the opcode -; table. The "RM" variant means the ModRM byte's R/M field (the third one) -; is the source, while its reg field (the middle one) is the target. This is -; what we want, because the R/M field is the one that gets indirection applied -; to it. Opcode 0x8B with an REX.W prefix is the all-64-bit RM variant. -; [Intel] volume 2B, chapter 4, section 4-3, "MOV". -; -; For the indirection modes, don't be confused by the many similar tables. -; 64-bit mode is encoded the same as 32-bit mode except for adding a REX.W -; prefix, as per 2.2.1.1, so you want table 2-2 to understand the ModRM byte. -; The presence or absence of an SIB byte is determined by where in that table -; we fall, and we aren't using a mode that has one. [Intel] volume 2A, -; chapter 2, section 2-1.5, table 2-2. -; -; We disallow rsp as a source because that's the mode that would want an SIB. -macro mov.qreg.indirect.qreg target, source - match =rbp, source - assert 0 - end match - qwordreg sreg, source - qwordreg treg, target - rex.w - db 0x8B - modrm 0, treg, sreg - match =rsp, source - ; R/M = rsp is the SIB case - sib 0, 4, sreg - ; no scaling, no indexing, source as base - end match -end macro - - -macro mov.qreg.disp8.qreg target, offset, source - qwordreg sreg, source - qwordreg treg, target - rex.w - db 0x8B - modrm 1, treg, sreg - match =rsp, source - ; R/M = rsp is the SIB case - sib 0, 4, sreg - ; no scaling, no indexing, source as base - end match - db offset -end macro - - -; Take a 64-bit source register, store its value into the address pointed to -; by a 64-bit target register. -; -; For a target of rbp, the only modes available also have displacement; we -; disallow that. Use mov.disp8.qreg.qreg for that case, and set a displacement -; of 0. -; -; In understanding this, pay close attention to the Op/En column in the opcode -; table. The "MR" variant means the ModRM byte's reg field (the middle one) -; is the source, while its R/M field (the third one) is the target. This is -; what we want, because the R/M field is the one that gets indirection applied -; to it. Opcode 0x89 with an REX.W prefix is the all-64-bit MR variant. -; [Intel] volume 2B, chapter 4, section 4-3, "MOV". -; -; For the indirection modes, don't be confused by the many similar tables. -; 64-bit mode is encoded the same as 32-bit mode except for adding a REX.W -; prefix, as per 2.2.1.1, so you want table 2-2 to understand the ModRM byte. -; The presence or absence of an SIB byte is determined by where in that table -; we fall, and we aren't using a mode that has one. [Intel] volume 2A, -; chapter 2, section 2-1.5, table 2-2. -; -; We disallow rsp as a target because that's the mode that would want an SIB. -; When you look at other addressing modes, be aware that the special treatment -; is for whichever register is specified in the R/M field. Sometimes that's -; the source, and sometimes it's the target, depending on the opcode. -macro mov.indirect.qreg.qreg target, source - match =rbp, target - assert 0 - end match - qwordreg sreg, source - qwordreg treg, target - rex.w - db 0x89 - modrm 0, sreg, treg - match =rsp, target - ; R/M = rsp is the SIB case - sib 0, 4, treg - ; no scaling, no indexing, target as base - end match -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, source - assert 0 - ; The SIB case. - else match =rbp, source - 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, source - assert 0 - ; The SIB case. - else match =rbp, source - 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, source - assert 0 - ; The SIB case. - else match =rbp, source - assert 0 - ; An unrelated addressing mode. - else - qwordreg sreg, source - dwordreg treg, target - db 0x8B - modrm 0, treg, sreg - end match -end macro - - -macro mov.qreg.indexed.qreg target, source, index, scale - match =rbp, source - assert 0 - ; This is divided into some subcases we don't wish to deal with yet. - else match =rsp, index - assert 0 - ; This is the case where it's not actually indexed after all. - else - qwordreg treg, target - qwordreg sreg, source - qwordreg ireg, index - scalefield sfield, scale - rex.w - db 0x8B - modrm 0, treg, 4 - sib sfield, ireg, sreg - end match -end macro - - -macro mov.indexed.qreg.qreg target, index, scale, source - match =rbp, source - assert 0 - ; This is divided into some subcases we don't wish to deal with yet. - else match =rsp, index - assert 0 - ; This is the case where it's not actually indexed after all. - else - qwordreg treg, target - qwordreg sreg, source - qwordreg ireg, index - scalefield sfield, scale - rex.w - db 0x89 - modrm 0, sreg, 4 - sib sfield, ireg, treg - end match -end macro - - -; Take a 64-bit source register, store its value into a high 64-bit target -; register (r8-r15). -; -; Notice that there are two ways to add another bit to the register encoding. -; Table 3-1 is about REX.B, but does not apply here, it's for instructions -; that use opcode bits to specify a register, and none of the -; register-to-register MOV variants do that (it's for immediate mode). -; -; Instead, we want the mechanism that uses REX.R as the extra bit, and it -; combines with the reg field of ModRM, as per 2.2.1.2. -; -; Therefore, we want the variant of MOV which puts the target in the reg -; field. That's Op/En "RM", opcode 0x8B with REX.WR. -; -; Mode 3 is direct addressing. -macro mov.oreg.qreg target, source - owordreg treg, target - qwordreg sreg, source - rex.wr - db 0x8B - modrm 3, treg, sreg -end macro - - -; Take a high 64-bit source register (r8-r15), store its value into a 64-bit -; target register. -; -; Notice that there are two ways to add another bit to the register encoding. -; Table 3-1 is about REX.B, but does not apply here, it's for instructions -; that use opcode bits to specify a register, and none of the -; register-to-register MOV variants do that (it's for immediate mode). -; -; Instead, we want the mechanism that uses REX.R as the extra bit, and it -; combines with the reg field of ModRM, as per 2.2.1.2. -; -; Therefore, we want the variant of MOV which puts the source in the reg -; field. That's Op/En "MR", opcode 0x89 with REX.WR. -; -; Mode 3 is direct addressing. -macro mov.qreg.oreg target, source - qwordreg treg, target - owordreg sreg, source - rex.wr - db 0x89 - modrm 3, sreg, treg -end macro - - -; This increments a 64-bit register by 1, in place; -macro inc.qreg target - qwordreg treg, target - rex.w - db 0xFF - modrm 3, 0, treg - ; The 0 is part of the opcode. -end macro - -; This decrements a 64-bit register by 1, in place; -macro dec.qreg target - qwordreg treg, target - rex.w - db 0xFF - modrm 3, 1, treg - ; The 1 is part of the opcode. -end macro - -; This adds a 64-bit register to another 64-bit register, in place. -macro add.qreg.qreg target, source - qwordreg treg, target - qwordreg sreg, source - rex.w - db 0x01 - modrm 3, sreg, treg -end macro - - -macro add.indirect.qreg.qreg target, source - match =rsp, target - assert 0 - ; The SIB case. - else match =rbp, target - assert 0 - ; An unrelated addressing mode. - else - qwordreg treg, target - qwordreg sreg, source - rex.w - db 0x01 - modrm 0, sreg, treg - end match -end macro - - -macro add.qreg.indirect.qreg target, source - match =rsp, source - assert 0 - ; The SIB case. - else match =rbp, source - assert 0 - ; An unrelated addressing mode - else - qwordreg treg, target - qwordreg sreg, source - rex.w - db 0x03 - modrm 0, treg, sreg - end match -end macro - - -; This adds a signed 8-bit immediate value to a 64-bit register, in place. -; -; Notice the use of 3 as the addressing mode. This says to use the register -; itself. The 0 in the reg field is part of the opcode. -macro add.qreg.bimm target, source - qwordreg treg, target - rex.w - db 0x83 - modrm 3, 0, treg - db source -end macro - - -; This adds a signed 32-bit immediate value to a 64-bit register, in place. -; -; Notice the use of 3 as the addressing mode. This says to use the register -; itself. The 0 in the reg field is part of the opcode. -macro add.qreg.dimm target, source - qwordreg treg, target - rex.w - db 0x81 - modrm 3, 0, treg - dd source -end macro - -; This subtracts a 64-bit register from another 64-bit register, in place. -macro sub.qreg.qreg target, source - qwordreg treg, target - qwordreg sreg, source - rex.w - db 0x2B - modrm 3, treg, sreg -end macro - - -macro sub.indirect.qreg.qreg target, source - match =rsp, target - ; The SIB case. - assert 0 - else - qwordreg treg, target - qwordreg sreg, source - rex.w - db 0x2B - modrm 0, sreg, treg - end match -end macro - - -; This subtracts a signed 8-bit immediate value from a 64-bit register, in -; place. -; -; Notice the use of 3 as the addressing mode. This says to use the register -; itself. The 5 in the reg field is part of the opcode. -macro sub.qreg.bimm target, source - qwordreg treg, target - rex.w - db 0x83 - modrm 3, 5, treg - db source -end macro - -; This subtracts a signed 32-bit immediate value from a 64-bit register, in -; place. -; -; Notice the use of 3 as the addressing mode. This says to use the register -; itself. The 5 in the reg field is part of the opcode. -macro sub.qreg.dimm target, source - qwordreg treg, target - rex.w - db 0x81 - modrm 3, 5, treg - dd source -end macro - -; Add with carry. -macro adc.qreg.bimm target, source - qwordreg treg, target - rex.w - db 0x83 - modrm 3, 2, treg - db source -end macro - -; Subtract with borrow. -macro sbb.qreg.bimm target, source - qwordreg treg, target - rex.w - db 0x83 - modrm 3, 3, treg - db source -end macro - -; This multiplies rax, as 64-bits, with another 64-bit register, in place. -; -; The 4 in the reg field is part of the opcode. -macro mul.rax.qreg source - qwordreg sreg, source - rex.w - db 0xF7 - modrm 3, 4, sreg -end macro - -; The official mnemonic for this is "div", but it's divmod: It takes a 128-bit -; dividend formed from concatenating rdx as the high half with rax as the low -; half, and divides it by a 64-bit divisor from a specified register. It -; stores the quotient, truncated towards zero, in rax, and it stores the -; remainder in rdx. This entire process is unsigned. -; -; The 6 in the reg field is part of the opcode. -macro div.rdxrax.qreg source - qwordreg sreg, source - rex.w - db 0xF7 - modrm 3, 6, sreg -end macro - -; Same as div, but signed. -; -; The 7 in the reg field is part of the opcode. -macro idiv.rdxrax.qreg source - qwordreg sreg, source - rex.w - db 0xF7 - modrm 3, 7, sreg -end macro - - -macro and.qreg.qreg target, source - qwordreg treg, target - qwordreg sreg, source - rex.w - db 0x23 - modrm 3, treg, sreg -end macro - -macro and.qreg.bimm target, source - qwordreg treg, target - rex.w - db 0x83 - modrm 3, 4, treg - ; The 4 is part of the opcode. - db source -end macro - -macro or.qreg.qreg target, source - qwordreg treg, target - qwordreg sreg, source - rex.w - db 0x0B - modrm 3, treg, sreg -end macro - -macro or.qreg.bimm target, source - qwordreg treg, target - rex.w - db 0x83 - modrm 3, 1, treg - ; The 4 is part of the opcode. - db source -end macro - -macro xor.qreg.qreg target, source - qwordreg treg, target - qwordreg sreg, source - rex.w - db 0x33 - modrm 3, treg, sreg -end macro - -macro not.qreg target - qwordreg treg, target - rex.w - db 0xF7 - modrm 3, 2, treg - ; The 2 is part of the opcode. -end macro - - -; This sets the flags to the same things they'd be set to if subtracting -; right from left. -macro cmp.qreg.qreg left, right - qwordreg lreg, left - qwordreg rreg, right - rex.w - db 0x3B - modrm 3, lreg, rreg -end macro - -; This sets the flags to the same things they'd be set to if and'ing right -; with left. -macro test.qreg.qreg left, right - qwordreg lreg, left - qwordreg rreg, right - rex.w - db 0x85 - modrm 3, rreg, lreg -end macro - -macro set.breg.cc target, condition - bytereg treg, target - conditioncode cc, condition - db 0x0F - opcodecc 0x90, cc - modrm 3, 0, treg -end macro - - -; Move from an 8-bit immediate value, to a location relative to a 64-bit -; register, with an 8-bit displacement and no indexing. -; -; This uses opcode 0xC6, which has w = 0. Since we run in 64-bit mode, that -; makes the operand size 8 bits, regardless of the current operand-size -; attribute. [Intel] volume 2D, appendix B, section B-1.4.3, table B-6. -macro mov.qreg.disp8.bimm target, offset, source - qwordreg treg, target - db 0xC6 - modrm 1, 0, treg - ; the 0 is part of the opcode - ; 4 is rsp, but it's a special case - match =rsp, target - ; R/M = rsp is the SIB case - sib 0, 4, treg - ; no scaling, no indexing, target as base - end match - db offset - db source -end macro - -; Move from a 16-bit immediate value, to a location relative to a 64-bit -; register, with an 8-bit displacement and no indexing. -; -; This uses opcode 0xC7, which has w = 1. We run in 64-bit mode, so that gives -; us an operand size of 32 bits by default. [Intel] volume 1, chapter 3, -; section 3-6.1, table 3-4. We want a 16-bit operand, so we use the -; operand-size prefix, 0x66, and we leave REX.W unset. -; -; We need to treat rsp specially because it's the SIB case, per table 2-2. -macro mov.qreg.disp8.wimm target, offset, source - qwordreg treg, target - db 0x66 - db 0xC7 - modrm 1, 0, treg - ; the 0 is part of the opcode - match =rsp, target - ; R/M = rsp is the SIB case - sib 0, 4, treg - ; no scaling, no indexing, target as base - end match - db offset - dw source -end macro - -; Move from a 32-bit immediate value, to a location relative to a 64-bit -; register, with an 8-bit displacement and no indexing. -; -; This uses opcode 0x67, which has w = 1. We run in 64-bit mode, so that gives -; us an operand size of 32 by default. [Intel] volume 2D, section B.1.43, -; table B-6. This is what we want, so we leave it. -macro mov.qreg.disp8.dimm target, offset, source - qwordreg treg, target - db 0xC7 - modrm 1, 0, treg - ; the 0 is part of the opcode - match =rsp, target - ; R/M = rsp is the SIB case - sib 0, 4, treg - ; no scaling, no indexing, target as base - end match - db offset - dd source -end macro - -; Move from a 64-bit register, to a 64-bit location relative to a 64-bit -; register, with an 8-bit displacement and no indexing. -; -; This uses opcode 0x89 with REX.W, so that gives us the reg field as the -; 64-bit source and the R/M field as the 64-bit destination. -; -; We need to treat a target of rsp specially because it's the SIB case per -; table 2-2. -macro mov.disp8.qreg.qreg offset, target, source - qwordreg sreg, source - qwordreg treg, target - rex.w - db 0x89 - modrm 1, sreg, treg - match =rsp, source - ; R/M = rsp is the SIB case - sib 0, 4, 4 - ; no scaling, no indexing, rsp as base - end match - db offset -end macro - -; Move from a 64-bit register, to a 64-bit location relative to a 64-bit -; register, with a 32-bit displacement and no indexing. -; -; This uses opcode 0x89 with REX.W, so that gives us the reg field as the -; 64-bit source and the R/M field as the 64-bit destination. -; -; We need to treat a target of rsp specially because it's the SIB case per -; table 2-2. -macro mov.qreg.disp32.qreg target, offset, source - qwordreg sreg, source - qwordreg treg, target - match =rsp, target - rex.w - db 0x89 - modrm 2, sreg, treg - ; treg is rsp by assumption, and R/M = rsp is the SIB case - sib 0, 4, 4 - ; no scaling, no indexing, rsp as base - dd offset - else - rex.w - db 0x89 - modrm 2, sreg, treg - dd offset - end match -end macro - -; Move from a 32-bit immediate value, to a 64-bit location relative to a -; 64-bit register, with an 8-bit displacement and no indexing. -; -; Note that there is no instruction to move a 64-bit immediate to memory. -; -; This uses opcode 0xC7, which has w = 1. We run in 64-bit mode, so that -; gives us an operand size of 32 by default. [Intel] volume 2D, -; section B.1.43, table B-6. We want a 64-bit operand, so we use the REX.W -; prefix, 0x48. -macro mov.qreg.disp8.dimm target, offset, source - qwordreg treg, target - match =rsp, target - rex.w - db 0xC7 - modrm 1, 0, treg - ; the 0 is part of the opcode - ; 4 is rsp, but it's a special case - sib 0, 4, treg - ; no scaling, no indexing, rsp as base - db offset - dd source - else - rex.w - db 0xC7 - modrm 1, 0, treg - ; the 0 is part of the opcode - db offset - dd source - end match -end macro - -; "Load effective address". Compute a 64-bit address as you would for -; indexed addressing, with an 8-bit displacement and no indexing, but instead -; of doing anything with the memory, just store the address itself into a -; register. -macro lea.qreg.disp8.qreg target, offset, source - qwordreg treg, target - qwordreg sreg, source - rex.w - db 0x8D - modrm 1, treg, sreg - match =rsp, source - ; R/M = rsp is the SIB case - sib 0, 4, sreg - ; no scaling, no indexing, rsp as base - end match - db offset -end macro - -macro lea.qreg.disp32.qreg target, offset, source - qwordreg treg, target - qwordreg sreg, source - rex.w - db 0x8D - modrm 2, treg, sreg - match =rsp, source - ; R/M = rsp is the SIB case - sib 0, 4, sreg - ; no scaling, no indexing, rsp as base - end match - dd offset -end macro - -macro lea.qreg.indexed.qreg target, source, index, scale - match =rbp, source - assert 0 - ; This is divided into some subcases we don't wish to deal with yet. - else match =rsp, index - assert 0 - ; This is the case where it's not actually indexed after all. - else - qwordreg treg, target - qwordreg sreg, source - qwordreg ireg, index - scalefield sfield, scale - rex.w - db 0x8D - modrm 0, treg, 4 - sib sfield, ireg, sreg - end match -end macro - -; Wow, we use ALL the instruction suffixes for this, huh. See [Intel] volume -; 2A, chapter 2, section 2-1, with particular attention to figure 2-1. -macro lea.qreg.disp8.indexed.qreg target, offset, source, index, scale - match =rbp, source - assert 0 - ; This is divided into some subcases we don't wish to deal with yet. - else match =rsp, index - assert 0 - ; This is the case where it's not actually indexed after all. - else - qwordreg treg, target - qwordreg sreg, source - qwordreg ireg, index - scalefield sfield, scale - rex.w - db 0x8D - modrm 1, treg, 4 - ; 1 in the mode field says we want a disp8. - ; 4 in the R/M field says we want an SIB byte. - sib sfield, ireg, sreg - db offset - end match -end macro - -macro mov.breg.breg target, source - bytereg treg, target - bytereg sreg, source - db 0x88 - modrm 3, sreg, treg -end macro - -macro mov.breg.bimm target, source - bytereg treg, target - db 0xC6 - modrm 3, 0, treg - ; the 0 is part of the opcode - db source -end macro - -; Clear the DF flag. This makes string instructions increment RSI. -macro cld - db 0xFC -end macro - -; Set the DF flag. This makes string instructions decrement RSI. -macro std - db 0xFD -end macro - -; Load 64 bits from the address in RSI into RAX. Then, increment or decrement -; RSI by 8 bytes, depending on the value of the DF flag. -macro lodsq - rex.w - db 0xAD -end macro - -macro cmps8 - db 0xA6 -end macro - -; [Intel] describes two different styles of mnemonic for the repeated string -; operations. See, their parameters are always rsi and rdi, or the smaller -; versions of those same specific registers. Intel thinks we might want to -; write out "rsi" explicitly, even though the only information it conveys is -; the size. The position we take is that it's better to let that be conveyed -; by the instruction name; otherwise it'd be a point of confusion for new -; readers, who might mistakenly think it's possible to pass it different -; registers. -; -; With the string instructions, the reader SHOULD be thinking, "Wait... -; where does this get its parameters from?" Writing them in a way that makes -; them appear simpler than they are would be confusing. -macro rep operation - match =movsb, operation - db 0xF3 ; rep prefix - db 0xA4 ; opcode - else match =movsw, operation - db 0xF3 ; rep prefix - db 0x66 ; operand-size prefix - db 0xA5 ; opcode - else match =movsd, operation - db 0xF3 ; rep prefix - db 0xA5 ; opcode - else match =movsq, operation - ; The "rep" instruction can also be thought of as a prefix to other - ; instructions, though only a few specific ones are allowed. Anyway, it - ; comes before the REX byte. - db 0xF3 - ; The rest of this is the same as the encoding of normal, non-repeated - ; movsq. - rex.w - db 0xA5 - ; There's no explicit parameters. String operations are magic. - else - assert 0 - end match -end macro - -macro repz operation - match =scasb, operation - db 0xF3 ; rep prefix - db 0xAe ; opcode - else - assert 0 - end match -end macro - -macro repnz operation - match =scasb, operation - db 0xF2 ; rep prefix - db 0xAE ; opcode - else - assert 0 - end match -end macro - -; Push a 64-bit value from a register onto the stack (the one pointed to by -; rsp). Decrement rsp, then write the value at the new location. -; -; In the corner case where rsp is also the value being pushed, the old value -; is the one used. -; -; There's an alternate encoding of this that uses a ModRM byte, but doing it -; without is more compact, so we do without. -macro push.qreg source - qwordreg sreg, source - opcodereg 0x50, sreg -end macro - -macro push.bimm source - db 0x6A - db source -end macro - -; Operand-size prefix makes it 16-bit. -; -; If you're trying to fake pushing a larger size by doing several 16-bit -; pushes, remember to start by pushing the low end and proceed upwards. -; [Intel] volume 1, chapter 9, section 9-2.4, "Memory Data Formats". -macro push.wimm source - db 0x66 - db 0x68 - dw source -end macro - -; There is no 64-bit immediate push. So, can we have a push instruction that -; pushes a 32-bit immediate value? Sort-of, but it's sign-extended to 64 bits, -; so rsp is decremented by 8, not by 4. This is that instruction. -; -; You need to do a really close read of a number of things to understand why. -; The opcode tables in [Intel] in volume 2D, appendix A, section A-3 give it -; the d64 annotation, which per table A-1 in section A-2.5 indicates that the -; operand size is always 64 bits and that there is no corresponding 32-bit -; version. Yet, the actual immediate value is still only 32 bits! Direct your -; attention to the instruction's details page, volume 2B, chapter 4, section -; 4-3, "PUSH". The description section clearly details that the immediate may -; be less than the operand size, which makes sense once you know it, but it -; doesn't explictly call out that the operand size is still 64 bits here. -; -; In general, the size of an immediate doesn't determine operand size, as you -; can read about in detail in [Intel] volume 1, chapter 3, section 3-6.1, with -; particular attention to table 3-4. -; -; Why is this surprising, given that it's consistent with the behavior of -; other instructions? Well, most instructions don't have such obvious -; side-effects. It's easy to not notice the operand size disagreeing with the -; immediate size when you'e only writing to a register, but changing the stack -; in an unexpected way breaks things much more obviously. -; -; Anyway, if you really want to decrement the stack pointer by 32 bits after -; a push, consider pushing a register. -macro push.dimm source - db 0x68 - dd source -end macro - -; Pop a 64-bit value into a register from the stack (the one pointed to by -; rsp). Read the value from the old location, then increment rsp. -; -; In the corner case where rsp is also the destination being written to, the -; read happens from the old location, then the write causes the increment to -; be irrelevant. -; -; There's an alternate encoding of this that uses a ModRM byte, but doing it -; without is more compact, so we do without. -macro pop.qreg target - qwordreg treg, target - opcodereg 0x58, treg -end macro - - -; Do an absolute indirect jump with a 64-bit register operand. That is: given -; a register which holds a pointer, read another address from the pointed-to -; memory and jump to it. -; -; Technically this is a "near" jump in x86 terms, but we just pretend far -; jumps and segments don't exist. They are still a thing in 64-bit mode, we -; just don't use them. -macro jmp.abs.indirect.qreg location - qwordreg lreg, location - db 0xFF - modrm 0, 4, lreg -end macro - -; The location is relative to the start of the instruction immediately -; following the jmp. -macro jmp.rel.bimm location - db 0xEB - db location -end macro - -; There in no 64-bit immediate "near" jump, so we use 32-bit. It's relatve, -; so that's honestly plenty. -; -; The location is relative to the start of the instruction immediately -; following the jmp. -macro jmp.rel.dimm location - db 0xE9 - dd location -end macro - -; The location is relative to the start of the instruction immediately -; following the jmp. -macro jmp.cc.rel.bimm condition, location - conditioncode cc, condition - opcodecc 0x70, cc - db location -end macro - -; The location is relative to the start of the instruction immediately -; following the jmp. -macro jmp.cc.rel.dimm condition, location - conditioncode cc, condition - db 0x0F - opcodecc 0x70, cc - dd location -end macro - -; Invoke a system call provided by the kernel. On Linux, the System V ABI -; describes the semantics of such calls (at least, on x86). -macro syscall - db 0x0F, 0x05 -end macro - - -; Halts the CPU. We can't actually run this in userspace, but the kernel will -; kill our process or the debugger will break, and those are the outcomes we -; actually want. -macro hlt - db 0xf4 -end macro - - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Executable file format ;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; -;;; Before we get into the body of the program, we do a lot of ELF-specific -;;; stuff to ensure that our output is in a format Linux knows how to run. -;;; -;;; First, we set the origin to load at. This is arbitrary, but it can't be -;;; zero. We tell flatassembler about it because it's used in label -;;; calculations; we can reference it as $$ any time we need it in future. -org 0x08000000 - -;;; -;;; Second, we output ELF's top-level file header. The only interesting -;;; thing here is the entry pointer. -;;; -elf_header: - ; * denotes mandatory fields according to breadbox - db 0x7F, "ELF" ; *magic number - db 2 ; 64-bit - db 1 ; little-endian - db 1 ; ELF header format version 1 - db 0 ; System-V ABI - db 8 DUP 0 ; (padding) - - dw 2 ; *executable - dw 0x3E ; *Intel x86-64 - dd 1 ; ELF format version - - dq _start ; *entry point - dq program_header - $$ ; *program header offset - dq 0 ; section header offset - dd 0 ; processor flags - dw elf_header_size - dw program_header_entry_size ; * - dw 1 ; *number of program header entries - dw 0 ; section header entry size - dw 0 ; number of section header entries - dw 0 ; section name string table index -; Save a copy of the size of this chunk for our future reference, by comparing -; the current posiion to the label above. -elf_header_size = $ - elf_header - -;;; -;;; Third, immediately after the ELF file header, we output ELF's program -;;; header, which lists the memory regions ("segments") we want to have and -;;; where we want them to come from. We list just a single region, which is -;;; the entire contents of the ELF file from disk. -;;; -;;; It would be more typical to use this header to ask the loader to give us -;;; separate code and data segments, and perhaps a stack or heap, but this -;;; keeps things simple, and we can create those things for ourselves later. -;;; -;;; We do have a little stack space available, though we don't explicitily -;;; request any; the kernel allocates it for us as part of exec() so that it -;;; can pass us argc and argv (which we ignore). That stack space will be at a -;;; random address, different every time, because of ASLR; that's a neat -;;; security feature, so we leave it as-is. -;;; -program_header: - dd 1 ; *"loadable" segment type - dd 0x05 ; *read+execute permission - dq 0 ; *offset in file - dq $$ ; *virtual address - ; required, but can be anything, subject to alignment - dq 0 ; physical address (ignored) - dq file_size ; *size in file - dq file_size ; *size in memory - dq 0 ; segment alignment - ; for relocation - will we be ASLR'd? -; Save the size of this chunk, as well. -program_header_entry_size = $ - program_header - -; Everything after this point is code or data, not headers, so save the start -; of it for use in size calculations later. -code_start: - - -;;;;;;;;;;;;;;;;;;;;;;; -;;; Execution model ;;; -;;;;;;;;;;;;;;;;;;;;;;; -;;; -;;; We use Forth-style dual stacks, one for values and one for control. We -;;; use rsp for values, just like C does. We use rbp for the control stack, -;;; which is a special Forth-y stack: These are pointers into the bodies of -;;; Forth words, not return addresses. -;;; -;;; The choice of rsp and rbp for the stack pointers imitates Jonesforth; -;;; I'm hopeful that it gives us convenient addressing modes, and will report -;;; back about that when I feel that I understand the implications. -;;; -;;; In Forth, everything is a "word", including mutable variables. -;;; Conceptually, a word is a unit of execution, which may be implemented -;;; either in machine code or as an array of pointer to other words. -;;; -;;; This polymorphism is implemented by having each word's contents begin -;;; with a "codeword", which is a pointer to machine code that "interprets" -;;; the rest of the contents. In the case of words implemented in machine -;;; code, the codeword points directly to that code, which is normally right -;;; next to it. -;;; -;;; Variables, to Forth, are simply one more thing that can be executed; the -;;; effect of executing a variable is to push its address onto the value -;;; stack. -;;; -;;; We adopt this model of words, codewords, and variables-as-words. It's -;;; really nice how it doesn't force anything else on us, not even a heap, -;;; though we do end up using a heap. -;;; -;;; We specifically implement a version of calling and returning that Forth -;;; calls indirect threaded code: The control stack is a stack of pointers -;;; into the middle of interpreted words. The interpreter snippet, called -;;; docol, implements calling. Each word is responsible for making sure -;;; returning works properly. Interpreted words accomplish this by ending with -;;; the word "exit", while machine-code words accomplish it by ending with a -;;; verbatim snippet called "next". -;;; -;;; Conceptually, "next" returns, but more specifically it accomplishes this -;;; by doing the caller's next dispatch for it; thus control never actually -;;; goes back to the caller's interpreter after initial setup. For performance -;;; reasons, "next" is always inlined, so we define it as a macro. -;;; -;;; The docol routine is just ordinary code, not a macro. It's defined later -;;; in this file, as a label. -;;; -;;; Notionally, we could consider not having a dictionary, and not giving -;;; our words names. However, it feels silly to stop when we're so close to -;;; being a full Forth, and using names for things solves a bootstrapping -;;; problem related to heap management - see the write-up of _start about how -;;; the heap is created, below. So, we add an additional header before the -;;; codeword for this purpose. -;;; -;;; The Forth dictionary is usually a linked list of every word that has -;;; ever been defined, with the newest at the head; the names of words are -;;; stored in string fields, often right next to the link pointer. We adopt -;;; this model, with the field sizes and order shown in the quick reference -;;; below. We break with Forth tradition in one way: Rather than having a -;;; length field, we use a null-terminated string. Thus, there's no length -;;; limit on names. This necessitates breaking out the flags (to be explained -;;; later) into their own byte, rather than taking bits from the length field -;;; for them. -;;; -;;; There's an important performance consideration: Executable words -;;; reference each other by pointers to their respective codewords. However, -;;; dictionary entries reference each other by pointers to their respective -;;; link fields. Traversing from the link field to the codeword is easy, -;;; though it's a non-constant-time operation: Just walk the string. In order -;;; to make Forth words easy to "decompile", it would be nice to also have a -;;; way to traverse backwards. We solve this by making the name field be -;;; null-terminated at both ends. Fun, yeah? -;;; -;;; -;;; -;;; -;;; -------------------------------------------------------------------------- -;;; Quick Reference -;;; -------------------------------------------------------------------------- -;;; -;;; The layout of an interpreted word: -;;; -;;; (overall start) -;;; 0x00 - 0x08 Link (to next-oldest word) -;;; 0x09 - 0x09 HM00000I Flags -;;; H - hidden -;;; M - metadata -;;; I - immediate -;;; all other bits reserved -;;; (name start) -;;; 0x0a - 0x0a Null byte (terminates name) -;;; 0x0b - name-end - 1 Name, as UTF-8 -;;; name-end - name-end Null byte (terminates name) -;;; (padding start) -;;; name-end + 1 - codeword-start - 1 Zero-pad to 8-byte boundary -;;; (it's possible this will be zero bytes long) -;;; (codeword start) -;;; ... + 0x00 - ... + 0x08 Codeword (ie. address of docol) -;;; (8-byte chunks) Addresses of other words -;;; - ... (end) Address of "exit" word -;;; -;;; The layout of a machine-code word is different only from the codeword on: -;;; -;;; ... + 0x00 - ... + 0x08 Addresss of next byte -;;; ... + 0x08 - ???? Arbitrary machine code -;;; - ... (end) Inlined implementation of next -;;; -;;; Also, words always start at 8-byte boundaries. -;;; -;;; -;;; REGISTER usage conventions: -;;; -;;; * rsi is the "instruction pointer" for the "interpreter". -;;; That is, it points to some word-pointer inside an array of -;;; word-pointers inside the content of the word they're part of. It always -;;; points to the next word that should be executed, whose execution hasn't -;;; begun yet. -;;; -;;; * rbp points to the top of the control stack -;;; These are former values of rsi, to eventually be returned to, from -;;; successively older callers as you look further up the stack. The stack -;;; grows downwards in memory. Since values are kept separately, the only -;;; thing on the control stack is return addresses, one per layer of call. -;;; -;;; * rsp points to the top of the value stack -;;; The value stack has no specific format, but it grows downwards in -;;; memory. In particular there's no concept of stack frames, because items -;;; on the stack don't belong to any particular word; the value stack in -;;; Forth is in part a mechanism for passing values between words. -;;; -;;; Additionally, immediately after beginning execution of a word: -;;; -;;; * rax points to the address of the codeword being executed -;;; The value of rax is purely for the callee's benefit, and does not need -;;; to be preserved. -;;; -;;; Other registers are purely discretionary, and are not preserved across -;;; calls. -;;; -;;; -;;; FLAG usage: -;;; -;;; * DF should be 0 -;;; We use lodsq extensively and that makes it increment rsi after using it. -;;; -;;; -------------------------------------------------------------------------- - -;;; -;;; Macro next -;;; ---------- -;;; -;;; Include this inline at the end of a word implemented in machine-code. -;;; Conceptually, it returns. What it actually does is do the next thing the -;;; caller would do, which is call the next word from the caller's array of -;;; word pointers. -;;; -;;; Registers in: -;;; -;;; * rsi points to the address of the word to execute -;;; -;;; Registers out: -;;; -;;; * rax points to the codeword in the contents of the word that was executed -;;; * rsi points to the next word-address after this one -;;; -;;; Flags -;;; * DF = 0 is required -;;; -macro next - ; Copy the next word's address from *rsi into rax. Increment rsi (as per the - ; DF flag). - lodsq - - ; Load the codeword from the word's contents, and jump to the interpreter it - ; points to. - jmp.abs.indirect.qreg rax -end macro - -;;; -;;; Macro beforenext -;;; ---------------- -;;; -;;; Sometimes we want to transfer control from a word implemented in -;;; machine-code to another word, without coming back after, as if we were -;;; simply jumping to it. This is an innovation of ours; Jonesforth doesn't do -;;; it. -;;; -;;; This implementation will work regardless of how the receiving word is -;;; implemented. It impersonates the "next" snippet, setting up rax to point -;;; to the codeword then jumping to the interpreter. Since it doesn't change -;;; the control stack or rsi, when the receiving word eventually invokes -;;; "next"; it will pick up in the same place as if this sending word had done -;;; it. -;;; -;;; Thus, notionally we are doing just this one transfer of control before -;;; eventually getting around to inlining "next". Hence the name. -;;; -macro beforenext target - ; Do a permanent transfer of control by setting rax and invoking the - ; codeword. Of course, we could jump to docol ourselves but this will work - ; regardless of what the receiving codeword is. - mov.qreg.qimm rax, target - jmp.abs.indirect.qreg rax -end macro - -;;; -;;; Macros pushcontrol -;;; popcontrol -;;; ------------------ -;;; -;;; Include these inline to push an address onto the control stack, or pop -;;; one off of it. You will recall the control stack is kept in rbp. The -;;; parameter is given in a user-specified register. -;;; -;;; Jonesforth's analogous macros are called PUSHRSP and POPRSP but I think -;;; that's super confusing, since rsp is also the name of a register, but a -;;; different one. I guess it was less confusing in 32-bit, since esp doesn't -;;; start with an "r". Anyway, this has to be named something that -;;; distinguishes it from Intel's PUSH and POP opcodes, so... -;;; -;;; "Load effective address" is just a cute way to do arithmetic on a -;;; register, here. To push or pop we decrement or increment rbp by 8. To -;;; actually interact with the space in the stack, we indirect through rbp. -;;; -;;; Registers in and out: -;;; -;;; * rbp points to the top of the control stack. -;;; -macro pushcontrol source - lea.qreg.disp8.qreg rbp, -8, rbp - mov.disp8.qreg.qreg 0, rbp, source -end macro - -macro popcontrol target - mov.qreg.disp8.qreg target, 0, rbp - lea.qreg.disp8.qreg rbp, 8, rbp -end macro - -;;; -;;; Routine _start -;;; -------------- -;;; -;;; This is the entry point of the whole program, the very first code we -;;; actually execute. Linkers traditionally call this _start, and on balance -;;; I think it's probably best to keep that name, though I've honestly never -;;; liked it... Anyway, the ELF header points to it and exec() jumps to it. -;;; Also, though it could be anywhere in the code part of the output, in order -;;; to make the hexdump pretty we put it at the start. -;;; -;;; The kernel gives us most registers zeroed, and rsp pointing to the -;;; command-line stuff (argc, argv, envp), which is at an ASLR'd address with -;;; some stack space allocated for us, despite the fact we didn't request any. -;;; It also gives us all the flags clear except IF, but we don't rely on that. -;;; Lastly, of course, it loads our code segment and sets the instruction -;;; pointer where we asked; we don't need to check what those addresses are, -;;; because they're not randomized. -;;; -;;; This routine is really only responsible for one-time initialization. -;;; -;;; Registers in: -;;; -;;; * rsp points to the logical top of the value stack -;;; The kernel sets this up for us, and we need to save it somewhere so -;;; Forth can use it. -;;; -;;; Registers out: -;;; -;;; * rsi points within "quit" -;;; Quit is the word that's Forth's closest equivalent to main(). -;;; * rsp points to the top of the value stack -;;; -;;; Notably, rbp is still uninitialialized after _start. -;;; -;;; Stack in: -;;; -;;; * argc, argv, envp in the usual Unix way -;;; We ignore them, though. -;;; -;;; Stack out: -;;; -;;; * The value of "heap", as a pointer -;;; The meaning of this will be explained below. -;;; -;;; Registers within: -;;; -;;; * rdi points to the base the heap was allocated at, once it exists -;;; This is the same value that "heap" will hold, once we reach a point -;;; where we have variables. Of course, variables are stored on the heap, -;;; hence this temporary measure. -;;; -;;; We also take this opportunity to define soeme memory layout parameters -;;; that this routine will be responsible for doing something with: -;;; -heap_requested_address = 0x0000001000000000 ; (very arbitrary) -heap_size = 0x0000000001000000 ; 16 MiB -control_stack_size = 0x10000 ; 64 KiB - -_start: - cld ; clear the DF flag - - ;;; - ;;; Prepare the heap. - ;;; - ;;; We could ask for a data segment in the program header, but where's the - ;;; fun in that? Instead, we call mmap(). - ;;; - ;;; If we wanted the kernel to do ASLR for us, passing address zero would - ;;; cause it to pick somewhere at random, but instead we choose our own - ;;; location. It's still not guaranteed to be where we ask for, so we still - ;;; do the work to record where it wound up. We could pass the "fixed" flag - ;;; and the kernel would trust us, but this gives us more options for - ;;; interoperating with other runtimes. - ;;; - mov.qreg.qimm rax, 9 ; mmap() - mov.qreg.qimm rdi, heap_requested_address ; address (very arbitrary) - mov.qreg.qimm rsi, heap_size ; size (one meg) - mov.qreg.qimm rdx, 0x07 ; protection (read+write+execute) - mov.oreg.qimm r10, 0x22 ; flags (private+anonymous) - mov.oreg.qimm r8, 0 ; file descriptor (ignored) - mov.oreg.qimm r9, 0 ; offset (ignored) - syscall - - ;;; - ;;; The return value of the system call is in rax, we'll use it in a sec. - ;;; We need to save this somewhere in case we ever want to munmap() it; - ;;; there's no widely-used name for it so we have to make one up. S0 and r0 - ;;; are widely-used names for the physical tops (logical bottoms) of the - ;;; value and control stacks, respectively, and we will eventually set those - ;;; up as well, so we should keep those names in mind. The control stack - ;;; lives within the heap, while the value stack is its own segment. This - ;;; value, though, is the physical bottom of the segment, meaning that it - ;;; stays the same even as we allocate and deallocate things within it. This - ;;; is unlike the two stack pointers, so we give it a name that doesn't - ;;; suggest similarity: "heap". - ;;; - ;;; Once Forth is fully set up, its internal variables will be accessed - ;;; through variable-words like any other Forth data, including "heap". To - ;;; get to that point, though, we need to be able to hold onto variable data - ;;; between now and then. In fact, if we don't have at least one of "heap" - ;;; and "here" (its counterpart which points to the logical top end), all - ;;; our efforts to hold onto anything seem a bit doomed. - ;;; - ;;; So, we temporarily dedicate rdi to "heap" - only within this routine - - ;;; and store everything else in ways that let us find things by reference - ;;; to it. We choose rdi because it works with the indexing modes we care - ;;; about, and its name suggests its function. - ;;; - ;;; The strategy Jonesforth uses is not applicable to us; Jonesforth - ;;; takes advantage of the linker to let its code segment refer to specific, - ;;; pre-allocated objects in the data segment. We are our own linker. - ;;; Hence, this approach. - ;;; - ;;; Keying things off "heap" is the fundamental decision, but to make sure - ;;; our variables are accessible both during early bootstrapping, and later, - ;;; we also have to be thoughtful about data structures. More on that in a - ;;; moment. - ;;; - mov.qreg.qreg rdi, rax - - ;;; - ;;; We also initialize rbp. We could hold off and let "quit" do this, but - ;;; doing it now is the easiest way to initialize the r0 variable, since - ;;; there's no instruction that moves a 64-bit immediate to memory. - ;;; - ;;; This is the moment at which we decide where the control stack starts! - ;;; Fun, right? "Allocation" is just a fancy word for picking where we want - ;;; something, then being consistent about it - like placing furniture in - ;;; your home. See below for a little more thought about why here in - ;;; particular. - ;;; - lea.qreg.disp32.qreg rbp, control_stack_size, rdi - - ;;; - ;;; Now we save some stuff onto the heap. These are the locations that - ;;; will eventually be the backing stores of the Forth variables, but we - ;;; don't create the word headers yet, since there's no requirement that - ;;; they be next to the backing stores. We'll do that later, once we have - ;;; word-writing infrastructure in place. For now, we just use their offsets - ;;; relative to the physical bottom of the heap, which are fixed. - ;;; - ;;; These will be the permanent homes of these values, though we have - ;;; copies of them elsewhere while we're still in this routine. - ;;; - mov.qreg.disp32.qreg rdi, control_stack_size + 0x00, rdi ; log - mov.qreg.disp32.qreg rdi, control_stack_size + 0x08, rsp ; s0 - mov.qreg.disp32.qreg rdi, control_stack_size + 0x10, rbp ; r0 - mov.qreg.qimm rax, final_word_name - mov.qreg.disp32.qreg rdi, control_stack_size + 0x18, rax ; latest - lea.qreg.disp32.qreg rax, control_stack_size + 0x28, rdi - mov.qreg.disp32.qreg rdi, control_stack_size + 0x20, rax ; here - ;;; - ;;; * "log" is the physical bottom of the log - ;;; The log grows upwards in memory, so this is also the logical - ;;; bottom. This comes from the address mmap() just returned to us. - ;;; The rest of quine.asm refers to the log as the heap. It's not a - ;;; heap, but it used to be called that. The self-hosted version of - ;;; Evocation has the fully revised and reconciled copy of all these - ;;; comments, it just felt like unnecessary tedium to do that here as - ;;; well. - ;;; * "s0" is the logical bottom of the value stack - ;;; The value stack grows downwards in memory, so this is the physical - ;;; top of it. This comes from the stack pointer the kernel initialized us - ;;; with. - ;;; * "r0" is the logical bottom of the control stack - ;;; The control stack also grows downwards, so this is its pysical top - ;;; as well. We allocate this dedicated space within the heap right here, - ;;; in this routine, through our choice of where to put things. - ;;; * "here" is the physical start of the unallocated space in the heap - ;;; We allocate heap space from bottom to top, by incrementing this - ;;; value. So, it would also be accurate to say that it points immediately - ;;; after the physical top of the allocated space. At any rate, the - ;;; address it points to is the first one that hasn't been used yet. - ;;; * "latest" is the address of the most-recently-defined word's header - ;;; Defining new words changes this value. - ;;; - ;;; s0 and r0 are mostly used when we want to initialize or reinitialize - ;;; their respective stacks - that is, discard all their contents at once. - ;;; - ;;; The value of r0 is the same address these variables start at, so - ;;; you'll want to do a close read of the implementation of pushcontrol - ;;; and convince yourself that it only ever writes things just below the rbp - ;;; address it receives, never right on top of it. - ;;; - ;;; As an aside, by the way, please notice that strictly speaking, r0 - ;;; could be a constant... but it isn't known until runtime, so we might as - ;;; well make it a variable. That will play nicely with any astonishing - ;;; memory shenanigans someone might wish to do in the future. - ;;; - ;;; Notice also that "here" points immediately after itself. This is just - ;;; a convenience, making it the last one like that so that the concern is - ;;; dealt with in a single place and is easy to keep up-to-date with code - ;;; changes. - ;;; - ;;; A little more detail about why we offset everything by - ;;; control_stack_size: We're carving out some space at the bottom of the - ;;; heap - which grows low-to-high - to be the control stack - which grows - ;;; high-to-low. So the control stack is allocated out of the heap as a - ;;; fixed-size, one-time thing, and then the variables come immediately - ;;; after that. We do need to use 32-bit displacement indexing to access - ;;; them this way, but that's no big deal. - ;;; - ;;; This is perhaps questionable, they should maybe be separate segments - ;;; created with separate calls to mmap(), but for now we're not worried - ;;; about overflow so we use the same allocation for both. - ;;; - ;;; We'll come back to these variables a bit later and generate the word - ;;; headers that point at them, but now we're almost ready to switch to - ;;; proper threaded-execution, so we finish that setup first... - ;;; - - ;;; - ;;; Push the value of "heap" onto the value stack so that it can be the - ;;; breadcrumb the threaded code needs to find... the backing store of - ;;; "heap". Yes, self-reference can be weird like that sometimes. There's - ;;; nothing stopping "quit" from reading rdi, it just violates the - ;;; abstraction... - ;;; - push.qreg rdi - - ;;; - ;;; We are about to set up rsi, we did rbp already, and rsp came to us - ;;; already set up. That's all that "next" needs, so take it away! - ;;; - mov.qreg.qimm rsi, cold_start - next - -;;; -;;; This isn't really a routine so much as it's an array of words (exactly -;;; one of them), which is what "next" wants rsi to point to. It's only ever -;;; used this one time, so we just put it right here. -;;; - - align 8 -cold_start: - ;;; Before handing off to us, _start pushed a single value onto the stack, - ;;; a pointer to the beginning of the heap. Now, we load our entire Forth - ;;; implementation onto that heap, beginning with the minimal set of words - ;;; needed to define more words. We do this because we need variables as - ;;; infrastructure so we can eventually have dynamic definitions. - ;;; - ;;; There's something non-obvious here: words implemented statically as - ;;; part of the executable image can't contain things that vary at runtime. - ;;; That means that even if these words tried to implement some sort of - ;;; dynamic lookup, they would have no way to find the root of whatever - ;;; dynamic data structure they use. Dynamism needs to be bootstrapped. - ;;; - ;;; In a more traditional C-style program, static code could look up - ;;; variables based on fixed addresses that are the same on every run. - ;;; Failing that, we could dedicate a register to it, though that's a - ;;; considerable expense. We chose not to do either of those things, because - ;;; we want the versatility that comes with not being picky about our - ;;; address space: It allows us to contemplate future improvements such as - ;;; ASLR, or embedding into other processes that impose their own addressing - ;;; constraints, or even coexisting with multiple versions of ourselves. - ;;; That choice does mean we have the hard version of this bootstrapping - ;;; problem, and copying ourselves to the heap is how we solve it. - ;;; - ;;; We do have the heap address right now, though that won't last. In case - ;;; it's unclear why not: keeping it on the stack would require all future - ;;; references to walk the stack, and somehow know when they've reached the - ;;; bottom. The stack is a good place to keep things with clearly delimited - ;;; lifetimes and visibility, but when we want something to live for our - ;;; entire program and be easy to find from any code within it, we need to - ;;; do something else. Anyway, since we have the address, we can use it for - ;;; the next little bit of setup. - ;;; - ;;; The first few words we define are our variables, which hardcode the - ;;; addresses they will return - but since we're doing this at runtime, - ;;; "hardcoding" can reflect where our heap is. This is the fundamental - ;;; trick that makes the heap usable. - ;;; - ;;; One more thing to notice: We already allocated the backing stores of - ;;; these variables, and populated their initial values, in _start. The - ;;; words we're defining return those same addresses for the same backing - ;;; stores. So, we have continuity: Stuff defined in terms of the - ;;; variable-words we're defining now will interoperate with the stuff that - ;;; we define in the "early" way, which includes those very words. Both the - ;;; early code and the later code are dealing with the same data structures, - ;;; they're just using a different technique to find them. - ;;; - ;;; This is the only hardcoding we need to do; by building on top of it, - ;;; we will soon reach a point where the rest of the system can be defined - ;;; within itself. - dq early_heap, litstring, "log", early_variable - dq early_s0, litstring, "s0", early_variable - dq early_r0, litstring, "r0", early_variable - dq early_latest, litstring, "latest", early_variable - dq early_here, litstring, "here", early_variable - - ;;; Now we define a heap version of docol. Strictly speaking it doesn't - ;;; need to be among the first words, it only needs to come before the first - ;;; words implemented in Forth. However, it's conceptually tidy to have it - ;;; that way, so that's what we do. - ;;; - ;;; Docol also presents a unique challenge, in that it's two snippets of - ;;; code and one of them needs to refer to the other. When we use docol as - ;;; the codeword of a word we're defining, we point to a snippet which acts - ;;; as an interpreter for the word's body. However, when we look up "docol" - ;;; in the dictionary, what we get is a word that returns the address of the - ;;; interpreter snippet, effectively acting as a constant. - ;;; - ;;; One way to make this work would be to use a forward-referencing - ;;; address using the labels system. However, it turns out that only docol - ;;; and zbranch would benefit from this, and we drastically simplify our - ;;; code by reworking things so that no forward reference is needed. - ;;; - ;;; What we do is define the interpreter snippet first, allocating space - ;;; for the machine code directly out of "here", with no word header nor any - ;;; dictionary entry pointing to it. We keep track of the address we put - ;;; that at, then we define the constant to point to it. - ;;; - ;;; While it may seem weird to use space that's "outside" of any word, - ;;; keep in mind that using the heap in creative ways is part of the spirit - ;;; of Forth. Jonesforth doesn't have this bootstapping problem, but its - ;;; variables use this same technique of putting the value before the word - ;;; header to avoid a forward reference. Also, words don't have end - ;;; delimiters, so who's to say what's inside or outside them? - dq early_here, fetch, dup - dq rsi, pack_pushcontrol - dq lit, 8, rax, add_reg64_imm8 - dq rax, rsi, mov_reg64_reg64 - dq pack_next - dq lit, 8, packalign - dq roll3, swap, early_here_store, swap - ; Now the interpreter snippet is in-place and "here" points after it, so - ; that future allocation won't step on it. We also still have a copy of its - ; start address, which we will now pass to early_variable. - dq litstring, "docol", early_variable - ; (While it might be tidy to have a separate "early_constant", it would do - ; the same thing. Late variables and constants will be different because the - ; real "variable" word will also be responsible for allocating the backing - ; store, but the only thing early_variable is doing is returning an - ; address.) - - ; Now we define a bunch of ordinary Forth words. Since we'll only ever be - ; calling these copies from within Forth, we're no longer limited by - ; flatassembler's syntax, so a lot of them have slightly different names - ; than they've had up to now. This will be noted below. - - dq litstring, "exit", early_create, early_self_codeword, early_here, fetch - dq rsi, pack_popcontrol, pack_next - dq lit, 8, packalign, early_here_store - - dq litstring, "swap", early_create, early_self_codeword, early_here, fetch - dq rax, pop_reg64, rbx, pop_reg64, rax, push_reg64, rbx, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - dq litstring, "drop", early_create, early_self_codeword, early_here, fetch - dq rax, pop_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "drop2". - dq litstring, "2drop", early_create, early_self_codeword, early_here, fetch - dq rax, pop_reg64, rax, pop_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - dq litstring, "roll", early_create, early_self_codeword, early_here, fetch - dq rcx, pop_reg64 - dq rcx, dec_reg64 - dq rsp, rcx, lit, 8, rbx, mov_reg64_indexed_reg64 - dq rsi, push_reg64 - dq rsp, rcx, lit, 8, rsi, lea_reg64_indexed_reg64 - dq rsp, rcx, lit, 8, lit, 8, rdi, lea_reg64_disp8_indexed_reg64 - dq std - dq rep_movs64 - dq cld - dq rsi, pop_reg64 - dq rbx, rsp, mov_indirect_reg64_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; Jonesforth calls this "-roll" and we could do that, but honestly the name - ; unroll sounds nicer and it's only a single character longer. You might say - ; it rolls off the tongue better. - dq litstring, "unroll", early_create, early_self_codeword, early_here, fetch - dq rcx, pop_reg64 - dq rcx, dec_reg64 - dq rcx, rdx, mov_reg64_reg64 - dq rsp, rbx, mov_reg64_indirect_reg64 - dq rsi, push_reg64 - dq rsp, lit, 16, rsi, lea_reg64_disp8_reg64 - dq rsp, lit, 8, rdi, lea_reg64_disp8_reg64 - dq rep_movs64 - dq rsi, pop_reg64 - dq rbx, rsp, rdx, lit, 8, mov_indexed_reg64_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "roll3". - dq litstring, "3roll", early_create, early_self_codeword, early_here, fetch - dq rax, pop_reg64 - dq rbx, pop_reg64 - dq rcx, pop_reg64 - dq rbx, push_reg64 - dq rax, push_reg64 - dq rcx, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "unroll3". - dq litstring, "3unroll", early_create, early_self_codeword - dq early_here, fetch - dq rax, pop_reg64 - dq rbx, pop_reg64 - dq rcx, pop_reg64 - dq rax, push_reg64 - dq rcx, push_reg64 - dq rbx, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - dq litstring, "dup", early_create, early_self_codeword, early_here, fetch - dq rax, pop_reg64 - dq rax, push_reg64 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "dup2". - dq litstring, "2dup", early_create, early_self_codeword, early_here, fetch - dq rax, pop_reg64 - dq rbx, pop_reg64 - dq rbx, push_reg64 - dq rax, push_reg64 - dq rbx, push_reg64 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "add". - dq litstring, "+", early_create, early_self_codeword, early_here, fetch - dq rbx, pop_reg64 - dq rax, pop_reg64 - dq rbx, rax, add_reg64_reg64 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "sub". - dq litstring, "-", early_create, early_self_codeword, early_here, fetch - dq rbx, pop_reg64 - dq rax, pop_reg64 - dq rbx, rax, sub_reg64_reg64 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "mul". - dq litstring, "*", early_create, early_self_codeword, early_here, fetch - dq rax, pop_reg64 - dq rbx, pop_reg64 - dq rbx, mul_reg64 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "divmod". Jonesforth calls it "/mod" but % is widely recognized - ; and has no special Forth significance. - dq litstring, "/%", early_create, early_self_codeword, early_here, fetch - dq rdx, rdx, xor_reg64_reg64 - dq rbx, pop_reg64 - dq rax, pop_reg64 - dq rbx, divmod_reg64 - dq rdx, push_reg64 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "eq". Jonesforth calls it "="; most languages would call it "==". - dq litstring, "=", early_create, early_self_codeword, early_here, fetch - dq rax, pop_reg64 - dq rbx, pop_reg64 - dq rbx, rax, cmp_reg64_reg64 - dq cc_equal, al, set_reg8_cc - dq lit, 0x01, rax, and_reg64_imm8 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "ne". Jonesforth calls it "<>", but even most modern SQL dialects - ; recognize C's legacy and allow "!=" these days. As someone who learned C - ; in childhood, this is not actually a hard call for us. - dq litstring, "!=", early_create, early_self_codeword, early_here, fetch - dq rax, pop_reg64 - dq rbx, pop_reg64 - dq rbx, rax, cmp_reg64_reg64 - dq cc_not_equal, al, set_reg8_cc - dq lit, 0x01, rax, and_reg64_imm8 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "gt". - dq litstring, ">", early_create, early_self_codeword, early_here, fetch - dq rax, pop_reg64 - dq rbx, pop_reg64 - dq rbx, rax, cmp_reg64_reg64 - dq cc_greater, al, set_reg8_cc - dq lit, 0x01, rax, and_reg64_imm8 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "lt". - dq litstring, "<", early_create, early_self_codeword, early_here, fetch - dq rax, pop_reg64 - dq rbx, pop_reg64 - dq rbx, rax, cmp_reg64_reg64 - dq cc_less, al, set_reg8_cc - dq lit, 0x01, rax, and_reg64_imm8 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "ge". - dq litstring, ">=", early_create, early_self_codeword, early_here, fetch - dq rax, pop_reg64 - dq rbx, pop_reg64 - dq rbx, rax, cmp_reg64_reg64 - dq cc_greater_equal, al, set_reg8_cc - dq lit, 0x01, rax, and_reg64_imm8 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "le". - dq litstring, "<=", early_create, early_self_codeword, early_here, fetch - dq rax, pop_reg64 - dq rbx, pop_reg64 - dq rbx, rax, cmp_reg64_reg64 - dq cc_less_equal, al, set_reg8_cc - dq lit, 0x01, rax, and_reg64_imm8 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "gt_unsigned". - dq litstring, ">unsigned", early_create - dq early_self_codeword, early_here, fetch - dq rax, pop_reg64 - dq rbx, pop_reg64 - dq rbx, rax, cmp_reg64_reg64 - dq cc_above, al, set_reg8_cc - dq lit, 0x01, rax, and_reg64_imm8 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "lt_unsigned". - dq litstring, "=unsigned", early_create - dq early_self_codeword, early_here, fetch - dq rax, pop_reg64 - dq rbx, pop_reg64 - dq rbx, rax, cmp_reg64_reg64 - dq cc_above_equal, al, set_reg8_cc - dq lit, 0x01, rax, and_reg64_imm8 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "le_unsigned". - dq litstring, "<=unsigned", early_create - dq early_self_codeword, early_here, fetch - dq rax, pop_reg64 - dq rbx, pop_reg64 - dq rbx, rax, cmp_reg64_reg64 - dq cc_below_equal, al, set_reg8_cc - dq lit, 0x01, rax, and_reg64_imm8 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - dq litstring, "&", early_create, early_self_codeword, early_here, fetch - dq rbx, pop_reg64 - dq rax, pop_reg64 - dq rbx, rax, and_reg64_reg64 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - dq litstring, "|", early_create, early_self_codeword, early_here, fetch - dq rbx, pop_reg64 - dq rax, pop_reg64 - dq rbx, rax, or_reg64_reg64 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - dq litstring, "xor", early_create, early_self_codeword, early_here, fetch - dq rbx, pop_reg64 - dq rax, pop_reg64 - dq rbx, rax, xor_reg64_reg64 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - dq litstring, "invert", early_create, early_self_codeword, early_here, fetch - dq rax, pop_reg64 - dq rax, not_reg64 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - dq litstring, "lit", early_create, early_self_codeword, early_here, fetch - dq lods64 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - dq litstring, "litstring", early_create, early_self_codeword - dq early_here, fetch - dq rsi, push_reg64 - dq rsi, rdi, mov_reg64_reg64 - dq rax, rax, xor_reg64_reg64 - dq rcx, rcx, xor_reg64_reg64 - dq rcx, not_reg64 - dq repnz_scas8 - dq rdi, rsi, mov_reg64_reg64 - dq lit, 7, rsi, add_reg64_imm8 - dq lit, 0xF8, rsi, and_reg64_imm8 - dq pack_next, lit, 8, packalign, early_here_store - - ; This is "store", but since we're finally in Forth we're no longer limited - ; by flatassembler's syntax, so we call it by its usual Forth name. - dq litstring, "!", early_create, early_self_codeword, early_here, fetch - dq rbx, pop_reg64 - dq rax, pop_reg64 - dq rax, rbx, mov_indirect_reg64_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This is "fetch". - dq litstring, "@", early_create, early_self_codeword, early_here, fetch - dq rax, pop_reg64 - dq rax, rax, mov_reg64_indirect_reg64 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This is "addstore". - dq litstring, "+!", early_create, early_self_codeword, early_here, fetch - dq rbx, pop_reg64 - dq rax, pop_reg64 - dq rax, rbx, add_indirect_reg64_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This is "substore". - dq litstring, "-!", early_create, early_self_codeword, early_here, fetch - dq rbx, pop_reg64 - dq rax, pop_reg64 - dq rax, rbx, sub_indirect_reg64_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "store8". Jonesforth calls it "c!" but we categorically reject - ; the use of letters that are meant to indicate byte sizes. It's unfriendly - ; to newcomers. There's some risk that this name will be confused for - ; meaning "store a value of 8", but that would not be a useful task, so - ; hopefully it'll be okay. - dq litstring, "8!", early_create, early_self_codeword, early_here, fetch - dq rbx, pop_reg64 - dq rax, pop_reg64 - dq al, rbx, mov_indirect_reg64_reg8 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "fetch8". - dq litstring, "8@", early_create, early_self_codeword, early_here, fetch - dq rbx, pop_reg64 - dq rax, rax, xor_reg64_reg64 - dq rbx, al, mov_reg8_indirect_reg64 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "store16". - dq litstring, "16!", early_create, early_self_codeword, early_here, fetch - dq rbx, pop_reg64 - dq rax, pop_reg64 - dq ax, rbx, mov_indirect_reg64_reg16 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "fetch16". - dq litstring, "16@", early_create, early_self_codeword, early_here, fetch - dq rbx, pop_reg64 - dq rax, rax, xor_reg64_reg64 - dq rbx, ax, mov_reg16_indirect_reg64 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "store32". - dq litstring, "32!", early_create, early_self_codeword, early_here, fetch - dq rbx, pop_reg64 - dq rax, pop_reg64 - dq eax, rbx, mov_indirect_reg64_reg32 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "fetch32". - dq litstring, "32@", early_create, early_self_codeword, early_here, fetch - dq rbx, pop_reg64 - dq rax, rax, xor_reg64_reg64 - dq rbx, eax, mov_reg32_indirect_reg64 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "store_control_stack". Jonesforth calls it RSP!, which looks as - ; if it's meant to be an Intel register name but is actually short for - ; return stack pointer. There is no register by that name, it's a - ; Forth-provided abstraction. That's super confusing, plus as discussed - ; above we call it the control stack not the return stack, so we call it... - dq litstring, "control!", 0, early_create, early_self_codeword - dq early_here, fetch - dq rbp, pop_reg64 - dq pack_next, lit, 8, packalign, early_here_store - ; This was "fetch_control_stack". - dq litstring, "control@", 0, early_create, early_self_codeword - dq early_here, fetch - dq rbp, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - ; This was "store_value_stack". Jonesforth calls it DSP!, for data stack - ; pointer. Again, there's no Intel register by that name, and we call it the - ; value stack, so... - dq litstring, "value!", early_create, early_self_codeword - dq early_here, fetch - dq rsp, pop_reg64 - dq pack_next, lit, 8, packalign, early_here_store - ; This was "fetch_value_stack". - dq litstring, "value@", early_create, early_self_codeword - dq early_here, fetch - dq rsp, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - dq litstring, "memcopy", early_create, early_self_codeword - dq early_here, fetch - dq rsi, rdx, mov_reg64_reg64 - dq rcx, pop_reg64 - dq rdi, pop_reg64 - dq rsi, pop_reg64 - dq rep_movs8 - dq rdx, rsi, mov_reg64_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - dq litstring, "memmove", early_create, early_self_codeword - dq early_here, fetch - dq rsi, rdx, mov_reg64_reg64 - dq rcx, pop_reg64 - dq rdi, pop_reg64 - dq rsi, pop_reg64 - dq rsi, rax, mov_reg64_reg64 - dq rdi, rax, cmp_reg64_reg64 - dq lit, 4, cc_below, jmp_cc_rel_imm8 - dq rep_movs8 - dq lit, 16, jmp_rel_imm8 - dq rcx, rsi, add_reg64_reg64 - dq rsi, dec_reg64 - dq rcx, rdi, add_reg64_reg64 - dq rdi, dec_reg64 - dq std - dq rep_movs8 - dq cld - dq rdx, rsi, mov_reg64_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - dq litstring, "stringlen", early_create, early_self_codeword - dq early_here, fetch - dq rdi, pop_reg64 - dq rdi, rbx, mov_reg64_reg64 - dq rax, rax, xor_reg64_reg64 - dq rcx, rcx, xor_reg64_reg64 - dq rcx, not_reg64 - dq repnz_scas8 - dq rbx, rdi, sub_reg64_reg64 - dq lit, 1, rdi, sub_reg64_imm8 - dq rdi, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "reverse_stringlen". - dq litstring, "reverse-stringlen", early_create, early_self_codeword - dq early_here, fetch - dq rdi, pop_reg64 - dq rdi, rbx, mov_reg64_reg64 - dq rax, rax, xor_reg64_reg64 - dq rcx, rcx, xor_reg64_reg64 - dq rcx, not_reg64 - dq std - dq repnz_scas8 - dq cld - dq rdi, rbx, sub_reg64_reg64 - dq lit, 1, rbx, sub_reg64_imm8 - dq rbx, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "reverse_padding_len". - dq litstring, "reverse-padding-len", early_create, early_self_codeword - dq early_here, fetch - dq rdi, pop_reg64 - dq rdi, rbx, mov_reg64_reg64 - dq rax, rax, xor_reg64_reg64 - dq lit, 9, rcx, mov_reg64_imm32 - dq std - dq repz_scas8 - dq cld - dq rdi, rbx, sub_reg64_reg64 - dq lit, 1, rbx, sub_reg64_imm8 - dq rbx, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - dq litstring, "stringcmp", early_create, early_self_codeword - dq early_here, fetch - dq rsi, rdx, mov_reg64_reg64 - dq rsi, pop_reg64 - dq rdi, pop_reg64 - dq rbx, rbx, xor_reg64_reg64 - dq rax, rax, xor_reg64_reg64 - dq rsi, rcx, mov_reg64_indirect_reg64 - dq cl, al, mov_reg8_reg8 - dq cmps8 - dq lit, 15, cc_equal, jmp_cc_rel_imm8 - dq cc_above, bl, set_reg8_cc - dq lit, 0, rbx, sbb_reg64_imm8 - dq rbx, push_reg64 - dq rdx, rsi, mov_reg64_reg64 - dq pack_next - dq rax, rax, test_reg64_reg64 - dq lit, -28, cc_not_equal, jmp_cc_rel_imm8 - dq lit, 0, push_imm32_extended64 - dq rdx, rsi, mov_reg64_reg64 - dq pack_next - dq lit, 8, packalign, early_here_store - - dq litstring, "branch", early_create, early_self_codeword, early_here, fetch - ; Save the address we're packing to; it will be the label we jump to from - ; zbranch. - dq dup, unroll3 - dq rsi, rsi, add_reg64_indirect_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "zbranch". - dq litstring, "0branch", early_create, early_self_codeword - dq early_here, fetch - dq rax, pop_reg64 - dq rax, rax, test_reg64_reg64 - ; Retrieve the saved address for the start of "branch". Compute the - ; relative offset from the current address to it. This will be a negative - ; number. Subtract an additional two bytes, to allow for the length of the - ; jmp instruction. - dq dup, lit, 4, roll, swap, sub, lit, 2, sub - ; It's slightly counterintuitive that the condition is called cc_equal; - ; that's a result of the condition names favoring cmp over test. While cmp - ; simulates subtraction, test simulates bitwise AND. What we're testing is - ; that the result is zero. - dq cc_equal, jmp_cc_rel_imm8 - dq lods64 - dq pack_next, lit, 8, packalign, early_here_store - - dq litstring, "execute", early_create, early_self_codeword - dq early_here, fetch - dq rax, pop_reg64 - dq rax, jmp_abs_indirect_reg64 - dq lit, 8, packalign, early_here_store - - ; This was "sys_exit". - ; - ; This name is exactly eight bytes long. Don't even ask (go read litstring's - ; code if you really need to know). - dq litstring, "sys-exit", 0, early_create, early_self_codeword - dq early_here, fetch - dq lit, 60, rax, mov_reg64_imm64 - dq rdi, pop_reg64 - dq syscall - dq hlt - ; This one, uniquely, doesn't need to be followed by the "next" macro. It - ; still needs alignment padding though. - dq lit, 8, packalign, early_here_store - - ; This was "sys_write". - dq litstring, "sys-write", early_create, early_self_codeword - dq early_here, fetch - dq rcx, pop_reg64 - dq rdx, pop_reg64 - dq rsi, push_reg64 - dq lit, 1, rax, mov_reg64_imm64 - dq lit, 1, rdi, mov_reg64_imm64 - dq rcx, rsi, mov_reg64_reg64 - dq syscall - dq rsi, pop_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This was "sys_read". - dq litstring, "sys-read", 0, early_create, early_self_codeword - dq early_here, fetch - dq rcx, pop_reg64 - dq rdx, pop_reg64 - dq rsi, push_reg64 - dq lit, 0, rax, mov_reg64_imm64 - dq lit, 0, rdi, mov_reg64_imm64 - dq rcx, rsi, mov_reg64_reg64 - dq syscall - dq rsi, pop_reg64 - dq rax, push_reg64 - dq pack_next, lit, 8, packalign, early_here_store - - ; This one has the honor of being the first word written in Forth. To do - ; that, it needs to be able to look up the words we've defined so far, to - ; reference them. We have a valid dictionary data structure, and early_find - ; is able to search it, so we can do that. - ; - ; One thing to be cautious of is that if we inadvertently reference a word - ; by the wrong name, we'll get the copy that's statically included in the - ; ELF, rather than the copy on the heap. Watch carefully for that, with all - ; the lookups from here on. - dq litstring, "emitstring", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "stringlen", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "sys-write", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "pow", early_create, early_docol_codeword - dq early_here, fetch, lit, 8, packalign, early_here_store - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "-", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "branch", early_find, entry_to_execution_token, early_comma - dq lit, -22*8, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "logfloor", 0, early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "2dup", early_find, entry_to_execution_token, early_comma - dq litstring, ">unsigned", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 6*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "<", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "branch", early_find, entry_to_execution_token, early_comma - dq lit, -45*8, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "logceil", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "2dup", early_find, entry_to_execution_token, early_comma - dq litstring, ">=unsigned", early_find, entry_to_execution_token - dq early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 6*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "<", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "branch", early_find, entry_to_execution_token, early_comma - dq lit, -45*8, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "dotbase_unsigned" - dq litstring, ".base-unsigned", early_create, early_docol_codeword - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "2dup", early_find, entry_to_execution_token, early_comma - dq litstring, "logfloor", 0, early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "2dup", early_find, entry_to_execution_token, early_comma - dq litstring, ">", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "branch", early_find, entry_to_execution_token, early_comma - dq lit, 2*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "2dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "-", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 6, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "pow", early_find, entry_to_execution_token, early_comma - dq litstring, "/%", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "/%", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 10, early_comma - dq litstring, ">", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "0", early_comma - dq litstring, "branch", early_find, entry_to_execution_token, early_comma - dq lit, 6*8, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 10, early_comma - dq litstring, "-", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "a", early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "value@", early_find, entry_to_execution_token, early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "-", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 3*8, early_comma - dq litstring, "branch", early_find, entry_to_execution_token, early_comma - dq lit, -51*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "dotbase". - dq litstring, ".base", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, ">", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 7*8, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, -1, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "-", early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, ".base-unsigned", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "dot". - dq litstring, ".", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 10, early_comma - dq litstring, ".base", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "dothex". - dq litstring, ".hex", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 16, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, ".base-unsigned", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "dothex8". - dq litstring, ".hex8", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 16, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 2, early_comma - dq litstring, ".base-unsigned", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "dothex16". - dq litstring, ".hex16", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 16, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, ".base-unsigned", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "dothex32". - dq litstring, ".hex32", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 16, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, ".base-unsigned", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "dothex64". - dq litstring, ".hex64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 16, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 16, early_comma - dq litstring, ".base-unsigned", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "crash", early_create, early_self_codeword, early_here, fetch - dq hlt - dq lit, 8, packalign, early_here_store - - ; This was "align_size". - dq litstring, "align-size", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "-", early_find, entry_to_execution_token, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "/%", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; We could in theory call this 64pack, by analogy to 32! and so on, but it's - ; kept like this to be more similar to reg64, imm64 etc. - ; - ; Also, unlike with ! we specify the size even for the 64-bit version, - ; because the user of pack64 and its variants is always doing something - ; where exact byte sizes are crucial. - dq litstring, "pack64", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "pack32", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "32!", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "pack16", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "16!", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 2, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "pack8", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "8!", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "packstring", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "stringlen", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "memcopy", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "pack_raw_string". - dq litstring, "pack-raw-string", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "stringlen", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "memcopy", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "packalign", early_create, early_docol_codeword - dq litstring, "2dup", early_find, entry_to_execution_token, early_comma - dq litstring, "/%", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "branch", early_find, entry_to_execution_token, early_comma - dq lit, -11*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "litpack64", early_create, early_self_codeword - dq early_here, fetch - dq lods64 - dq rax, push_reg64 - ; ("heap", modified "here") - dq swap, litstring, "pack64", early_find, entry_to_execution_token - ; (modified "here", "heap", execution token) - dq swap, unroll3, pack_beforenext - dq lit, 8, packalign, early_here_store - - dq litstring, "litpack32", early_create, early_self_codeword - dq early_here, fetch - dq lods64 - dq rax, push_reg64 - ; ("heap", modified "here") - dq swap, litstring, "pack32", early_find, entry_to_execution_token - ; (modified "here", "heap", execution token) - dq swap, unroll3, pack_beforenext - dq lit, 8, packalign, early_here_store - - dq litstring, "litpack16", early_create, early_self_codeword - dq early_here, fetch - dq lods64 - dq rax, push_reg64 - ; ("heap", modified "here") - dq swap, litstring, "pack16", early_find, entry_to_execution_token - ; (modified "here", "heap", execution token) - dq swap, unroll3, pack_beforenext - dq lit, 8, packalign, early_here_store - - ; This name is exactly eight bytes long. Don't even ask (go read litstring's - ; code if you really need to know). - dq litstring, "litpack8", 0, early_create, early_self_codeword - dq early_here, fetch - dq lods64 - dq rax, push_reg64 - ; ("heap", modified "here") - dq swap, litstring, "pack8", early_find, entry_to_execution_token - ; (modified "here", "heap", execution token) - dq swap, unroll3, pack_beforenext - dq lit, 8, packalign, early_here_store - - dq litstring, "unpack64", 0, early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "unpack32", 0, early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "32@", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "unpack16", 0, early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "16@", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 2, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "unpack8", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "8@", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "unpackalign", early_create, early_docol_codeword - dq litstring, "align-size", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; The flatassembler names of all these were the same, but without the - ; colons, and with underscores instead of hyphens. - dq litstring, ":rax", early_keyword - dq litstring, ":rcx", early_keyword - dq litstring, ":rdx", early_keyword - dq litstring, ":rbx", early_keyword - dq litstring, ":rsp", early_keyword - dq litstring, ":rbp", early_keyword - dq litstring, ":rsi", early_keyword - dq litstring, ":rdi", early_keyword - dq litstring, ":r8", early_keyword - dq litstring, ":r9", early_keyword - dq litstring, ":r10", early_keyword - dq litstring, ":r11", early_keyword - dq litstring, ":r12", early_keyword - dq litstring, ":r13", early_keyword - dq litstring, ":r14", early_keyword - dq litstring, ":r15", early_keyword - dq litstring, ":eax", early_keyword - dq litstring, ":ecx", early_keyword - dq litstring, ":edx", early_keyword - dq litstring, ":ebx", early_keyword - dq litstring, ":esp", early_keyword - dq litstring, ":ebp", early_keyword - dq litstring, ":esi", early_keyword - dq litstring, ":edi", early_keyword - dq litstring, ":ax", early_keyword - dq litstring, ":cx", early_keyword - dq litstring, ":dx", early_keyword - dq litstring, ":bx", early_keyword - dq litstring, ":sp", early_keyword - dq litstring, ":bp", early_keyword - dq litstring, ":si", early_keyword - dq litstring, ":di", early_keyword - dq litstring, ":al", early_keyword - dq litstring, ":cl", early_keyword - dq litstring, ":dl", early_keyword - dq litstring, ":bl", early_keyword - dq litstring, ":ah", early_keyword - dq litstring, ":ch", early_keyword - dq litstring, ":dh", early_keyword - dq litstring, ":bh", early_keyword - dq litstring, ":cc-overflow", early_keyword - dq litstring, ":cc-no-overflow", early_keyword - dq litstring, ":cc-below", early_keyword - dq litstring, ":cc-above-equal", early_keyword - dq litstring, ":cc-equal", early_keyword - dq litstring, ":cc-not-equal", early_keyword - dq litstring, ":cc-below-equal", early_keyword - dq litstring, ":cc-above", early_keyword - dq litstring, ":cc-sign", 0, early_keyword - dq litstring, ":cc-not-sign", early_keyword - dq litstring, ":cc-even", 0, early_keyword - dq litstring, ":cc-odd", early_keyword - dq litstring, ":cc-less", 0, early_keyword - dq litstring, ":cc-greater-equal", early_keyword - dq litstring, ":cc-less-equal", early_keyword - dq litstring, ":cc-greater", early_keyword - - dq litstring, "reg64", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":rax", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":rcx", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":rdx", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 2, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":rbx", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 3, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":rsp", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":rbp", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":rsi", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 6, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":rdi", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 7, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "Paramete", early_comma, lit, "r to reg", early_comma - dq lit, "64 is no", early_comma, lit, "t a reg6", early_comma - dq lit, "4.", early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "sys-exit", 0, early_find, entry_to_execution_token - dq early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "extrareg64", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":r8", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":r9", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":r10", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 2, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":r11", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 3, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":r12", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":r13", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":r14", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 6, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":r15", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 7, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "Paramete", early_comma, lit, "r to ext", early_comma - dq lit, "rareg64 ", early_comma, lit, "is not a", early_comma - dq lit, "n extrar", early_comma, lit, "eg64.", early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "sys-exit", 0, early_find, entry_to_execution_token - dq early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "reg32", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":eax", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":ecx", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":edx", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 2, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":ebx", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 3, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":esp", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":ebp", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":esi", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 6, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":edi", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 7, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "Paramete", early_comma, lit, "r to reg", early_comma - dq lit, "32 is no", early_comma, lit, "t a reg3", early_comma - dq lit, "2.", early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "sys-exit", 0, early_find, entry_to_execution_token - dq early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "reg16", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":ax", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":cx", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":dx", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 2, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":bx", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 3, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":sp", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":bp", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":si", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 6, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":di", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 7, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "Paramete", early_comma, lit, "r to reg", early_comma - dq lit, "16 is no", early_comma, lit, "t a reg1", early_comma - dq lit, "6.", early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "sys-exit", 0, early_find, entry_to_execution_token - dq early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "reg8", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":al", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":cl", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":dl", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 2, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":bl", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 3, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":ah", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":ch", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":dh", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 6, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":bh", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 7, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "Paramete", early_comma, lit, "r to reg", early_comma - dq lit, "8 is not", early_comma, lit, " a reg8.", early_comma - dq lit, 0, early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "sys-exit", 0, early_find, entry_to_execution_token - dq early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "scalefield", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 2, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 2, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 3, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "Paramete", early_comma, lit, "r to sca", early_comma - dq lit, "lefield ", early_comma, lit, "is not 1", early_comma - dq lit, ", 2, 4, ", early_comma, lit, "or 8.", early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "sys-exit", 0, early_find, entry_to_execution_token - dq early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "conditioncode", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":cc-overflow", early_find, entry_to_execution_token - dq early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":cc-no-overflow", early_find, entry_to_execution_token - dq early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":cc-below", early_find, entry_to_execution_token - dq early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 2, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":cc-above-equal", early_find, entry_to_execution_token - dq early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 3, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":cc-equal", early_find, entry_to_execution_token - dq early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":cc-not-equal", early_find, entry_to_execution_token - dq early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":cc-below-equal", early_find, entry_to_execution_token - dq early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 6, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":cc-above", early_find, entry_to_execution_token - dq early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 7, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":cc-sign", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":cc-not-sign", early_find, entry_to_execution_token - dq early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 9, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":cc-even", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 10, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":cc-odd", early_find, entry_to_execution_token - dq early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 11, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":cc-less", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 12, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":cc-greater-equal", early_find, entry_to_execution_token - dq early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 13, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":cc-less-equal", early_find, entry_to_execution_token - dq early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 14, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":cc-greater", early_find, entry_to_execution_token - dq early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 15, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "Paramete", early_comma, lit, "r to con", early_comma - dq lit, "ditionco", early_comma, lit, "de is no", early_comma - dq lit, "t a cond", early_comma, lit, "ition co", early_comma - dq lit, "de.", early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "sys-exit", 0, early_find, entry_to_execution_token - dq early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "rex_w". - dq litstring, "rex-w", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x48, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "rex_b". - dq litstring, "rex-b", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x41, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "rex_wb". - dq litstring, "rex-wb", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x49, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "opcodereg", early_create, early_docol_codeword - dq litstring, "|", early_find, entry_to_execution_token, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "opcodecc", 0, early_create, early_docol_codeword - dq litstring, "|", early_find, entry_to_execution_token, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "modrm", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "|", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 64, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "|", early_find, entry_to_execution_token, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "sib", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "|", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 64, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "|", early_find, entry_to_execution_token, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "addressing_reg64". - dq litstring, "addressing-reg64", 0, early_create, early_docol_codeword - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 3, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "modrm", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "addressing_indirect_reg64". - dq litstring, "addressing-indirect-reg64", early_create - dq early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":rbp", early_find, entry_to_execution_token, early_comma - dq litstring, "!=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 23*8, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":rsp", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "modrm", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, ":rsp", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "sib", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "R/M para", early_comma, lit, "meter to", early_comma - dq lit, " address", early_comma, lit, "ing-indi", early_comma - dq lit, "rect-reg", early_comma, lit, "64 is :r", early_comma - dq lit, "bp.", early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "sys-exit", 0, early_find, entry_to_execution_token - dq early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "addressing_disp8_reg64". - dq litstring, "addressing-disp8-reg64", early_create - dq early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":rsp", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "modrm", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, ":rsp", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "sib", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "addressing_disp32_reg64". - dq litstring, "addressing-disp32-reg64", early_create - dq early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":rsp", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 2, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "modrm", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, ":rsp", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "sib", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "pack32", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "addressing_indexed_reg64". - dq litstring, "addressing-indexed-reg64", 0, early_create - dq early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, ":rbp", early_find, entry_to_execution_token, early_comma - dq litstring, "!=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 23*8, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 6, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "modrm", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "scalefield", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "sib", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "Base par", early_comma, lit, "ameter t", early_comma - dq lit, "o addres", early_comma, lit, "sing-ind", early_comma - dq lit, "exed-reg", early_comma, lit, "64 is :r", early_comma - dq lit, "bp.", early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "sys-exit", 0, early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "addressing_disp8_indexed_reg64". - dq litstring, "addressing-disp8-indexed-reg64", early_create - dq early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 6, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 7, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "modrm", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "scalefield", early_find, entry_to_execution_token - dq early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "sib", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "addressing_reg8". - dq litstring, "addressing-reg8", early_create, early_docol_codeword - dq litstring, "reg8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 3, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "modrm", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "cld", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xFC, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "std", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xFD, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_reg64_imm32". - dq litstring, "mov-reg64-imm32", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xC7, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "pack32", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_reg64_imm64". - dq litstring, "mov-reg64-imm64", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xB8, early_comma - dq litstring, "opcodereg", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "pack64", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_extrareg64_imm64". - dq litstring, "mov-extrareg64-imm64", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-wb", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "extrareg64", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xB8, early_comma - dq litstring, "opcodereg", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "pack64", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_reg64_reg64". - dq litstring, "mov-reg64-reg64", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x89, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_indirect_reg64_reg64". - dq litstring, "mov-indirect-reg64-reg64", 0, early_create - dq early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x89, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-indirect-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_disp8_reg64_reg64". - dq litstring, "mov-disp8-reg64-reg64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x89, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-disp8-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_reg64_indirect_reg64". - dq litstring, "mov-reg64-indirect-reg64", 0, early_create - dq early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x8B, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-indirect-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_reg64_disp8_reg64". - dq litstring, "mov-reg64-disp8-reg64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x8B, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-disp8-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_reg64_disp32_reg64". - dq litstring, "mov-reg64-disp32-reg64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x89, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-disp32-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_reg64_indexed_reg64". - dq litstring, "mov-reg64-indexed-reg64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x8B, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-indexed-reg64", 0, early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_indexed_reg64_reg64". - dq litstring, "mov-indexed-reg64-reg64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x89, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-indexed-reg64", 0, early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_indirect_reg64_reg32". - dq litstring, "mov-indirect-reg64-reg32", 0, early_create - dq early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x89, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "reg32", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-indirect-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_indirect_reg64_reg32". - dq litstring, "mov-disp8-reg64-reg32", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x89, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg32", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-disp8-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ;; This was "mov_reg32_indirect_reg64". - dq litstring, "mov-reg32-indirect-reg64", 0, early_create - dq early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x8B, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg32", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-indirect-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_reg32_disp8_reg64". - dq litstring, "mov-reg32-disp8-reg64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x8B, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg32", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-disp8-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_indirect_reg64_reg16". - dq litstring, "mov-indirect-reg64-reg16", 0, early_create - dq early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x66, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x89, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "reg16", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-indirect-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_disp8_reg64_reg16". - dq litstring, "mov-disp8-reg64-reg16", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x66, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x89, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg16", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-disp8-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_reg16_indirect_reg64". - dq litstring, "mov-reg16-indirect-reg64", 0, early_create - dq early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x66, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x8B, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg16", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-indirect-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_reg16_disp8_reg64". - dq litstring, "mov-reg16-disp8-reg64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x66, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x8B, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg16", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-disp8-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_indirect_reg64_reg8". - dq litstring, "mov-indirect-reg64-reg8", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x88, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "reg8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-indirect-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_disp8_reg64_reg8". - dq litstring, "mov-disp8-reg64-reg8", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x88, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-disp8-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_reg8_indirect_reg64". - dq litstring, "mov-reg8-indirect-reg64", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x8A, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-indirect-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_reg8_disp8_reg64". - dq litstring, "mov-reg8-disp8-reg64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x8A, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-disp8-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mov_reg8_reg8". - dq litstring, "mov-reg8-reg8", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x88, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "reg8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg8", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "lea_reg64_disp8_reg64". - dq litstring, "lea-reg64-disp8-reg64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x8D, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-disp8-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "lea_reg64_disp32_reg64". - dq litstring, "lea-reg64-disp32-reg64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x8D, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-disp32-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "lea_reg64_indexed_reg64". - dq litstring, "lea-reg64-indexed-reg64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x8D, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-indexed-reg64", 0, early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "lea_reg64_disp8_indexed_reg64". - dq litstring, "lea-reg64-disp8-indexed-reg64", early_create - dq early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 6, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x8D, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 6, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 3, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 3, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-disp8-indexed-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "push_reg64". - dq litstring, "push-reg64", early_create, early_docol_codeword - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x50, early_comma - dq litstring, "opcodereg", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "push_extrareg64". - dq litstring, "push-extrareg64", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-b", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "extrareg64", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x50, early_comma - dq litstring, "opcodereg", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "pop_reg64". - dq litstring, "pop-reg64", early_create, early_docol_codeword - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x58, early_comma - dq litstring, "opcodereg", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "pop_extrareg64". - dq litstring, "pop-extrareg64", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-b", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "extrareg64", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x58, early_comma - dq litstring, "opcodereg", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was push_imm32_extended64". - dq litstring, "push-imm32-extended64", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x68, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "pack32", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "movs8", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA4, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "movs16", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x66, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA5, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "movs32", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA5, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "movs64", early_create, early_docol_codeword - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA5, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "rep_movs8". - dq litstring, "rep-movs8", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA4, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "rep_movs16". - dq litstring, "rep-movs16", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x66, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA5, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "rep_movs32". - dq litstring, "rep-movs32", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA5, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "rep_movs64". - dq litstring, "rep-movs64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA5, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - dq litstring, "lods8", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAC, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "lods16", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x66, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAD, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "lods32", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAD, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "lods64", early_create, early_docol_codeword - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAD, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "rep_lods8". - dq litstring, "rep-lods8", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAC, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "rep_lods16". - dq litstring, "rep-lods16", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x66, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAD, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "rep_lods32". - dq litstring, "rep-lods32", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAD, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "rep_lods64". - dq litstring, "rep-lods64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAD, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "stos8", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAA, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "stos16", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x66, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAB, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "stos32", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAB, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "stos64", early_create, early_docol_codeword - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAB, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "rep_stos8". - dq litstring, "rep-stos8", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAA, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "rep_stos16". - dq litstring, "rep-stos16", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x66, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAB, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "rep_stos32". - dq litstring, "rep-stos32", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAB, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "rep_stos64". - dq litstring, "rep-stos64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAB, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "cmps8", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA6, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "cmps16", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x66, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA7, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "cmps32", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA7, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "cmps64", early_create, early_docol_codeword - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA7, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "repz_cmps8". - dq litstring, "repz-cmps8", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA6, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "repz_cmps16". - dq litstring, "repz-cmps16", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x66, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA7, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "repz_cmps32". - dq litstring, "repz-cmps32", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA7, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "repz_cmps64". - dq litstring, "repz-cmps64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA7, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "repnz_cmps8". - dq litstring, "repnz-cmps8", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF2, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA6, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "repnz_cmps16". - dq litstring, "repnz-cmps16", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF2, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x66, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA7, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "repnz_cmps32". - dq litstring, "repnz-cmps32", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF2, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA7, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "repnz_cmps64". - dq litstring, "repnz-cmps64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF2, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xA7, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "scas8", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAE, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "scas16", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x66, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAF, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "scas32", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAF, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "scas64", early_create, early_docol_codeword - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAF, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "repz_scas8". - dq litstring, "repz-scas8", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAE, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "repz_scas16". - dq litstring, "repz-scas16", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x66, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAF, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "repz_scas32". - dq litstring, "repz-scas32", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAF, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "repz_scas64". - dq litstring, "repz-scas64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF3, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAF, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "repnz_scas8". - dq litstring, "repnz-scas8", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF2, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAE, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "repnz_scas16". - dq litstring, "repnz-scas16", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF2, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x66, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAF, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "repnz_scas32". - dq litstring, "repnz-scas32", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF2, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAF, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "repnz_scas64". - dq litstring, "repnz-scas64", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF2, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xAF, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "add_reg64_reg64". - dq litstring, "add-reg64-reg64", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x01, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "add_indirect_reg64_reg64". - dq litstring, "add-indirect-reg64-reg64", 0, early_create - dq early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x01, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-indirect-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "add_reg64_indirect_reg64". - dq litstring, "add-reg64-indirect-reg64", 0, early_create - dq early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x03, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-indirect-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "add_reg64_imm8". - dq litstring, "add-reg64-imm8", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x83, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "sub_reg64_reg64". - dq litstring, "sub-reg64-reg64", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x2B, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "sub_indirect_reg64_reg64". - dq litstring, "sub-indirect-reg64-reg64", 0, early_create - dq early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x2B, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-indirect-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "sub_reg64_imm8". - dq litstring, "sub-reg64-imm8", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x83, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "sbb_reg64_imm8". - dq litstring, "sbb-reg64-imm8", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x83, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 3, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "mul_reg64". - dq litstring, "mul-reg64", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF7, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "divmod_reg64". - dq litstring, "divmod-reg64", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF7, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 6, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "idivmod_reg64". - dq litstring, "idivmod-reg64", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF7, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 7, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "inc_reg64". - dq litstring, "inc-reg64", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xFF, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "dec_reg64". - dq litstring, "dec-reg64", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xFF, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "and_reg64_reg64". - dq litstring, "and-reg64-reg64", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x23, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "and_reg64_imm8". - dq litstring, "and-reg64-imm8", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x83, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "or_reg64_reg64". - dq litstring, "or-reg64-reg64", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x0B, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "or_reg64_imm8". - dq litstring, "or-reg64-imm8", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x83, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "xor_reg64_reg64". - dq litstring, "xor-reg64-reg64", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x33, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "not_reg64". - dq litstring, "not-reg64", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF7, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 2, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "cmp_reg64_reg64". - dq litstring, "cmp-reg64-reg64", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x3B, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "test_reg64_reg64". - dq litstring, "test-reg64-reg64", 0, early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "rex-w", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x85, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "reg64", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-reg64", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "set_reg8_cc". - dq litstring, "set-reg8-cc", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x0F, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "conditioncode", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x90, early_comma - dq litstring, "opcodecc", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "reg8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 3, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "modrm", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "jmp_cc_rel_imm8". - dq litstring, "jmp-cc-rel-imm8", early_create, early_docol_codeword - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "conditioncode", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x70, early_comma - dq litstring, "opcodecc", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "jmp_cc_rel_imm32". - dq litstring, "jmp-cc-rel-imm32", 0, early_create, early_docol_codeword - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x0F, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "conditioncode", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x70, early_comma - dq litstring, "opcodecc", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "pack32", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "jmp_abs_indirect_reg64". - dq litstring, "jmp-abs-indirect-reg64", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xFF, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "addressing-indirect-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "jmp_rel_imm8". - dq litstring, "jmp-rel-imm8", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xEB, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "jmp_rel_imm32". - dq litstring, "jmp-rel-imm32", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xE9, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "pack32", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "syscall", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x0F, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x05, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "hlt", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xF4, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "pack_next". - dq litstring, "pack-next", early_create, early_docol_codeword - dq litstring, "lods64", early_find, entry_to_execution_token, early_comma - dq litstring, ":rax", early_find, entry_to_execution_token, early_comma - dq litstring, "jmp-abs-indirect-reg64", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "pack_beforenext". - dq litstring, "pack-beforenext", early_create, early_docol_codeword - dq litstring, ":rax", early_find, entry_to_execution_token, early_comma - dq litstring, "mov-reg64-imm64", early_find, entry_to_execution_token - dq early_comma - dq litstring, ":rax", early_find, entry_to_execution_token, early_comma - dq litstring, "jmp-abs-indirect-reg64", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "pack_pushcontrol". - dq litstring, "pack-pushcontrol", 0, early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, ":rbp", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, -8, early_comma - dq litstring, ":rbp", early_find, entry_to_execution_token, early_comma - dq litstring, "lea-reg64-disp8-reg64", early_find, entry_to_execution_token - dq early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, ":rbp", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "mov-disp8-reg64-reg64", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "pack_popcontrol". - dq litstring, "pack-popcontrol", early_create, early_docol_codeword - dq litstring, ":rbp", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "mov-reg64-disp8-reg64", early_find, entry_to_execution_token - dq early_comma - dq litstring, ":rbp", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, ":rbp", early_find, entry_to_execution_token, early_comma - dq litstring, "lea-reg64-disp8-reg64", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "entry_to_execution_token". - dq litstring, "entry-to-execution-token", 0, early_create - dq early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 10, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "stringlen", early_find, entry_to_execution_token, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 7, early_comma - dq litstring, "invert", early_find, entry_to_execution_token, early_comma - dq litstring, "&", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "execution_token_to_entry". - dq litstring, "execution-token-to-entry", 0, early_create - dq early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "-", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "reverse-padding-len", early_find, entry_to_execution_token - dq early_comma - dq litstring, "-", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "reverse-stringlen", early_find, entry_to_execution_token - dq early_comma - dq litstring, "-", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 9, early_comma - dq litstring, "-", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "fetch_entry_flags". - dq litstring, "entry-flags@", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xFF, early_comma - dq litstring, "&", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "store_entry_flags". - dq litstring, "entry-flags!", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xFF, early_comma - dq litstring, "&", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xFFFFFFFFFFFFFF00, early_comma - dq litstring, "&", early_find, entry_to_execution_token, early_comma - dq litstring, "|", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "entry_to_name". - dq litstring, "entry-to-name", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 10, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "find_in". - dq litstring, "find-in", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 4*8, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "entry-flags@", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x80, early_comma - dq litstring, "&", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x80, early_comma - dq litstring, "!=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma - dq litstring, "2dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 10, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "stringcmp", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 4*8, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "branch", early_find, entry_to_execution_token, early_comma - dq lit, -28*8, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "next_newer_entry_in". - dq litstring, "next-newer-entry-in", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 4*8, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "2dup", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "!=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 4*8, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "branch", early_find, entry_to_execution_token, early_comma - dq lit, -16*8, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "guess_entry_end_in". - dq litstring, "guess-entry-end-in", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "entry-flags@", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x01, early_comma - dq litstring, "&", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x01, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 6*8, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "next-newer-entry-in", early_find, entry_to_execution_token - dq early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 4*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "show_hex_between". - dq litstring, "show-hex-between", 0, early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "entry-to-execution-token", 0, early_find - dq entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "2dup", early_find, entry_to_execution_token, early_comma - dq litstring, ">=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 4*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, " ", early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, ".hex64", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "branch", early_find, entry_to_execution_token, early_comma - dq lit, -17*8, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "show_source_between". - dq litstring, "show-source-between", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "entry-to-execution-token", 0, early_find - dq entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "2dup", early_find, entry_to_execution_token, early_comma - dq litstring, ">=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 4*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "execution-token-to-entry", 0, early_find - dq entry_to_execution_token, early_comma - dq litstring, "entry-to-name", early_find, entry_to_execution_token - dq early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, " ", early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "lit", early_comma - dq litstring, "stringcmp", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 57*8, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "litpack8", early_comma, lit, 0, early_comma - dq litstring, "stringcmp", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 50*8, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "litpack1", early_comma, lit, "6", early_comma - dq litstring, "stringcmp", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 43*8, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "litpack3", early_comma, lit, "2", early_comma - dq litstring, "stringcmp", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 36*8, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "litpack6", early_comma, lit, "4", early_comma - dq litstring, "stringcmp", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 29*8, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "branch", early_comma - dq litstring, "stringcmp", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 23*8, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "zbranch", early_comma - dq litstring, "stringcmp", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 17*8, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "0branch", early_comma - dq litstring, "stringcmp", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 11*8, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "litstrin", early_comma, lit, "g", early_comma - dq litstring, "stringcmp", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 16*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "branch", early_find, entry_to_execution_token, early_comma - dq lit, -82*8, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, " ", early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, ".", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "branch", early_find, entry_to_execution_token, early_comma - dq lit, -94*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, " ", early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x22, early_comma - dq litstring, "value@", early_find, entry_to_execution_token, early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x22, early_comma - dq litstring, "value@", early_find, entry_to_execution_token, early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "stringlen", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "/%", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "branch", early_find, entry_to_execution_token, early_comma - dq lit, -126*8, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; This was "show_source_or_hex_between". - dq litstring, "show-source-or-hex-between", early_create - dq early_docol_codeword - dq litstring, "2dup", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 2*8, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "entry-to-execution-token", 0, early_find - dq entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "-", early_find, entry_to_execution_token, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 3*8, early_comma - dq litstring, "show-hex-between", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "show-source-between", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ;;; Now here we have some "original" words that rely on the heap and don't - ;;; have flatassembler-based equivalents. - - ; This has the distinction of having been written in Evocation, in - ; interpret.e, and then back-ported to flatassembler. This is the version - ; that makes clever use of memmove, if we do say so ourselves, to handle - ; immediate-mode string literals as input. - ; - ; In: - ; name string - dq litstring, "create", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "stringlen", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "here", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 10, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "memmove", early_find, entry_to_execution_token, early_comma - dq litstring, "here", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "latest", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "pack64", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "pack8", early_find, entry_to_execution_token, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "packalign", early_find, entry_to_execution_token, early_comma - dq litstring, "here", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "latest", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "here", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; In: - ; value to append to current word-in-progress - dq litstring, ",", early_create, early_docol_codeword - dq litstring, "here", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "pack64", early_find, entry_to_execution_token, early_comma - dq litstring, "here", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "self-codeword", early_create, early_docol_codeword - dq litstring, "here", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, ",", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; In: - ; address for new variable word to return - ; name string - dq litstring, "variable", 0, early_create, early_docol_codeword - dq litstring, "create", early_find, entry_to_execution_token, early_comma - dq litstring, "self-codeword", early_find, entry_to_execution_token - dq early_comma - dq litstring, "here", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, ":rax", early_find, entry_to_execution_token, early_comma - dq litstring, "mov-reg64-imm64", early_find, entry_to_execution_token - dq early_comma - dq litstring, ":rax", early_find, entry_to_execution_token, early_comma - dq litstring, "push-reg64", early_find, entry_to_execution_token - dq early_comma - dq litstring, "pack-next", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "packalign", early_find, entry_to_execution_token, early_comma - dq litstring, "here", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; Allocates bytes on the heap by incrementing the global "here" pointer. - ; The "here" pointer is kept aligned to an 8-byte boundary, regardless of - ; the size requested. - ; - ; This does not create dictionary entries, it's just a raw memory - ; interface. It's suitable for allocating data or scratch space. - ; - ; In: - ; size in bytes - ; Out: - ; pointer to start - dq litstring, "allocate", 0, early_create, early_docol_codeword - dq litstring, "here", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - ; (size, here value, here value) - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "packalign", early_find, entry_to_execution_token, early_comma - dq litstring, "here", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; Takes a string pointer which must be equal to the current value of - ; "here", ; indicating it is in the temporary allocation space, and - ; allocates it permanently by advancing "here" to the next aligned address - ; after it. - ; - ; In: - ; string pointer - ; Out: - ; string pointer - dq litstring, "allocate-string", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "stringlen", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "packalign", early_find, entry_to_execution_token, early_comma - dq litstring, "here", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; In: - ; pointer to buffer metadata - ; Out: - ; pointer to buffer "physical-start" field - dq litstring, "buffer-physical-start", early_create, early_docol_codeword - ; The physical-start field happens to be the first thing in the metadata, so - ; this is an nop, but it still exists as a word because having it reduces - ; confusion. - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; In: - ; pointer to buffer metadata - ; Out: - ; pointer to buffer "physical-length" field - dq litstring, "buffer-physical-length", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; In: - ; pointer to buffer metadata - ; Out: - ; pointer to buffer "logical-start" field - dq litstring, "buffer-logical-start", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 2*8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; In: - ; pointer to buffer metadata - ; Out: - ; pointer to buffer "logical-length" field - dq litstring, "buffer-logical-length", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 3*8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; In: - ; pointer to input buffer metadata - ; Out: - ; pointer to input buffer "refill" field - dq litstring, "input-buffer-refill", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4*8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; In: - ; pointer to input buffer metadata - ; Out: - ; pointer to input buffer "next-source" field - dq litstring, "input-buffer-next-source", 0, early_create - dq early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; Given an initialized buffer (input or otherwise), sets its logical-start - ; and logical-length fields to indicate the buffer is empty. This relies on - ; the buffer having a backing store attached, but does not alter the backing - ; store or its contents. - ; - ; In: - ; pointer to buffer metadata - dq litstring, "clear-buffer", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-physical-start", early_find, entry_to_execution_token - dq early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - ; (address of backing store, metadata pointer) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - ; (metadata pointer, address of backing store, metadata pointer) - dq litstring, "buffer-logical-start", early_find, entry_to_execution_token - dq early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-logical-length", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; Sets all fields in an input buffer metadata structure to zero, - ; effectively detaching and leaking any backing store that had been attached - ; to it. Suitable for use during initialization. - ; - ; In: - ; pointer to input buffer metadata - dq litstring, "zero-input-buffer-metadata", early_create - dq early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-physical-start", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-physical-length", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-logical-start", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-logical-length", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "input-buffer-refill", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - ; Notice the absence of a dup this time. - dq litstring, "input-buffer-next-source", 0, early_find - dq entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; Allocates buffer metadata, with no backing store attached. Initializes - ; the metadata to all zeroes. - ; - ; Out: - ; pointer to buffer metadata - dq litstring, "allocate-input-buffer-metadata", early_create - dq early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 6*8, early_comma - dq litstring, "allocate", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "zero-input-buffer-metadata", early_find - dq entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; Allocates input buffer metadata and a backing store, in one operation. - ; Points the metadata to the backing store. - ; - ; In: - ; buffer capacity in bytes - ; Out: - ; pointer to buffer metadata - dq litstring, "allocate-input-buffer", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 6*8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "allocate", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "zero-input-buffer-metadata", early_find - dq entry_to_execution_token, early_comma - ; (capacity in bytes, metadata pointer) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 6*8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - ; (capacity in bytes, metadata pointer, metadata pointer, physical start) - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-physical-start", early_find, entry_to_execution_token - dq early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - ; (capacity in bytes, metadata pointer) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-physical-length", early_find, entry_to_execution_token - dq early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - ; (metadata pointer) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "clear-buffer", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; Sets the backing store of an input buffer to point at a null-teriminated - ; string and read from it. - ; - ; In: - ; pointer to buffer metadata - ; pointer to string - dq litstring, "attach-string-to-input-buffer", early_create - dq early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - ; (string pointer, metadata pointer) - dq litstring, "2dup", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-physical-start", early_find, entry_to_execution_token - dq early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - ; (string pointer, metadata pointer) - dq litstring, "2dup", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-logical-start", early_find, entry_to_execution_token - dq early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - ; (string pointer, metadata pointer) - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "stringlen", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - ; (string length, metadata pointer) - dq litstring, "2dup", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-physical-length", early_find, entry_to_execution_token - dq early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - ; (string length, metadata pointer) - dq litstring, "buffer-logical-length", early_find, entry_to_execution_token - dq early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ;;; Here we have some imperative code that runs immediately, to initialize - ;;; some runtime data structures. - - ; First, we insert a metadata word header to delimit the space. Otherwise - ; "describe" would crash when attempting to describe - ; "attach-string-to-input-buffer". - ; (heap pointer) - dq litstring, "main-input-buffer-metadata", early_create - dq litstring, "main-input-buffer-metadata", early_find - dq lit, 1, store_entry_flags - - ; Having done that, now we do the runtime allocation. - ; (heap pointer) - dq litstring, "allocate-input-buffer-metadata", early_find - dq entry_to_execution_token, execute - - ; We also initialize the metadata here, pointing it to the boot source as - ; its backing store. We could do that later, but it's convenient to do it - ; here. - ; (heap pointer, metadata pointer) - dq swap, litstring, "attach-string-to-input-buffer", early_find - ; (metadata pointer, heap pointer, entry pointer) - dq entry_to_execution_token, swap, unroll3 - ; (heap pointer, metadata pointer, execution token) - dq swap, dup, unroll3 - ; (heap pointer, metadata pointer, execution token, metadata pointer) - dq lit, boot_source, roll3 - ; (heap pointer, metadata pointer, metadata pointer, string pointer, - ; execution token) - dq execute - - ; Finally, we define the named variable "main-input-buffer" so we can find - ; it again. - ; (heap pointer, metadata pointer) - dq swap, litstring, "variable", 0, early_find, entry_to_execution_token - ; (metadata pointer, heap pointer, execution token) - dq swap, unroll3 - ; (heap pointer, metadata pointer, execution token) - dq litstring, "main-input-buffer", swap - ; (heap pointer, metadata pointer, string pointer, execution token) - dq execute - - - ; (metadata pointer) - dq litstring, "consume-from", early_create, early_docol_codeword - - ; If the length is zero, exit without doing anything. - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-logical-length", early_find, entry_to_execution_token - dq early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 2*8, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; Decrement the logical length. We do this now to get it over with, since - ; adjusting the start pointer is more complex. - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-logical-length", early_find, entry_to_execution_token - dq early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "-", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - ; (metadata pointer) - - ; We compute the physical end. We'll need it in adjusting the logical start, - ; and doing it now means less stack juggling later. - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-physical-start", early_find, entry_to_execution_token - dq early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-physical-length", early_find, entry_to_execution_token - dq early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - ; (physical end, metadata pointer) - - ; Compute the incremented logical start. - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-logical-start", early_find, entry_to_execution_token - dq early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - ; (physical end, metadata pointer, updated start pointer) - - ; Check whether the updated start is equal to the physical end. - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - ; (metadata pointer, updated start, updated start, physical end) - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - - ; If the logical start pointer is now equal to the physical end pointer, - ; we want to wrap to the physical start. That's what makes it a circular - ; buffer. - ; (metadata pointer, updated start) - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-physical-start", early_find, entry_to_execution_token - dq early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - - ; However we got here, save the updated logical start pointer. - ; (metadata pointer, updated start) - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-logical-start", early_find, entry_to_execution_token - dq early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - ; (metadata pointer) - dq litstring, "peek-from", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-logical-length", early_find, entry_to_execution_token - dq early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 28*8, early_comma - - ; If the length is zero, there is no input, but we can still try calling - ; the "refill" word. - ; (metadata pointer) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "input-buffer-refill", early_find, entry_to_execution_token - dq early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 17*8, early_comma - - ; If the refill word is nonzero, call it. It expects a copy of the metadata - ; pointer as its parameter, so set that up. - ; (metadata pointer, refill word) - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "execute", early_find, entry_to_execution_token, early_comma - ; (metadata pointer) - ; Now we check if the length is still zero. - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "buffer-logical-length", early_find, entry_to_execution_token - dq early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 10*8, early_comma - - ; The length is zero even after calling the refill word, so return null. - ; (metadata pointer) - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; If the refill word is zero, we can't help, just return null. - ; (metadata pointer, refill word) - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; The buffer is non-empty, so read a byte from it. We might have reached - ; this point either from the original check, or from the second check after - ; calling the refill word. - ; - ; While it might be more extensible to call an "unpack" word here, such as - ; unpack8, we actually just want to get the value, and delegate the pointer - ; adjustments to "consume". - ; - ; (metadata pointer) - dq litstring, "buffer-logical-start", early_find, entry_to_execution_token - dq early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "8@", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - ; (metadata pointer) - dq litstring, "key-from", 0, early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "peek-from", early_find, entry_to_execution_token, early_comma - ; (metadata pointer, result byte) - ; We unconditionally consume, because we have no way to distinguish between - ; reading a zero byte and having nothing left to read. - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "consume-from", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - dq litstring, "is-space", 0, early_create, early_docol_codeword - - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x20, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x09, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x0a, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x0b, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x0c, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x0d, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - dq litstring, "peek", early_create, early_docol_codeword - dq litstring, "main-input-buffer", early_find, entry_to_execution_token - dq early_comma - dq litstring, "peek-from", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "consume", early_create, early_docol_codeword - dq litstring, "main-input-buffer", early_find, entry_to_execution_token - dq early_comma - dq litstring, "consume-from", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "key", early_create, early_docol_codeword - dq litstring, "main-input-buffer", early_find, entry_to_execution_token - dq early_comma - dq litstring, "key-from", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - ;;; As a convenience for "word", we have some facilities for working with - ;;; stack-allocated strings. Yeah, trippy concept. Also, it would be a - ;;; buffer overrun hazard if we were worried about that, which is why this - ;;; is no longer common practice in C. - ;;; - ;;; The most important of these is accumulate-string, but we need some - ;;; smaller pieces first. - - ; In: - ; (multiple words) string - ; (multiple words) items to be left alone - ; item to be unrolled - ; number of items above string that participate in the unroll - ; Out: - ; item that was unrolled - ; (multiple words) string - ; (multiple words) items left alone - dq litstring, "unroll-past-string", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - ; (string, other items, top item, byte offset to string start) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "value@", early_find, entry_to_execution_token, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - ; We have two copies of the offset present, in addition to the stuff we want - ; to rotate. So, the actual string starts two words on... We could have - ; adjusted the offset instead, but we'll want the unmodified offset again - ; later. - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 16, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - ; (string, other items, top item, offset to start, string pointer) - dq litstring, "stringlen", early_find, entry_to_execution_token, early_comma - ; Same reasoning as in accumulate-string (see below). - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "align-size", early_find, entry_to_execution_token, early_comma - ; (string, other items, top item, offset to start, string length w/ padding) - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "/%", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - ; (string, other items, top item, number of words to unroll) - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; In: - ; (multiple words) string - ; item to be swapped - ; Out: - ; item that was swapped - ; (multiple words) string - dq litstring, "swap-past-string", 0, early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "unroll-past-string", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; In: - ; (multiple words) string - dq litstring, "dropstring", early_create, early_docol_codeword - dq litstring, "value@", early_find, entry_to_execution_token, early_comma - dq litstring, "stringlen", early_find, entry_to_execution_token, early_comma - ; Same reasoning as in accumulate-string (see below). - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "align-size", early_find, entry_to_execution_token, early_comma - dq litstring, "value@", early_find, entry_to_execution_token, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - ; At the time we fetched the stack pointer, there was an extra value atop - ; it, so we have to add one more word. - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "value!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; In: - ; (multiple words) string - ; item to be kept - ; Out: - ; item that was kept - dq litstring, "dropstring-with-result", early_create, early_docol_codeword - dq litstring, "swap-past-string", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "dropstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; In: - ; (multiple words) string-so-far - ; new character byte - ; Out: - ; (multiple words) updated string-so-far - dq litstring, "accumulate-string", early_create - dq early_docol_codeword - - ; Compute the address of the final word of the string. - ; - ; It's a little bit difficult to get the start pointer right, since all - ; our intermediate products affect what we get from value@, so we compute - ; that just once, here at the beginning. - dq litstring, "value@", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - ; (string so far, new character byte, pointer to start of string) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "stringlen", early_find, entry_to_execution_token, early_comma - ; There are two concerns here that overlap: First, we always want at least - ; one word. Recall that a length of zero bytes won't receive any alignment - ; padding because it's already divisible by 8. Second, the result of - ; stringlen doesn't include the null byte, which might be in a word by - ; itself that needs to be counted. We can address both of them by - ; unconditionally adding 1 to the length before applying alignment. - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - ; Pad the length for alignment. - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "align-size", early_find, entry_to_execution_token - dq early_comma - ; We want an offset from the first word of the string to the last word of - ; the string, so we subtract one word from the length. - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "-", early_find, entry_to_execution_token, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - ; (string so far, new character byte, address of final word) - - ; Examine the final word of the string, leaving other stuff undisturbed. - ; Work low-to-high to figure out where to store the new byte, taking the - ; first one that's available. - ; (string so far, new character byte, address of final word) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x00000000000000FF, early_comma - dq litstring, "&", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 6*8, early_comma - ; (string so far, new character byte, address of final word, old value) - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "|", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - ; (string so far, new character byte, address of final word, old value) - - ; This next part is repeated several times, changing only the offsets, for - ; bytes 1 through 6; bytes 0 (above) and 7 (way below) are different. - ; (string so far, new character byte, address of final word, old value) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x000000000000FF00, early_comma - dq litstring, "&", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 9*8, early_comma - ; (string so far, new character byte, address of final word, old value) - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x0000000000000100, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "|", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; Highly repetitive code, see above. - ; (string so far, new character byte, address of final word, old value) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x0000000000FF0000, early_comma - dq litstring, "&", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 9*8, early_comma - ; (string so far, new character byte, address of final word, old value) - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x0000000000010000, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "|", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; Highly repetitive code, see above. - ; (string so far, new character byte, address of final word, old value) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x00000000FF000000, early_comma - dq litstring, "&", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 9*8, early_comma - ; (string so far, new character byte, address of final word, old value) - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x0000000001000000, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "|", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; Highly repetitive code, see above. - ; (string so far, new character byte, address of final word, old value) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x000000FF00000000, early_comma - dq litstring, "&", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 9*8, early_comma - ; (string so far, new character byte, address of final word, old value) - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x0000000100000000, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "|", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; Highly repetitive code, see above. - ; (string so far, new character byte, address of final word, old value) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x0000FF0000000000, early_comma - dq litstring, "&", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 9*8, early_comma - ; (string so far, new character byte, address of final word, old value) - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x0000010000000000, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "|", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; Highly repetitive code, see above. - ; (string so far, new character byte, address of final word, old value) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x00FF000000000000, early_comma - dq litstring, "&", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 9*8, early_comma - ; (string so far, new character byte, address of final word, old value) - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x0001000000000000, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "|", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; The top byte of the final word is always zero (or else stringlen - ; wouldn't have called it the final word), so we don't need to check it, we - ; can just use it. - ; - ; We need to put the new value in the top byte, which will mean we have no - ; null terminator, so we also need to start a new word. - ; - ; There is a fiddly order-dependency here: unroll-past-string relies on - ; being able to find the null terminator, which won't work if we've gotten - ; rid of it. Also, calling it will move all the earlier words, including - ; the one we intend to write to, which will invalidate any pointer we're - ; keeping at that point. There's a few ways to resolve this; what we do is - ; put the new terminator in place first, manually nudge the pointer, and - ; then write the new value. - ; (string so far, new character byte, address of final word, old value) - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x0100000000000000, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "|", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - ; (string so far, new value, address of final word) - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 3, early_comma - dq litstring, "unroll-past-string", early_find, entry_to_execution_token - dq early_comma - ; (new null terminator, string so far, new value, invalid address) - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "-", early_find, entry_to_execution_token, early_comma - ; (new null terminator, string so far, new value, updated address) - dq litstring, "!", early_find, entry_to_execution_token, early_comma - ; (updated string) - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - ; Okay, this is the big one, the lexer! Wow. - ; - ; Out: - ; (multiple words) string - dq litstring, "word", early_create, early_docol_codeword - - ; We allocate an empty string first, so that the result of "key" will - ; conveniently be on the easy-to-find end of it. - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - - ; Skip whitespace. - dq litstring, "key", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "is-space", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 4*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "branch", early_find, entry_to_execution_token, early_comma - dq lit, -7*8, early_comma - - ; Early exit if it's a zero byte. - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 6*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "dropstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - dq litstring, "accumulate-string", early_find, entry_to_execution_token - dq early_comma - - dq litstring, "peek", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "is-space", 0, early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - dq litstring, "consume", early_find, entry_to_execution_token, early_comma - dq litstring, "accumulate-string", early_find, entry_to_execution_token - dq early_comma - dq litstring, "branch", early_find, entry_to_execution_token, early_comma - dq lit, -14*8, early_comma - - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - dq litstring, "find", early_create, early_docol_codeword - dq litstring, "latest", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "find-in", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - ; In: - ; character - ; Out: - ; 1 for true, 0 for false - dq litstring, "is-alphanumeric", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "0", early_comma - dq litstring, ">", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - - ; Less than "0". - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "9", early_comma - dq litstring, ">=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - - ; Less than or equal to "9". - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "A", early_comma - dq litstring, ">", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - - ; Less than "A". - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "Z", early_comma - dq litstring, ">=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - - ; Less than or equal to "Z". - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "a", early_comma - dq litstring, ">", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - - ; Less than "a". - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "z", early_comma - dq litstring, ">=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma - - ; Less than or equal to "z". - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; Greater than "z". - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - ; In: - ; character - ; Out: - ; value - dq litstring, "generalized-digit-value", early_create, early_docol_codeword - - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "a", early_comma - dq litstring, "<=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma - - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "a", early_comma - dq litstring, "-", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 10, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "A", early_comma - dq litstring, "<=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma - - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "A", early_comma - dq litstring, "-", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 10, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "0", early_comma - dq litstring, "-", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - ; In: - ; character - ; base - ; Out: - ; value (if successful) - ; error indicator (zero indicates success) - dq litstring, "decode-generalized-digit", 0, early_create - dq early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "is-alphanumeric", early_find, entry_to_execution_token - dq early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 14*8, early_comma - - ; It's alphanumeric. - ; (base, character) - dq litstring, "generalized-digit-value", early_find - dq entry_to_execution_token, early_comma - ; (base, value) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - ; (value, value, base) - dq litstring, ">", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 4*8, early_comma - - ; It's in range. - ; (value) - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; It's out of range. - ; (value) - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; It's not alphanumeric. - ; (base, character) - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - ; In: - ; string pointer - ; base - ; Out: - ; result (if successful) - ; error indicator (zero indicates success) - dq litstring, "read-base-unsigned", early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - - ; If the first byte is null, this is an error - dq litstring, "unpack8", early_find, entry_to_execution_token, early_comma - ; (numeric base, current point in string, character) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 7*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; Decode the first byte as a generalized digit in the base. - ; (numeric base, current point in string, character) - ; If the first byte is less than "0", this is an error. - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - ; (numeric base, current point in string, character, numeric base) - dq litstring, "decode-generalized-digit", 0, early_find - dq entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 6*8, early_comma - - ; (numeric base, current point in string) - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; The first byte is a valid generalized digit in the appropriate base, so - ; let's get started. - ; (numeric base, current point in string, initial value) - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - - ; Start of the loop. - ; (numeric base, result so far, current point in string) - dq litstring, "unpack8", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma - - ; A null after the first character is valid, and indicates we're done. - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; Decode the latest byte as a generalized digit in the base. - ; (numeric base, result so far, current point in string, latest byte) - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - ; (numeric base, result so far, current point in string, character - ; numeric base) - dq litstring, "decode-generalized-digit", 0, early_find - dq entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 7*8, early_comma - - ; If the latest character is not a valid digit, that's an error. - ; (numeric base, result so far, current point in string) - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; The latest character is valid, so incorporate it and loop. - ; (numeric base, result so far, current point in string, latest value) - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "roll", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 5, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "branch", early_find, entry_to_execution_token, early_comma - dq lit, -42*8, early_comma - - dq early_here, fetch, lit, 8, packalign, early_here_store - - - ; In: - ; string pointer - ; Out: - ; result (if successful) - ; error indicator (zero indicates success) - dq litstring, "read-integer-unsigned", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "unpack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "0", early_comma - dq litstring, "!=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 6*8, early_comma - - ; This is the case where the leading digit is not a zero. - ; (original string pointer, advanced string pointer) - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 10, early_comma - dq litstring, "read-base-unsigned", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; This is the case where the leading digit is a zero. - ; (original string pointer, advanced string pointer) - dq litstring, "unpack8", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "x", early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma - - ; This is the case where the second character is equal to "x". - ; (original string pointer, doubly advanced string pointer, character) - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 16, early_comma - dq litstring, "read-base-unsigned", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "o", early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma - - ; This is the case where the second character is equal to "o". - ; (original string pointer, doubly advanced string pointer, character) - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "read-base-unsigned", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "b", early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma - - ; This is the case where the second character is equal to "b". - ; (original string pointer, doubly advanced string pointer, character) - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 2, early_comma - dq litstring, "read-base-unsigned", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; This is the case where the second character is something else. - ; (original string pointer, doubly advanced string pointer, character) - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 10, early_comma - dq litstring, "read-base-unsigned", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - - ; In: - ; string pointer - ; Out: - ; result (if successful) - ; error indicator (zero indicates success) - dq litstring, "read-integer", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "unpack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "-", early_comma - dq litstring, "!=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 4*8, early_comma - - ; This is the case where it's non-negative. - ; (original string pointer, advanced string pointer) - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "read-integer-unsigned", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; This is the case where it's negative. - ; (original string pointer, advanced string pointer) - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "read-integer-unsigned", early_find, entry_to_execution_token - dq early_comma - ; (result maybe, exit code) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 2*8, early_comma - - ; Failure - ; (non-zero exit code) - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; Success - ; (result, zero exit code) - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, -1, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - ; In: - ; string pointer - ; Out: - ; result (if successful) - ; error indicator (zero indicates success) - dq litstring, "read-decimal", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "unpack8", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, "-", early_comma - dq litstring, "!=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 6*8, early_comma - - ; This is the case where it's non-negative. - ; (original string pointer, advanced string pointer) - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 10, early_comma - dq litstring, "read-base-unsigned", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; This is the case where it's negative. - ; (original string pointer, advanced string pointer) - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 10, early_comma - dq litstring, "read-base-unsigned", early_find, entry_to_execution_token - dq early_comma - ; (result maybe, exit code) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 2*8, early_comma - - ; Failure - ; (non-zero exit code) - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; Success - ; (result, zero exit code) - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, -1, early_comma - dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - dq litstring, "interpreter-flags-storage", early_create - dq litstring, "interpreter-flags-storage", early_find - dq dup, lit, 1, store_entry_flags - dq entry_to_execution_token - ; (heap pointer, storage pointer) - dq swap, lit, 0, early_comma - dq litstring, "variable", 0, early_find, entry_to_execution_token - ; (storage pointer, heap pointer, execution token) - dq swap, unroll3 - ; (heap pointer, storage pointer, execution token) - dq litstring, "interpreter-flags", swap - ; (heap pointer, storage pointer, string pointer, execution token) - dq execute - - - dq litstring, "hide-entry", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "entry-flags@", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x80, early_comma - dq litstring, "|", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "entry-flags!", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - dq litstring, "unhide-entry", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "entry-flags@", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x80, early_comma - dq litstring, "invert", early_find, entry_to_execution_token, early_comma - dq litstring, "&", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "entry-flags!", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - dq litstring, "set-word-immediate", early_create, early_docol_codeword - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "entry-flags@", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x01, early_comma - dq litstring, "|", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "entry-flags!", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - dq litstring, "[", early_create, early_docol_codeword - dq litstring, "interpreter-flags", early_find - dq entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x01, early_comma - dq litstring, "invert", early_find, entry_to_execution_token, early_comma - dq litstring, "&", early_find, entry_to_execution_token, early_comma - dq litstring, "interpreter-flags", early_find - dq entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; Run some imperative code to fix the flags. - dq litstring, "set-word-immediate", early_find, entry_to_execution_token - dq swap, litstring, "[", early_find, roll3, execute - - - dq litstring, "]", early_create, early_docol_codeword - dq litstring, "interpreter-flags", early_find - dq entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x01, early_comma - dq litstring, "|", early_find, entry_to_execution_token, early_comma - dq litstring, "interpreter-flags", early_find - dq entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - dq litstring, ":", early_create, early_docol_codeword - dq litstring, "word", early_find, entry_to_execution_token, early_comma - dq litstring, "value@", early_find, entry_to_execution_token, early_comma - dq litstring, "create", early_find, entry_to_execution_token, early_comma - dq litstring, "dropstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "docol", early_find, entry_to_execution_token, early_comma - dq litstring, ",", early_find, entry_to_execution_token, early_comma - dq litstring, "latest", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "hide-entry", early_find, entry_to_execution_token - dq early_comma - ; If this feels backwards, imagine to yourself that everything that ISN'T - ; defining a word body is part of an implicit [ ... ] sequence. Doing so - ; doesn't really change anything, but may make you happier. - dq litstring, "]", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - dq litstring, ";", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, ",", early_find, entry_to_execution_token, early_comma - dq litstring, "latest", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "unhide-entry", early_find, entry_to_execution_token - dq early_comma - ; As above. - dq litstring, "[", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - ; Run some imperative code to fix the flags. - dq litstring, "set-word-immediate", early_find, entry_to_execution_token - dq swap, litstring, ";", early_find, roll3, execute - - - dq litstring, ";asm", early_create, early_docol_codeword - dq litstring, "here", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "pack-next", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "packalign", early_find, entry_to_execution_token, early_comma - dq litstring, "here", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "latest", early_find, entry_to_execution_token, early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "unhide-entry", early_find, entry_to_execution_token - dq early_comma - dq litstring, "entry-to-execution-token", 0, early_find - dq entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 8, early_comma - dq litstring, "+", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "[", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - dq litstring, "set-word-immediate", early_find, entry_to_execution_token - dq swap, litstring, ";asm", early_find, roll3, execute - - - ; Although we will eventually define the word "'" to give us the symbol of a - ; word, it will rely on being able to compile a literal. Rather than do - ; lots of string processing later, we choose to define this word now to - ; avoid having to look up the word "lit" as part of that. - ; - ; In: - ; value - dq litstring, "literal", early_create, early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq litstring, ",", early_find, entry_to_execution_token, early_comma - dq litstring, ",", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - ; Now the single most important word... - dq litstring, "interpret", early_create, early_docol_codeword - dq litstring, "word", early_find, entry_to_execution_token, early_comma - - ; If no word was returned, exit. - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 3*8, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; The string is on the top of the stack, so to get a pointer to it we get - ; the stack address. - ; (string) - dq litstring, "value@", early_find, entry_to_execution_token, early_comma - dq litstring, "find", early_find, entry_to_execution_token, early_comma - - ; Check whether the word was found in the dictionary. - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "!=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 25*8, early_comma - - ; If the word is in the dictionary, check what mode we're in, then... - dq litstring, "dropstring-with-result", early_find, entry_to_execution_token - dq early_comma - ; (entry pointer) - dq litstring, "interpreter-flags", early_find, entry_to_execution_token - dq early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x01, early_comma - dq litstring, "&", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 14*8, early_comma - - ; ... if we're in compile mode, there's still a chance it's an immediate - ; word, in which case we branch over to interpret mode... - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "entry-flags@", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 1, early_comma - dq litstring, "&", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 4*8, early_comma - ; ... but it's a regular word, so append it to the heap. - dq litstring, "entry-to-execution-token", 0, early_find - dq entry_to_execution_token, early_comma - dq litstring, ",", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; ... if we're in interpret mode, or the word is immediate, run it. - dq litstring, "entry-to-execution-token", 0, early_find - dq entry_to_execution_token, early_comma - dq litstring, "execute", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; If it's not in the dictionary, check whether it's a decimal number. - dq litstring, "drop", early_find, entry_to_execution_token, early_comma - ; As before, we get the stack address and use it as a string pointer. - ; (string) - dq litstring, "value@", early_find, entry_to_execution_token, early_comma - dq litstring, "read-integer", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma - dq litstring, "=", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 16*8, early_comma - - ; It's a number. - dq litstring, "interpreter-flags", early_find, entry_to_execution_token - dq early_comma - dq litstring, "@", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0x01, early_comma - dq litstring, "&", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 7*8, early_comma - - ; We're in compile mode; append first "lit", then the number, to the heap. - ; The version of "lit" we use is the one that's current when we ourselves - ; are compiled, hardcoded; doing a dynamic lookup would require dealing with - ; what happens if it's not found. - dq litstring, "dropstring-with-result", early_find, entry_to_execution_token - dq early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq litstring, ",", early_find, entry_to_execution_token, early_comma - dq litstring, ",", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; We're in interpret mode; push the number to the stack. Or at least, that's - ; what the code we're interpreting will see. Really it's already on the - ; stack, just clean everything else up and leave it there. - dq litstring, "dropstring-with-result", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - - ; If it's neither in the dictionary nor a number, just print an error. - dq litstring, "litstring", early_find, entry_to_execution_token, early_comma - dq lit, "No such ", early_comma, lit, "word: ", early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "value@", early_find, entry_to_execution_token, early_comma - dq litstring, "emitstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "dropstring", early_find, entry_to_execution_token - dq early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - - - ; The next layer is built now, so let's move on to it. - ; - ; We've chosen to defer creating "quit" until we're in interpreted mode, - ; so we can't call "quit" here, we need to call "interpret". Since - ; "interpret" doesn't loop, we need to call it a few times in a row - just - ; enough times for the code in boot_source, which it'll be interpreting, to - ; create and invoke "quit". - ; - ; We could allocate a real word that does that, but then it would stick - ; around after it's no longer needed. Instead, we create a trampoline, which - ; has a "docol" codeword, some calls to "interpret", but nothing else, then - ; we call it the same way we would call an ordinary word given its execution - ; token. - ; - ; To avoid needing to explicitly clean up the trampoline, we never - ; formally allocate it. Since we know exactly what code it'll be running, we - ; also know how much heap space that code will use. We put the trampoline - ; immediately after the end of where "quit" will be, so that the very next - ; heap allocations after creating "quit" will overwrite the trampoline. - ; - ; For simplicity's sake, we use the flatassembler copies of docol, lit, - ; and sys_exit. It would be possible to use the heap copies, but we have - ; these ones for just a few moments longer, so we might as well use them. - dq litstring, "interpret", early_find, entry_to_execution_token - dq swap, early_here, fetch - ; (interpret, heap pointer, here pointer) - - ; Consult the definition of "quit" in boot_source and count how many words - ; the compiled implementation of it will take up. - ; - ; That will include one for the next-entry pointer; one for the name and - ; flags (it's short enough to fit, even with the null terminators); one for - ; the codeword pointer to docol; one for each word that's explicitly added - ; as part of its body in the source; and one for a trailing "exit" that's - ; added by ";" and never reached. - ; - ; Whatever total you get, that's how many words to add to "here", on this - ; line, to obtain the trampoline's start location. - ; - ; Notionally, less might appear to work, but you'd be racing to execute a - ; word before overwriting it, so it isn't a great idea. - dq lit, 10*8, add - ; (interpret, heap pointer, start of trampoline) - - dq dup, lit, 4, roll, swap - ; (heap pointer, start of trampoline, interpret, current point in trampoline) - dq lit, docol, pack64 - - ; In boot_source, count how many interpreted words there are from the - ; initial ":" to the invocation of "quit", inclusive. Don't forget that - ; ": quit" is only a single interpreted word, because ":" reads a word to - ; use as a name, and that one is never seen by "interpret". - ; - ; Whatever total you get, adjust the number of repeated lines just below, - ; to put that exact number of copies of the execution token for "interpret" - ; into the trampoline. - ; - ; (heap pointer, start of trampoline, interpret, current point in trampoline) - dq swap, dup, unroll3, pack64 - dq swap, dup, unroll3, pack64 - dq swap, dup, unroll3, pack64 - dq swap, dup, unroll3, pack64 - dq swap, dup, unroll3, pack64 - dq swap, dup, unroll3, pack64 - dq swap, dup, unroll3, pack64 - dq swap, dup, unroll3, pack64 - dq swap, dup, unroll3, pack64 - dq swap, dup, unroll3, pack64 - dq swap, dup, unroll3, pack64 - dq swap, dup, unroll3, pack64 - dq swap, dup, unroll3, pack64 - dq swap, dup, unroll3, pack64 - - dq swap, drop - ; (heap pointer, start of trampoline, current point in trampoline) - - ; The trampoline will never get past the above calls to "interpret", but if - ; it does, complain. - dq lit, lit, pack64, lit, 1, pack64, lit, sys_exit, pack64 - dq drop - ; (heap pointer, start of trampoline) - - ; Get rid of that heap pointer on the stack, we're finally done with it! - dq swap, drop - dq execute - - ; We won't be coming back, but if we do, complain about that, too. - dq lit, 1, sys_exit - - - ;;; For triage's sake, here's an inventory of everything else in the file. - ;;; - ;;; Macros: - ;;; next, beforenext, pushcontrol, popcontrol - ;;; Assembly: - ;;; docol (the constant, and the actual codeword implementation) - ;;; needs a label - ;;; pushcontrol, next - ;;; exit - ;;; popcontrol, next - ;;; swap, drop, drop2, roll, unroll, roll3, unroll3, dup, dup2 - ;;; add, sub, mul, divmod - ;;; eq, ne, gt, lt, ge, le - ;;; gt_unsigned, lt_unsigned, ge_unsigned, le_unsigned - ;;; and, or, xor, invert - ;;; lit, litstring - ;;; store, fetch - ;;; store_control_stack,fetch_control_stack, - ;;; store_value_stack, fetch_value_stack, - ;;; addstore, substore, store8, fetch8, store16, fetch16, store32, fetch32 - ;;; memcopy, stringlen - ;;; reverse_stringlen, reverse_padding_len - ;;; stringcmp - ;;; no dependencies except next for any of these - ;;; branch, zbranch - ;;; sorta needs a label but might be avoidable - ;;; needs next - ;;; execute - ;;; sys_exit, sys_write - ;;; nothing special - ;;; Forth: - ;;; emitstring - ;;; stringlen, sys_write, basics - ;;; pow logfloor logceil - ;;; dotbase_unsigned, dotbase, dot - ;;; dothex, dothex8, dothex16, dothex32, dothex64 - ;;; Assembly: - ;;; crash - ;;; nothing special - ;;; Forth: - ;;; pack64, pack32, pack16, pack8, packstring, packalign - ;;; only the basics above - ;;; Assembly: - ;;; litpack64, litpack32, litpack16, litpack8 - ;;; beforenext, pack* - ;;; Forth: - ;;; rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi - ;;; r8, r9, r10, r11, r12, r13, r14, r15 - ;;; eax, ecx, edx, ebx, esp, ebp, esi, edi - ;;; ax, cx, dx, bx, sp, bp, si, di - ;;; al, cl, dl, bl, ah, ch, dh, bh - ;;; cc_overflow, cc_no_overflow, cc_below, cc_above_equal, cc_equal, - ;;; cc_not_equal, cc_below_equal, cc_above, cc_sign, cc_not_sign, cc_even, - ;;; cc_odd, cc_less, cc_greater_equal, cc_less_equal, cc_greater - ;;; only the basics above - ;;; reg64, extrareg64, reg32, reg16, reg8, scalefield, conditioncode - ;;; only the basics plus optional emitstring and sys_exit - ;;; (notice that these are forward references!) - ;;; rex_w, rex_wb, opcodereg, opcodecc, modrm, sib - ;;; only the basics above - ;;; addressing_reg64, addressing_indirect_reg64, addressing_disp8_reg64, - ;;; addressing_indexed_reg64, addressing_disp8_indexed_reg64, - ;;; addressing_reg8 - ;;; basics plus earlier assembly stuff - ;;; cld, std, - ;;; mov_reg64_imm32, - ;;; mov_reg64_imm64, mov_extrareg64_imm64, - ;;; mov_reg64_reg64, - ;;; mov_indirect_reg64_reg64, mov_disp8_reg64_reg64, - ;;; mov_reg64_indirect_reg64, mov_reg64_disp8_reg64, - ;;; mov_reg64_indexed_reg64, mov_indexed_reg64_reg64, - ;;; mov_indirect_reg64_reg32, mov_disp8_reg64_reg32, - ;;; mov_reg32_indirect_reg64, mov_reg32_disp8_reg64, - ;;; mov_indirect_reg64_reg16, mov_disp8_reg64_reg16, - ;;; mov_reg16_indirect_reg64, mov_reg16_disp8_reg64, - ;;; mov_indirect_reg64_reg8, mov_disp8_reg64_reg8, - ;;; mov_reg8_indirect_reg64, mov_reg8_disp8_reg64, - ;;; mov_reg8_reg8, - ;;; lea_reg64_disp8_reg64, lea_reg64_indexed_reg64, - ;;; lea_reg64_disp8_indexed_reg64, - ;;; push_reg64, pop_reg64, push_imm32_extended, - ;;; movs8, movs16, movs32, movs64, - ;;; rep_movs8, rep_movs16, rep_movs32, rep_movs64, - ;;; lods8, lods16, lods32, lods64, - ;;; rep_lods8, rep_lods16, rep_lods32, rep_lods64, - ;;; stos8, stos16, stos32, stos64, - ;;; rep_stos8, rep_stos16, rep_stos32, rep_stos64, - ;;; cmps8, cmps16, cmps32, cmps64, - ;;; repz_cmps8, repz_cmps16, repz_cmps32, repz_cmps64, - ;;; repnz_cmps8, repnz_cmps16, repnz_cmps32, repnz_cmps64, - ;;; scas8, scas16, scas32, scas64, - ;;; repz_scas8, repz_scas16, repz_scas32, repz_scas64, - ;;; repnz_scas8, repnz_scas16, repnz_scas32, repnz_scas64, - ;;; add_reg64_reg64, add_indirect_reg64_reg64, add_reg64_indirect_reg64, - ;;; add_reg64_imm8, - ;;; sub_reg64_reg64, sub_indirect_reg64_reg64, - ;;; sub_reg64_imm8, sbb_reg64_imm8 - ;;; mul_reg64, divmod_reg64, idivmod_reg64, inc_reg64, dec_reg64, - ;;; and_reg64_reg64, and_reg64_imm8, - ;;; or_reg64_reg64, or_reg64_imm8, - ;;; xox_reg64_reg64, - ;;; not_reg64, - ;;; cmp_reg64_reg64, test_reg64_reg64, - ;;; set_reg8_cc, jmp_cc_rel_imm8, jmp_cc_rel_im32, - ;;; jmp_abs_indirect_reg64, jmp_rel_imm8, jmp_rel_imm32, - ;;; syscall, hlt - ;;; basics plus assembly helpers - ;;; pack_next, pack_beforenext, pack_pushcontrol, pack_popcontrol, - ;;; basics, assembly stuff - ;;; entry_to_execution_token, execution_token_to_entry, - ;;; fetch_entry_flags, store_entry_flags, - ;;; entry_to_name, - ;;; find_in, next_newer_entry_in, guess_entry_end_in, - ;;; show_hex_between, show_source_between, show_source_or_hex_between, - ;;; some interdependencies here but it's all topologically sorted - ;;; Forth, not needed on heap: - ;;; early_heap, early_s0, early_r0, early_latest, early_here - ;;; early_find, early_next_newer_entry, early_guess_entry_end, - ;;; early_show_hex, early_show_source, early_show_source_or_hex - ;;; early_describe, early_describe_all, - ;;; TODO there should really be non-early versions of these two - ;;; early_create, early_comma, early_self_codeword, early_docol_codeword, - ;;; early_here_store, early_variable - ;;; - ;;; It's likely that nothing past this point is required for the heap copy, - ;;; but it's here for completeness. - ;;; - ;;; Forth, subject to reconsideration: - ;;; quit - ;;; quine (this is a forward reference) - ;;; Forth: - ;;; quine - ;;; early_here (removable), all_contents (forward) - ;;; sys_write, basics - ;;; use_label, set_label - ;;; only basics - ;;; Forth: - ;;; all_contents, elf_file_header, elf_program_header - ;;; output_start_routine - ;;; nothing special in any of these (they do want use/set_label) - ;;; self_raw - ;;; self-reference - ;;; Not a real word: - ;;; end_segment - ;;; - dq quit - -;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Now we are in Forth ;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; -;;; Everything we define from here on out is an actual Forth word, with a -;;; proper header and everything. So, you'll see some more preamble before the -;;; definitions. -;;; -;;; Keep in mind, though, that, although we have threaded execution, we -;;; don't yet have Forth-style variables. That's because the heap is at a -;;; dynamically-chosen location, so none of this read-only code that we're -;;; defining now can reference it. Before invoking cold_start, we thoughtfully -;;; put the value of "heap" on the stack for ourselves; our first task will be -;;; to dynamically allocate some words on the heap that know how to find the -;;; heap. We'll do that by defining bootstrapping versions of the -;;; word-defining words, which will eventually be replaced. - -; Token pasting is possible in flatassembler, but kind of a pain. -calminstruction defword_label_helper name - local full_name, address - arrange full_name, name#=_name ; do the token-pasting - compute address, $ ; compute the current address - publish full_name:, address ; bind the label -end calminstruction - -; The only time we actually use this variant is docol. -macro defword_unlabeled name, flags - align 8 - defword_label_helper name - dq latest_word - latest_word = $ - 8 - db flags, 0x00, `name, 0x00 - align 8 -end macro - -; This is the variant we use to define ordinary words. -macro defword name, flags - defword_unlabeled name, flags - label name -end macro - -latest_word = 0 - -;;; -;;; Routine docol -;;; ------------- -;;; -;;; Reference this via its label as the codeword of a word to make it an -;;; "interpreted" word. Concretely, it saves rsi (the "instruction pointer") -;;; to the control stack, takes the address of the codeword from rax and -;;; increments it in-place to form the new instruction pointer, and copies -;;; that to rsi. -;;; -;;; Having then done this, we're now in the state that normal execution -;;; expects, so docol ends by it using "next" to begin the callee's execution, -;;; kicking off a nested call. -;;; -;;; The name is said to be short for "do colon", because Forth high-level -;;; code begins word definitions with a colon. -;;; -;;; Registers in: -;;; -;;; * rsi is the caller's instruction pointer -;;; * rbp is the control stack pointer -;;; * rax is the address of the callee's codeword -;;; -;;; Registers out: -;;; -;;; * rsi is the callee's instruction pointer -;;; * rbp is the control stack pointer -defword_unlabeled docol, 0 -docol_constant: - ; Evaluated as a word, docol is a constant which returns a pointer. - dq $ + 8 - mov.qreg.qimm rax, docol - push.qreg rax - next - align 8 -docol: - ; Since docol is not a normal word, the label points to the value we care - ; about from the assembly side of things, which is the address we use as the - ; codeword. - pushcontrol rsi - add.qreg.bimm rax, 8 - mov.qreg.qreg rsi, rax - next - -latest_word = docol_name - -;;; -;;; This is the mechanism to "return" from a word interpreted by docol. -;;; We pop the control stack, and then, since this is threaded execution, we -;;; do the next thing the caller wants to do, by inlining "next". -;;; -defword exit, 0 - dq $ + 8 - popcontrol rsi - next - - -;;; -;;; Stack manipulation routines -;;; --------------------------- -;;; -;;; We start with the three traditional stack operations, swap drop and -;;; roll. Sorry to fans of the name "ROT"; we were an HP calculator kid. It'll -;;; always be roll to us. Anyway, we do a couple other operations too. Since -;;; our goal right now is just to bootstrap the heap, we keep this short and -;;; sweet. -;;; -;;; There is definitely plenty of optimization that could be done. -;;; - -defword swap, 0 - dq $ + 8 - pop.qreg rax - pop.qreg rbx - push.qreg rax - push.qreg rbx - next - -defword drop, 0 - dq $ + 8 - pop.qreg rax - next - -defword drop2, 0 - dq $ + 8 - pop.qreg rax - pop.qreg rax - next - -; Rotates "up" (pops its parameter, n; nth item then becomes current item). -; -; We implement this the high-performance way, with rep movsq, aka the -; instruction that exists to optimize C's memcpy(). The details of setting -; that up are complex; see below. -defword roll, 0 - dq $ + 8 - - ; Pop our parameter. The rep instruction takes rcx as its count, so we - ; reduce copying by using it to hold our count, as well. - pop.qreg rcx - - ; We have n - 1 items to slide, so decrement rcx. For the purpose of - ; counting how many repetitions will happen, it's one-based. This is because - ; the rep instruction performs a single movsq, then decrements rcx, then - ; stops if rcx is zero. - dec.qreg rcx - - ; Retrieve the nth item, for later. For this purpose we're thinking in - ; zero-based terms, so we do this after already having decremented rcx. - mov.qreg.indexed.qreg rbx, rsp, rcx, 8 - - ; The source address for movsq is rsi and the destination is rdi; we can - ; use rdi as we wish, but rsi is our Forth "instruction pointer", so we must - ; save and restore it. Doing so alters rsp, so we have to adjust the address - ; calculations by eight bytes as compared to the expressions above, but - ; happily we can use the disp8 field to do that. We'd be using disp8 anyway - ; because it's helpful. - push.qreg rsi - - ; Now we set up parameters for the memory-sliding operation. We have - ; n - 1 items to copy, moving the range rsp through rsp + (n-2)*8 onto the - ; range rsp + 8 through rsp + (n-1)*8. That's with the value of rsp as it - ; exists at this moment (it's going to change soon). - ; - ; We're sliding them upwards in memory, so we start at the high end so - ; that we're always moving into a location that doesn't have anything - ; precious. We use lea as a convenient way to do the stack math. - ; - ; When rcx is 1, we want rsp + 8. - lea.qreg.indexed.qreg rsi, rsp, rcx, 8 - ; When rcx is 1, we want rsp + 16. - lea.qreg.disp8.indexed.qreg rdi, 8, rsp, rcx, 8 - ; - ; Using rcx = 1 is the most convenient example to use for figuring out the - ; arithmetic. It's a linear relationship, so as long as we get the 8-byte - ; stride correct, we just need to pick a single point and verify that our - ; math is right for that point, and it'll be right for any value of rcx. - - ; Another of our Forth conventions is that the DF flag should be kept at - ; zero, which directs string instruction to increment rsi. Here, however, - ; because our source and destination ranges overlap, we need to start at the - ; high end, which means we need it to decrement. So we set DF to one, and - ; we'll clear it after. - std - rep movsq - - ; Set everything back. - cld - pop.qreg rsi - - ; There is now an extra item at the low end of the stack (the top) that - ; needs to go away, and coincidentally we have a value in rbx that needs to - ; be in that spot. Rather than doing a drop and push, we overwrite it, to - ; save a little work. - mov.indirect.qreg.qreg rsp, rbx - - ; All done, wow! What a mouthful. - next - -; Rotates "down" (pops its parameter, n; current item then becomes nth item). -; -; We implement this the high-performance way, with rep movsq, aka the -; instruction that exists to optimize C's memcpy(). The details of setting -; that up are complex; see below. -defword unroll, 0 - dq $ + 8 - - ; Pop our parameter. The rep instruction takes rcx as its count, so we - ; reduce copying by using it to hold our count, as well. - pop.qreg rcx - - ; We have n - 1 items to slide, so decrement rcx. Also, save a copy of it in - ; rdx after doing that, for later. - dec.qreg rcx - mov.qreg.qreg rdx, rcx - - ; Retrieve the 0th item, for later. - mov.qreg.indirect.qreg rbx, rsp - - ; Now we set up parameters for the memory-sliding operation. We have - ; n - 1 items to copy, moving the range rsp + 8 through rsp + (n-1)*8 onto - ; the range rsp through rsp + (n-2)*8. That's with the value of rsp as it - ; exists at this moment (it's going to change soon). - ; - ; We're sliding them downwards in memory, so we start at the low end so - ; that we're always moving into a location that doesn't have anything - ; precious. We use lea as a convenient way to do the stack math. - ; - ; As with roll, we need to save rsi and adjust those rsp calculations - ; accordingly. - push.qreg rsi - - ; Regardless of rcx, we want rsp + 16. - lea.qreg.disp8.qreg rsi, 16, rsp - ; Regardless of rcx, we want rsp + 8. - lea.qreg.disp8.qreg rdi, 8, rsp - - ; With roll, we were starting at the high end. Here, we start at the low - ; end, which means we need rsi to increment after each repetition. That's - ; what it does when the DF flag is clear, and another of our Forth - ; conventions is to keep it clear normally. So, we don't have to touch DF! - ; Yay! - rep movsq - - ; Restore our original rsi. - pop.qreg rsi - - ; There is now an extra item in the middle of the stack, at the high end of - ; the sliding we did, that needs to be overwritten with our value in rbx. - ; Since we destructively updated our count in rcx, we saved a copy of the - ; count in rdx, and we use that to find the right address. - ; - ; When the original count was n, we want rsp + (n-1)*8, so we saved rdx - ; after decrementing rcx, above. - mov.indexed.qreg.qreg rsp, rdx, 8, rbx - - ; All done, wow! What a mouthful. - next - -; Rotates "up" (third item becomes current item) -defword roll3, 0 - dq $ + 8 - pop.qreg rax - pop.qreg rbx - pop.qreg rcx - push.qreg rbx - push.qreg rax - push.qreg rcx - next - -; Rotates "down" (current item becomes third item) -defword unroll3, 0 - dq $ + 8 - pop.qreg rax - pop.qreg rbx - pop.qreg rcx - push.qreg rax - push.qreg rcx - push.qreg rbx - next - -defword dup, 0 - dq $ + 8 - pop.qreg rax - push.qreg rax - push.qreg rax - next - -defword dup2, 0 - dq $ + 8 - pop.qreg rax - pop.qreg rbx - push.qreg rbx - push.qreg rax - push.qreg rbx - push.qreg rax - next - -;;; -;;; Arithmetic routines -;;; ------------------- -;;; -;;; No surprises here. Again, since our goal is to bootstrap the heap, we -;;; keep it short. Also again, this is nowhere near optimal. -;;; - -defword add, 0 - dq $ + 8 - pop.qreg rbx - pop.qreg rax - add.qreg.qreg rax, rbx - push.qreg rax - next - -defword sub, 0 - dq $ + 8 - pop.qreg rbx - pop.qreg rax - sub.qreg.qreg rax, rbx - push.qreg rax - next - -defword mul, 0 - dq $ + 8 - pop.qreg rax - pop.qreg rbx - mul.rax.qreg rbx - push.qreg rax - next - -defword divmod, 0 - dq $ + 8 - xor.qreg.qreg rdx, rdx ; rdx is the high bits of the input; zero it - pop.qreg rbx - pop.qreg rax - div.rdxrax.qreg rbx - push.qreg rdx ; remainder - push.qreg rax ; quotient - next - -;;; -;;; Comparison routines -;;; ------------------- -;;; - -; So. This is subtle. These comparison routines all have the same structure. -; Notice that eq and ne are commutative, whereas the others are not, so -; consider gt as the archetypical one when reasoning about correctness. To -; test if A > B, we do cmp A, B, which sets the flags the same way as -; subtracting B from A does. The mnemonic names of the condition codes are -; based on the assumption you do it in this order. -; -; We want to treat the top of the stack as the first operand, so we carefully -; pop in the appropriate order. -; -; There are both signed and unsigned variants of the condition codes. We use -; the signed ones. - -defword eq, 0 - dq $ + 8 - pop.qreg rax - pop.qreg rbx - cmp.qreg.qreg rax, rbx - set.breg.cc al, equal - and.qreg.bimm rax, 0x01 - push.qreg rax - next - -defword ne, 0 - dq $ + 8 - pop.qreg rax - pop.qreg rbx - cmp.qreg.qreg rax, rbx - set.breg.cc al, not_equal - and.qreg.bimm rax, 0x01 - push.qreg rax - next - -defword gt, 0 - dq $ + 8 - pop.qreg rax - pop.qreg rbx - cmp.qreg.qreg rax, rbx - set.breg.cc al, greater - and.qreg.bimm rax, 0x01 - push.qreg rax - next - -; Is the top of the stack less than the second item in the stack? -defword lt, 0 - dq $ + 8 - pop.qreg rax - pop.qreg rbx - cmp.qreg.qreg rax, rbx - set.breg.cc al, less - and.qreg.bimm rax, 0x01 - push.qreg rax - next - -defword ge, 0 - dq $ + 8 - pop.qreg rax - pop.qreg rbx - cmp.qreg.qreg rax, rbx - set.breg.cc al, greater_equal - and.qreg.bimm rax, 0x01 - push.qreg rax - next - -defword le, 0 - dq $ + 8 - pop.qreg rax - pop.qreg rbx - cmp.qreg.qreg rax, rbx - set.breg.cc al, less_equal - and.qreg.bimm rax, 0x01 - push.qreg rax - next - -defword gt_unsigned, 0 - dq $ + 8 - pop.qreg rax - pop.qreg rbx - cmp.qreg.qreg rax, rbx - set.breg.cc al, above - and.qreg.bimm rax, 0x01 - push.qreg rax - next - -defword lt_unsigned, 0 - dq $ + 8 - pop.qreg rax - pop.qreg rbx - cmp.qreg.qreg rax, rbx - set.breg.cc al, below - and.qreg.bimm rax, 0x01 - push.qreg rax - next - -defword ge_unsigned, 0 - dq $ + 8 - pop.qreg rax - pop.qreg rbx - cmp.qreg.qreg rax, rbx - set.breg.cc al, above_equal - and.qreg.bimm rax, 0x01 - push.qreg rax - next - -defword le_unsigned, 0 - dq $ + 8 - pop.qreg rax - pop.qreg rbx - cmp.qreg.qreg rax, rbx - set.breg.cc al, below_equal - and.qreg.bimm rax, 0x01 - push.qreg rax - next - -;;; -;;; Bitwise routines -;;; ---------------- -;;; - -defword and, 0 - dq $ + 8 - pop.qreg rbx - pop.qreg rax - and.qreg.qreg rax, rbx - push.qreg rax - next - -defword or, 0 - dq $ + 8 - pop.qreg rbx - pop.qreg rax - or.qreg.qreg rax, rbx - push.qreg rax - next - -defword xor, 0 - dq $ + 8 - pop.qreg rbx - pop.qreg rax - xor.qreg.qreg rax, rbx - push.qreg rax - next - -; The HP overloads the name "not", so we follow the Forth convention. -defword invert, 0 - dq $ + 8 - pop.qreg rax - not.qreg rax - push.qreg rax - next - -;;; -;;; Routine lit -;;; ------------ -;;; - -defword lit, 0 - dq $ + 8 - lodsq - push.qreg rax - next - -defword litstring, 0 - dq $ + 8 - ; The string immediately follows the codeword in memory, so rsi is already - ; pointing to it. That address will be our returned result, so we push it to - ; the stack. - push.qreg rsi - - ; Now we need to skip over the string, so that rsi will be valid for the - ; next Forth word. To do that, we're going to do a string operation with - ; scasb, which takes rdi as the address to look at. This means scasb is - ; treating its operand as analogous to the destination operand of movs*. - mov.qreg.qreg rdi, rsi - ; We want to compare for equality with zero; scasb looks in al for the other - ; half of the comparison, so we clear rax. - xor.qreg.qreg rax, rax - ; Counterintuitively, we do need to pass a count. We pass -1, which will - ; always work. - xor.qreg.qreg rcx, rcx - not.qreg rcx - ; The DF flag is zero per our Forth execution-model convention, which means - ; scasb increments rdi after each iteration. This is what we want, so - ; there's no need to mess with it. - ; - ; We also need to worry about ZF, but fortunately that "not" will make sure - ; it's clear. - ; - ; So, we're ready; do it! - repnz scasb - ; The scasb completes, incrementing rdi, before the repnz checks its - ; condition. So, rdi is now pointing immediately after the terminating null - ; byte. Of course, we want this in rsi for Forth's purposes. - mov.qreg.qreg rsi, rdi - - ; Finally, we need to align rsi to the next word boundary. - add.qreg.bimm rsi, 7 - and.qreg.bimm rsi, NOT 7 - - 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 $ + 8 - pop.qreg rbx - pop.qreg rax - mov.indirect.qreg.qreg rbx, rax - next - -defword fetch, 0 - dq $ + 8 - pop.qreg rax - mov.qreg.indirect.qreg rax, rax - push.qreg rax - next - -; Address on top, value second -; I might have done it the other way, but this is what Jonesforth does and it -; seems reasonable enough. -defword addstore, 0 - dq $ + 8 - pop.qreg rbx - pop.qreg rax - add.indirect.qreg.qreg rbx, rax - next - -defword substore, 0 - dq $ + 8 - pop.qreg rbx - pop.qreg rax - sub.indirect.qreg.qreg rbx, rax - next - -defword store8, 0 - dq $ + 8 - pop.qreg rbx - pop.qreg rax - mov.indirect.qreg.breg rbx, al - next - -defword fetch8, 0 - dq $ + 8 - pop.qreg rbx - xor.qreg.qreg rax, rax - mov.breg.indirect.qreg al, rbx - push.qreg rax - next - -defword store16, 0 - dq $ + 8 - pop.qreg rbx - pop.qreg rax - mov.indirect.qreg.wreg rbx, ax - next - -defword fetch16, 0 - dq $ + 8 - pop.qreg rbx - xor.qreg.qreg rax, rax - mov.wreg.indirect.qreg ax, rbx - push.qreg rax - next - -defword store32, 0 - dq $ + 8 - pop.qreg rbx - pop.qreg rax - mov.indirect.qreg.dreg rbx, eax - next - -defword fetch32, 0 - dq $ + 8 - pop.qreg rbx - xor.qreg.qreg rax, rax - mov.dreg.indirect.qreg eax, rbx - push.qreg rax - next - -; Before we get too deep into it, we also define a few reflection routines -; that retrieve, or set, the address of either of the two stacks. -; -; The result, or the new value, is on the top of the data stack. That's the -; same as how it works for any other word, but given the metacircular nature -; of these ones it's easy to get confused about that... -defword store_control_stack, 0 - dq $ + 8 - pop.qreg rbp - next -defword fetch_control_stack, 0 - dq $ + 8 - push.qreg rbp - next -defword store_value_stack, 0 - dq $ + 8 - ; Per Intel's description of POP this reads from the old location, and there - ; is no increment applied to the resulting value. See, the description says - ; it increments the register then overwrites it, in that order. - pop.qreg rsp - next -defword fetch_value_stack, 0 - dq $ + 8 - ; Per Intel's description of PUSH this pushes the old value. - push.qreg rsp - next - -; Copy one non-overlapping block of memory over another. For the overlapping -; logic, see roll and unroll. This always copies at byte granularity, for ease -; of implementation. -; -; Jonesforth calls this CMOVE and has a CCOPY which is a single byte. POSIX, -; however, has memcpy() for non-overlapping blocks and memmove() for -; overlapping blocks. We follow the latter convention, because it feels like -; the more important distinction. -; -; Also, the "c" was meant to indicate that it works at one-byte granularity, -; but that isn't, uh... actually an important property here, and as a blanket -; call we're not using letters to denote data sizes. So we call it "memcopy". -; Apologies to the C programming tradition but vowels are good, actually. -; -; Jonesforth also offers C@C! as another name for its CCOPY, but neither -; "@!" nor "mem@mem!" seems particulaly nice. -; -; Stack in: -; destination -; source -; length -; (top) -defword memcopy, 0 - dq $ + 8 - ; We need to save and restore rsi; the other registers we can trample. - mov.qreg.qreg rdx, rsi - pop.qreg rcx - pop.qreg rdi - pop.qreg rsi - ; We start from the low end, since that's easier arithmetic. So, we get to - ; leave the DF flag alone. - rep movsb - mov.qreg.qreg rsi, rdx - next - -; (written much later) -; -; In: -; destination -; source -; length -defword memmove, 0 - dq $ + 8 - ; We need to save and restore rsi; the other registers we can trample. - mov.qreg.qreg rdx, rsi - pop.qreg rcx - pop.qreg rdi - pop.qreg rsi - - ; We need to check source < destination to decide which end to start from. - mov.qreg.qreg rax, rsi - cmp.qreg.qreg rax, rdi - ; Relative offsets are from the start of the instruction after the jmp. - jmp.cc.rel.bimm below, 4 - - ; If source is greater, we are sliding downwards so we start from the low - ; end. So, we get to leave the DF flag alone. - rep movsb ; 2 bytes - jmp.rel.bimm 16 ; 2 bytes - - ; If destination is greater, we are sliding upwards so we start from the - ; high end. So, we have to save and restore DF. Also, we have to adjust the - ; pointers. - add.qreg.qreg rsi, rcx ; 3 bytes - dec.qreg rsi ; 3 bytes - add.qreg.qreg rdi, rcx ; 3 bytes - dec.qreg rdi ; 3 bytes - std ; 1 byte - rep movsb ; 2 bytes - cld ; 1 byte - - mov.qreg.qreg rsi, rdx - next - - -; Stack in: -; string address -; Stack out: -; string length not including null byte -defword stringlen, 0 - dq $ + 8 - pop.qreg rdi - mov.qreg.qreg rbx, rdi - xor.qreg.qreg rax, rax - xor.qreg.qreg rcx, rcx - not.qreg rcx - repnz scasb - sub.qreg.qreg rdi, rbx - sub.qreg.bimm rdi, 1 - push.qreg rdi - next - -; Stack in: -; address of final non-null byte at the end of a string -; Stack out: -; backwards string length not including null byte at start -defword reverse_stringlen, 0 - dq $ + 8 - pop.qreg rdi - - mov.qreg.qreg rbx, rdi - xor.qreg.qreg rax, rax - xor.qreg.qreg rcx, rcx - not.qreg rcx - - std - repnz scasb - cld - - sub.qreg.qreg rbx, rdi - sub.qreg.bimm rbx, 1 - - push.qreg rbx - next - -; If you have a variable-length string followed by alignment padding, and -; you want to traverse it in reverse, you also need to skip the alignment -; padding... -; -; Stack in: -; address of final null byte in alignment padding of total length up to 8 -; Stack out: -; number of null bytes (from end) until nearest non-null byte, or 8 -defword reverse_padding_len, 0 - dq $ + 8 - pop.qreg rdi - - mov.qreg.qreg rbx, rdi - xor.qreg.qreg rax, rax - mov.qreg.dimm rcx, 9 - - std - repz scasb - cld - - sub.qreg.qreg rbx, rdi - sub.qreg.bimm rbx, 1 - - push.qreg rbx - next - -; We make this work using exactly two jump instructions, which is likely the -; minimum possible. To avoid relying on labels, we hand-compute the byte -; offsets, so every instruction within their ranges is annotated with its -; length in bytes. Good fun. -; -; Stack in: -; left string address -; right string address -; Stack out: -; comparison value (0 for equal, 1 for left > right, -1 for left < right) -defword stringcmp, 0 - dq $ + 8 - ; Save the rsi register. - ; - ; Happily, we don't need a lot of registers for this code, so we can - ; dedicate rdx to this and not have to deal with stack juggling.. - mov.qreg.qreg rdx, rsi - - ; Get the parameters off the stack. - ; - ; For reasons that will be explained below, the left and right strings - ; from our caller's perspective are swapped from the perspective of the - ; comparisons we'll be doing. The rdi register points to the right-hand - ; operand of the "cmps" instruction, while rsi points to the left-hand - ; operand; [Intel] volume 2A, chapter 3, section 4-3.3, "CMPS"; note that - ; the PDF mis-numbers the sections in the second half of chapter 3. - pop.qreg rsi - pop.qreg rdi - - ; For the comparison-unequal loop-exit code, we'll need rbx set to zero. - ; The easy way to do that is by xor'ing it with itself, but doing it at the - ; end of the loop would overwrite the comparison flags, which we need. So we - ; do it in advance, and carefully don't touch it anywhere else. - ; - ; See the list of which instructions affect the flags in [Intel] volume 1, - ; appendix A, section A-1, table A-2. - xor.qreg.qreg rbx, rbx - - ; We also clear rax; we'll be using al later, and it will be convenient to - ; know the upper bits are always zero. - xor.qreg.qreg rax, rax - - ; Now we've initialized everything we need; everything after this point is - ; part of the loop. - - ; At the start of each iteration, save a copy of the byte we're at now. We - ; need to do this before cmps because the pointers will increment; we'll - ; eventually use it to test whether we've reached the end delimiter. - ; - ; We do a 64-bit load into rcx, which is otherwise unused, then copy the - ; low byte from cl to al. This avoids having to think about addressing modes - ; that combine 64-bit addresses with smaller data sizes; those are very - ; subtle. - mov.qreg.indirect.qreg rcx, rsi ; 3 bytes - mov.breg.breg al, cl ; 2 bytes - - ; Now do the cmps, which is the heart of the loop. - ; - ; Note that, in addition to relying on this comparison to test content - ; bytes against each other, in the event that one string is a prefix of the - ; other, this will also test content bytes against null delimiters. The - ; longer string will compare as "greater", because zero is less than all - ; other possible byte values. This is what we want. - ; - ; Since strings of different lengths are necessarily unequal, letting this - ; test do the work of detecting that also means we don't have to deal with - ; scenarios where we're past the end of one string but not the other. - cmps8 ; 1 byte - - ; The flags are now set based on the simulated subtraction of the next - ; bytes from the two strings. If they were unequal, the loop will end. If - ; they were equal, we have another test to do before we're finished with - ; this iteration. So we put the loop-end code next, and conditionally jump - ; forward past it. - ; - ; Recall that relative offsets are from the start of the instruction after - ; the jmp. - jmp.cc.rel.bimm equal, 15 ; 2 bytes - - ; If we got here, the strings are unequal, so we need to turn the flags - ; into a comparison value. We cleared rbx earlier; now we set its low bit to - ; the "above" flag, then use sbb to subtract the "carry" flag (which it - ; thinks of as the "borrow" flag). - ; - ; Recall that "carry" is based on whether the comparison would cause a - ; change to the next bit "outside" the bits being compared; [Intel] - ; volume 1, chapter 3, section 3-4.3.1. Since the comparison is a - ; subtraction, "carry" is true when the right-hand byte is strictly greater - ; than the left-hand byte. - ; - ; Also recall that "zero", also called "equal", is based on whether the - ; comparison's result produces output that's all zero bits. Since the - ; comparison is a subtraction, "zero" is true when the two bytes are - ; identical. - ; - ; The "above" condition is not a flag, but a composite of flags. It's true - ; when both "carry" and "zero" are false; [Intel] volume 1, chapter 7, - ; section 7-3.1.1, table 7-2. For us, this is equivalent to saying the - ; left-hand byte is strictly greater than the right-hand. - ; - ; So, after the "set" instruction, rbx is 1 if left > right, and 0 if - ; left = right or left < right. The "sbb" instruction with an immediate - ; value of zero subtracts the value of the carry flag from rbx; the flag is - ; true in the case where left < right, and false otherwise. So, after the - ; "sbb", rbx is 1 if left > right, 0 if left = right, and -1 if - ; left < right. - ; - ; This sounds like the opposite of what we want, but recall that we - ; exchanged the operands, so these are the values our caller is expecting. - ; While it might be tempting to look for a way to not need that - ; transposition, and indeed there exists an approach using "not above", it's - ; fiddly in a way that's even harder to explain. - ; - ; Note that it's important that the "jmp" and "set" instructions don't - ; change the flags (see table A-2 again), so the "cmps" is the most recent - ; thing that did. The "sbb" instruction does change them, but we don't need - ; them again after that point so it doesn't matter. - ; - ; Finally, we need to restore rsi before we return to Forth. - ; - ; The two-instruction set-sbb sequence is one of those classic assembly - ; programming tricks that often goes unexplained, because most of its appeal - ; is its brevity and a proper explanation is quite lengthy. Please enjoy - ; this gift of knowledge, and thanks to our friends who showed it to us. - set.breg.cc bl, above ; 3 bytes - sbb.qreg.bimm rbx, 0 ; 4 bytes - push.qreg rbx ; 1 byte - mov.qreg.qreg rsi, rdx ; 3 bytes - next ; 4 bytes - - ; If we got here, the current bytes are equal to each other. We still need - ; to test if they're null terminators; if so, we exit, and if not, we loop. - ; - ; At the beginning of this iteration, we saved a copy of the byte being - ; inspected in rax. The "test" instruction simulates a xor and sets the - ; flags accordingly. We check the "not equal" condition, also known as "not - ; zero", and jump backwards to the start of the loop when that's the case. - ; - ; Recall that relative offsets are from the start of the instruction after - ; the jmp. - test.qreg.qreg rax, rax ; 3 bytes - jmp.cc.rel.bimm not_equal, -28 ; 2 bytes - - ; If we got here, we got all the way to the end of both strings and found - ; a null byte, so we return 0 to indicate they're equal. - ; - ; We can use push.dimm even though our stack holds 64-bit values, because - ; it gets sign-extended. - ; - ; We need to restore rsi before we return to Forth. - push.dimm 0 - mov.qreg.qreg rsi, rdx - next - - -;;;;;;;;;;;;;;;;; -;;; Branching ;;; -;;;;;;;;;;;;;;;;; - -; This takes a number of bytes, not machine words. That allows it to be used -; for putting weird things embedded in the code. -; -; The offset is relative to the start of the word the number of bytes is in, -; so, make sure to have it skip itself. -defword branch, 0 - dq $ + 8 - add.qreg.indirect.qreg rsi, rsi - next - -; This should probably be 0branch, but right now the auto-label code is picky. -defword zbranch, 0 - dq $ + 8 - pop.qreg rax - test.qreg.qreg rax, rax - ; Please notice the 8-bit branch to the nearby word. - jmp.cc.rel.bimm zero, branch + 8 - zbranch_after_jmp -zbranch_after_jmp: - lodsq ; just a convenient way to skip rsi forward - next - -; This is like next, but instead of using rsi as the "instruction pointer", it -; takes a codeword address from the value stack. -; -; In the event that the codeword is docol, docol will handle any manipulation -; of the control stack that needs to happen. Yes, it really is that simple. -defword execute, 0 - dq $ + 8 - pop.qreg rax - jmp.abs.indirect.qreg rax - -;;;;;;;;;;;;;;;;;;;; -;;; System calls ;;; -;;;;;;;;;;;;;;;;;;;; -;;; -;;; The kernel preserves every register except rax, rcx, and r11. The system -;;; call number goes in rax, as does the return value. Parameters go in rdi, -;;; rsi, rdx, r10, r8, and r9, in that order. [SysV] A.2.1. -;;; -;;; Notice that rsi is our control stack, so we have to save it (for -;;; syscalls with at least two parameters). We can use the value stack to do -;;; that, since rsp is preserved. We don't save other registers because our -;;; caller should do that, if it cares. -;;; - -;;; -;;; This does the Linux exit() system call, passing it an exit code taken -;;; from the stack. -;;; -defword sys_exit, 0 - dq $ + 8 - - mov.qreg.qimm rax, 60 ; syscall number - pop.qreg rdi ; exit code - syscall - - ; In the event we're still here, let's minimize confusion. - hlt - - -;;; -;;; This does the Linux write() system call, passing it an address from the -;;; top of the stack and a length from the second position on the stack. It -;;; writes to file descriptor 1, which is stdout. -;;; -;;; For our length parameter, we can pop directly from the stack into rdx, -;;; which directly becomes the syscall parameter. For our address parameter, -;;; the syscall wants it in rsi, which we also care about, so we have to do a -;;; little juggling. -;;; -defword sys_write, 0 - dq $ + 8 - pop.qreg rcx ; address from stack - pop.qreg rdx ; length from stack, passed directly - push.qreg rsi ; save rsi - mov.qreg.qimm rax, 1 ; syscall number - mov.qreg.qimm rdi, 1 ; file descriptor - mov.qreg.qreg rsi, rcx ; pass address - syscall - pop.qreg rsi ; restore rsi - next - - -; In: -; length -; address -defword sys_read, 0 - dq $ + 8 - pop.qreg rcx ; address from stack - pop.qreg rdx ; length from stack, passed directly - push.qreg rsi ; save rsi - mov.qreg.qimm rax, 0 ; syscall number - mov.qreg.qimm rdi, 0 ; file descriptor - mov.qreg.qreg rsi, rcx ; pass address - syscall - pop.qreg rsi ; restore rsi - push.qreg rax ; return length - next - - -;;;;;;;;;;;;;;;;;;;;;;;; -;;; I/O conveniences ;;; -;;;;;;;;;;;;;;;;;;;;;;;; - - -defword emitstring, 0 - dq docol, dup, stringlen, swap, sys_write, exit - - -; The main word for this next part is "dot"; the stuff preceding it is -; internals used to implement it. -; -; Although this could notionally be emitinteger for symmetry, it's -; well-known under the name dot and as a single period character, and that -; name participates in conventions for names of other things. So, we go with -; it. -; -; Unlike Jonesforth, we do not have a global "base" variable, and this word -; does not change its behavior depending on that value. It's always base ten. -; -; This is an extremely inefficient implementation, but on the plus side, -; doing that avoids having to think about any sort of memory management or -; recursion, and lets us stick entirely with the trivial control-flow -; constructs we already have. - -; In: -; base -; exponent -; Out: -; base to the power of exponent -defword pow, 0 - dq docol - dq lit, 1, swap - ; If the count of remaining powers is NOT equal to zero, the comparison will - ; return 0, which will cause the zbranch to skip the rest of the line. - dq dup, lit, 0, eq, zbranch, 5*8, drop, swap, drop, exit - ; (base, result so far, count of remaining powers) - dq lit, 1, sub, unroll3 - ; (updated count of remaining powers, base, result so far) - dq swap, dup, lit, 4, unroll - ; (base, updated count of remaining powers, result so far, base) - dq mul, swap - ; (base, updated result so far, updated count of remaining powers) - dq branch, -22*8 - -; In: -; base -; value -; Out: -; floor of logarithm of value, in base base -defword logfloor, 0 - dq docol - - ; Start with a product equal to the base, and a count of 0. - dq swap, dup, unroll3, lit, 0 - - ; This is the start of the loop body. - ; (base, value, product so far, count of powers included so far) - dq unroll3, dup2 - ; (base, count so far, value, product so far) - dq gt_unsigned, zbranch, 6*8 - - ; If we get here, we're done. - ; (base, count so far, value, product so far) - dq drop, drop, swap, drop, exit - - ; If we're here, we need to do another loop. - ; (base, count so far, value, product so far) - dq lit, 4, roll, dup, lit, 5, unroll, mul, roll3, lit, 1, add - ; (base, value, updated product so far, updated count so far) - - ; If the product is less than the base, we overflowed. In that case, the - ; product-so-far is the maximum, so just return it. - dq lit, 4, roll, dup, lit, 5, unroll, roll3, dup, lit, 4, unroll - dq lt, zbranch, 8*8 - dq lit, 4, unroll, drop, drop, drop, exit - - ; Nothing else weird going on, so loop. - dq branch, -45*8 - -; In: -; base -; value -; Out: -; celing of logarithm of value, in base base -defword logceil, 0 - dq docol - - ; Start with a product of 1 and a count of 0. - dq lit, 1, lit, 0 - - ; This is the start of the loop body. - ; (base, value, product so far, count of powers included so far) - dq unroll3, dup2 - ; (base, count so far, value, product so far) - dq ge_unsigned, zbranch, 6*8 - - ; If we get here, we're done. - ; (base, count so far, value, product so far) - dq drop, drop, swap, drop, exit - - ; If we're here, we need to do another loop. - ; (base, count so far, value, product so far) - dq lit, 4, roll, dup, lit, 5, unroll, mul, roll3, lit, 1, add - ; (base, value, updated product so far, updated count so far) - - ; If the product is less than the base, we overflowed. In that case, the - ; product-so-far is the maximum, so just return it. - dq lit, 4, roll, dup, lit, 5, unroll, roll3, dup, lit, 4, unroll - dq lt, zbranch, 8*8 - dq lit, 4, unroll, drop, drop, drop, exit - - ; Nothing else weird going on, so loop. - dq branch, -45*8 - -; In: -; integer to print -; base to print in -; width to zero-pad to -defword dotbase_unsigned, 0 - dq docol - - ; (input, base, width) - ; Compute how many digits we need to display. Because we use logfloor, the - ; logic of always printing at least one digit is already handled for us. - dq unroll3, swap, dup2, logfloor, lit, 1, add - ; (width, base, input, number of digits if no padding) - dq lit, 4, roll, dup2, gt, zbranch, 5*8 - ; (base, input, number of digits if no padding, width) - ; If we're here, we should use the padded width - dq swap, drop, branch, 2*8 - ; (base, input, number of digits if no padding, width) - ; If we're here, we should use the unpadded width - dq drop - - ; (base, input, number of digits remaining) - ; This is the start of the loop. - dq dup2, lit, 1, sub - ; (base, input, number of digits remaining, input, intermediate value) - dq lit, 5, roll, dup, lit, 6, unroll, swap - ; (base, input, number of digits remaining, input, base, intermediate value) - dq pow, divmod, swap, drop - ; (base, input, number of digits remaining, - ; input divided by base^x appropriately) - dq lit, 4, roll, dup, lit, 5, unroll - ; (base, input, number of digits remaining, - ; input divided by base^x appropriately, base) - dq divmod, drop - - ; (base, input, number of digits remaining, current digit) - ; We construct a one-character string on the stack, then use a pointer to - ; it. It will always contain its own null-termination without us having to - ; do anything special to that end. - dq dup, lit, 10, gt, zbranch, 5*8 - dq lit, "0", branch, 6*8 - dq lit, 10, sub, lit, "a" - dq add - dq fetch_value_stack, emitstring - - ; We deallocate the string by dropping it. - ; - ; Saying it like that makes it sound obvious; contemplate it until it feels - ; surprising. - dq drop - - dq lit, 1, sub - dq dup, zbranch, 3*8, branch, -51*8 - dq drop, drop, drop, exit - -; In: -; integer to print -; base to print in -defword dotbase, 0 - dq docol - - dq swap - ; (base, input) - - ; Deal with negative numbers. - dq dup, lit, 0, gt, zbranch, 7*8 - dq lit, -1, mul - dq litstring, "-", emitstring - - dq swap, lit, 0, dotbase_unsigned, exit - -; In: -; integer to print -defword dot, 0 - dq docol, lit, 10, dotbase, exit -defword dothex, 0 - dq docol, lit, 16, lit, 0, dotbase_unsigned, exit -defword dothex8, 0 - dq docol, lit, 16, lit, 2, dotbase_unsigned, exit -defword dothex16, 0 - dq docol, lit, 16, lit, 4, dotbase_unsigned, exit -defword dothex32, 0 - dq docol, lit, 16, lit, 8, dotbase_unsigned, exit -defword dothex64, 0 - dq docol, lit, 16, lit, 16, dotbase_unsigned, exit - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Development utilities ;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; This peforms the "hlt" instruction (Intel's mnemomic, short for "halt"), -; which will cause the program to exit with a segmentation fault. If you're -; running under a debugger, this is a convenient way to get execution to stop -; at a certain point. -; -; It's called "crash" rather than "hlt" to distinguish it from the word -; which outputs the instruction as machine code. -defword crash, 0 - dq $ + 8 - hlt - - -;;;;;;;;;;;;;;;;;;;;;; -;;; Output helpers ;;; -;;;;;;;;;;;;;;;;;;;;;; -;;; -;;; These routines are for building up data structures in-memory. Sometimes -;;; they're used for structures that are meant to stay in memory; other times -;;; it's a buffer that will become output. -;;; -;;; The general pattern is that each routine takes an output address and -;;; some specific datum, and returns the output address adjusted to point -;;; after the new datum. That makes them easy to chain together. - -; In: base address, value -; Out: new base address -defword pack64, 0 - dq docol - dq swap, dup, unroll3, store, lit, 8, add - dq exit -defword pack32, 0 - dq docol - dq swap, dup, unroll3, store32, lit, 4, add - dq exit -defword pack16, 0 - dq docol - dq swap, dup, unroll3, store16, lit, 2, add - dq exit -defword pack8, 0 - dq docol - dq swap, dup, unroll3, store8, lit, 1, add - dq exit - -; This works on C-style strings, which are characters followed by a null -; terminator. The packed data includes the null terminator. -; -; Stack in: -; base address, string pointer -; Stack out: -; new base address -defword packstring, 0 - dq docol - dq dup, stringlen, lit, 1, add, dup - ; base/destination, source, length, length - dq lit, 4, roll, dup, lit, 4, unroll - ; source, destination, length, length, base/destination - dq add, lit, 4, unroll - ; new base, source, destination, length - dq memcopy - dq exit - -; This also works on C-style strings, relying on the null terminator, but -; the packed data does not include it. -; -; Stack in: -; base address, string pointer -; Stack out: -; new base address -defword pack_raw_string, 0 - dq docol - dq dup, stringlen, dup - ; base/destination, source, length, length - dq lit, 4, roll, dup, lit, 4, unroll - ; source, destination, length, length, base/destination - dq add, lit, 4, unroll - ; new base, source, destination, length - dq memcopy - dq exit - -; Stack in: -; base address -; byte size -; Stack out: -; new base address -defword packalign, 0 - dq docol - dq dup2, divmod, drop, zbranch, 8*8 - dq swap, lit, 0, pack8, swap - dq branch, -11*8 - dq drop, exit - -; In the interests of reducing our executable's size, since a lot of it goes -; to pack* invocations, we define words that combine lit with pack*. This -; shaves roughly 700 bytes as of when it was added. -defword litpack64, 0 - dq $ + 8 - lodsq - push.qreg rax - beforenext pack64 -defword litpack32, 0 - dq $ + 8 - lodsq - push.qreg rax - beforenext pack32 -defword litpack16, 0 - dq $ + 8 - lodsq - push.qreg rax - beforenext pack16 -defword litpack8, 0 - dq $ + 8 - lodsq - push.qreg rax - beforenext pack8 - - -;;;;;;;;;;;;;;;;;;;;; -;;; Input helpers ;;; -;;;;;;;;;;;;;;;;;;;;; -;;; -;;; These routines are for examining data structures in-memory. -;;; -;;; Similarly to the output routines, each routine takes an input address, -;;; which it updates to point after the data item being read. Since this is -;;; input, the routines return data items rather than accepting them. - -; In: -; proposed size -; alignment -; Out: -; adjusted size -defword align_size, 0 - dq docol - dq dup, unroll3, dup, unroll3 - ; (alignment, proposed size, alignment) - dq lit, 1, sub, add, swap, divmod, swap, drop, mul - dq exit - -; In: base address -; Out: new base address, value -defword unpack64, 0 - dq docol - dq dup, fetch, swap, lit, 8, add, swap - dq exit -defword unpack32, 0 - dq docol - dq dup, fetch32, swap, lit, 4, add, swap - dq exit -defword unpack16, 0 - dq docol - dq dup, fetch16, swap, lit, 2, add, swap - dq exit -defword unpack8, 0 - dq docol - dq dup, fetch8, swap, lit, 1, add, swap - dq exit - -; You might think this would be identical to packalign, but packalign has -; side effects. -; -; Stack in: -; base address -; byte size -; Stack out: -; new base address -defword unpackalign, 0 - dq docol, align_size, exit - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Assembly language, but in Forth ;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; -;;; It's all backwards and stuff. -;;; -;;; Okay, but seriously, the convention is: target on the top of the stack, -;;; source behind it. This is similar to how the Forth "store" and "fetch" -;;; words work. -;;; -;;; These routines use the output helpers, defined above. They're called in -;;; the same way: an output address, followed by data items specific to what's -;;; being output. - -; We define a bunch of keywords, which evaluate to their own codeword -; addresses. -defword rax, 0 - dq docol, lit, rax, exit -defword rcx, 0 - dq docol, lit, rcx, exit -defword rdx, 0 - dq docol, lit, rdx, exit -defword rbx, 0 - dq docol, lit, rbx, exit -defword rsp, 0 - dq docol, lit, rsp, exit -defword rbp, 0 - dq docol, lit, rbp, exit -defword rsi, 0 - dq docol, lit, rsi, exit -defword rdi, 0 - dq docol, lit, rdi, exit -defword r8, 0 - dq docol, lit, r8, exit -defword r9, 0 - dq docol, lit, r9, exit -defword r10, 0 - dq docol, lit, r10, exit -defword r11, 0 - dq docol, lit, r11, exit -defword r12, 0 - dq docol, lit, r12, exit -defword r13, 0 - dq docol, lit, r13, exit -defword r14, 0 - dq docol, lit, r14, exit -defword r15, 0 - dq docol, lit, r15, exit -defword eax, 0 - dq docol, lit, eax, exit -defword ecx, 0 - dq docol, lit, ecx, exit -defword edx, 0 - dq docol, lit, edx, exit -defword ebx, 0 - dq docol, lit, ebx, exit -defword esp, 0 - dq docol, lit, esp, exit -defword ebp, 0 - dq docol, lit, ebp, exit -defword esi, 0 - dq docol, lit, esi, exit -defword edi, 0 - dq docol, lit, edi, exit -defword ax, 0 - dq docol, lit, ax, exit -defword cx, 0 - dq docol, lit, cx, exit -defword dx, 0 - dq docol, lit, dx, exit -defword bx, 0 - dq docol, lit, bx, exit -defword sp, 0 - dq docol, lit, sp, exit -defword bp, 0 - dq docol, lit, bp, exit -defword si, 0 - dq docol, lit, si, exit -defword di, 0 - dq docol, lit, di, exit -defword al, 0 - dq docol, lit, al, exit -defword cl, 0 - dq docol, lit, cl, exit -defword dl, 0 - dq docol, lit, dl, exit -defword bl, 0 - dq docol, lit, bl, exit -defword ah, 0 - dq docol, lit, ah, exit -defword ch, 0 - dq docol, lit, ch, exit -defword dh, 0 - dq docol, lit, dh, exit -defword bh, 0 - dq docol, lit, bh, exit -defword cc_overflow, 0 - dq docol, lit, cc_overflow, exit -defword cc_no_overflow, 0 - dq docol, lit, cc_no_overflow, exit -defword cc_below, 0 - dq docol, lit, cc_below, exit -defword cc_above_equal, 0 - dq docol, lit, cc_above_equal, exit -defword cc_equal, 0 - dq docol, lit, cc_equal, exit -defword cc_not_equal, 0 - dq docol, lit, cc_not_equal, exit -defword cc_below_equal, 0 - dq docol, lit, cc_below_equal, exit -defword cc_above, 0 - dq docol, lit, cc_above, exit -defword cc_sign, 0 - dq docol, lit, cc_sign, exit -defword cc_not_sign, 0 - dq docol, lit, cc_not_sign, exit -defword cc_even, 0 - dq docol, lit, cc_even, exit -defword cc_odd, 0 - dq docol, lit, cc_odd, exit -defword cc_less, 0 - dq docol, lit, cc_less, exit -defword cc_greater_equal, 0 - dq docol, lit, cc_greater_equal, exit -defword cc_less_equal, 0 - dq docol, lit, cc_less_equal, exit -defword cc_greater, 0 - dq docol, lit, cc_greater, exit - -; Stack in: -; register name -; Stack out: -; 3-bit encoded value for register -defword reg64, 0 - dq docol - dq dup, rax, eq, zbranch, 5*8, drop, lit, 0, exit - dq dup, rcx, eq, zbranch, 5*8, drop, lit, 1, exit - dq dup, rdx, eq, zbranch, 5*8, drop, lit, 2, exit - dq dup, rbx, eq, zbranch, 5*8, drop, lit, 3, exit - dq dup, rsp, eq, zbranch, 5*8, drop, lit, 4, exit - dq dup, rbp, eq, zbranch, 5*8, drop, lit, 5, exit - dq dup, rsi, eq, zbranch, 5*8, drop, lit, 6, exit - dq dup, rdi, eq, zbranch, 5*8, drop, lit, 7, exit - dq litstring, "Parameter to reg64 is not a reg64.", emitstring - dq lit, 1, sys_exit - -; Stack in: -; register name -; Stack out: -; 3-bit encoded value for register -defword extrareg64, 0 - dq docol - dq dup, r8, eq, zbranch, 5*8, drop, lit, 0, exit - dq dup, r9, eq, zbranch, 5*8, drop, lit, 1, exit - dq dup, r10, eq, zbranch, 5*8, drop, lit, 2, exit - dq dup, r11, eq, zbranch, 5*8, drop, lit, 3, exit - dq dup, r12, eq, zbranch, 5*8, drop, lit, 4, exit - dq dup, r13, eq, zbranch, 5*8, drop, lit, 5, exit - dq dup, r14, eq, zbranch, 5*8, drop, lit, 6, exit - dq dup, r15, eq, zbranch, 5*8, drop, lit, 7, exit - dq litstring, "Parameter to extrareg64 is not an extrareg64.", emitstring - dq lit, 1, sys_exit - -; Stack in: -; register name -; Stack out: -; 3-bit encoded value for register -defword reg32, 0 - dq docol - dq dup, eax, eq, zbranch, 5*8, drop, lit, 0, exit - dq dup, ecx, eq, zbranch, 5*8, drop, lit, 1, exit - dq dup, edx, eq, zbranch, 5*8, drop, lit, 2, exit - dq dup, ebx, eq, zbranch, 5*8, drop, lit, 3, exit - dq dup, esp, eq, zbranch, 5*8, drop, lit, 4, exit - dq dup, ebp, eq, zbranch, 5*8, drop, lit, 5, exit - dq dup, esi, eq, zbranch, 5*8, drop, lit, 6, exit - dq dup, edi, eq, zbranch, 5*8, drop, lit, 7, exit - dq litstring, "Parameter to reg32 is not a reg32.", emitstring - dq lit, 1, sys_exit - -; Stack in: -; register name -; Stack out: -; 3-bit encoded value for register -defword reg16, 0 - dq docol - dq dup, ax, eq, zbranch, 5*8, drop, lit, 0, exit - dq dup, cx, eq, zbranch, 5*8, drop, lit, 1, exit - dq dup, dx, eq, zbranch, 5*8, drop, lit, 2, exit - dq dup, bx, eq, zbranch, 5*8, drop, lit, 3, exit - dq dup, sp, eq, zbranch, 5*8, drop, lit, 4, exit - dq dup, bp, eq, zbranch, 5*8, drop, lit, 5, exit - dq dup, si, eq, zbranch, 5*8, drop, lit, 6, exit - dq dup, di, eq, zbranch, 5*8, drop, lit, 7, exit - dq litstring, "Parameter to reg16 is not a reg16.", emitstring - dq lit, 1, sys_exit - -; Stack in: -; register name -; Stack out: -; 3-bit encoded value for register -defword reg8, 0 - dq docol - dq dup, al, eq, zbranch, 5*8, drop, lit, 0, exit - dq dup, cl, eq, zbranch, 5*8, drop, lit, 1, exit - dq dup, dl, eq, zbranch, 5*8, drop, lit, 2, exit - dq dup, bl, eq, zbranch, 5*8, drop, lit, 3, exit - dq dup, ah, eq, zbranch, 5*8, drop, lit, 4, exit - dq dup, ch, eq, zbranch, 5*8, drop, lit, 5, exit - dq dup, dh, eq, zbranch, 5*8, drop, lit, 6, exit - dq dup, bh, eq, zbranch, 5*8, drop, lit, 7, exit - dq litstring, "Parameter to reg8 is not a reg8.", 0, 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, lit, 1, eq, zbranch, 5*8, drop, lit, 0, exit - dq dup, lit, 2, eq, zbranch, 5*8, drop, lit, 1, exit - dq dup, lit, 4, eq, zbranch, 5*8, drop, lit, 2, exit - dq dup, lit, 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 - -; [Intel] volume 2D, appendix B, section B-1.4.7, table B-10. Also see the -; individual opcode pages. -; -; Stack in: -; condition name -; Stack out: -; 4-bit encoded value for condition code in opcodes -defword conditioncode, 0 - dq docol - dq dup, cc_overflow, eq, zbranch, 5*8, drop, lit, 0, exit - dq dup, cc_no_overflow, eq, zbranch, 5*8, drop, lit, 1, exit - dq dup, cc_below, eq, zbranch, 5*8, drop, lit, 2, exit - dq dup, cc_above_equal, eq, zbranch, 5*8, drop, lit, 3, exit - dq dup, cc_equal, eq, zbranch, 5*8, drop, lit, 4, exit - dq dup, cc_not_equal, eq, zbranch, 5*8, drop, lit, 5, exit - dq dup, cc_below_equal, eq, zbranch, 5*8, drop, lit, 6, exit - dq dup, cc_above, eq, zbranch, 5*8, drop, lit, 7, exit - dq dup, cc_sign, eq, zbranch, 5*8, drop, lit, 8, exit - dq dup, cc_not_sign, eq, zbranch, 5*8, drop, lit, 9, exit - dq dup, cc_even, eq, zbranch, 5*8, drop, lit, 10, exit - dq dup, cc_odd, eq, zbranch, 5*8, drop, lit, 11, exit - dq dup, cc_less, eq, zbranch, 5*8, drop, lit, 12, exit - dq dup, cc_greater_equal, eq, zbranch, 5*8, drop, lit, 13, exit - dq dup, cc_less_equal, eq, zbranch, 5*8, drop, lit, 14, exit - dq dup, cc_greater, eq, zbranch, 5*8, drop, lit, 15, exit - dq litstring, "Parameter to conditioncode is not a condition code." - dq emitstring - dq lit, 1, sys_exit - -; Stack: -; output point -defword rex_w, 0 - dq docol, lit, 0x48, pack8, exit -defword rex_b, 0 - dq docol, lit, 0x41, pack8, exit -defword rex_wb, 0 - dq docol, lit, 0x49, pack8, exit - -; Stack: -; output point -; 3-bit encoded value for register -; opcode byte -defword opcodereg, 0 - dq docol, or, pack8, exit - -; Stack: -; output point -; 4-bit encoded value for condition code -; opcode byte -defword opcodecc, 0 - dq docol, or, pack8, exit - -; The low-level word that outputs a modrm byte given fully-processed, -; numeric values for its fields. Most code will want to call one of the -; higher-level modrm_* words, instead. -; -; Stack -; output point -; mode ("mod") field -; register/opcode field -; register/memory ("RM") field -defword modrm, 0 - dq docol, swap, lit, 8, mul, or, swap, lit, 64, mul, or, pack8, exit - -; Stack -; output point -; scale field -; index field -; base field -defword sib, 0 - dq docol, swap, lit, 8, mul, or, swap, lit, 64, mul, or, pack8, exit - -; The simplest of the modrm modes: Direct register addressing. There are no -; special cases to check. -; -; It's important to notice that the R/M field may describe either a source, -; or a target, depending on what the instruction is. So, this helper doesn't -; get to know that. It also doesn't get to know whether the value in the -; reg/op field describes a register, or if instead it's an extension of the -; opcode. The caller is responsible for figuring that all out. -; -; Stack: -; output point -; reg/op field value (raw number) -; reg/mem field register name -defword addressing_reg64, 0 - dq docol, reg64, lit, 3, unroll3, modrm, exit - -; This is a helper for assembly instructions that want to do a form of -; addressing that requires a value of 1 in the modrm byte's mode field, and -; do not want to do any indexing. -; -; Its main responsibility is to deal with the scenario that requires an SIB -; byte, which happens when the R/M field has a value of 4, which would -; otherwise refer to the register rsp. In that situation, it also generates -; an SIB byte which indicates a scale of 1, no indexing, and rsp as the base -; register. -; -; Stack: -; output point -; reg/op field value (raw number) -; reg/mem field register name -defword addressing_indirect_reg64, 0 - dq docol - ; Exit with an error if the R/M register is rbp. - dq dup, rbp, ne, zbranch, 23*8 - ; Check whether the R/M register is rsp; save the test result for later. - dq dup, rsp, eq, lit, 4, unroll - ; (equality result, output point, reg/op value, reg/mem name) - dq reg64, lit, 0, unroll3, modrm - ; (equality result, output point) - ; If the R/M register was rsp, we need an SIB byte; otherwise, skip it. - dq swap, zbranch, 8*8, lit, 0, lit, 4, rsp, reg64, sib - dq exit - dq litstring, "R/M parameter to addressing_indirect_reg64 is rbp." - dq emitstring - dq lit, 1, sys_exit - -; Stack: -; output point -; reg/op field value (raw number) -; reg/mem field register name -; 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. - dq lit, 4, unroll - dq reg64, lit, 1, unroll3, modrm - ; If the R/M register was rsp, we need an SIB byte; otherwise, skip it. - dq roll3, zbranch, 8*8, lit, 0, lit, 4, rsp, reg64, sib - ; The displacement byte. - dq swap, pack8 - dq exit - -; Stack: -; output point -; reg/op field value (raw number) -; reg/mem field register name -; displacement value -defword addressing_disp32_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. - dq lit, 4, unroll - dq reg64, lit, 2, unroll3, modrm - ; If the R/M register was rsp, we need an SIB byte; otherwise, skip it. - dq roll3, zbranch, 8*8, lit, 0, lit, 4, rsp, reg64, sib - ; The displacement value. - dq swap, pack32 - dq exit - -; 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, 23*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 -; reg/op field value (raw number) -; reg/mem field register name -defword addressing_reg8, 0 - dq docol, reg8, lit, 3, unroll3, modrm, exit - -; Stack: -; output point -defword cld, 0 - dq docol, lit, 0xFC, pack8, exit - -; Stack: -; output point -defword std, 0 - dq docol, lit, 0xFD, pack8, exit - -; Stack: -; output point -; immediate value -; register name -defword mov_reg64_imm32, 0 - dq docol - dq roll3, rex_w, lit, 0xC7, pack8, swap - dq lit, 0, swap, addressing_reg64 - dq swap, pack32 - dq exit - -; Stack: -; output point -; immediate value -; register name -defword mov_reg64_imm64, 0 - dq docol - dq roll3, rex_w, swap, reg64, lit, 0xB8, opcodereg, swap, pack64 - dq exit -defword mov_extrareg64_imm64, 0 - dq docol - dq roll3, rex_wb, swap, extrareg64, lit, 0xB8, opcodereg, swap, pack64 - dq exit - -; Stack: -; output point -; source register name -; target register name -defword mov_reg64_reg64, 0 - dq docol - dq roll3, rex_w, lit, 0x89, pack8, unroll3 - dq swap, reg64, swap, addressing_reg64 - dq exit - -; Stack: -; output point -; source register name -; target register name -defword mov_indirect_reg64_reg64, 0 - dq docol - dq roll3, rex_w, lit, 0x89, pack8, unroll3 - dq swap, reg64, swap, addressing_indirect_reg64 - dq exit - -; Stack: -; output point -; source register name -; target register name -; target displacement value -defword mov_disp8_reg64_reg64, 0 - dq docol - dq lit, 4, roll, rex_w, lit, 0x89, pack8, lit, 4, unroll - dq roll3, reg64, unroll3, addressing_disp8_reg64 - dq exit - -; Stack: -; output point -; source register name -; target register name -defword mov_reg64_indirect_reg64, 0 - dq docol - dq roll3, rex_w, lit, 0x8B, pack8, unroll3 - dq reg64, swap, addressing_indirect_reg64 - dq exit - -; Stack: -; output point -; source register name -; source displacement value -; target register name -defword mov_reg64_disp8_reg64, 0 - dq docol - dq lit, 4, roll, rex_w, lit, 0x8B, pack8, lit, 4, unroll - dq reg64, unroll3, addressing_disp8_reg64 - dq exit - -; Stack: -; output point -; source register name -; source displacement value -; target register name -defword mov_reg64_disp32_reg64, 0 - dq docol - dq lit, 4, roll, rex_w, lit, 0x89, pack8, lit, 4, unroll - dq roll3, reg64, swap, roll3, addressing_disp32_reg64 - dq exit - -; Stack: -; output point -; source base 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 -; target base register name -; target index register name -; target index scale factor, as a count of bytes -defword mov_indexed_reg64_reg64, 0 - dq docol - dq lit, 5, roll, rex_w, lit, 0x89, pack8, lit, 5, unroll - dq lit, 4, roll, reg64, lit, 4, unroll - dq unroll3, swap, addressing_indexed_reg64 - dq exit - -; Stack: -; output point -; source register name -; target register name -defword mov_indirect_reg64_reg32, 0 - dq docol - dq roll3, lit, 0x89, pack8, unroll3 - dq swap, reg32, swap, addressing_indirect_reg64 - dq exit - -; Stack: -; output point -; source register name -; target register name -; target displacement value -defword mov_disp8_reg64_reg32, 0 - dq docol - dq lit, 4, roll, lit, 0x89, pack8, lit, 4, unroll - dq roll3, reg32, unroll3, addressing_disp8_reg64 - dq exit - -; Stack: -; output point -; source register name -; target register name -defword mov_reg32_indirect_reg64, 0 - dq docol - dq roll3, lit, 0x8B, pack8, unroll3 - dq reg32, swap, addressing_indirect_reg64 - dq exit - -; Stack: -; output point -; source register name -; source displacement value -; target register name -defword mov_reg32_disp8_reg64, 0 - dq docol - dq lit, 4, roll, lit, 0x8B, pack8, lit, 4, unroll - dq reg32, unroll3, addressing_disp8_reg64 - dq exit - -; Stack: -; output point -; source register name -; target register name -defword mov_indirect_reg64_reg16, 0 - dq docol - dq roll3, lit, 0x66, pack8, lit, 0x89, pack8, unroll3 - dq swap, reg16, swap, addressing_indirect_reg64 - dq exit - -; Stack: -; output point -; source register name -; target register name -; target displacement value -defword mov_disp8_reg64_reg16, 0 - dq docol - dq lit, 4, roll, lit, 0x66, pack8, lit, 0x89, pack8, lit, 4, unroll - dq roll3, reg16, unroll3, addressing_disp8_reg64 - dq exit - -; Stack: -; output point -; source register name -; target register name -defword mov_reg16_indirect_reg64, 0 - dq docol - dq roll3, lit, 0x66, pack8, lit, 0x8B, pack8, unroll3 - dq reg16, swap, addressing_indirect_reg64 - dq exit - -; Stack: -; output point -; source register name -; source displacement value -; target register name -defword mov_reg16_disp8_reg64, 0 - dq docol - dq lit, 4, roll, lit, 0x66, pack8, lit, 0x8B, pack8, lit, 4, unroll - dq reg16, unroll3, addressing_disp8_reg64 - dq exit - -; Stack: -; output point -; source register name -; target register name -defword mov_indirect_reg64_reg8, 0 - dq docol - dq roll3, lit, 0x88, pack8, unroll3 - dq swap, reg8, swap, addressing_indirect_reg64 - dq exit - -; Stack: -; output point -; source register name -; target register name -; target displacement value -defword mov_disp8_reg64_reg8, 0 - dq docol - dq lit, 4, roll, lit, 0x88, pack8, lit, 4, unroll - dq roll3, reg8, unroll3, addressing_disp8_reg64 - dq exit - -; Stack: -; output point -; source register name -; target register name -defword mov_reg8_indirect_reg64, 0 - dq docol - dq roll3, lit, 0x8A, pack8, unroll3 - dq reg8, swap, addressing_indirect_reg64 - dq exit - -; Stack: -; output point -; source register name -; source displacement value -; target register name -defword mov_reg8_disp8_reg64, 0 - dq docol - dq lit, 4, roll, pack8, lit, 0x8A, pack8, lit, 4, unroll - dq reg8, unroll3, addressing_disp8_reg64 - dq exit - -; Stack: -; output point -; source register name -; target register name -defword mov_reg8_reg8, 0 - dq docol - dq roll3, lit, 0x88, pack8, unroll3 - dq swap, reg8, swap, addressing_reg8 - dq exit - -; Stack: -; output point -; source register name -; source displacement value -; target register name -defword lea_reg64_disp8_reg64, 0 - dq docol - dq lit, 4, roll, rex_w, lit, 0x8D, pack8, lit, 4, unroll - dq reg64, unroll3, addressing_disp8_reg64 - dq exit - -; Stack: -; output point -; source register name -; source displacement value -; target register name -defword lea_reg64_disp32_reg64, 0 - dq docol - dq lit, 4, roll, rex_w, lit, 0x8D, pack8, lit, 4, unroll - dq reg64, unroll3, addressing_disp32_reg64 - dq exit - -; Stack: -; output point -; source base 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 base 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 - -; Stack: -; output point -; source register name -defword push_extrareg64, 0 - dq docol, swap, rex_b, swap, extrareg64, lit, 0x50, opcodereg, exit - -; Stack: -; output point -; target register name -defword pop_reg64, 0 - dq docol, reg64, lit, 0x58, opcodereg, exit - -; Stack: -; output point -; target register name -defword pop_extrareg64, 0 - dq docol, swap, rex_b, swap, extrareg64, lit, 0x58, opcodereg, exit - -; Stack: -; output point -; immediate value -defword push_imm32_extended64, 0 - dq docol, swap, lit, 0x68, pack8, swap, pack32, exit - - -;;; -;;; String instructions -;;; -;;; What makes these useful is that they take their parameters from certain -;;; fixed registers, which are chosen such that the operations chain into each -;;; other well. Thus you can use them to build various block-memory and string -;;; operations, and even if you need unusual forms of loop unrolling or -;;; alignment tweaking, the code will end up uniform in structure. On modern -;;; processors, this is even the high-performance approach, due to highly -;;; optimized microcode, though these operations were inefficient when they -;;; were first invented. -;;; -;;; We break with the Intel mnemonics, which follow the pattern -;;; movsb/movsw/movsd/movsq, because this would otherwise be the only place we -;;; use the b/w/d/q thing instead of 8/16/32/64. Tradition and -;;; pronounceability are both nice things, but approachability to newcomers is -;;; important, too. -;;; -;;; Some of these are repeatable; whether you view the repeatable variants -;;; as different instructions is up to you. At any rate the machine code -;;; representation of the repeatable variants is the same as for the regular -;;; variants with an extra prefix, so we define them together. -;;; -;;; This is a proper superset of the flatassembler implementations of string -;;; instructions. The wisdom of that is questionable, but at least it's noted -;;; here... - -; Stack: -; output point -defword movs8, 0 - dq docol, lit, 0xA4, pack8, exit -defword movs16, 0 - dq docol, lit, 0x66, pack8, lit, 0xA5, pack8, exit -defword movs32, 0 - dq docol, lit, 0xA5, pack8, exit -defword movs64, 0 - dq docol, rex_w, lit, 0xA5, pack8, exit -defword rep_movs8, 0 - dq docol, lit, 0xF3, pack8, lit, 0xA4, pack8, exit -defword rep_movs16, 0 - dq docol, lit, 0xF3, pack8, lit, 0x66, pack8, lit, 0xA5, pack8, exit -defword rep_movs32, 0 - dq docol, lit, 0xF3, pack8, lit, 0xA5, pack8, exit -defword rep_movs64, 0 - dq docol, lit, 0xF3, pack8, rex_w, lit, 0xA5, pack8, exit - -; Stack: -; output point -defword lods8, 0 - dq docol, lit, 0xAC, pack8, exit -defword lods16, 0 - dq docol, lit, 0x66, pack8, lit, 0xAD, pack8, exit -defword lods32, 0 - dq docol, lit, 0xAD, pack8, exit -defword lods64, 0 - dq docol, rex_w, lit, 0xAD, pack8, exit -defword rep_lods8, 0 - dq docol, lit, 0xF3, pack8, lit, 0xAC, pack8, exit -defword rep_lods16, 0 - dq docol, lit, 0xF3, pack8, lit, 0x66, pack8, lit, 0xAD, pack8, exit -defword rep_lods32, 0 - dq docol, lit, 0xF3, pack8, lit, 0xAD, pack8, exit -defword rep_lods64, 0 - dq docol, lit, 0xF3, pack8, rex_w, lit, 0xAD, pack8, exit - -; Stack: -; output pint -defword stos8, 0 - dq docol, lit, 0xAA, pack8, exit -defword stos16, 0 - dq docol, lit, 0x66, pack8, lit, 0xAB, pack8, exit -defword stos32, 0 - dq docol, lit, 0xAB, pack8, exit -defword stos64, 0 - dq docol, rex_w, lit, 0xAB, pack8, exit -defword rep_stos8, 0 - dq docol, lit, 0xF3, pack8, lit, 0xAA, pack8, exit -defword rep_stos16, 0 - dq docol, lit, 0xF3, pack8, lit, 0x66, pack8, lit, 0xAB, pack8, exit -defword rep_stos32, 0 - dq docol, lit, 0xF3, pack8, lit, 0xAB, pack8, exit -defword rep_stos64, 0 - dq docol, lit, 0xF3, pack8, rex_w, lit, 0xAB, pack8, exit - -; Stack: -; output point -defword cmps8, 0 - dq docol, lit, 0xA6, pack8, exit -defword cmps16, 0 - dq docol, lit, 0x66, pack8, lit, 0xA7, pack8, exit -defword cmps32, 0 - dq docol, lit, 0xA7, pack8, exit -defword cmps64, 0 - dq docol, rex_w, lit, 0xA7, pack8, exit -defword repz_cmps8, 0 - dq docol, lit, 0xF3, pack8, lit, 0xA6, pack8, exit -defword repz_cmps16, 0 - dq docol, lit, 0xF3, pack8, lit, 0x66, pack8, lit, 0xA7, pack8, exit -defword repz_cmps32, 0 - dq docol, lit, 0xF3, pack8, lit, 0xA7, pack8, exit -defword repz_cmps64, 0 - dq docol, lit, 0xF3, pack8, rex_w, lit, 0xA7, pack8, exit -defword repnz_cmps8, 0 - dq docol, lit, 0xF2, pack8, lit, 0xA6, pack8, exit -defword repnz_cmps16, 0 - dq docol, lit, 0xF2, pack8, lit, 0x66, pack8, lit, 0xA7, pack8, exit -defword repnz_cmps32, 0 - dq docol, lit, 0xF2, pack8, lit, 0xA7, pack8, exit -defword repnz_cmps64, 0 - dq docol, lit, 0xF2, pack8, rex_w, lit, 0xA7, pack8, exit - -; Stack: -; output point -defword scas8, 0 - dq docol, lit, 0xAE, pack8, exit -defword scas16, 0 - dq docol, lit, 0x66, pack8, lit, 0xAF, pack8, exit -defword scas32, 0 - dq docol, lit, 0xAF, pack8, exit -defword scas64, 0 - dq docol, rex_w, lit, 0xAF, pack8, exit -defword repz_scas8, 0 - dq docol, lit, 0xF3, pack8, lit, 0xAE, pack8, exit -defword repz_scas16, 0 - dq docol, lit, 0xF3, pack8, lit, 0x66, pack8, lit, 0xAF, pack8, exit -defword repz_scas32, 0 - dq docol, lit, 0xF3, pack8, lit, 0xAF, pack8, exit -defword repz_scas64, 0 - dq docol, lit, 0xF3, pack8, rex_w, lit, 0xAF, pack8, exit -defword repnz_scas8, 0 - dq docol, lit, 0xF2, pack8, lit, 0xAE, pack8, exit -defword repnz_scas16, 0 - dq docol, lit, 0xF2, pack8, lit, 0x66, pack8, lit, 0xAF, pack8, exit -defword repnz_scas32, 0 - dq docol, lit, 0xF2, pack8, lit, 0xAF, pack8, exit -defword repnz_scas64, 0 - dq docol, lit, 0xF2, pack8, rex_w, lit, 0xAF, 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, addressing_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, addressing_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, addressing_indirect_reg64 - dq exit - -; Stack: -; output point -; source value -; target register name -defword add_reg64_imm8, 0 - dq docol - dq roll3, rex_w, lit, 0x83, pack8, swap, lit, 0, swap, addressing_reg64 - dq swap, pack8 - dq exit - -; Stack: -; output point -; source register name -; target register name -defword sub_reg64_reg64, 0 - dq docol - dq roll3, rex_w, lit, 0x2B, pack8, unroll3 - dq reg64, swap, addressing_reg64 - dq 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, addressing_indirect_reg64 - dq exit - -; Stack: -; output point -; source value -; target register name -defword sub_reg64_imm8, 0 - dq docol - dq roll3, rex_w, lit, 0x83, pack8, swap, lit, 5, swap, addressing_reg64 - dq swap, pack8 - dq exit - -; Stack: -; output point -; source value -; target register name -defword sbb_reg64_imm8, 0 - dq docol - dq roll3, rex_w, lit, 0x83, pack8, swap, lit, 3, swap, addressing_reg64 - dq swap, pack8 - dq exit - -; The target register is always rax. -; -; Stack: -; output point -; source register name -defword mul_reg64, 0 - dq docol - dq swap, rex_w, lit, 0xF7, pack8, swap - dq lit, 4, swap, addressing_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, addressing_reg64 - dq exit - -; 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, addressing_reg64 - dq exit - -; Stack: -; output point -; target register name -defword inc_reg64, 0 - dq docol - dq swap, rex_w, lit, 0xFF, pack8, swap, lit, 0, swap, addressing_reg64 - dq exit - -; Stack: -; output point -; target register name -defword dec_reg64, 0 - dq docol - dq swap, rex_w, lit, 0xFF, pack8, swap, lit, 1, swap, addressing_reg64 - dq exit - -; 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, addressing_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, addressing_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, addressing_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, addressing_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, addressing_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, addressing_reg64 - dq exit - -; Stack: -; output point -; left register name -; right register name -defword cmp_reg64_reg64, 0 - dq docol - dq roll3, rex_w, lit, 0x3B, pack8, unroll3 - dq reg64, swap, addressing_reg64 - dq exit - -; Stack: -; output point -; left register name -; right register name -defword test_reg64_reg64, 0 - dq docol - dq roll3, rex_w, lit, 0x85, pack8, unroll3 - dq swap, reg64, swap, addressing_reg64 - dq exit - -; Stack: -; output point -; condition code name -; target register name -defword set_reg8_cc, 0 - dq docol - dq roll3, lit, 0x0F, pack8 - dq roll3, conditioncode, lit, 0x90, opcodecc - dq swap, reg8, lit, 3, lit, 0, roll3, modrm - dq exit - -; Stack: -; output point -; address offset value -; condition code name -defword jmp_cc_rel_imm8, 0 - dq docol - dq roll3, swap, conditioncode, lit, 0x70, opcodecc - dq swap, pack8 - dq exit - -; Stack: -; output point -; address offset value -; condition code name -defword jmp_cc_rel_imm32, 0 - dq docol - dq unroll3, lit, 0x0F, pack8 - dq swap, conditioncode, lit, 0x70, opcodecc - dq swap, pack32 - dq exit - -; Stack: -; output point -; register name -defword jmp_abs_indirect_reg64, 0 - dq docol - dq swap, lit, 0xFF, pack8, swap - dq lit, 4, swap, addressing_indirect_reg64 - dq exit - -; Stack: -; output point -; address offset value -defword jmp_rel_imm8, 0 - dq docol - dq swap, lit, 0xEB, pack8 - dq swap, pack8 - dq exit - -; Stack: -; output point -; address offset value -defword jmp_rel_imm32, 0 - dq docol - dq swap, lit, 0xE9, pack8 - dq swap, pack32 - dq exit - -; Stack: -; output point -defword syscall, 0 - dq docol, lit, 0x0F, pack8, lit, 0x05, pack8, exit - -; Stack: -; output point -defword hlt, 0 - dq docol, lit, 0xF4, pack8, exit - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Runtime word definition ;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; -;;; We need to be able to use Forth code that defines other Forth code; it -;;; will be the easiest way to create our Forth-flavored assembly languge. To -;;; do that, there's a critical bootstrapping problem: The variables that we -;;; allocate on the heap in _start must be used by the Forth words that define -;;; other Forth words (and, in general, they are needed for anything that -;;; does memory management). Since the heap's address isn't known until -;;; runtime, we can't use build-time labels to locate the heap or the -;;; variables on it, in the way we've done for everything up to now. -;;; -;;; In fact, it's worse than that: nothing we define at build time can -;;; statically reference anything on the heap; it must always be given the -;;; heap's address as a parameter. That also means statically defined words -;;; can't reference runtime words, at all, except via special code that goes -;;; outside the normal Forth execution model. -;;; -;;; So, what we'll want to do to deal with that is copy ourselves onto the -;;; heap, and run the rest of the program from there. It would be okay in -;;; principle to keep a few things such as docol in the static code segment, -;;; as long as they don't need to reference the heap, though it might in some -;;; sense be more elegant to entirely abandon the code segment and run -;;; heap-only. At any rate, to keep the set of stuff we have to copy small, -;;; we'll want to make the change-over as soon as possible. -;;; -;;; Following a common Forth practice, we implement variables as words that -;;; push the corresponding addresses onto the stack. Since the variables that -;;; define the heap are ON the heap, we will definitely need two distinct -;;; versions of these; having the two versions be almost-compatible allows us -;;; to minimize code duplication. Since they do have slightly different -;;; interfaces, we prefix the names of the early ones with "early_". - -; First, we have some words that follow the pack* idioms and are used to -; build specific assembly-based constructs needed in word implementations. -; You can think of them as macros. They are in a sense reimplementations of -; their flatassembler equivalents, which are far, far above, and have more -; documentation. -; -; Stack in: -; base address -; Stack out: -; new base address -defword pack_next, 0 - dq docol, lods64, rax, jmp_abs_indirect_reg64, exit - -; This is another helper "macro" that we'll use in defining assembly words -; from Forth. As before, see the flatassembler version for more explanation. -; -; Stack in: -; base address -; destination address (absolute) -; Stack out: -; new base address -defword pack_beforenext, 0 - dq docol, rax, mov_reg64_imm64, rax, jmp_abs_indirect_reg64, exit - -; This is another helper "macro" that we'll use in defining assembly words -; from Forth. In particular, this one is used in docol. As before, see the -; flatassembler version for more explanation. -; -; Stack in: -; base address -; source register keyword -; Stack out: -; new base address -defword pack_pushcontrol, 0 - dq docol - dq swap, rbp, lit, -8, rbp, lea_reg64_disp8_reg64, swap - dq rbp, lit, 0, mov_disp8_reg64_reg64 - dq exit - -; This is another helper "macro" that we'll use in defining assembly words -; from Forth. In particular, this one is used in "exit". See the flatassembler -; version for more explanation. -; -; Stack in: -; base address -; target register keyword -; Stack out: -; new base address -defword pack_popcontrol, 0 - dq docol - dq rbp, lit, 0, roll3, mov_reg64_disp8_reg64 - dq rbp, lit, 8, rbp, lea_reg64_disp8_reg64 - dq exit - -; Now, we have a bunch of words that are used for traversing the Forth -; core data structures that describe words. First, we have a couple that -; relate to individual words and their pieces... -; -; Jonesforth calls this "TFCA" and ">CFA"; its author speculates that the -; original meaning is "code field address". -defword entry_to_execution_token, 0 - dq docol - ; Skip next-entry pointer, flag byte, and start terminator. - dq lit, 10, add - ; Skip string contents. - dq dup, stringlen, add - ; Skip one for the null terminator, seven more for alignment. - dq lit, 8, add - ; Zero the low bits and now it's aligned. - dq lit, 7, invert, and - dq exit - -; Jonesforth calls this "CFA>". Jonesforth's implementation searches the -; entire dictionary, since its word header format isn't designed to be -; traversed in reverse, but ours is, so it should be fast. -defword execution_token_to_entry, 0 - dq docol - dq lit, 1, sub - dq dup, reverse_padding_len, sub - dq dup, reverse_stringlen, sub - dq lit, 9, sub - dq exit - -; Stack in: -; entry address -; Stack out: -; flags byte -defword fetch_entry_flags, 0 - dq docol - dq lit, 8, add, fetch, lit, 0xFF, and - dq exit - -; Stack in: -; entry address -; flags byte -defword store_entry_flags, 0 - dq docol - dq swap, lit, 8, add, dup, fetch - ; (new flags byte, address of flags byte, old flags byte + context) - dq roll3, lit, 0xFF, and - dq swap, lit, 0xFFFFFFFFFFFFFF00, and, or - dq swap, store - dq exit - -defword entry_to_name, 0 - dq docol - dq lit, 10, add - dq exit - -; Now, having finished with individual words, we have a bunch of stuff that -; traverses the overall dictionary structure, which is formed by a linked list -; using the pointer that each word starts with. -; -; This one is the backend for early_find_in; it will eventually also be the -; backend for a non-early version. -; -; Stack in: -; dictionary to search within -; name string to find -; Stack out: -; execution token or 0 -defword find_in, 0 - dq docol - ; It will be more convenient to have the dictionary pointer on top. - dq swap - - ; If the dictionary pointer is null, exit. - ; (name string to find, current word pointer) - dq dup, lit, 0, eq, zbranch, 4*8, swap, drop, exit - - ; Check this entry's "hidden" flag. - ; (name string to find, current word pointer) - dq dup, fetch_entry_flags, lit, 0x80, and, lit, 0x80, ne, zbranch, 8*8 - - ; Test whether this entry is a match. - ; (name string to find, current word pointer) - dq dup2, lit, 10, add, stringcmp, zbranch, 4*8 - - ; If we're here, it's not a match; traverse the pointer and repeat. - ; (name string to find, current word pointer) - dq fetch, branch, -28*8 - - ; If we're here, it's a match. Clean up our working state and exit. - ; (name string to find, current word pointer) - dq swap, drop, exit - -; This is the backend for early_next_newer_entry_in; it will eventually also -; be the backend for a non-early version. -; -; This returns zero if the entry isn't found at all. -; -; Stack in: -; dictionary to search within -; entry address -; Stack out: -; entry address or 0 -defword next_newer_entry_in, 0 - dq docol - ; Dictionary pointer on top - dq swap - ; Exit if null - dq dup, lit, 0, eq, zbranch, 4*8, swap, drop, exit - ; Test if it's a match - dq dup2, fetch, ne, zbranch, 4*8 - ; Non-match case; loop - dq fetch, branch, -16*8 - ; Match case; return - dq swap, drop, exit - -; This is the backend for early_guess_entry_end; it will eventually also be -; the backend for a non-early version. -; -; Stack in: -; "here" value -; dictionary to search within -; entry address -; Stack out: -; next entry address or 0 -defword guess_entry_end_in, 0 - dq docol - ; Check whether the entry is flagged as metadata... - dq dup, fetch_entry_flags, lit, 0x40, and, lit, 0x40, eq, zbranch, 6*8 - ; ... if so, return the same entry address as the result, which means we're - ; saying the length is zero. - dq swap, drop, swap, drop, exit - ; If not, search backwards from the end to find the following entry. - ; (here, original entry address) - dq dup, unroll3 - ; (original entry address, here, original entry address) - dq next_newer_entry_in - ; (original entry address, here, next entry address or 0) - - ; Check whether we were able to find the next-entry address. - dq dup, lit, 0, eq, zbranch, 4*8 - - ; This is the branch where the original entry is not in the list. Return - ; the original entry address as the result; as above, this means we're - ; saying the length is zero. Since we don't have anything else to go on, - ; this is the safe assumption. - dq drop, drop, exit - - ; This is the branch where we found it. Return the next entry address. - dq swap, drop, swap, drop, exit - -; That's it for the code that traverses the dictionary; now we have some -; code meant for use in debugging, which prints out the contents of individual -; words' bodies. -; -; This one is the backend for early_show_hex; it will eventually also be the -; backend for a non-early version. -; -; Stack in: -; entry address -; end address -defword show_hex_between, 0 - dq docol - dq swap, entry_to_execution_token, lit, 8, add - ; (end address, current address) - dq dup2, ge, zbranch, 4*8, drop, drop, exit - dq litstring, " ", emitstring - dq dup, fetch, dothex64 - dq lit, 8, add - dq branch, -17*8 - -; This one "decompiles" a Forth word, printing the names of the codewords it -; consists of. It also understands all the built-in literal-related words, and -; serves as an example of how to do that. -; -; This is the backend for early_show_source; it will eventually also be the -; backend for a non-early version. -; -; Stack in: -; entry address -; end address -defword show_source_between, 0 - dq docol - - dq swap, entry_to_execution_token, lit, 8, add - ; (end address, current address) - - ; This is the start of the loop. - ; - ; If it's zero-length, don't try to print its contents. - dq dup2, ge, zbranch, 4*8, drop, drop, exit - - ; If it's not a word address, the fetch will segfault. We accept this. - dq dup, fetch, execution_token_to_entry, entry_to_name - - ; (end address, current address, name) - - dq litstring, " ", emitstring - dq dup, emitstring - dq swap, lit, 8, add, swap - - dq dup, litstring, "lit", stringcmp, zbranch, 57*8 ; 6 words - dq dup, litstring, "litpack8", 0, stringcmp, zbranch, 50*8 ; 7 words - dq dup, litstring, "litpack16", stringcmp, zbranch, 43*8 ; 7 words - dq dup, litstring, "litpack32", stringcmp, zbranch, 36*8 ; 7 words - dq dup, litstring, "litpack64", stringcmp, zbranch, 29*8 ; 7 words - dq dup, litstring, "branch", stringcmp, zbranch, 23*8 ; 6 words - dq dup, litstring, "zbranch", stringcmp, zbranch, 17*8 ; 6 words - dq dup, litstring, "0branch", stringcmp, zbranch, 11*8 ; 6 words - dq dup, litstring, "litstring", stringcmp, zbranch, 16*8 ; 7 words - - ; This is the plain, non-lit branch. - dq drop, branch, -82*8 - - ; This is the lit branch that expects to be followed by a single word. - dq litstring, " ", emitstring - dq drop, dup, fetch, dot - dq lit, 8, add - dq branch, -94*8 - - ; This is the lit branch that expects to be followed by a string. First, we - ; print the string... - dq drop - dq litstring, " ", emitstring - dq lit, 0x22, fetch_value_stack, emitstring, drop - dq dup, emitstring - dq lit, 0x22, fetch_value_stack, emitstring, drop - - ; ... then, we skip the string. - ; - ; We always add a word as padding. If the length is a multiple of 8, this is - ; the zero word following the contents. If it's not, the division rounds - ; down so the padding word has the tail of the contents in it too. - dq dup, stringlen, lit, 8, divmod, swap, drop, lit, 1, add - ; (end address, current address, n words including padding) - dq lit, 8, mul, add - - dq branch, -126*8 - -; This is the backend for early_show_source_or_hex; it will eventually also -; be the backend for a non-early version. -; -; Stack in: -; entry address -; end address -defword show_source_or_hex_between, 0 - dq docol - - ; If it's zero-length, don't try to print its contents. - dq dup2, eq, zbranch, 2*8, exit - - dq swap, dup, unroll3, swap, roll3 - ; (entry address, end address, entry address) - dq entry_to_execution_token, dup, fetch, lit, 8, sub, eq, zbranch, 3*8 - dq show_hex_between, exit - dq show_source_between, exit - - -;;;;;;;;;;;;;; -;;; Lexing ;;; -;;;;;;;;;;;;;; - - -; In: -; next input address -; Out: -; next input address (updated) -; input byte -defword key, 0 - dq docol - dq dup, dup, lit, -8, and, fetch, swap, lit, 7, and - ; (next input address, 64-bit input word, byte index within word) - dq dup, zbranch, 13*8 - dq lit, 1, sub, swap, lit, 256, divmod, swap, drop, swap, branch, -14*8 - dq drop, lit, 0xFF, and - dq swap, lit, 1, add, swap - dq exit - - - -;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Heap bootstrapping ;;; -;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; -;;; Now, we have a little more work to do before we can bootstrap the heap. -;;; We have all these early_* words which rely on being told explicitly where -;;; the heap is, most of them pertaining to defining words at runtime. Once -;;; the heap exists, these won't be needed, so we never actually copy them to -;;; the heap. To make sure that's easy to keep track of, they're all together -;;; at the end here. -;;; -;;; The goal is that none of these do any particularly interesting work, -;;; instead deferring to implementations defined in other sections that will -;;; be re-used by the later, fully-bootstrapped stuff. At the moment, some of -;;; them still do interesting things; it's a work in progress. - -; Stack in: -; heap address -; Stack out: -; heap address -; requested variable address -defword early_heap, 0 - dq docol, dup, lit, control_stack_size, add, exit -defword early_s0, 0 - dq docol, early_heap, lit, 8, add, exit -defword early_r0, 0 - dq docol, early_heap, lit, 16, add, exit -defword early_latest, 0 - dq docol, early_heap, lit, 24, add, exit -defword early_here, 0 - dq docol, early_heap, lit, 32, add, exit - -; Stack in: -; heap address -; name string to find -; Stack out: -; heap address -; execution token or 0 -defword early_find, 0 - dq docol, swap, early_latest, fetch, swap, unroll3, swap, find_in, exit - -; Stack in: -; heap address -; entry address -; Stack out: -; heap address -; entry address or 0 -defword early_next_newer_entry, 0 - dq docol - dq swap, early_latest, fetch, swap, unroll3, swap, next_newer_entry_in - dq exit - -; This doesn't work on the entry at the end of the ELF .text segment. It does -; work on everything else. -; Stack in: -; heap address -; entry address -; Stack out: -; heap address -; guessed entry end address (first byte that's not part of it) -defword early_guess_entry_end, 0 - dq docol - dq swap, early_here, fetch, swap, early_latest, fetch, swap - ; (entry, here, latest, heap) - dq lit, 4, unroll, roll3 - ; (heap, here, latest, entry) - dq guess_entry_end_in - dq exit - -; Stack in: -; heap address -; entry address -; Stack out: -; heap address -defword early_show_hex, 0 - dq docol - dq dup, unroll3, early_guess_entry_end, swap, unroll3 - ; (heap address, entry address, end address) - dq show_hex_between - dq exit - -; Stack in: -; heap address -; entry address -; Stack out: -; heap address -defword early_show_source, 0 - dq docol - dq dup, unroll3, early_guess_entry_end, swap, unroll3 - ; (heap address, entry address, end address) - dq show_source_between - dq exit - -; Stack in: -; heap address -; entry address -; Stack out: -; heap address -defword early_show_source_or_hex, 0 - dq docol - dq dup, unroll3, early_guess_entry_end, swap, unroll3 - ; (heap address, entry address, end address) - dq show_source_or_hex_between - dq exit - -; Stack in: -; heap address -; entry address -; Stack out: -; heap address -defword early_describe, 0 - dq docol - dq litstring, 0x0a, emitstring - dq dup, dothex64 - dq litstring, 0x0a, emitstring - dq dup, entry_to_name, emitstring, litstring, ":", emitstring - dq litstring, 0x0a, emitstring - dq litstring, " ", emitstring - dq early_show_source_or_hex - dq litstring, 0x0a, emitstring - dq exit - -; Stack in: -; heap address -defword early_describe_all, 0 - dq docol - dq early_latest - dq dup, lit, 0, eq, zbranch, 3*8, drop, exit - ; Start of the loop - dq fetch - dq dup, lit, 0, eq, zbranch, 3*8, drop, exit - dq dup2, early_describe, drop - dq branch, -13*8 - dq exit - -; Allocate space by incrementing "here", and output a word header in it. -; Also add it to the "latest" linked list. Use zero as the flag values; -; callers that want something else can do that themselves. -; -; We'll use the pack* words to do this, the way they update the pointer is -; convenient. -; -; See "Execution model", above, for reminders of the details of this format. -; Create is responsible for everything up to the codeword, not including it. -; -; This is surprisingly painful to implement, in terms of stack juggling, but -; then there's a sense in which it's the core trick to bootstrapping the heap. -; -; Stack in: -; heap address -; name string -; Stack out: -; heap address -defword early_create, 0 - dq docol - ; Retrieve the values of "here" and "latest". - dq swap, early_here, fetch, swap, early_latest, fetch, swap, lit, 4, unroll - ; Pack the old value of "latest" as the first field of the header, linking - ; from the newly-defined word to the next-newest word. - dq pack64 - ; Pack a null byte as the flags. - dq lit, 0, pack8 - ; Pack another null byte as the start terminator of the name (which is - ; terminated at both ends). - dq lit, 0, pack8 - ; Pack the name and its end terminator. - dq swap, packstring - ; Alignment before the codeword. - dq lit, 8, packalign - ; Retrieve the value of "here" (which still doesn't reflect our additions), - ; and store it at the address of "latest". It's the start of our - ; newly-defined word, which makes it the latest word. - dq swap, early_here, fetch, swap, early_latest, swap, unroll3, store, swap - ; Retrieve the address of "here" again and store our updated value there. - dq swap, early_here, swap, unroll3, store - dq exit - -; Stack in: -; heap address -; value to append to current word-in-progress -; Stack out: -; heap address -defword early_comma, 0 - dq docol - ; Retrieve the value of "here" and pack the value there. - dq swap, early_here, fetch, swap, unroll3, swap, pack64 - ; Store the updated value of "here". - dq swap, early_here, swap, unroll3, store - dq exit - -; Stack in: -; heap address -; Stack out: -; heap address -defword early_self_codeword, 0 - dq docol, early_here, fetch, lit, 8, add, early_comma, exit - -; Stack in: -; heap address -; Stack out: -; heap address -defword early_docol_codeword, 0 - dq docol - dq litstring, "docol", early_find - dq entry_to_execution_token, execute, early_comma - dq exit - -; Stack in: -; heap address -; new value to overwrite "here" -; Stack out: -; heap address -defword early_here_store, 0 - dq docol, swap, early_here, swap, unroll3, store, exit - -; Stack in: -; heap address -; address for new variable word to return -; name string -; Stack out: -; heap address -defword early_variable, 0 - dq docol - dq swap, unroll3, early_create, early_self_codeword - ; (address to return, heap address) - dq early_here, fetch, swap, unroll3, swap - ; (heap address, modified "here" value, address to return) - dq rax, mov_reg64_imm64, rax, push_reg64 - ; (heap address, modified "here" value) - dq pack_next, lit, 8, packalign, early_here_store - dq exit - -; Stack in: -; heap address -; name string -; Stack out: -; heap address -defword early_keyword, 0 - dq docol - dq early_create, early_here, fetch, swap - ; (self codeword address, heap address) - dq early_docol_codeword - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq swap, early_comma - ; (heap address) - dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq early_here, fetch, lit, 8, packalign, early_here_store - dq exit - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Now.... what was our original goal, again? ;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; -;;; Finally, having fully bootstrapped our runtime environment, we move on -;;; to the core stuff we actually want to accomplish. For this quine, that's -;;; outputting itself. - -;;; -;;; One of the most charming naming traditions in Forth is that the -;;; top-level word that stays running forever, is called "quit". -;;; -defword quit, 0 - dq docol - - ;;; - ;;; Although we initialized rbp already, we do so again because we'll want - ;;; that on subsequent visits to this word - it's the main thing it's for. - ;;; Keep in mind that rsi is the actual "instruction pointer", and we're - ;;; leaving it unchanged, we just get rid of everything above it. - ;;; - ;dq r0, control! ; overwrite rbp to reset the control stack - ; TODO though the implementation of r0 is trivial, it depends on where we - ; put the heap, so it can't be hardcoded, we'll have to build it in RAM. - ; the same therefore goes for anything that needs to call it. so we can't - ; call it here, now, yet - we have prep work to do first - - ;;; - ;;; Do the read-eval-print-loop, which is the main body of the Forth - ;;; interpreter. - ;;; - ;dq interpret ; run the repl - dq quine - - ;;; - ;;; If the repl ever exits, do it all again. - ;;; - ;dq branch, quit - $ - dq lit, 0, sys_exit - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; (new) Implementation strategy ;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; -;;; We assemble the entire file contents in a heap-allocated buffer. When -;;; the file is fully assembled, we output it. -;;; -defword quine, 0 - dq docol - - ; We still have "heap" on the stack, so we can call early_here. Add a - ; constant to "here" in-place, keeping a copy of the pointer ... - dq early_here, lit, 0x78, swap, addstore - ; ... and now we have allocated a block of memory, with its address on the - ; stack. We also still have "heap" at the bottom of the stack, for future - ; use. - - ; We have one label, and two pieces of information about it: value and - ; status. We keep them on the stack. We also have a mutable copy of the - ; buffer's address. - ; - ; This stack layout is the interface used throughout the "assembler"; this - ; quine routine uses it when calling the routines that build the various - ; pieces of the output, and those pieces in turn use it when calling the - ; label-handling routines. - ; - ; Stack: - ; "heap" - ; start address of allocated output - ; label's value - ; label's status - ; address of current output point within allocated block - ; (top) - ; - ; Status is a bit field: - ; bit zero is whether it was used before being defined - ; bit one is whether it's been defined - ; bit two is whether the guessed value wound up equaling the actual value - dq dup, lit, 0, lit, 0, roll3 - - ; This takes an address to write to on the stack, writes stuff there, and - ; returns the next address after where it stopped Writing. - dq all_contents - - ; The two-pass magick: ; Reset the output offset to the beginning of the - ; block. - dq drop, roll3, dup, lit, 4, unroll - dq all_contents - - ; Drop the copy of the buffer's address. - dq drop - - ; Drop the label data. - dq drop, drop - - ; This takes a buffer's address on the stack, skips an ELF file header and - ; program header based on hardcoded size, computes an offset (secretly - ; hardcoded), and writes that offset into an appopriate place in the middle - ; of those headers. It then returns the length of the used portion of the - ; buffer. - ;dq lit, 0x78, swap - dq lit, file_size, swap - - ; write() from stack-allocated buffer - dq sys_write - - dq exit - -; Stack in: -; output memory start -; label value (guessed or actual) -; label status -; output memory current point -; Stack out: -; output memory start -; label value (guessed or actual) -; label status (potentially modified) -; output memory current point -; label value for caller to use -defword use_label, 0 - dq docol - - ; Fetch the status - dq swap - ; Check the bit that indicates it's been set. - dq dup, lit, 2, and, zbranch, 10*8 - - ; If we're here, it has been set already, so just put the status back... - dq swap - ; Fetch the actual value... - dq lit, 3, roll, dup, lit, 4, unroll - ; ... and exit - dq exit - - ; If we're here, it hasn't been set yet, so mark it used-before-set. - dq lit, 1, or - ; Put the status back... - dq swap - ; Fetch the guessed value... - dq lit, 3, roll, dup, lit, 4, unroll - ; ... and exit - dq exit - -; Stack in: -; output memory start -; label value (guessed or actual) -; label status -; output memory current point -; Stack out: -; output memory start -; label value (now set to actual) -; label status (modified) -; output memory current point -defword set_label, 0 - dq docol - - ; Compute the current offset, to use as the actual value - dq dup, lit, 5, roll, dup, lit, 6, unroll, sub - ; old value, status, point, new value - - ; Overwrite the old actual value; keep a copy - dq dup, lit, 5, roll - ; status, point, new value, new value, old value - dq eq, swap - ; status, point, equality, new value - dq lit, 4, unroll - ; new value, status, point, equality - - ; We don't need to branch. Now we mark the status as having been defined, - ; and we also set bit 2 if appropriate. - dq lit, 4, mul - dq lit, 3, roll, or, lit, 2, or, swap - - dq exit - - -; This takes an address to write to on the stack, writes stuff there, and -; returns the next address after where it stopped Writing. -; -; It also makes use of label stuff, further back on the stack. -defword all_contents, 0 - dq docol - dq elf_file_header, elf_program_header - dq output_start_routine - dq self_raw - dq set_label - dq exit - -;;; -;;; ELF header -;;; -;;; This is the top-level ELF header, for the entire file. An ELF always has -;;; exactly one of this header, which is always at the start of the file. -;;; -defword elf_file_header, 0 - dq docol - - dq litpack32, 0x7f bappend "ELF" ; magic number - dq litpack8, 2 ; 64-bit - dq litpack8, 1 ; little-endian - dq litpack8, 1 ; ELF header format v1 - dq litpack8, 0 ; System-V ABI - dq litpack64, 0 ; (padding) - - dq litpack16, 2 ; executable - dq litpack16, 0x3e ; Intel x86-64 - dq litpack32, 1 ; ELF format version - - ; Compute the entry pointer. - dq litpack64, _start ; entry point - ; The offset of _start. This includes the origin, intentionally. - - dq litpack64, 64 ; program header offset - ; We place the program header immediately after the ELF header. This - ; offset is from the start of the file. - dq litpack64, 0 ; section header offset - dq litpack32, 0 ; processor flags - dq litpack16, 64 ; ELF header size - dq litpack16, 56 ; program header entry size - dq litpack16, 1 ; number of program header entries - dq litpack16, 0 ; section header entry size - dq litpack16, 0 ; number of section header entries - dq litpack16, 0 ; section name string table index - - dq exit - - -;;; -;;; Program header -;;; -;;; An ELF program header consists of any number of these entries; they are -;;; always consecutive, but may be anywhere in the file. We always have -;;; exactly one, and it's always right after the ELF file header. -;;; -defword elf_program_header, 0 - dq docol - - dq litpack32, 1 ; "loadable" segment type - dq litpack32, 0x05 ; read+execute permission - dq litpack64, 0 ; offset in file - dq litpack64, $$ ; virtual address - ; required, but can be anything, subject to alignment - dq litpack64, 0 ; physical address (ignored) - - ; Fill in 0 as the file size for now, to avoid unitialized memory. - dq use_label, pack64 ; size in file - dq use_label, pack64 ; size in memory - - dq litpack64, 0 ; segment alignment - ; for relocation, but this doesn't apply to us - - dq exit - - -defword output_start_routine, 0 - dq docol - dq cld - dq lit, 9, rax, mov_reg64_imm64 - dq lit, heap_requested_address, rdi, mov_reg64_imm64 - dq lit, heap_size, rsi, mov_reg64_imm64 - dq lit, 0x07, rdx, mov_reg64_imm64 - dq lit, 0x22, r10, mov_extrareg64_imm64 - dq lit, 0, r8, mov_extrareg64_imm64 - dq lit, 0, r9, mov_extrareg64_imm64 - dq syscall - dq rax, rdi, mov_reg64_reg64 - dq exit - - -; write() the machine code by using self-reference -; TODO do this in a "real" quine way -defword self_raw, 0 - dq docol - dq dup - dq lit, elf_header + 0xc4 ; source - dq lit, file_size - 0xc4 ; length - ; destination destination source length - dq dup, lit, 4, roll, add, lit, 4, unroll - ; result destination source length - dq memcopy ; broken since memcopy args change - dq exit - - -; Routines that traverse the raw code need a way to guess where the end of a -; word's contents are, lest they traverse off the edge of the world and -; segfault. On the heap, we have the "here" pointer to provide an upper bound. -; For code that's loaded from the ELF's text segment, we don't get to do that, -; so we need another way. -; -; We could notionally use syscalls to check how large the text segment is, but -; that would make us more dependent on specifics of the ABI and the kernel. -; Instead, we invent this concept of a metadata word, which is designated with -; a new flag bit and exists to annotate the address space rather than to be -; invoked. The traversal routines hardcode the expectation that the text -; segment ends with a metadata word. Also, they skip metadata words when -; describing things. -; -; Since the boot source is a raw string, not a Forth word, it also needs to -; be flagged as metadata. For convenience's sake, we use a single metadata -; word both to delimit the segment end, and to hold the boot source. Cute, -; right? -defword boot_source, 0x40 - ; Keep in mind that these words don't exist in memory, so branching won't - ; have the intended effect. Any logic that requires branching needs to be - ; written to the heap instead, and branch while running there. In fact, - ; let's start out with an example of that, which is also our top-level - ; routine! - dq ": quit r0 @ control! interpret branch [ -2 8 * , ] ; quit " - ; o/~ Like a whirlpool and it never ends. o/~ - ; - ; This implementation of quit does the same thing it does in Jonesforth: - ; First, it wipes the control stack, completely emptying it so that whatever - ; calls brought us here are forgotten and no longer relevant to what happens - ; going forward. Second, it calls interpret repeatedly, forever. - ; - ; Interpret will return control to quit after every iteration. The control - ; stack doesn't get wiped on those iterations, but user code that wants to - ; halt its own execution can always call quit to do that, which will once - ; again wipe the control stack. Isn't that trippy? Instead of unwinding the - ; stack it just overwrites it! - ; - ; Notice that we immediately call quit, before doing anything else. That's - ; load-bearing. Keep it that way. To get this far, we used a trampoline, - ; created in cold_start, that calls interpret in an unrolled loop, just - ; barely enough times to successfully reach that invocation. If you make - ; quit longer, make sure to also make the trampoline longer and adjust its - ; starting location. It's been defined with no extra length, in order to - ; make sure things will crash in a noticeable way if anyone modifies it - ; without that follow-through. It would be important to have a close look at - ; the trampoline setup regardless, because it's allocated in space that this - ; code could easily overwrite by accident, so it's better to have it fail in - ; a predictable way than an unpredictable one. - - ; From here, we can do more or less whatever we want; nearly all the - ; bootstrapping concerns have been dealt with. We do have to make sure every - ; line in boot_source that outputs a string outputs one that's an exact - ; multiple of eight bytes long; any accidental null-padding that - ; flatassembler inserts will be treated as a string terminator by - ; attach-string-to-input-buffer. - - ; In general, we're going to want to be able to go on little excursions - ; where we define utility words that are only useful for one task, then - ; deallocate that stuff after we're done with it. We implement "forget", - ; which removes both dictionary entries and heap allocations for the entry - ; pointer it's given and everything that came after. - ; - ; The implementation strategy is the same as Jonesforth's version, but - ; Jonesforth runs in immediate mode and reads a word to operate on, whereas - ; ours takes an entry pointer and runs in either compiled or immediate - ; modes. - ; - ; In: - ; entry pointer - dq ": forget dup @ latest ! here ! ; " - - ; We'll be defining a lot of immediate words, so we should set up a terse - ; way to do that. - dq ": make-immediate latest @ set-word-immediate ; " - dq ": make-hidden latest @ hide-entry ; " - dq ": make-visible latest @ unhide-entry ; " - - ; The word "'" quotes the following word, looking it up and treating it as - ; a constant. In immediate mode, the constant winds up on the stack; in - ; compile mode it gets compiled. - ; - ; There are a few possible implementation strategies here. Running as an - ; immediate word means there's a clear and unambiguous concept of "the - ; following word", so that's what we do; otherwise we'd have to get clever - ; about somehow finding out where we were called from. That means we take on - ; what would otherwise be the interpreter's responsibility, of checking what - ; mode we're in. Happily, that's easy to do. - ; - ; Though it might be nice to have high-level flow control for this, our - ; implementation of "if" below relies on "'" several times, whereas "'" only - ; branches once. So we bootstrap "'" first. - dq ": ' word value@ find dropstring-with-result " - dq " interpreter-flags @ 1 & 0branch [ 2 8 * , ] literal " - dq " ; make-immediate " - - ; Sooner or later we'll want to define recursive words; this one lets us - ; do that. It compiles into a call to the word that's currently being - ; defined (strictly speaking, the one whose definition was most recently - ; begun). - dq ": recurse latest @ entry-to-execution-token , ; make-immediate " - - ; We use a novel suffix-based approach to flow control. We define words - ; { and } which describe the boundaries of blocks of code, leaving a - ; description on the value stack, while still compiling the contents - ; normally. - ; - ; Then follow-up words such as "if" can use that information to slide - ; the blocks around and insert any needed branches and other logic. - ; - ; After compiling a { ... } block, the stack is (start pointer, length). - dq ": { here @ ; make-immediate " - dq ": } dup here @ swap - ; make-immediate " - - ; (start pointer, length) - dq ": if 2dup swap dup 5 8 * + 3roll " - ; (start pointer, length, start pointer, adjusted start pointer, length) - dq " memmove " - ; (start pointer, length) - dq " swap here @ swap here ! swap " - ; (old here, length) - dq " ' lit entry-to-execution-token , 0 , " - dq " ' != entry-to-execution-token , " - ; The branch length needs to be one word longer than the block length, - ; because the length field itself is part of the scope of the branch. - dq " ' 0branch entry-to-execution-token , dup 8 + , " - ; (old here, length) - dq " drop 5 8 * + here ! ; make-immediate " - - ; (start pointer, length) - dq ": unless 2dup swap dup 5 8 * + 3roll " - ; (start pointer, length, start pointer, adjusted start pointer, length) - dq " memmove " - ; (start pointer, length) - dq " swap here @ swap here ! swap " - ; (old here, length) - dq " ' lit entry-to-execution-token , 0 , " - dq " ' = entry-to-execution-token , " - ; The branch length needs to be one word longer than the block length, - ; because the length field itself is part of the scope of the branch. - dq " ' 0branch entry-to-execution-token , dup 8 + , " - ; (old here, length) - dq " drop 5 8 * + here ! ; make-immediate " - - ; (true start, true length, false start, false length) - dq ": if-else " - ;dq " dup 4 roll dup 5 unroll + " - ; - ; First we slide the false-block forward, then the true-block. We slide - ; them both directly into their final positions, leaving space at the start - ; for a test and branch, and space in between for an unconditional branch. - ; Those spaces will take five words, and two words, respectively. So the - ; false-block gets moved by seven words, and the true-block gets moved by - ; five words. - ; - ; Note that this has diverged slightly from the self-hosted version, - ; because in this version we don't have "pick" yet. - dq " 2dup swap dup 7 8 * + 3roll memmove " - dq " 4 roll dup 5 unroll 4 roll dup 5 unroll " - dq " swap dup 5 8 * + 3roll memmove " - - ; (true start, true length, false start, false length) - ; - ; Now we write out the initial test-and-branch. - dq " 4 roll dup 5 unroll here @ 6 unroll here ! " - ; (old here, true start, true length, false start, false length) - dq " ' lit entry-to-execution-token , 0 , " - dq " ' != entry-to-execution-token , " - ; Branch past the length field, the true-block, and the unconditional - ; branch in the middle. - dq " ' 0branch entry-to-execution-token , " - dq " 3roll dup 4 unroll 3 8 * + , " - ; - ; Next, write out the unconditional branch in the middle. - dq " swap dup 3unroll 5 8 * + here ! " - dq " ' branch entry-to-execution-token , " - ; Branch past the length field and the false-block. - dq " dup 8 + , " - ; - ; Set "here" to point to the true end. - dq " drop drop drop drop 7 8 * + here ! " - dq " ; make-immediate " - - ; (start, length) - dq ": forever " - dq " ' branch entry-to-execution-token , 8 + -1 * , drop " - dq " ; make-immediate " - - ; This slides the body forward, leaving the test where it is. It puts a - ; conditional branch in-between them, then appends an unconditional branch - ; at the end. - ; - ; (test start, test length, body start, body length) - dq ": while " - ; The conditional branch needs five words. - dq " 2dup swap dup 5 8 * + 3roll memmove " - dq " here @ 5 unroll swap dup 3unroll here ! " - ; (old here, test start, test length, body start, body length) - dq " ' lit entry-to-execution-token , 0 , " - dq " ' != entry-to-execution-token , " - ; Branch past the length field, the body, and the unconditional branch. - dq " ' 0branch entry-to-execution-token , " - dq " dup 3 8 * + , " - ; Set "here" to the new end. - dq " 5 8 * 6 roll + here ! " - ; (test start, test length, body start, body length) - ; Unconditionally branch backwards past the branch word, the body, the - ; conditional branch, and the test. - dq " ' branch entry-to-execution-token , " - dq " 6 8 * + swap drop + swap drop -1 * , " - dq " ; make-immediate " - - ; This use of bitwise and is okay because they're both either 0 or 1. - ; We'll have logical and real soon now, be patient... :) - dq ": is-in-heap dup log @ <= swap here @ > & ; " - -; dq ": unlink-pre-heap-words " -; dq " latest @ " -; dq " dup { dup is-in-heap 0 = { drop exit } if } " -; dq " { drop exit } if-else " -; dq " { dup @ is-in-heap } { @ } while " -; dq " 0 swap ! ; " - ; Do it immediately, so that we don't accidentally rely on any of that. - ;dq "unlink-pre-heap-words " - - ; Now some fancier stack combinators. - ; - ; While it might be nice, for performance reasons, to do these in - ; assembler, for now it's more important to have them at all. - dq ": 1- 1 - ; " - dq ": 1+ 1 + ; " - dq ": max 2dup >= { swap drop } { drop } if-else ; " - dq ": min 2dup <= { swap drop } { drop } if-else ; " - - dq ": over swap dup 3unroll ; " - dq ": pick 2 + dup roll dup 3roll unroll ; " - ; Standard Forth doesn't have equivalents of our ndrop and ndup. The HP - ; calls them DROPN and DUPN but that doesn't go well with ie. 2dup or 3roll, - ; so we do it like this. - dq ": ndrop { dup } { swap drop 1- } while drop ; " - dq ": ndup dup 1+ swap { dup } " - dq " { swap dup pick 3unroll swap 1- } while 2drop ; " - dq ": 3drop drop drop drop ; " - dq ": 3dup 2 pick 2 pick 2 pick ; " - - dq ": && 0 != swap 0 != * ; " - dq ": || | 0 != ; " - dq ": not 0 = ; " - dq ": negate -1 * ; " - - dq ": align-floor dup 3unroll /% swap drop * ; " - - dq ": nexit 8 * control@ + r0 @ min control! ; " - - ; Let's have strings now. - dq ": s"" " - dq " consume " - dq " interpreter-flags @ 1 & " - dq " { ' litstring entry-to-execution-token , } if " - dq " here @ key { dup dup 34 != && } { pack8 key } while " - dq " drop 0 pack8 " - dq " interpreter-flags @ 1 & " - dq " { 8 packalign here ! } " - dq " { drop here @ } if-else " - dq " ; make-immediate " - - ; Finicky semantics, but also important. - dq ": ."" " - dq " ' s"" entry-to-execution-token execute " - dq " interpreter-flags @ 1 & " - dq " { ' emitstring entry-to-execution-token , } " - dq " { emitstring } if-else " - dq " ; make-immediate " - - ; While we're thinking about input, let's also have comments. - dq ": ~ " - dq " key { dup dup 10 != && } { drop key } while drop " - dq " ; make-immediate " - - ; Some output formatting tools. - dq ": space 32 value@ emitstring drop ; " - dq ": newline 10 value@ emitstring drop ; " - dq ": indent { dup } { space 1- } while drop ; " - dq ": .hexn 16 swap .base-unsigned ; " - - ; Some debugging tools. - dq ": stack " - dq " s0 @ 8 - { dup value@ 8 + != } " - dq " { dup s0 @ 8 - != { space } if dup @ . 8 - } " - dq " while drop newline ; " - dq ": stackhex " - dq " s0 @ 8 - { dup value@ 8 + != } " - dq " { dup s0 @ 8 - != { space } if dup @ .hex64 8 - } " - dq " while drop newline ; " - - dq ": oldest-entry " - dq " latest @ { dup @ } { @ } while ; " - - dq ": oldest-entry-in " - dq " dup " - dq " dup { { dup @ } { @ } while } if " - dq " dup 3roll = { drop 0 } if ; " - - dq ": next-newer-entry " - dq " latest @ " - dq " 2dup = { 2drop 0 exit } if " - dq " { dup { 2dup @ != } if } " - dq " { @ } while swap drop ; " - - dq ": guess-entry-end " - dq " dup entry-flags@ 64 & 64 = { exit } if " - dq " dup next-newer-entry dup " - dq " { drop dup is-in-heap { drop here @ } { drop } if-else " - dq " exit } unless " - dq " swap drop ; " - - dq ": containing-entry " - dq " dup is-in-heap { drop 0 exit } unless " - dq " latest @ { dup { 2dup > } { 0 } if-else } " - dq " { @ } while swap drop ; " - - dq ": is-assembly-word " - dq " entry-to-execution-token dup 8 + swap @ = ; " - - dq ": is-docol-itself " - dq " entry-to-name s"" docol"" stringcmp 0 = ; " - - - ; If the buffer is empty, make sure its logical position is at the - ; physical start. Otherwise, leave it alone. - ; - ; In: - ; pointer to buffer metadata - dq ": normalize-buffer " - dq " dup buffer-logical-length @ 0 = " - dq " { dup buffer-physical-start @ swap " - dq " buffer-logical-start ! } { drop } if-else " - dq " ; " - - - ; Find the next contiguous area of a buffer to write incoming data to. - ; This will begin at the logical end. Depending on the order things are in, - ; the available space might run from there to the physical end, or to the - ; logical start. Those are the only two possibilities. - ; - ; If the buffer is full, this will return as normal but the length will - ; be zero. The caller should make sure to respect that. - ; - ; In: - ; pointer to buffer metadata - ; Out: - ; destination start - ; destination length - dq ": compute-next-buffer-free-block " - dq " dup buffer-physical-start @ swap dup buffer-physical-length @ " - dq " swap 3unroll + swap " - ; (physical end, metadata pointer) - dq " dup buffer-logical-start @ swap dup buffer-logical-length @ " - dq " swap 3unroll + swap 3unroll " - ; (metadata pointer, physical end, logical end not yet wrapped) - - dq " 2dup >= " - dq " { " - ; If the logical end is greater than or equal to the physical end, find - ; where it wraps to and start from there. - dq " swap - swap dup buffer-physical-start @ swap 3unroll + " - ; (metadata pointer, destination start) - ; In this scenario, the logical start is the end of the free space, so - ; compute how far away it is. - dq " dup 3roll " - ; (destination start, destination start, metadata pointer) - dq " buffer-logical-start @ swap - } " - - dq " { " - dq " 3roll drop " - dq " dup 3roll swap - " - ; If the logical end is less than the physical end, it is the destination; - ; the physical end is also the end of the free space, so compute how far - ; away it is. - dq " } if-else " - ; (destination start, destination length) - dq " ; " - - - - ; In: - ; pointer to buffer metadata - dq ": refill-input-buffer-from-stdin " - dq " dup normalize-buffer " - dq " dup compute-next-buffer-free-block " - ; Check whether the buffer is full. If not, do a read. If so, that's not - ; an error, just clean up and take no action. - dq " dup { swap sys-read " - dq " dup -2 = " - dq " { drop drop s"" Read error."" emitstring 0 sys-exit } " - dq " { swap dup buffer-logical-length @ 3roll + " - dq " swap buffer-logical-length ! } if-else } " - dq " { drop drop } if-else ; " - - - ; Though we only do it once, this is a bit involved so we provide it as a - ; word. Notionally there are situations in which it could come up again, so - ; it seems worth having around. - ; - ; It actually needs to run as a compiled word no matter what; if it were - ; run in interpret mode it would cut itself off from the rest of itself. - ; However, if we didn't want to keep it around we could have it forget - ; itself... - dq ": relink-main-input-buffer-to-stdin " - dq " 1024 allocate dup main-input-buffer buffer-physical-start ! " - dq " main-input-buffer buffer-logical-start ! " - dq " 1024 main-input-buffer buffer-physical-length ! " - dq " 0 main-input-buffer buffer-logical-length ! " - dq " ' refill-input-buffer-from-stdin entry-to-execution-token " - dq " main-input-buffer input-buffer-refill ! " - dq " ; " - - - ; Notionally, it might make sense to define "create" in terms of - ; "create-in". Any change like that is being postponed to after the removal - ; of flatassembler, when refactorings will be easier. - ; - ; In: - ; name string pointer - ; dictionary handle (points to a pointer to the first item) - dq ": create-in " - dq " dup @ here @ swap pack64 " - ; (name string pointer, dictionary handle, output point) - dq " 0 pack8 0 pack8 " - dq " 3roll packstring " - dq " 8 packalign " - ; (dictionary handle, output point) - dq " swap here @ swap ! " - ; (output point) - dq " here ! " - dq " ; " - - - ; The word named "docol" has the job of returning the value that gets used - ; as the actual codeword. We make the assumption that the codeword will - ; point somewhere near the entry header; we allow for the possibility that - ; it might be before or after. - ; - ; Generally, it's possible for there to be several copies of docol due to - ; alternate heaps and things like that, so the goal is to recognize any of - ; them. - dq ": is-docol-codeword " - dq " dup is-in-heap { drop 0 exit } unless " - dq " containing-entry dup " - dq " { dup is-docol-itself " - dq " { drop 1 } " - dq " { next-newer-entry dup { is-docol-itself } if } if-else " - dq " } if ; " - - ; TODO this only works on heap words - dq ": is-docol-word " - dq " dup is-assembly-word { drop 0 exit } if " - dq " entry-to-execution-token @ is-docol-codeword ; " - - dq ": word-heading " - dq " dup entry-to-name dup emitstring space " - dq " stringlen 1+ 54 swap - 0 max indent dup .hex64 " - dq " dup entry-flags@ dup " - dq " { space " - dq " dup 128 & { s"" H"" emitstring } if " - dq " dup 64 & { s"" M"" emitstring } if " - dq " dup 1 & { s"" I"" emitstring } if " - dq " } if drop " - dq " dup is-assembly-word { s"" asm"" emitstring } " - dq " { dup is-docol-word { s"" raw"" emitstring } unless " - dq " } if-else drop " - dq " newline ; " - - dq ": list-dictionary " - dq " oldest-entry { dup } " - dq " { dup word-heading next-newer-entry } while drop ; " - - ; (content end, content start, label start) - dq ": hexdump-row " - dq " 2 indent dup .hex32 dup 4 unroll " - dq " 0 { dup 16 > } " - dq " { dup 7 & 0 = { space } if space " - dq " 2dup + dup 4 pick <= swap 5 pick > && " - dq " { 2dup + 8@ .hex8 } { space space } if-else " - dq " 1+ } while " - dq " newline 5 ndrop ; " - - ; (end, start) - dq ": hexdump-between " - dq " dup 16 1- invert & " - dq " { dup 3 pick > } " - dq " { 3dup hexdump-row 16 + } while 3 ndrop ; " - - ; (start, length) - dq ": hexdump-from swap dup 3unroll + swap hexdump-between ; " - - ; (start) - dq ": hexdump 64 hexdump-from ; " - - dq ": describe-hex " - dq " dup word-heading " - dq " dup guess-entry-end swap entry-to-execution-token " - dq " hexdump-between ; " - - dq ": is-codeword " - dq " dup is-in-heap { drop 0 exit } unless " - dq " dup containing-entry dup { 2drop 0 exit } unless " - dq " entry-to-execution-token = ; " - - dq ": describe-docol " - dq " dup word-heading " - dq " dup guess-entry-end swap entry-to-execution-token 8 + " - dq " { 2dup < } " - dq " { space dup @ dup is-codeword " - dq " { execution-token-to-entry entry-to-name emitstring } " - dq " { . } if-else " - dq " 8 + } while newline ; " - - dq ": describe " - dq " dup is-docol-word " - dq " { describe-docol } { describe-hex } if-else ; " - - dq ": describe-all " - dq " oldest-entry { dup } " - dq " { dup describe next-newer-entry } while drop ; " - - dq ": bye 0 sys-exit ; " - - ;dq ": foo 5 { dup } " - ;dq " { 4 indent 97 value@ emitstring drop newline 1- } " - ;dq " while drop ; foo " - ;dq ": foo 5 6 > { 42 . } if ; foo ' foo forget " - ;dq ": foo 5 6 > { 42 } { 69 } if-else . ; foo ' foo forget " - ;dq ": foo { 5 . } forever ; foo ' foo forget " - ;dq ": foo 0 { dup 5 > } { dup . 1+ } while drop ; foo ' foo forget " - - ;dq "s"" foo"" value@ emitstring dropstring " - ;dq ": foo s"" zotzotza"" emitstring ; ' foo describe " - ;dq ": foo 1 { s"" zotzotza"" emitstring } if ; ' foo describe " - ;dq "s"" zotzotza"" emitstring stack " - ;dq "68719476736 containing-entry stackhex " - ;dq "68719587456 containing-entry stackhex " - ;dq "587456 containing-entry stackhex " - ;dq "68719607808 containing-entry stackhex " - ;dq "list-dictionary " - ;dq "describe-all " - ;dq ": doittoit 8 allocate-input-buffer " - ;dq " dup stackhex refill-input-buffer-from-stdin " - ;dq " dup key-from drop " - ;dq " dup key-from drop " - ;dq " dup key-from drop " - ;dq " dup key-from drop " - ;dq " stackhex dup 256 hexdump-from " - ;dq " dup refill-input-buffer-from-stdin " - ;dq " stackhex dup 256 hexdump-from " - ;dq " dup refill-input-buffer-from-stdin " - ;dq " stackhex dup 256 hexdump-from " - ;dq " dup refill-input-buffer-from-stdin " - ;dq " stackhex dup 256 hexdump-from " - ;dq " bye ; doittoit " - dq " " - - ; TODO running "variable" interactively doesn't work because the string and - ; the "create" invocation step on each other. this is a big deal and really - ; needs to be fixed. - ; TODO find_in/find-in is backwards compared to create-in. - ; TODO define ( ... ) comments - ; TODO define constant (double-check variable) - ; TODO consider defining is-hidden and is-immediate - ; TODO define ? - ; TODO define allot and cells - ; TODO consider what text stuff to define - ; TODO control stack trace - ; TODO make an interactive debugger - ; TODO argc argv envp etc - ; TODO consider "unused" and some replacement for "brk" - ; TODO consider file API - ; TODO consider ";asm" or something - ; TODO consider a welcome message - - ; The last in a long series of perilous handoffs. :) - dq " relink-main-input-buffer-to-stdin " - ; We'll never get here, but if we do, it's an error. - dq " 1 sys-exit " - - dq 0 - - -final_word_name = latest_word -code_size = $ - code_start -file_size = $ - $$ - -- cgit 1.4.1