about summary refs log tree commit diff stats
path: root/html/mu_instructions.html
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2021-03-25 14:33:04 -0700
committerKartik Agaram <vc@akkartik.com>2021-03-25 14:33:04 -0700
commit681c0156a93599ed7199ee801ebc7f3f79914575 (patch)
treee3c58fc3411ae1b70eb5060827bc4ec4130b2dbd /html/mu_instructions.html
parentc2aeba0a110eb57fe41ab3388970e55274e15e14 (diff)
downloadmu-681c0156a93599ed7199ee801ebc7f3f79914575.tar.gz
.
Diffstat (limited to 'html/mu_instructions.html')
-rw-r--r--html/mu_instructions.html431
1 files changed, 431 insertions, 0 deletions
diff --git a/html/mu_instructions.html b/html/mu_instructions.html
new file mode 100644
index 00000000..ff5a2fe3
--- /dev/null
+++ b/html/mu_instructions.html
@@ -0,0 +1,431 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>~/play/mu/mu_instructions.html</title>
+<meta name="Generator" content="Vim/8.1">
+<meta name="plugin-version" content="vim8.1_v1">
+<meta name="syntax" content="none">
+<meta name="settings" content="use_css,no_foldcolumn,expand_tabs,prevent_copy=">
+<meta name="colorscheme" content="minimal-light">
+<style type="text/css">
+<!--
+pre { font-family: monospace; color: #000000; background-color: #c6c6c6; }
+body { font-family: monospace; color: #000000; background-color: #c6c6c6; }
+* { font-size: 1em; }
+.PreProc { color: #c000c0; }
+.muComment { color: #005faf; }
+.Constant { color: #008787; }
+.Special { color: #ff6060; }
+-->
+</style>
+</head>
+<body>
+<pre id='vimCodeElement'>
+<span class="muComment">## Mu's instructions and their table-driven translation</span>
+
+See <a href="http://akkartik.name/akkartik-convivial-20200607.pdf">http://akkartik.name/akkartik-convivial-20200607.pdf</a> for the complete
+story. In brief: Mu is a statement-oriented language. Blocks consist of flat
+lists of instructions. Instructions can have inputs after the operation, and
+outputs to the left of a '<span class="Special">&lt;-</span>'. Inputs and outputs must be variables. They can't
+include nested expressions. Variables can be literals ('n'), or live in a
+register ('var/reg') or in memory ('var') at some 'stack-offset' from the 'ebp'
+register. Outputs must be registers. To modify a variable in memory, pass it in
+by reference as an input. (Inputs are more precisely called 'inouts'.)
+Conversely, registers that are just read from must not be passed as outputs.
+
+The following chart shows all the instruction forms supported by Mu, along with
+the SubX instruction they're translated to.
+
+<span class="muComment">## Integer instructions</span>
+
+These instructions use the general-purpose registers.
+
+var/<span class="Constant">eax</span> <span class="Special">&lt;-</span> increment              =&gt; <span class="Constant">&quot;40/increment-eax&quot;</span>
+var/<span class="Constant">ecx</span> <span class="Special">&lt;-</span> increment              =&gt; <span class="Constant">&quot;41/increment-ecx&quot;</span>
+var/<span class="Constant">edx</span> <span class="Special">&lt;-</span> increment              =&gt; <span class="Constant">&quot;42/increment-edx&quot;</span>
+var/<span class="Constant">ebx</span> <span class="Special">&lt;-</span> increment              =&gt; <span class="Constant">&quot;43/increment-ebx&quot;</span>
+var/<span class="Constant">esi</span> <span class="Special">&lt;-</span> increment              =&gt; <span class="Constant">&quot;46/increment-esi&quot;</span>
+var/<span class="Constant">edi</span> <span class="Special">&lt;-</span> increment              =&gt; <span class="Constant">&quot;47/increment-edi&quot;</span>
+increment var                     =&gt; <span class="Constant">&quot;ff 0/subop/increment *(ebp+&quot;</span> var.stack-offset <span class="Constant">&quot;)&quot;</span>
+increment *var/reg                =&gt; <span class="Constant">&quot;ff 0/subop/increment *&quot;</span> reg
+
+var/<span class="Constant">eax</span> <span class="Special">&lt;-</span> decrement              =&gt; <span class="Constant">&quot;48/decrement-eax&quot;</span>
+var/<span class="Constant">ecx</span> <span class="Special">&lt;-</span> decrement              =&gt; <span class="Constant">&quot;49/decrement-ecx&quot;</span>
+var/<span class="Constant">edx</span> <span class="Special">&lt;-</span> decrement              =&gt; <span class="Constant">&quot;4a/decrement-edx&quot;</span>
+var/<span class="Constant">ebx</span> <span class="Special">&lt;-</span> decrement              =&gt; <span class="Constant">&quot;4b/decrement-ebx&quot;</span>
+var/<span class="Constant">esi</span> <span class="Special">&lt;-</span> decrement              =&gt; <span class="Constant">&quot;4e/decrement-esi&quot;</span>
+var/<span class="Constant">edi</span> <span class="Special">&lt;-</span> decrement              =&gt; <span class="Constant">&quot;4f/decrement-edi&quot;</span>
+decrement var                     =&gt; <span class="Constant">&quot;ff 1/subop/decrement *(ebp+&quot;</span> var.stack-offset <span class="Constant">&quot;)&quot;</span>
+decrement *var/reg                =&gt; <span class="Constant">&quot;ff 1/subop/decrement *&quot;</span> reg
+
+var/reg <span class="Special">&lt;-</span> add var2/reg2          =&gt; <span class="Constant">&quot;01/add-to %&quot;</span> reg <span class="Constant">&quot; &quot;</span> reg2 <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> add var2               =&gt; <span class="Constant">&quot;03/add *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> add *var2/reg2         =&gt; <span class="Constant">&quot;03/add *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+add-to var1, var2/reg             =&gt; <span class="Constant">&quot;01/add-to *(ebp+&quot;</span> var1.stack-offset <span class="Constant">&quot;) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+add-to *var1/reg1, var2/reg2      =&gt; <span class="Constant">&quot;01/add-to *&quot;</span> reg1 <span class="Constant">&quot; &quot;</span> reg2 <span class="Constant">&quot;/r32&quot;</span>
+var/<span class="Constant">eax</span> <span class="Special">&lt;-</span> add n                  =&gt; <span class="Constant">&quot;05/add-to-eax &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+var/reg <span class="Special">&lt;-</span> add n                  =&gt; <span class="Constant">&quot;81 0/subop/add %&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+add-to var, n                     =&gt; <span class="Constant">&quot;81 0/subop/add *(ebp+&quot;</span> var.stack-offset <span class="Constant">&quot;) &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+add-to *var/reg, n                =&gt; <span class="Constant">&quot;81 0/subop/add *&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+
+var/reg <span class="Special">&lt;-</span> subtract var2/reg2     =&gt; <span class="Constant">&quot;29/subtract-from %&quot;</span> reg <span class="Constant">&quot; &quot;</span> reg2 <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> subtract var2          =&gt; <span class="Constant">&quot;2b/subtract *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> subtract *var2/reg2    =&gt; <span class="Constant">&quot;2b/subtract *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> reg1 <span class="Constant">&quot;/r32&quot;</span>
+subtract-from var1, var2/reg2     =&gt; <span class="Constant">&quot;29/subtract-from *(ebp+&quot;</span> var1.stack-offset <span class="Constant">&quot;) &quot;</span> reg2 <span class="Constant">&quot;/r32&quot;</span>
+subtract-from *var1/reg1, var2/reg2 =&gt; <span class="Constant">&quot;29/subtract-from *&quot;</span> reg1 <span class="Constant">&quot; &quot;</span> reg2 <span class="Constant">&quot;/r32&quot;</span>
+var/<span class="Constant">eax</span> <span class="Special">&lt;-</span> subtract n             =&gt; <span class="Constant">&quot;2d/subtract-from-eax &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+var/reg <span class="Special">&lt;-</span> subtract n             =&gt; <span class="Constant">&quot;81 5/subop/subtract %&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+subtract-from var, n              =&gt; <span class="Constant">&quot;81 5/subop/subtract *(ebp+&quot;</span> var.stack-offset <span class="Constant">&quot;) &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+subtract-from *var/reg, n         =&gt; <span class="Constant">&quot;81 5/subop/subtract *&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+
+var/reg <span class="Special">&lt;-</span> and var2/reg2          =&gt; <span class="Constant">&quot;21/and-with %&quot;</span> reg <span class="Constant">&quot; &quot;</span> reg2 <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> and var2               =&gt; <span class="Constant">&quot;23/and *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot; &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> and *var2/reg2         =&gt; <span class="Constant">&quot;23/and *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+and-with var1, var2/reg           =&gt; <span class="Constant">&quot;21/and-with *(ebp+&quot;</span> var1.stack-offset <span class="Constant">&quot;) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+and-with *var1/reg1, var2/reg2    =&gt; <span class="Constant">&quot;21/and-with *&quot;</span> reg1 <span class="Constant">&quot; &quot;</span> reg2 <span class="Constant">&quot;/r32&quot;</span>
+var/<span class="Constant">eax</span> <span class="Special">&lt;-</span> and n                  =&gt; <span class="Constant">&quot;25/and-with-eax &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+var/reg <span class="Special">&lt;-</span> and n                  =&gt; <span class="Constant">&quot;81 4/subop/and %&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+and-with var, n                   =&gt; <span class="Constant">&quot;81 4/subop/and *(ebp+&quot;</span> var.stack-offset <span class="Constant">&quot;) &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+and-with *var/reg, n              =&gt; <span class="Constant">&quot;81 4/subop/and *&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+
+var/reg <span class="Special">&lt;-</span> or var2/reg2           =&gt; <span class="Constant">&quot;09/or-with %&quot;</span> reg <span class="Constant">&quot; &quot;</span> reg2 <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> or var2                =&gt; <span class="Constant">&quot;0b/or *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> or *var2/reg2          =&gt; <span class="Constant">&quot;0b/or *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+or-with var1, var2/reg2           =&gt; <span class="Constant">&quot;09/or-with *(ebp+&quot;</span> var1.stack-offset <span class="Constant">&quot; &quot;</span> reg2 <span class="Constant">&quot;/r32&quot;</span>
+or-with *var1/reg1, var2/reg2     =&gt; <span class="Constant">&quot;09/or-with *&quot;</span> reg1 <span class="Constant">&quot; &quot;</span> reg2 <span class="Constant">&quot;/r32&quot;</span>
+var/<span class="Constant">eax</span> <span class="Special">&lt;-</span> or n                   =&gt; <span class="Constant">&quot;0d/or-with-eax &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+var/reg <span class="Special">&lt;-</span> or n                   =&gt; <span class="Constant">&quot;81 1/subop/or %&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+or-with var, n                    =&gt; <span class="Constant">&quot;81 1/subop/or *(ebp+&quot;</span> var.stack-offset <span class="Constant">&quot;) &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+or-with *var/reg, n               =&gt; <span class="Constant">&quot;81 1/subop/or *&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+
+var/reg <span class="Special">&lt;-</span> xor var2/reg2          =&gt; <span class="Constant">&quot;31/xor-with %&quot;</span> reg <span class="Constant">&quot; &quot;</span> reg2 <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> xor var2               =&gt; <span class="Constant">&quot;33/xor *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> xor *var2/reg2         =&gt; <span class="Constant">&quot;33/xor *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+xor-with var1, var2/reg           =&gt; <span class="Constant">&quot;31/xor-with *(ebp+&quot;</span> var1.stack-offset <span class="Constant">&quot;) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+xor-with *var1/reg1, var2/reg2    =&gt; <span class="Constant">&quot;31/xor-with *&quot;</span> reg1 <span class="Constant">&quot; &quot;</span> reg2 <span class="Constant">&quot;/r32&quot;</span>
+var/<span class="Constant">eax</span> <span class="Special">&lt;-</span> xor n                  =&gt; <span class="Constant">&quot;35/xor-with-eax &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+var/reg <span class="Special">&lt;-</span> xor n                  =&gt; <span class="Constant">&quot;81 6/subop/xor %&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+xor-with var, n                   =&gt; <span class="Constant">&quot;81 6/subop/xor *(ebp+&quot;</span> var.stack-offset <span class="Constant">&quot;) &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+xor-with *var/reg, n              =&gt; <span class="Constant">&quot;81 6/subop/xor *&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+
+var/reg <span class="Special">&lt;-</span> negate                 =&gt; <span class="Constant">&quot;f7 3/subop/negate %&quot;</span> reg
+negate var                        =&gt; <span class="Constant">&quot;f7 3/subop/negate *(ebp+&quot;</span> var.stack-offset <span class="Constant">&quot;)&quot;</span>
+negate *var/reg                   =&gt; <span class="Constant">&quot;f7 3/subop/negate *&quot;</span> reg
+
+var/reg <span class="Special">&lt;-</span> shift-left n           =&gt; <span class="Constant">&quot;c1/shift 4/subop/left %&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+var/reg <span class="Special">&lt;-</span> shift-right n          =&gt; <span class="Constant">&quot;c1/shift 5/subop/right %&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+var/reg <span class="Special">&lt;-</span> shift-right-signed n   =&gt; <span class="Constant">&quot;c1/shift 7/subop/right-signed %&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+shift-left var, n                 =&gt; <span class="Constant">&quot;c1/shift 4/subop/left *(ebp+&quot;</span> var.stack-offset <span class="Constant">&quot;) &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+shift-left *var/reg, n            =&gt; <span class="Constant">&quot;c1/shift 4/subop/left *&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+shift-right var, n                =&gt; <span class="Constant">&quot;c1/shift 5/subop/right *(ebp+&quot;</span> var.stack-offset <span class="Constant">&quot;) &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+shift-right *var/reg, n           =&gt; <span class="Constant">&quot;c1/shift 5/subop/right *&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+shift-right-signed var, n         =&gt; <span class="Constant">&quot;c1/shift 7/subop/right-signed *(ebp+&quot;</span> var.stack-offset <span class="Constant">&quot;) &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+shift-right-signed *var/reg, n    =&gt; <span class="Constant">&quot;c1/shift 7/subop/right-signed *&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+
+var/<span class="Constant">eax</span> <span class="Special">&lt;-</span> copy n                 =&gt; <span class="Constant">&quot;b8/copy-to-eax &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+var/<span class="Constant">ecx</span> <span class="Special">&lt;-</span> copy n                 =&gt; <span class="Constant">&quot;b9/copy-to-ecx &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+var/<span class="Constant">edx</span> <span class="Special">&lt;-</span> copy n                 =&gt; <span class="Constant">&quot;ba/copy-to-edx &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+var/<span class="Constant">ebx</span> <span class="Special">&lt;-</span> copy n                 =&gt; <span class="Constant">&quot;bb/copy-to-ebx &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+var/<span class="Constant">esi</span> <span class="Special">&lt;-</span> copy n                 =&gt; <span class="Constant">&quot;be/copy-to-esi &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+var/<span class="Constant">edi</span> <span class="Special">&lt;-</span> copy n                 =&gt; <span class="Constant">&quot;bf/copy-to-edi &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+var/reg <span class="Special">&lt;-</span> copy var2/reg2         =&gt; <span class="Constant">&quot;89/&lt;- %&quot;</span> reg <span class="Constant">&quot; &quot;</span> reg2 <span class="Constant">&quot;/r32&quot;</span>
+copy-to var1, var2/reg            =&gt; <span class="Constant">&quot;89/&lt;- *(ebp+&quot;</span> var1.stack-offset <span class="Constant">&quot;) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+copy-to *var1/reg1, var2/reg2     =&gt; <span class="Constant">&quot;89/&lt;- *&quot;</span> reg1 <span class="Constant">&quot; &quot;</span> reg2 <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> copy var2              =&gt; <span class="Constant">&quot;8b/-&gt; *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> copy *var2/reg2        =&gt; <span class="Constant">&quot;8b/-&gt; *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> copy n                 =&gt; <span class="Constant">&quot;c7 0/subop/copy %&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+copy-to var, n                    =&gt; <span class="Constant">&quot;c7 0/subop/copy *(ebp+&quot;</span> var.stack-offset <span class="Constant">&quot;) &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+copy-to *var/reg, n               =&gt; <span class="Constant">&quot;c7 0/subop/copy *&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+
+var/reg <span class="Special">&lt;-</span> copy-byte var2/reg2    =&gt; <span class="Constant">&quot;8a/byte-&gt; %&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+                                     <span class="Constant">&quot;81 4/subop/and %&quot;</span> reg <span class="Constant">&quot; 0xff/imm32&quot;</span>
+var/reg <span class="Special">&lt;-</span> copy-byte *var2/reg2   =&gt; <span class="Constant">&quot;8a/byte-&gt; *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+                                     <span class="Constant">&quot;81 4/subop/and %&quot;</span> reg <span class="Constant">&quot; 0xff/imm32&quot;</span>
+copy-byte-to *var1/reg1, var2/reg2  =&gt; <span class="Constant">&quot;88/byte&lt;- *&quot;</span> reg1 <span class="Constant">&quot; &quot;</span> reg2 <span class="Constant">&quot;/r32&quot;</span>
+
+compare var1, var2/reg2           =&gt; <span class="Constant">&quot;39/compare *(ebp+&quot;</span> var1.stack-offset <span class="Constant">&quot;) &quot;</span> reg2 <span class="Constant">&quot;/r32&quot;</span>
+compare *var1/reg1, var2/reg2     =&gt; <span class="Constant">&quot;39/compare *&quot;</span> reg1 <span class="Constant">&quot; &quot;</span> reg2 <span class="Constant">&quot;/r32&quot;</span>
+compare var1/reg1, var2           =&gt; <span class="Constant">&quot;3b/compare&lt;- *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> reg1 <span class="Constant">&quot;/r32&quot;</span>
+compare var/reg, *var2/reg2       =&gt; <span class="Constant">&quot;3b/compare&lt;- *&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+compare var/<span class="Constant">eax</span>, n                =&gt; <span class="Constant">&quot;3d/compare-eax-with &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+compare var/reg, n                =&gt; <span class="Constant">&quot;81 7/subop/compare %&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+compare var, n                    =&gt; <span class="Constant">&quot;81 7/subop/compare *(ebp+&quot;</span> var.stack-offset <span class="Constant">&quot;) &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+compare *var/reg, n               =&gt; <span class="Constant">&quot;81 7/subop/compare *&quot;</span> reg <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot;/imm32&quot;</span>
+
+var/reg <span class="Special">&lt;-</span> multiply var2          =&gt; <span class="Constant">&quot;0f af/multiply *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> multiply var2/reg2     =&gt; <span class="Constant">&quot;0f af/multiply %&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> multiply *var2/reg2    =&gt; <span class="Constant">&quot;0f af/multiply *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+
+<span class="muComment">## Floating-point operations</span>
+
+These instructions operate on either floating-point registers (xreg) or
+general-purpose registers (reg) in indirect mode.
+
+var/xreg <span class="Special">&lt;-</span> add var2/xreg2        =&gt; <span class="Constant">&quot;f3 0f 58/add %&quot;</span> xreg2 <span class="Constant">&quot; &quot;</span> xreg1 <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> add var2              =&gt; <span class="Constant">&quot;f3 0f 58/add *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> add *var2/reg2        =&gt; <span class="Constant">&quot;f3 0f 58/add *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+
+var/xreg <span class="Special">&lt;-</span> subtract var2/xreg2   =&gt; <span class="Constant">&quot;f3 0f 5c/subtract %&quot;</span> xreg2 <span class="Constant">&quot; &quot;</span> xreg1 <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> subtract var2         =&gt; <span class="Constant">&quot;f3 0f 5c/subtract *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> subtract *var2/reg2   =&gt; <span class="Constant">&quot;f3 0f 5c/subtract *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+
+var/xreg <span class="Special">&lt;-</span> multiply var2/xreg2   =&gt; <span class="Constant">&quot;f3 0f 59/multiply %&quot;</span> xreg2 <span class="Constant">&quot; &quot;</span> xreg1 <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> multiply var2         =&gt; <span class="Constant">&quot;f3 0f 59/multiply *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> multiply *var2/reg2   =&gt; <span class="Constant">&quot;f3 0f 59/multiply *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+
+var/xreg <span class="Special">&lt;-</span> divide var2/xreg2     =&gt; <span class="Constant">&quot;f3 0f 5e/divide %&quot;</span> xreg2 <span class="Constant">&quot; &quot;</span> xreg1 <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> divide var2           =&gt; <span class="Constant">&quot;f3 0f 5e/divide *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> divide *var2/reg2     =&gt; <span class="Constant">&quot;f3 0f 5e/divide *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+
+There are also some exclusively floating-point instructions:
+
+var/xreg <span class="Special">&lt;-</span> reciprocal var2/xreg2 =&gt; <span class="Constant">&quot;f3 0f 53/reciprocal %&quot;</span> xreg2 <span class="Constant">&quot; &quot;</span> xreg1 <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> reciprocal var2       =&gt; <span class="Constant">&quot;f3 0f 53/reciprocal *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> reciprocal *var2/reg2 =&gt; <span class="Constant">&quot;f3 0f 53/reciprocal *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+
+var/xreg <span class="Special">&lt;-</span> square-root var2/xreg2 =&gt; <span class="Constant">&quot;f3 0f 51/square-root %&quot;</span> xreg2 <span class="Constant">&quot; &quot;</span> xreg1 <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> square-root var2       =&gt; <span class="Constant">&quot;f3 0f 51/square-root *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> square-root *var2/reg2 =&gt; <span class="Constant">&quot;f3 0f 51/square-root *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+
+var/xreg <span class="Special">&lt;-</span> inverse-square-root var2/xreg2 =&gt; <span class="Constant">&quot;f3 0f 52/inverse-square-root %&quot;</span> xreg2 <span class="Constant">&quot; &quot;</span> xreg1 <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> inverse-square-root var2       =&gt; <span class="Constant">&quot;f3 0f 52/inverse-square-root *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> inverse-square-root *var2/reg2 =&gt; <span class="Constant">&quot;f3 0f 52/inverse-square-root *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+
+var/xreg <span class="Special">&lt;-</span> min var2/xreg2        =&gt; <span class="Constant">&quot;f3 0f 5d/min %&quot;</span> xreg2 <span class="Constant">&quot; &quot;</span> xreg1 <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> min var2              =&gt; <span class="Constant">&quot;f3 0f 5d/min *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> min *var2/reg2        =&gt; <span class="Constant">&quot;f3 0f 5d/min *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+
+var/xreg <span class="Special">&lt;-</span> max var2/xreg2        =&gt; <span class="Constant">&quot;f3 0f 5f/max %&quot;</span> xreg2 <span class="Constant">&quot; &quot;</span> xreg1 <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> max var2              =&gt; <span class="Constant">&quot;f3 0f 5f/max *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> max *var2/reg2        =&gt; <span class="Constant">&quot;f3 0f 5f/max *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+
+Remember, when these instructions use indirect mode, they still use an integer
+register. Floating-point registers can't hold addresses.
+
+Most instructions operate exclusively on integer or floating-point operands.
+The only exceptions are the instructions for converting between integers and
+floating-point numbers.
+
+var/xreg <span class="Special">&lt;-</span> convert var2/reg2     =&gt; <span class="Constant">&quot;f3 0f 2a/convert-to-float %&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> convert var2          =&gt; <span class="Constant">&quot;f3 0f 2a/convert-to-float *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> convert *var2/reg2    =&gt; <span class="Constant">&quot;f3 0f 2a/convert-to-float *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+
+Converting floats to ints performs rounding by default. (We don't mess with the
+MXCSR control register.)
+
+var/reg <span class="Special">&lt;-</span> convert var2/xreg2     =&gt; <span class="Constant">&quot;f3 0f 2d/convert-to-int %&quot;</span> xreg2 <span class="Constant">&quot; &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> convert var2           =&gt; <span class="Constant">&quot;f3 0f 2d/convert-to-int *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> convert *var2/reg2     =&gt; <span class="Constant">&quot;f3 0f 2d/convert-to-int *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+
+There's a separate instruction for truncating the fractional part.
+
+var/reg <span class="Special">&lt;-</span> truncate var2/xreg2     =&gt; <span class="Constant">&quot;f3 0f 2c/truncate-to-int %&quot;</span> xreg2 <span class="Constant">&quot; &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> truncate var2           =&gt; <span class="Constant">&quot;f3 0f 2c/truncate-to-int *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg <span class="Special">&lt;-</span> truncate *var2/reg2     =&gt; <span class="Constant">&quot;f3 0f 2c/truncate-to-int *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+
+There are no instructions accepting floating-point literals. To obtain integer
+literals in floating-point registers, copy them to general-purpose registers
+and then convert them to floating-point.
+
+One pattern you may have noticed above is that the floating-point instructions
+above always write to registers. The only exceptions are `copy` instructions,
+which can write to memory locations.
+
+var/xreg <span class="Special">&lt;-</span> copy var2/xreg2       =&gt; <span class="Constant">&quot;f3 0f 11/&lt;- %&quot;</span> xreg <span class="Constant">&quot; &quot;</span> xreg2 <span class="Constant">&quot;/x32&quot;</span>
+copy-to var1, var2/xreg           =&gt; <span class="Constant">&quot;f3 0f 11/&lt;- *(ebp+&quot;</span> var1.stack-offset <span class="Constant">&quot;) &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> copy var2             =&gt; <span class="Constant">&quot;f3 0f 10/-&gt; *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+var/xreg <span class="Special">&lt;-</span> copy *var2/reg2       =&gt; <span class="Constant">&quot;f3 0f 10/-&gt; *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+
+Comparisons must always start with a register:
+
+compare var1/xreg1, var2/xreg2    =&gt; <span class="Constant">&quot;0f 2f/compare %&quot;</span> xreg2 <span class="Constant">&quot; &quot;</span> xreg1 <span class="Constant">&quot;/x32&quot;</span>
+compare var1/xreg1, var2          =&gt; <span class="Constant">&quot;0f 2f/compare *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> xreg1 <span class="Constant">&quot;/x32&quot;</span>
+
+<span class="muComment">## Blocks</span>
+
+In themselves, blocks generate no instructions. However, if a block contains
+variable declarations, they must be cleaned up when the block ends.
+
+Clean up var on the stack         =&gt; <span class="Constant">&quot;81 0/subop/add %esp &quot;</span> size-of(var) <span class="Constant">&quot;/imm32&quot;</span>
+Clean up var/reg                  =&gt; <span class="Constant">&quot;8f 0/subop/pop %&quot;</span> reg
+
+Clean up var/xreg                 =&gt; <span class="Constant">&quot;f3 0f 10/-&gt; *esp &quot;</span> xreg <span class="Constant">&quot;/x32&quot;</span>
+                                     <span class="Constant">&quot;81 0/subop/add %esp 4/imm32&quot;</span>
+
+<span class="muComment">## Jumps</span>
+
+Besides having to clean up any variable declarations (see above) between
+themselves and their target, jumps translate like this:
+
+<span class="PreProc">break</span>                             =&gt; <span class="Constant">&quot;e9/jump break/disp32&quot;</span>
+<span class="PreProc">break</span> label                       =&gt; <span class="Constant">&quot;e9/jump &quot;</span> label <span class="Constant">&quot;:break/disp32&quot;</span>
+<span class="PreProc">loop</span>                              =&gt; <span class="Constant">&quot;e9/jump loop/disp32&quot;</span>
+<span class="PreProc">loop</span> label                        =&gt; <span class="Constant">&quot;e9/jump &quot;</span> label <span class="Constant">&quot;:loop/disp32&quot;</span>
+
+<span class="PreProc">break-if-=</span>                        =&gt; <span class="Constant">&quot;0f 84/jump-if-= break/disp32&quot;</span>
+<span class="PreProc">break-if-=</span> label                  =&gt; <span class="Constant">&quot;0f 84/jump-if-= &quot;</span> label <span class="Constant">&quot;:break/disp32&quot;</span>
+<span class="PreProc">loop-if-=</span>                         =&gt; <span class="Constant">&quot;0f 84/jump-if-= loop/disp32&quot;</span>
+<span class="PreProc">loop-if-=</span> label                   =&gt; <span class="Constant">&quot;0f 84/jump-if-= &quot;</span> label <span class="Constant">&quot;:loop/disp32&quot;</span>
+
+<span class="PreProc">break-if-!=</span>                       =&gt; <span class="Constant">&quot;0f 85/jump-if-!= break/disp32&quot;</span>
+<span class="PreProc">break-if-!=</span> label                 =&gt; <span class="Constant">&quot;0f 85/jump-if-!= &quot;</span> label <span class="Constant">&quot;:break/disp32&quot;</span>
+<span class="PreProc">loop-if-!=</span>                        =&gt; <span class="Constant">&quot;0f 85/jump-if-!= loop/disp32&quot;</span>
+<span class="PreProc">loop-if-!=</span> label                  =&gt; <span class="Constant">&quot;0f 85/jump-if-!= &quot;</span> label <span class="Constant">&quot;:loop/disp32&quot;</span>
+
+<span class="PreProc">break-if-&lt;</span>                        =&gt; <span class="Constant">&quot;0f 8c/jump-if-&lt; break/disp32&quot;</span>
+<span class="PreProc">break-if-&lt;</span> label                  =&gt; <span class="Constant">&quot;0f 8c/jump-if-&lt; &quot;</span> label <span class="Constant">&quot;:break/disp32&quot;</span>
+<span class="PreProc">loop-if-&lt;</span>                         =&gt; <span class="Constant">&quot;0f 8c/jump-if-&lt; loop/disp32&quot;</span>
+<span class="PreProc">loop-if-&lt;</span> label                   =&gt; <span class="Constant">&quot;0f 8c/jump-if-&lt; &quot;</span> label <span class="Constant">&quot;:loop/disp32&quot;</span>
+
+<span class="PreProc">break-if-&gt;</span>                        =&gt; <span class="Constant">&quot;0f 8f/jump-if-&gt; break/disp32&quot;</span>
+<span class="PreProc">break-if-&gt;</span> label                  =&gt; <span class="Constant">&quot;0f 8f/jump-if-&gt; &quot;</span> label <span class="Constant">&quot;:break/disp32&quot;</span>
+<span class="PreProc">loop-if-&gt;</span>                         =&gt; <span class="Constant">&quot;0f 8f/jump-if-&gt; loop/disp32&quot;</span>
+<span class="PreProc">loop-if-&gt;</span> label                   =&gt; <span class="Constant">&quot;0f 8f/jump-if-&gt; &quot;</span> label <span class="Constant">&quot;:loop/disp32&quot;</span>
+
+<span class="PreProc">break-if-&lt;=</span>                       =&gt; <span class="Constant">&quot;0f 8e/jump-if-&lt;= break/disp32&quot;</span>
+<span class="PreProc">break-if-&lt;=</span> label                 =&gt; <span class="Constant">&quot;0f 8e/jump-if-&lt;= &quot;</span> label <span class="Constant">&quot;:break/disp32&quot;</span>
+<span class="PreProc">loop-if-&lt;=</span>                        =&gt; <span class="Constant">&quot;0f 8e/jump-if-&lt;= loop/disp32&quot;</span>
+<span class="PreProc">loop-if-&lt;=</span> label                  =&gt; <span class="Constant">&quot;0f 8e/jump-if-&lt;= &quot;</span> label <span class="Constant">&quot;:loop/disp32&quot;</span>
+
+<span class="PreProc">break-if-&gt;=</span>                       =&gt; <span class="Constant">&quot;0f 8d/jump-if-&gt;= break/disp32&quot;</span>
+<span class="PreProc">break-if-&gt;=</span> label                 =&gt; <span class="Constant">&quot;0f 8d/jump-if-&gt;= &quot;</span> label <span class="Constant">&quot;:break/disp32&quot;</span>
+<span class="PreProc">loop-if-&gt;=</span>                        =&gt; <span class="Constant">&quot;0f 8d/jump-if-&gt;= loop/disp32&quot;</span>
+<span class="PreProc">loop-if-&gt;=</span> label                  =&gt; <span class="Constant">&quot;0f 8d/jump-if-&gt;= &quot;</span> label <span class="Constant">&quot;:loop/disp32&quot;</span>
+
+<span class="PreProc">break-if-addr&lt;</span>                    =&gt; <span class="Constant">&quot;0f 82/jump-if-addr&lt; break/disp32&quot;</span>
+<span class="PreProc">break-if-addr&lt;</span> label              =&gt; <span class="Constant">&quot;0f 82/jump-if-addr&lt; &quot;</span> label <span class="Constant">&quot;:break/disp32&quot;</span>
+<span class="PreProc">loop-if-addr&lt;</span>                     =&gt; <span class="Constant">&quot;0f 82/jump-if-addr&lt; loop/disp32&quot;</span>
+<span class="PreProc">loop-if-addr&lt;</span> label               =&gt; <span class="Constant">&quot;0f 82/jump-if-addr&lt; &quot;</span> label <span class="Constant">&quot;:loop/disp32&quot;</span>
+
+<span class="PreProc">break-if-addr&gt;</span>                    =&gt; <span class="Constant">&quot;0f 87/jump-if-addr&gt; break/disp32&quot;</span>
+<span class="PreProc">break-if-addr&gt;</span> label              =&gt; <span class="Constant">&quot;0f 87/jump-if-addr&gt; &quot;</span> label <span class="Constant">&quot;:break/disp32&quot;</span>
+<span class="PreProc">loop-if-addr&gt;</span>                     =&gt; <span class="Constant">&quot;0f 87/jump-if-addr&gt; loop/disp32&quot;</span>
+<span class="PreProc">loop-if-addr&gt;</span> label               =&gt; <span class="Constant">&quot;0f 87/jump-if-addr&gt; &quot;</span> label <span class="Constant">&quot;:loop/disp32&quot;</span>
+
+<span class="PreProc">break-if-addr&lt;=</span>                   =&gt; <span class="Constant">&quot;0f 86/jump-if-addr&lt;= break/disp32&quot;</span>
+<span class="PreProc">break-if-addr&lt;=</span> label             =&gt; <span class="Constant">&quot;0f 86/jump-if-addr&lt;= &quot;</span> label <span class="Constant">&quot;:break/disp32&quot;</span>
+<span class="PreProc">loop-if-addr&lt;=</span>                    =&gt; <span class="Constant">&quot;0f 86/jump-if-addr&lt;= loop/disp32&quot;</span>
+<span class="PreProc">loop-if-addr&lt;=</span> label              =&gt; <span class="Constant">&quot;0f 86/jump-if-addr&lt;= &quot;</span> label <span class="Constant">&quot;:loop/disp32&quot;</span>
+
+<span class="PreProc">break-if-addr&gt;=</span>                   =&gt; <span class="Constant">&quot;0f 83/jump-if-addr&gt;= break/disp32&quot;</span>
+<span class="PreProc">break-if-addr&gt;=</span> label             =&gt; <span class="Constant">&quot;0f 83/jump-if-addr&gt;= &quot;</span> label <span class="Constant">&quot;:break/disp32&quot;</span>
+<span class="PreProc">loop-if-addr&gt;=</span>                    =&gt; <span class="Constant">&quot;0f 83/jump-if-addr&gt;= loop/disp32&quot;</span>
+<span class="PreProc">loop-if-addr&gt;=</span> label              =&gt; <span class="Constant">&quot;0f 83/jump-if-addr&gt;= &quot;</span> label <span class="Constant">&quot;:loop/disp32&quot;</span>
+
+Similar float variants like `<span class="PreProc">break-if-float&lt;`</span> are aliases for the corresponding
+`addr` equivalents. The x86 instruction set stupidly has floating-point
+operations only update a subset of flags.
+
+<span class="muComment">## Returns</span>
+
+The `<span class="PreProc">return</span>` instruction cleans up variable declarations just like an unconditional
+`<span class="PreProc">jump</span>` to end of function, but also emits a series of copies before the final
+`<span class="PreProc">jump</span>`, copying each argument of `<span class="PreProc">return</span>` to the register appropriate to the
+respective function output. This doesn't work if a function output register
+contains a later `<span class="PreProc">return</span>` argument (e.g. if the registers for two outputs are
+swapped in `<span class="PreProc">return</span>`), so you can't do that.
+
+<span class="PreProc">return</span>                            =&gt; <span class="Constant">&quot;c3/return&quot;</span>
+
+---
+
+In the following instructions types are provided for clarity even if they must
+be provided in an earlier 'var' declaration.
+
+<span class="muComment"># Address operations</span>
+
+var/reg: (addr T) <span class="Special">&lt;-</span> address var2: T
+  =&gt; <span class="Constant">&quot;8d/copy-address *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+
+<span class="muComment"># Array operations</span>
+
+var/reg: (addr T) <span class="Special">&lt;-</span> index arr/rega: (addr array T), idx/regi: int
+  | if size-of(T) is <span class="Constant">1</span>, <span class="Constant">2</span>, <span class="Constant">4</span> or <span class="Constant">8</span>
+      =&gt; <span class="Constant">&quot;(__check-mu-array-bounds *&quot;</span> rega <span class="Constant">&quot; %&quot;</span> regi <span class="Constant">&quot; &quot;</span> size-of(T) <span class="Constant">&quot;)&quot;</span>
+         <span class="Constant">&quot;8d/copy-address *(&quot;</span> rega <span class="Constant">&quot;+&quot;</span> regi <span class="Constant">&quot;&lt;&lt;&quot;</span> log2(size-of(T)) <span class="Constant">&quot;+4) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg: (addr T) <span class="Special">&lt;-</span> index arr: (array T len), idx/regi: int
+  =&gt; <span class="Constant">&quot;(__check-mu-array-bounds *(ebp+&quot;</span> arr.stack-offset <span class="Constant">&quot;) %&quot;</span> regi <span class="Constant">&quot; &quot;</span> size-of(T) <span class="Constant">&quot;)&quot;</span>
+     <span class="Constant">&quot;8d/copy-address *(ebp+&quot;</span> regi <span class="Constant">&quot;&lt;&lt;&quot;</span> log2(size-of(T)) <span class="Constant">&quot;+&quot;</span> (arr.stack-offset + <span class="Constant">4</span>) <span class="Constant">&quot;) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg: (addr T) <span class="Special">&lt;-</span> index arr/rega: (addr array T), n
+  =&gt; <span class="Constant">&quot;(__check-mu-array-bounds *&quot;</span> rega <span class="Constant">&quot; &quot;</span> n <span class="Constant">&quot; &quot;</span> size-of(T) <span class="Constant">&quot;)&quot;</span>
+     <span class="Constant">&quot;8d/copy-address *(&quot;</span> rega <span class="Constant">&quot;+&quot;</span> (n*size-of(T)+<span class="Constant">4</span>) <span class="Constant">&quot;) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg: (addr T) <span class="Special">&lt;-</span> index arr: (array T len), n
+  =&gt; <span class="Constant">&quot;(__check-mu-array-bounds *(ebp+&quot;</span> arr.stack-offset <span class="Constant">&quot;) &quot;</span> n <span class="Constant">&quot; &quot;</span> size-of(T) <span class="Constant">&quot;)&quot;</span>
+     <span class="Constant">&quot;8d/copy-address *(ebp+&quot;</span> (arr.stack-offset+<span class="Constant">4</span>+n*size-of(T)) <span class="Constant">&quot;) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+
+var/reg: (offset T) <span class="Special">&lt;-</span> compute-offset arr: (addr array T), idx/regi: int  <span class="muComment"># arr can be in reg or mem</span>
+  =&gt; <span class="Constant">&quot;69/multiply %&quot;</span> regi <span class="Constant">&quot; &quot;</span> size-of(T) <span class="Constant">&quot;/imm32 &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg: (offset T) <span class="Special">&lt;-</span> compute-offset arr: (addr array T), idx: int       <span class="muComment"># arr can be in reg or mem</span>
+  =&gt; <span class="Constant">&quot;69/multiply *(ebp+&quot;</span> idx.stack-offset <span class="Constant">&quot;) &quot;</span> size-of(T) <span class="Constant">&quot;/imm32 &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg: (addr T) <span class="Special">&lt;-</span> index arr/rega: (addr array T), o/rego: (offset T)
+  =&gt; <span class="Constant">&quot;(__check-mu-array-bounds %&quot;</span> rega <span class="Constant">&quot; %&quot;</span> rego <span class="Constant">&quot; 1 \&quot;&quot; function-name &quot;</span>\<span class="Constant">&quot;)&quot;</span>
+     <span class="Constant">&quot;8d/copy-address *(&quot;</span> rega <span class="Constant">&quot;+&quot;</span> rego <span class="Constant">&quot;+4) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+
+Computing the length of an array is complex.
+
+var/reg: int <span class="Special">&lt;-</span> length arr/reg2: (addr array T)
+  | if T is byte (TODO)
+      =&gt; <span class="Constant">&quot;8b/-&gt; *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+  | if size-of(T) is <span class="Constant">4</span> or <span class="Constant">8</span> or <span class="Constant">16</span> or <span class="Constant">32</span> or <span class="Constant">64</span> or <span class="Constant">128</span>
+      =&gt; <span class="Constant">&quot;8b/-&gt; *&quot;</span> reg2 <span class="Constant">&quot; &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+         <span class="Constant">&quot;c1/shift 5/subop/logic-right %&quot;</span> reg <span class="Constant">&quot; &quot;</span> log2(size-of(T)) <span class="Constant">&quot;/imm8&quot;</span>
+  | otherwise
+      x86 has no instruction to divide by a literal, so
+      we need up to <span class="Constant">3</span> extra registers! <span class="Constant">eax</span>/<span class="Constant">edx</span> for division and say <span class="Constant">ecx</span>
+      =&gt; if reg is not <span class="Constant">eax</span>
+          <span class="Constant">&quot;50/push-eax&quot;</span>
+         if reg is not <span class="Constant">ecx</span>
+          <span class="Constant">&quot;51/push-ecx&quot;</span>
+         if reg is not <span class="Constant">edx</span>
+          <span class="Constant">&quot;52/push-edx&quot;</span>
+         <span class="Constant">&quot;8b/-&gt; *&quot;</span> reg2 <span class="Constant">&quot; eax/r32&quot;</span>
+         <span class="Constant">&quot;31/xor %edx 2/r32/edx&quot;</span>  <span class="muComment"># sign-extend, but array size can't be negative</span>
+         <span class="Constant">&quot;b9/copy-to-ecx &quot;</span> size-of(T) <span class="Constant">&quot;/imm32&quot;</span>
+         <span class="Constant">&quot;f7 7/subop/idiv-eax-edx-by %ecx&quot;</span>
+         if reg is not <span class="Constant">eax</span>
+           <span class="Constant">&quot;89/&lt;- %&quot;</span> reg <span class="Constant">&quot; 0/r32/eax&quot;</span>
+         if reg is not <span class="Constant">edx</span>
+          <span class="Constant">&quot;5a/pop-to-edx&quot;</span>
+         if reg is not <span class="Constant">ecx</span>
+          <span class="Constant">&quot;59/pop-to-ecx&quot;</span>
+         if reg is not <span class="Constant">eax</span>
+          <span class="Constant">&quot;58/pop-to-eax&quot;</span>
+
+<span class="muComment"># User-defined types</span>
+
+If a record (product) <span class="PreProc">type</span> T was defined to have elements a, b, c, ... of
+types T_a, T_b, T_c, ..., then accessing one of those elements f of <span class="PreProc">type</span> T_f:
+
+var/reg: (addr T_f) <span class="Special">&lt;-</span> get var2/reg2: (addr T), f
+  =&gt; <span class="Constant">&quot;8d/copy-address *(&quot;</span> reg2 <span class="Constant">&quot;+&quot;</span> offset(f) <span class="Constant">&quot;) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+var/reg: (addr T_f) <span class="Special">&lt;-</span> get var2: T, f
+  =&gt; <span class="Constant">&quot;8d/copy-address *(ebp+&quot;</span> var2.stack-offset <span class="Constant">&quot;+&quot;</span> offset(f) <span class="Constant">&quot;) &quot;</span> reg <span class="Constant">&quot;/r32&quot;</span>
+
+<span class="muComment"># Allocating memory</span>
+
+allocate in: (addr handle T)
+  =&gt; <span class="Constant">&quot;(allocate Heap &quot;</span> size-of(T) <span class="Constant">&quot; &quot;</span> in <span class="Constant">&quot;)&quot;</span>
+
+populate in: (addr handle array T), num  <span class="muComment"># can be literal or variable on stack or register</span>
+  =&gt; <span class="Constant">&quot;(allocate-array2 Heap &quot;</span> size-of(T) <span class="Constant">&quot; &quot;</span> num <span class="Constant">&quot; &quot;</span> in <span class="Constant">&quot;)&quot;</span>
+
+populate-stream in: (addr handle stream T), num  <span class="muComment"># can be literal or variable on stack or register</span>
+  =&gt; <span class="Constant">&quot;(new-stream Heap &quot;</span> size-of(T) <span class="Constant">&quot; &quot;</span> num <span class="Constant">&quot; &quot;</span> in <span class="Constant">&quot;)&quot;</span>
+
+<span class="muComment"># Some miscellaneous helpers to avoid error-prone size computations</span>
+
+clear x: (addr T)
+  =&gt; <span class="Constant">&quot;(zero-out &quot;</span> s <span class="Constant">&quot; &quot;</span> size-of(T) <span class="Constant">&quot;)&quot;</span>
+
+read-from-stream s: (addr stream T), out: (addr T)
+  =&gt; <span class="Constant">&quot;(read-from-stream &quot;</span> s <span class="Constant">&quot; &quot;</span> out <span class="Constant">&quot; &quot;</span> size-of(T) <span class="Constant">&quot;)&quot;</span>
+
+write-to-stream s: (addr stream T), in: (addr T)
+  =&gt; <span class="Constant">&quot;(write-to-stream &quot;</span> s <span class="Constant">&quot; &quot;</span> in <span class="Constant">&quot; &quot;</span> size-of(T) <span class="Constant">&quot;)&quot;</span>
+
+vim&#0058;ft=mu:nowrap:textwidth=<span class="Constant">0</span>
+</pre>
+</body>
+</html>
+<!-- vim: set foldmethod=manual : -->