diff options
| author | Irene Knapp <ireneista@irenes.space> | 2025-11-02 21:24:26 -0800 |
|---|---|---|
| committer | Irene Knapp <ireneista@irenes.space> | 2025-11-02 21:24:26 -0800 |
| commit | 87b0b396a720535f2b0ad85fb1682e7a9fb0acb2 (patch) | |
| tree | 5caf2e0c0c64a12da5262a6b76830ac965b69b9e | |
| parent | 97574977ac5f8ce4595c2bbf4eba4ee49877ba23 (diff) | |
downcase _all_ the things
this will get more painful the longer we put it off Force-Push: yes Change-Id: I82430303d9d9d8a317eb8f020316e2145020a5c8
| -rw-r--r-- | quine.asm | 733 |
1 files changed, 368 insertions, 365 deletions
diff --git a/quine.asm b/quine.asm index 800d232..55a3983 100644 --- a/quine.asm +++ b/quine.asm @@ -136,26 +136,26 @@ 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 + 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 + 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 opcode >= 0 & opcode < 256 & opcode AND 7 = 0 assert reg >= 0 & reg < 8 - db opcode or reg + db opcode OR reg end macro macro opcodecc opcode, cc - assert opcode >= 0 & opcode < 256 & opcode and 15 = 0 + assert opcode >= 0 & opcode < 256 & opcode AND 15 = 0 assert cc >= 0 & cc < 16 - db opcode or cc + db opcode OR cc end macro macro scalefield sfield, scale @@ -901,7 +901,7 @@ macro cmp.qreg.qreg left, right modrm 3, lreg, rreg end macro -; This sets the flags to the same things they'd be set to if AND'ing right +; 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 @@ -1349,7 +1349,7 @@ elf_header: db 1 ; little-endian db 1 ; ELF header format version 1 db 0 ; System-V ABI - db 8 dup 0 ; (padding) + db 8 DUP 0 ; (padding) dw 2 ; *executable dw 0x3E ; *Intel x86-64 @@ -1438,18 +1438,18 @@ code_start: ;;; 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 +;;; 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. +;;; 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 +;;; 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. +;;; reasons, "next" is always inlined, so we define it as a macro. ;;; -;;; DOCOL is just ordinary code, not a macro. It's defined later in this -;;; file, as a label. +;;; 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 @@ -1500,15 +1500,15 @@ code_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) +;;; ... + 0x00 - ... + 0x08 Codeword (ie. address of docol) ;;; (8-byte chunks) Addresses of other words -;;; - ... (end) Address of EXIT word +;;; - ... (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 +;;; - ... (end) Inlined implementation of next ;;; ;;; Also, words always start at 8-byte boundaries. ;;; @@ -1551,7 +1551,7 @@ code_start: ;;; -------------------------------------------------------------------------- ;;; -;;; Macro NEXT +;;; Macro next ;;; ---------- ;;; ;;; Include this inline at the end of a word implemented in machine-code. @@ -1571,7 +1571,7 @@ code_start: ;;; Flags ;;; * DF = 0 is required ;;; -macro NEXT +macro next ; Copy the next word's address from *rsi into rax. Increment rsi (as per the ; DF flag). lodsq @@ -1582,7 +1582,7 @@ macro NEXT end macro ;;; -;;; Macro BEFORENEXT +;;; Macro beforenext ;;; ---------------- ;;; ;;; Sometimes we want to transfer control from a word implemented in @@ -1591,25 +1591,26 @@ end macro ;;; it. ;;; ;;; This implementation will work regardless of how the receiving word is -;;; implemented. It impersonates NEXT, 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. +;;; 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. +;;; eventually getting around to inlining "next". Hence the name. ;;; -macro BEFORENEXT target +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 + ; 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 +;;; Macros pushcontrol +;;; popcontrol ;;; ------------------ ;;; ;;; Include these inline to push an address onto the control stack, or pop @@ -1630,12 +1631,12 @@ end macro ;;; ;;; * rbp points to the top of the control stack. ;;; -macro PUSHCONTROL source +macro pushcontrol source lea.qreg.disp8.qreg rbp, -8, rbp mov.indirect.qreg.qreg rbp, source end macro -macro POPCONTROL target +macro popcontrol target mov.qreg.indirect.qreg target, rbp lea.qreg.disp8.qreg rbp, 8, rbp end macro @@ -1669,8 +1670,8 @@ end macro ;;; ;;; Registers out: ;;; -;;; * rsi points within QUIT -;;; QUIT is the word that's Forth's closest equivalent to main(). +;;; * 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. @@ -1682,13 +1683,13 @@ end macro ;;; ;;; Stack out: ;;; -;;; * The value of HEAP, as a pointer +;;; * 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 +;;; 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. ;;; @@ -1727,7 +1728,7 @@ _start: ;;; ;;; 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 + ;;; 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 @@ -1735,16 +1736,16 @@ _start: ;;; 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. + ;;; 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. + ;;; 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 - + ;;; 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. @@ -1754,7 +1755,7 @@ _start: ;;; 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 + ;;; 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. @@ -1762,8 +1763,8 @@ _start: 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 + ;;; 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! @@ -1785,45 +1786,45 @@ _start: ;;; 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 ; HEAP - mov.qreg.disp32.qreg rdi, control_stack_size + 0x08, rsp ; S0 - mov.qreg.disp32.qreg rdi, control_stack_size + 0x10, rbp ; R0 + mov.qreg.disp32.qreg rdi, control_stack_size + 0x00, rdi ; heap + 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 + 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 + mov.qreg.disp32.qreg rdi, control_stack_size + 0x20, rax ; here ; TODO also consider STATE - ; strictly speaking, R0 could be a constant... but it isn't known until + ; strictly speaking, r0 could be a constant... but it isn't known until ; runtime, so we might as well make it a variable ;;; - ;;; * HEAP is the physical bottom of the heap + ;;; * "heap" is the physical bottom of the heap ;;; The heap grows upwards in memory, so this is also the logical ;;; bottom. This comes from the address mmap() just returned to us. - ;;; * S0 is the logical bottom of the value stack + ;;; * "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 + ;;; * "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 + ;;; * "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 + ;;; * "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 + ;;; 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 + ;;; 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. ;;; - ;;; Notice that HERE points immediately after itself. This is just a + ;;; Notice 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. @@ -1846,31 +1847,32 @@ _start: ;;; ;;; - ;;; 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 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! + ;;; already set up. That's all that "next" needs, so take it away! ;;; mov.qreg.qimm rsi, cold_start - NEXT + 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 +;;; 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: -;;; TODO this is probably where we should deal with that HEAP that we passed +;;; TODO this is probably where we should deal with that "heap" that we passed ;;; on the stack - dq QUIT + dq quit ;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Now we are in Forth ;;; @@ -1884,7 +1886,7 @@ cold_start: ;;; 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 +;;; 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. @@ -1897,7 +1899,7 @@ calminstruction defword_label_helper name publish full_name:, address ; bind the label end calminstruction -; The only time we actually use this variant is DOCOL. +; The only time we actually use this variant is docol. macro defword_unlabeled name, flags align 8 defword_label_helper name @@ -1916,7 +1918,7 @@ end macro latest_word = 0 ;;; -;;; Routine DOCOL +;;; Routine docol ;;; ------------- ;;; ;;; Reference this via its label as the codeword of a word to make it an @@ -1926,7 +1928,7 @@ latest_word = 0 ;;; 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, +;;; 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 @@ -1942,74 +1944,74 @@ latest_word = 0 ;;; ;;; * 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. +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 + mov.qreg.qimm rax, docol push.qreg rax - NEXT + next align 8 -DOCOL: - ; Since DOCOL is not a normal word, the label points to the value we care +docol: + ; Since docol is not a normal word, the label points to the value we care ; about from the assembly side of things, wich is the address we use as the ; codeword. - PUSHCONTROL rsi + pushcontrol rsi add.qreg.bimm rax, 8 mov.qreg.qreg rsi, rax - NEXT + next -latest_word = DOCOL_name +latest_word = docol_name ;;; -;;; This is the mechanism to "return" from a word interpreted by DOCOL. +;;; 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. +;;; do the next thing the caller wants to do, by inlining "next". ;;; -defword EXIT, 0 +defword exit, 0 dq $ + 8 - POPCONTROL rsi - NEXT + 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 +;;; 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 +defword swap, 0 dq $ + 8 pop.qreg rax pop.qreg rbx push.qreg rax push.qreg rbx - NEXT + next -defword DROP, 0 +defword drop, 0 dq $ + 8 pop.qreg rax - NEXT + next -defword DROP2, 0 +defword drop2, 0 dq $ + 8 pop.qreg rax pop.qreg rax - NEXT + 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 +defword roll, 0 dq $ + 8 ; Pop our parameter. The rep instruction takes rcx as its count, so we @@ -2072,14 +2074,14 @@ defword ROLL, 0 mov.indirect.qreg.qreg rsp, rbx ; All done, wow! What a mouthful. - NEXT + 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 +defword unroll, 0 dq $ + 8 ; Pop our parameter. The rep instruction takes rcx as its count, so we @@ -2103,7 +2105,7 @@ defword UNROLL, 0 ; 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 + ; As with roll, we need to save rsi and adjust those rsp calculations ; accordingly. push.qreg rsi @@ -2112,7 +2114,7 @@ defword UNROLL, 0 ; 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 + ; 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! @@ -2132,10 +2134,10 @@ defword UNROLL, 0 mov.indexed.qreg.qreg rsp, rdx, 8, rbx ; All done, wow! What a mouthful. - NEXT + next ; Rotates "up" (third item becomes current item) -defword ROLL3, 0 +defword roll3, 0 dq $ + 8 pop.qreg rax pop.qreg rbx @@ -2143,10 +2145,10 @@ defword ROLL3, 0 push.qreg rbx push.qreg rax push.qreg rcx - NEXT + next ; Rotates "down" (current item becomes third item) -defword UNROLL3, 0 +defword unroll3, 0 dq $ + 8 pop.qreg rax pop.qreg rbx @@ -2154,14 +2156,14 @@ defword UNROLL3, 0 push.qreg rax push.qreg rcx push.qreg rbx - NEXT + next -defword DUP, 0 +defword dup, 0 dq $ + 8 pop.qreg rax push.qreg rax push.qreg rax - NEXT + next ;;; ;;; Arithmetic routines @@ -2171,31 +2173,31 @@ defword DUP, 0 ;;; keep it short. Also again, this is nowhere near optimal. ;;; -defword ADD, 0 +defword add, 0 dq $ + 8 pop.qreg rbx pop.qreg rax add.qreg.qreg rax, rbx push.qreg rax - NEXT + next -defword SUB, 0 +defword sub, 0 dq $ + 8 pop.qreg rbx pop.qreg rax sub.qreg.qreg rax, rbx push.qreg rax - NEXT + next -defword MUL, 0 +defword mul, 0 dq $ + 8 pop.qreg rax pop.qreg rbx mul.rax.qreg rbx push.qreg rax - NEXT + next -defword DIVMOD, 0 +defword divmod, 0 dq $ + 8 xor.qreg.qreg rdx, rdx ; rdx is the high bits of the input; zero it pop.qreg rbx @@ -2203,14 +2205,14 @@ defword DIVMOD, 0 div.rdxrax.qreg rbx push.qreg rdx ; remainder push.qreg rax ; quotient - NEXT + next ;;; ;;; Comparison routines ;;; ------------------- ;;; -defword EQ, 0 +defword eq, 0 dq $ + 8 pop.qreg rbx pop.qreg rax @@ -2218,9 +2220,9 @@ defword EQ, 0 set.breg.cc al, equal and.qreg.bimm rax, 0x01 push.qreg rax - NEXT + next -defword NE, 0 +defword ne, 0 dq $ + 8 pop.qreg rbx pop.qreg rax @@ -2228,9 +2230,9 @@ defword NE, 0 set.breg.cc al, not.equal and.qreg.bimm rax, 0x01 push.qreg rax - NEXT + next -defword GT, 0 +defword gt, 0 dq $ + 8 pop.qreg rbx pop.qreg rax @@ -2238,10 +2240,10 @@ defword GT, 0 set.breg.cc al, greater and.qreg.bimm rax, 0x01 push.qreg rax - NEXT + next ; Is the top of the stack less than the second item in the stack? -defword LT, 0 +defword lt, 0 dq $ + 8 pop.qreg rbx pop.qreg rax @@ -2249,73 +2251,73 @@ defword LT, 0 set.breg.cc al, less and.qreg.bimm rax, 0x01 push.qreg rax - NEXT + next -defword GE, 0 +defword ge, 0 dq $ + 8 pop.qreg rbx pop.qreg rax set.breg.cc al, greater.equal cmp.qreg.qreg rax, rbx push.qreg rax - NEXT + next -defword LE, 0 +defword le, 0 dq $ + 8 pop.qreg rbx pop.qreg rax set.breg.cc al, less.equal cmp.qreg.qreg rax, rbx push.qreg rax - NEXT + next ;;; ;;; Bitwise routines ;;; ---------------- ;;; -defword AND, 0 +defword and, 0 dq $ + 8 pop.qreg rbx pop.qreg rax and.qreg.qreg rax, rbx push.qreg rax - NEXT + next -defword OR, 0 +defword or, 0 dq $ + 8 pop.qreg rbx pop.qreg rax or.qreg.qreg rax, rbx push.qreg rax - NEXT + next -defword XOR, 0 +defword xor, 0 dq $ + 8 pop.qreg rbx pop.qreg rax xor.qreg.qreg rax, rbx push.qreg rax - NEXT + next ; The HP overloads the name "not", so we follow the Forth convention. -defword INVERT, 0 +defword invert, 0 dq $ + 8 pop.qreg rax not.qreg rax push.qreg rax - NEXT + next ;;; -;;; Routine LIT +;;; Routine lit ;;; ------------ ;;; -defword LIT, 0 +defword lit, 0 dq $ + 8 lodsq push.qreg rax - NEXT + next ;;; ;;; Memory access routines @@ -2327,84 +2329,84 @@ defword LIT, 0 ;;; ; Address on the top of the stack, value in the second position -defword STORE, 0 +defword store, 0 dq $ + 8 pop.qreg rbx pop.qreg rax mov.indirect.qreg.qreg rbx, rax - NEXT + next -defword FETCH, 0 +defword fetch, 0 dq $ + 8 pop.qreg rax mov.qreg.indirect.qreg rax, rax push.qreg rax - NEXT + 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 +defword addstore, 0 dq $ + 8 pop.qreg rbx pop.qreg rax add.indirect.qreg.qreg rbx, rax - NEXT + next -defword SUBSTORE, 0 +defword substore, 0 dq $ + 8 pop.qreg rbx pop.qreg rax sub.indirect.qreg.qreg rbx, rax - NEXT + next -defword STORE8, 0 +defword store8, 0 dq $ + 8 pop.qreg rbx pop.qreg rax mov.indirect.qreg.breg rbx, al - NEXT + next -defword FETCH8, 0 +defword fetch8, 0 dq $ + 8 pop.qreg rbx xor.qreg.qreg rax, rax mov.breg.indirect.qreg al, rbx - NEXT + next -defword STORE16, 0 +defword store16, 0 dq $ + 8 pop.qreg rbx pop.qreg rax mov.indirect.qreg.wreg rbx, ax - NEXT + next -defword FETCH16, 0 +defword fetch16, 0 dq $ + 8 pop.qreg rbx xor.qreg.qreg rax, rax mov.wreg.indirect.qreg ax, rbx - NEXT + next -defword STORE32, 0 +defword store32, 0 dq $ + 8 pop.qreg rbx pop.qreg rax mov.indirect.qreg.dreg rbx, eax - NEXT + next -defword FETCH32, 0 +defword fetch32, 0 dq $ + 8 pop.qreg rbx xor.qreg.qreg rax, rax mov.dreg.indirect.qreg eax, rbx - NEXT + 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 +; 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, +; 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. @@ -2414,7 +2416,7 @@ defword FETCH32, 0 ; source ; length ; (top) -defword CCOPY, 0 +defword ccopy, 0 dq $ + 8 ; We need to save and restore rsi; the other registers we can trample. mov.qreg.qreg rdx, rsi @@ -2425,7 +2427,7 @@ defword CCOPY, 0 ; leave the DF flag alone. rep movsb mov.qreg.qreg rsi, rdx - NEXT + next ;;;;;;;;;;;;;;;;; ;;; Branching ;;; @@ -2436,21 +2438,21 @@ defword CCOPY, 0 ; ; 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 +defword branch, 0 dq $ + 8 add.qreg.indirect.qreg rsi, rsi - NEXT + next -; This should probably be 0BRANCH, but right now the auto-label code is picky. -defword ZBRANCH, 0 +; 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 + jmp.cc.rel.bimm zero, branch + 8 - zbranch_after_jmp zbranch_after_jmp: lodsq ; just a convenient way to skip rsi forward - NEXT + next ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -2474,7 +2476,7 @@ zbranch_after_jmp: ;;; ;;; 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, +;;; 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, @@ -2491,17 +2493,17 @@ zbranch_after_jmp: ; heap address ; Stack out: ; heap address -; requestd variable address +; requested variable address defword early_heap, 0 - dq DOCOL, DUP, LIT, control_stack_size, ADD, EXIT + dq docol, dup, lit, control_stack_size, add, exit defword early_s0, 0 - dq DOCOL, early_heap, LIT, 8, ADD, EXIT + dq docol, early_heap, lit, 8, add, exit defword early_r0, 0 - dq DOCOL, early_heap, LIT, 16, ADD, EXIT + dq docol, early_heap, lit, 16, add, exit defword early_latest, 0 - dq DOCOL, early_heap, LIT, 24, ADD, EXIT + dq docol, early_heap, lit, 24, add, exit defword early_here, 0 - dq DOCOL, early_heap, LIT, 32, ADD, EXIT + dq docol, early_heap, lit, 32, add, exit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Now.... what was our original goal, again? ;;; @@ -2515,8 +2517,8 @@ defword early_here, 0 ;;; 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 +defword quit, 0 + dq docol ;;; ;;; Although we initialized rbp already, we do so again because we'll want @@ -2524,8 +2526,8 @@ defword QUIT, 0 ;;; 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 + ;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 @@ -2534,14 +2536,14 @@ defword QUIT, 0 ;;; Do the read-eval-print-loop, which is the main body of the Forth ;;; interpreter. ;;; - ;dq INTERPRET ; run the repl - dq QUINE + ;dq interpret ; run the repl + dq quine ;;; ;;; If the repl ever exits, do it all again. ;;; - ;dq BRANCH, QUIT - $ - dq SYS_EXIT + ;dq branch, quit - $ + dq sys_exit ;;;;;;;;;;;;;;;;;;;; @@ -2561,7 +2563,7 @@ defword QUIT, 0 ;;; ;;; This does the Linux exit() system call, passing it exit code zero. ;;; -defword SYS_EXIT, 0 +defword sys_exit, 0 dq $ + 8 mov.qreg.qimm rax, 60 ; syscall number @@ -2582,7 +2584,7 @@ defword SYS_EXIT, 0 ;;; the syscall wants it in rsi, which we also care about, so we have to do a ;;; little juggling. ;;; -defword SYS_WRITE, 0 +defword sys_write, 0 dq $ + 8 pop.qreg rcx ; address from stack pop.qreg rdx ; length from stack, passed directly @@ -2592,7 +2594,7 @@ defword SYS_WRITE, 0 mov.qreg.qreg rsi, rcx ; pass address syscall pop.qreg rsi ; restore rsi - NEXT + next ;;;;;;;;;;;;;;;;;;;;;; @@ -2601,46 +2603,46 @@ defword SYS_WRITE, 0 ; 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 +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 ; 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 +; 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 +defword litpack64, 0 dq $ + 8 lodsq push.qreg rax - BEFORENEXT PACK64 -defword LITPACK32, 0 + beforenext pack64 +defword litpack32, 0 dq $ + 8 lodsq push.qreg rax - BEFORENEXT PACK32 -defword LITPACK16, 0 + beforenext pack32 +defword litpack16, 0 dq $ + 8 lodsq push.qreg rax - BEFORENEXT PACK16 -defword LITPACK8, 0 + beforenext pack16 +defword litpack8, 0 dq $ + 8 lodsq push.qreg rax - BEFORENEXT PACK8 + beforenext pack8 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -2650,26 +2652,27 @@ defword LITPACK8, 0 ;;; 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 +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 + ; 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. + ; 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 + ; 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 + ; "heap" ; start address of allocated output ; label's value ; label's status @@ -2680,35 +2683,35 @@ defword QUINE, 0 ; 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 + 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 + 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 + dq drop, roll3, dup, lit, 4, unroll + dq all_contents ; Drop the copy of the buffer's address. - dq DROP + dq drop ; Drop the label data. - dq DROP, DROP + 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 + ;dq lit, 0x78, swap + dq lit, file_size, swap ; write() from stack-allocated buffer - dq SYS_WRITE + dq sys_write - dq EXIT + dq exit ; Stack in: ; output memory start @@ -2721,29 +2724,29 @@ defword QUINE, 0 ; label status (potentially modified) ; output memory current point ; label value for caller to use -defword USE_LABEL, 0 - dq DOCOL +defword use_label, 0 + dq docol ; Fetch the status - dq SWAP + dq swap ; Check the bit that indicates it's been set. - dq DUP, LIT, 2, AND, ZBRANCH, 10*8 + 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 + dq swap ; Fetch the actual value... - dq LIT, 3, ROLL, DUP, LIT, 4, UNROLL + dq lit, 3, roll, dup, lit, 4, unroll ; ... and exit - dq EXIT + dq exit ; If we're here, it hasn't been set yet, so mark it used-before-set. - dq LIT, 1, OR + dq lit, 1, or ; Put the status back... - dq SWAP + dq swap ; Fetch the guessed value... - dq LIT, 3, ROLL, DUP, LIT, 4, UNROLL + dq lit, 3, roll, dup, lit, 4, unroll ; ... and exit - dq EXIT + dq exit ; Stack in: ; output memory start @@ -2755,30 +2758,30 @@ defword USE_LABEL, 0 ; label value (now set to actual) ; label status (modified) ; output memory current point -defword SET_LABEL, 0 - dq DOCOL +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 + 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 + dq dup, lit, 5, roll ; status, point, new value, new value, old value - dq EQ, SWAP + dq eq, swap ; status, point, equality, new value - dq LIT, 4, UNROLL + 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 lit, 4, mul + dq lit, 3, roll, or, lit, 2, or, swap - dq EXIT + dq exit -defword HLT, 0 +defword hlt, 0 dq $ + 8 hlt @@ -2787,13 +2790,13 @@ defword HLT, 0 ; 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 +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 @@ -2801,37 +2804,37 @@ defword ALL_CONTENTS, 0 ;;; 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 +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 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 + 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 + dq litpack64, _start ; entry point ; The offset of _start. This includes the origin, intentionally. - dq LITPACK64, 64 ; program header offset + 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 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 + dq exit ;;; @@ -2841,53 +2844,53 @@ defword ELF_FILE_HEADER, 0 ;;; 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 +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 + 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) + 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 use_label, pack64 ; size in file + dq use_label, pack64 ; size in memory - dq LITPACK64, 0 ; segment alignment + dq litpack64, 0 ; segment alignment ; for relocation, but this doesn't apply to us - dq EXIT + dq exit -defword OUTPUT_START_ROUTINE, 0 - dq DOCOL +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, 0x03, 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 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, 0x03, 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 + 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 +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 + dq dup, lit, 4, roll, add, lit, 4, unroll ; result destination source length - dq CCOPY - dq EXIT + dq ccopy + dq exit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -2899,83 +2902,83 @@ defword SELF_RAW, 0 ; We define a bunch of keywords, which evaluate to their own codeword ; addresses. defword rax, 0 - dq DOCOL, LIT, rax, EXIT + dq docol, lit, rax, exit defword rcx, 0 - dq DOCOL, LIT, rcx, EXIT + dq docol, lit, rcx, exit defword rdx, 0 - dq DOCOL, LIT, rdx, EXIT + dq docol, lit, rdx, exit defword rbx, 0 - dq DOCOL, LIT, rbx, EXIT + dq docol, lit, rbx, exit defword rsp, 0 - dq DOCOL, LIT, rsp, EXIT + dq docol, lit, rsp, exit defword rbp, 0 - dq DOCOL, LIT, rbp, EXIT + dq docol, lit, rbp, exit defword rsi, 0 - dq DOCOL, LIT, rsi, EXIT + dq docol, lit, rsi, exit defword rdi, 0 - dq DOCOL, LIT, rdi, EXIT + dq docol, lit, rdi, exit defword r8, 0 - dq DOCOL, LIT, r8, EXIT + dq docol, lit, r8, exit defword r9, 0 - dq DOCOL, LIT, r9, EXIT + dq docol, lit, r9, exit defword r10, 0 - dq DOCOL, LIT, r10, EXIT + dq docol, lit, r10, exit defword r11, 0 - dq DOCOL, LIT, r11, EXIT + dq docol, lit, r11, exit defword r12, 0 - dq DOCOL, LIT, r12, EXIT + dq docol, lit, r12, exit defword r13, 0 - dq DOCOL, LIT, r13, EXIT + dq docol, lit, r13, exit defword r14, 0 - dq DOCOL, LIT, r14, EXIT + dq docol, lit, r14, exit defword r15, 0 - dq DOCOL, LIT, r15, EXIT + dq docol, lit, r15, 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 SYS_EXIT + 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 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 SYS_EXIT + 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 sys_exit ; Stack: ; output point defword rex_w, 0 - dq DOCOL, LIT, 0x48, PACK8, EXIT + dq docol, lit, 0x48, pack8, exit defword rex_wb, 0 - dq DOCOL, LIT, 0x49, PACK8, EXIT + 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 + dq docol, or, pack8, exit ; Stack ; output point @@ -2983,40 +2986,40 @@ defword opcodereg, 0 ; register/opcode field ; register/memory ("RM") field defword modrm, 0 - dq DOCOL, SWAP, LIT, 8, MUL, OR, SWAP, LIT, 64, MUL, OR, PACK8, EXIT + dq docol, swap, lit, 8, mul, or, swap, lit, 64, mul, or, pack8, exit ; Stack: ; output point defword cld, 0 - dq DOCOL, LIT, 0xFC, PACK8, EXIT + dq docol, lit, 0xFC, pack8, 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 + 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 + 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 reg64, SWAP, reg64, SWAP, LIT, 3, UNROLL3, modrm - dq EXIT + dq docol + dq roll3, rex_w, lit, 0x89, pack8, unroll3 + dq reg64, swap, reg64, swap, lit, 3, unroll3, modrm + dq exit ; Stack: ; output point defword syscall, 0 - dq DOCOL, LIT, 0x0F, PACK8, LIT, 0x05, PACK8, EXIT + dq docol, lit, 0x0F, pack8, lit, 0x05, pack8, exit final_word_name = syscall_name |