From e25b9e0a4d931141bf191340639d7232c235cdaf Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Mon, 23 Mar 2020 20:55:57 -0700 Subject: 6163 --- html/mu_instructions.html | 248 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 html/mu_instructions.html diff --git a/html/mu_instructions.html b/html/mu_instructions.html new file mode 100644 index 00000000..d986552a --- /dev/null +++ b/html/mu_instructions.html @@ -0,0 +1,248 @@ + + + + +~/Attic/Repos/mu/mu_instructions.html + + + + + + + + +
+## Mu's instructions and their table-driven translation
+
+Mu is a statement-oriented language. Blocks consist of flat lists of instructions.
+The following chart shows all the instruction forms supported by Mu, along
+with the instruction they're translated to. Variables of the form "var/reg"
+live in a register, and other variables are assumed to live on the stack at
+some 'stack-offset' from ebp.
+
+var/eax <- increment              => "40/increment-eax"
+var/ecx <- increment              => "41/increment-ecx"
+var/edx <- increment              => "42/increment-edx"
+var/ebx <- increment              => "43/increment-ebx"
+var/esi <- increment              => "46/increment-esi"
+var/edi <- increment              => "47/increment-edi"
+increment var                     => "ff 0/subop/increment *(ebp+" var.stack-offset ")"
+increment *var/reg                => "ff 0/subop/increment *" reg
+
+var/eax <- decrement              => "48/decrement-eax"
+var/ecx <- decrement              => "49/decrement-ecx"
+var/edx <- decrement              => "4a/decrement-edx"
+var/ebx <- decrement              => "4b/decrement-ebx"
+var/esi <- decrement              => "4e/decrement-esi"
+var/edi <- decrement              => "4f/decrement-edi"
+decrement var                     => "ff 1/subop/decrement *(ebp+" var.stack-offset ")"
+decrement *var/reg                => "ff 1/subop/decrement *" reg
+
+var/reg <- add var2/reg2          => "01/add-to %" reg " " reg2 "/r32"
+var/reg <- add var2               => "03/add *(ebp+" var2.stack-offset ") " reg "/r32"
+var/reg <- add *var2/reg2         => "03/add *" reg2 " " reg "/r32"
+add-to var1, var2/reg             => "01/add-to *(ebp+" var1.stack-offset ") " reg "/r32"
+var/eax <- add n                  => "05/add-to-eax " n "/imm32"
+var/reg <- add n                  => "81 0/subop/add %" reg " " n "/imm32"
+add-to var, n                     => "81 0/subop/add *(ebp+" var.stack-offset ") " n "/imm32"
+add-to *var/reg, n                => "81 0/subop/add *" reg " " n "/imm32"
+
+var/reg <- subtract var2/reg2     => "29/subtract-from %" reg " " reg2 "/r32"
+var/reg <- subtract var2          => "2b/subtract *(ebp+" var2.stack-offset ") " reg "/r32"
+var/reg <- subtract *var2/reg2    => "2b/subtract *" reg2 " " reg1 "/r32"
+subtract-from var1, var2/reg2     => "29/subtract-from *(ebp+" var1.stack-offset ") " reg2 "/r32"
+var/eax <- subtract n             => "2d/subtract-from-eax " n "/imm32"
+var/reg <- subtract n             => "81 5/subop/subtract %" reg " " n "/imm32"
+subtract-from var, n              => "81 5/subop/subtract *(ebp+" var.stack-offset ") " n "/imm32"
+subtract-from *var/reg, n         => "81 5/subop/subtract *" reg " " n "/imm32"
+
+var/reg <- and var2/reg2          => "21/and-with %" reg " " reg2 "/r32"
+var/reg <- and var2               => "23/and *(ebp+" var2.stack-offset " " reg "/r32"
+var/reg <- and *var2/reg2         => "23/and *" reg2 " " reg "/r32"
+and-with var1, var2/reg           => "21/and-with *(ebp+" var1.stack-offset ") " reg "/r32"
+var/eax <- and n                  => "25/and-with-eax " n "/imm32"
+var/reg <- and n                  => "81 4/subop/and %" reg " " n "/imm32"
+and-with var, n                   => "81 4/subop/and *(ebp+" var.stack-offset ") " n "/imm32"
+and-with *var/reg, n              => "81 4/subop/and *" reg " " n "/imm32"
+
+var/reg <- or var2/reg2           => "09/or-with %" reg " " reg2 "/r32"
+var/reg <- or var2                => "0b/or *(ebp+" var2.stack-offset ") " reg "/r32"
+var/reg <- or *var2/reg2          => "0b/or *" reg2 " " reg "/r32"
+or-with var1, var2/reg2           => "09/or-with *(ebp+" var1.stack-offset " " reg2 "/r32"
+var/eax <- or n                   => "0d/or-with-eax " n "/imm32"
+var/reg <- or n                   => "81 1/subop/or %" reg " " n "/imm32"
+or-with var, n                    => "81 1/subop/or *(ebp+" var.stack-offset ") " n "/imm32"
+or-with *var/reg, n               => "81 1/subop/or *" reg " " n "/imm32"
+
+var/reg <- xor var2/reg2          => "31/xor-with %" reg " " reg2 "/r32"
+var/reg <- xor var2               => "33/xor *(ebp+" var2.stack-offset ") " reg "/r32"
+var/reg <- xor *var2/reg2         => "33/xor *" reg2 " " reg "/r32"
+xor-with var1, var2/reg           => "31/xor-with *(ebp+" var1.stack-offset ") " reg "/r32"
+var/eax <- xor n                  => "35/xor-with-eax " n "/imm32"
+var/reg <- xor n                  => "81 6/subop/xor %" reg " " n "/imm32"
+xor-with var, n                   => "81 6/subop/xor *(ebp+" var.stack-offset ") " n "/imm32"
+xor-with *var/reg, n              => "81 6/subop/xor *" reg " " n "/imm32"
+
+var/eax <- copy n                 => "b8/copy-to-eax " n "/imm32"
+var/ecx <- copy n                 => "b9/copy-to-ecx " n "/imm32"
+var/edx <- copy n                 => "ba/copy-to-edx " n "/imm32"
+var/ebx <- copy n                 => "bb/copy-to-ebx " n "/imm32"
+var/esi <- copy n                 => "be/copy-to-esi " n "/imm32"
+var/edi <- copy n                 => "bf/copy-to-edi " n "/imm32"
+var/reg <- copy var2/reg2         => "89/<- %" reg " " reg2 "/r32"
+copy-to var1, var2/reg            => "89/<- *(ebp+" var1.stack-offset ") " reg "/r32"
+var/reg <- copy var2              => "8b/-> *(ebp+" var2.stack-offset ") " reg "/r32"
+var/reg <- copy *var2/reg2        => "8b/-> *" reg2 " " reg "/r32"
+var/reg <- copy n                 => "c7 0/subop/copy %" reg " " n "/imm32"
+copy-to var, n                    => "c7 0/subop/copy *(ebp+" var.stack-offset ") " n "/imm32"
+copy-to *var/reg, n               => "c7 0/subop/copy *" reg " " n "/imm32"
+
+compare var1, var2/reg2           => "39/compare *(ebp+" var1.stack-offset ") " reg2 "/r32"
+compare *var1/reg1, var2/reg2     => "39/compare *" reg1 " " reg2 "/r32"
+compare var1/reg1, var2           => "3b/compare<- *(ebp+" var2.stack-offset ") " reg1 "/r32"
+compare var/reg, *var2/reg2       => "3b/compare<- *" reg " " n "/imm32"
+compare var/eax, n                => "3d/compare-eax-with " n "/imm32"
+compare var, n                    => "81 7/subop/compare *(ebp+" var.stack-offset ") " n "/imm32"
+compare *var/reg, n               => "81 7/subop/compare *" reg " " n "/imm32"
+
+var/reg <- multiply var2          => "0f af/multiply *(ebp+" var2.stack-offset ") " reg "/r32"
+var/reg <- multiply *var2/reg2    => "0f af/multiply *" reg2 " " reg "/r32"
+
+break                             => "e9/jump break/disp32"
+break label                       => "e9/jump " label ":break/disp32"
+loop                              => "e9/jump loop/disp32"
+loop label                        => "e9/jump " label ":loop/disp32"
+
+break-if-=                        => "0f 84/jump-if-= break/disp32"
+break-if-= label                  => "0f 84/jump-if-= " label ":break/disp32"
+loop-if-=                         => "0f 84/jump-if-= loop/disp32"
+loop-if-= label                   => "0f 84/jump-if-= " label ":loop/disp32"
+
+break-if-!=                       => "0f 85/jump-if-!= break/disp32"
+break-if-!= label                 => "0f 85/jump-if-!= " label ":break/disp32"
+loop-if-!=                        => "0f 85/jump-if-!= loop/disp32"
+loop-if-!= label                  => "0f 85/jump-if-!= " label ":loop/disp32"
+
+break-if-<                        => "0f 8c/jump-if-< break/disp32"
+break-if-< label                  => "0f 8c/jump-if-< " label ":break/disp32"
+loop-if-<                         => "0f 8c/jump-if-< loop/disp32"
+loop-if-< label                   => "0f 8c/jump-if-< " label ":loop/disp32"
+
+break-if->                        => "0f 8f/jump-if-> break/disp32"
+break-if-> label                  => "0f 8f/jump-if-> " label ":break/disp32"
+loop-if->                         => "0f 8f/jump-if-> loop/disp32"
+loop-if-> label                   => "0f 8f/jump-if-> " label ":loop/disp32"
+
+break-if-<=                       => "0f 8e/jump-if-<= break/disp32"
+break-if-<= label                 => "0f 8e/jump-if-<= " label ":break/disp32"
+loop-if-<=                        => "0f 8e/jump-if-<= loop/disp32"
+loop-if-<= label                  => "0f 8e/jump-if-<= " label ":loop/disp32"
+
+break-if->=                       => "0f 8d/jump-if->= break/disp32"
+break-if->= label                 => "0f 8d/jump-if->= " label ":break/disp32"
+loop-if->=                        => "0f 8d/jump-if->= loop/disp32"
+loop-if->= label                  => "0f 8d/jump-if->= " label ":loop/disp32"
+
+break-if-addr<                    => "0f 82/jump-if-addr< break/disp32"
+break-if-addr< label              => "0f 82/jump-if-addr< " label ":break/disp32"
+loop-if-addr<                     => "0f 82/jump-if-addr< loop/disp32"
+loop-if-addr< label               => "0f 82/jump-if-addr< " label ":loop/disp32"
+
+break-if-addr>                    => "0f 87/jump-if-addr> break/disp32"
+break-if-addr> label              => "0f 87/jump-if-addr> " label ":break/disp32"
+loop-if-addr>                     => "0f 87/jump-if-addr> loop/disp32"
+loop-if-addr> label               => "0f 87/jump-if-addr> " label ":loop/disp32"
+
+break-if-addr<=                   => "0f 86/jump-if-addr<= break/disp32"
+break-if-addr<= label             => "0f 86/jump-if-addr<= " label ":break/disp32"
+loop-if-addr<=                    => "0f 86/jump-if-addr<= loop/disp32"
+loop-if-addr<= label              => "0f 86/jump-if-addr<= " label ":loop/disp32"
+
+break-if-addr>=                   => "0f 83/jump-if-addr>= break/disp32"
+break-if-addr>= label             => "0f 83/jump-if-addr>= " label ":break/disp32"
+loop-if-addr>=                    => "0f 83/jump-if-addr>= loop/disp32"
+loop-if-addr>= label              => "0f 83/jump-if-addr>= " label ":loop/disp32"
+
+In the following instructions types are provided for clarity even if they must
+be provided in an earlier 'var' declaration.
+
+Address operations
+
+var/reg: (addr T) <- address var: T
+  => "8d/copy-address *(ebp+" var.stack-offset ") " reg "/r32"
+
+Array operations (TODO: bounds-checking)
+
+var/reg <- length arr/reg2: (addr array T)
+  => "8b/-> *" reg2 " " reg "/r32"
+var/reg <- index arr/rega: (addr array T), idx/regi: int  # if size(T) is 4 or 8
+  => "8d/copy-address *(" rega "+" regi "<<" log2(size(T)) "+4) " reg "/r32"
+var/reg <- index arr: (array T sz), idx/regi: int
+  => "8d/copy-address *(ebp+" regi "<<" log2(size(T)) "+" (arr.stack-offset + 4) ") " reg "/r32"
+var/reg <- index arr/rega: (addr array T), n
+  => "8d/copy-address *(" rega "+" (n*size(T)+4) ") " reg "/r32"
+var/reg <- index arr: (array T sz), n
+  => "8d/copy-address *(ebp+" (arr.stack-offset+4+n*size(T)) ") " reg "/r32"
+
+var/reg: (offset T) <- compute-offset arr: (addr array T), idx/regi: int  # arr can be in reg or mem
+  => "69/multiply %" regi " " size(T) "/imm32 " reg "/r32"
+var/reg: (offset T) <- compute-offset arr: (addr array T), idx: int       # arr can be in reg or mem
+  => "69/multiply *(ebp+" idx.stack-offset ") " size(T) "/imm32 " reg "/r32"
+var/reg <- index arr/rega: (addr array T), o/rego: offset
+  => "8d/copy-address *(" rega "+" rego "+4) " reg "/r32"
+
+User-defined types
+
+If a record (product) type 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 type T_f:
+
+var/reg: (addr T_f) <- get var2/reg2: (addr F), f
+  => "8d/copy-address *(" reg2 "+" offset(f) ") " reg "/r32"
+var/reg: (addr T_f) <- get var2: (addr F), f
+  => "8d/copy-address *(ebp+" var2.stack-offset "+" offset(f) ") " reg "/r32"
+
+Handles for safe access to the heap
+
+copy-handle-to dest: (handle T), src: (handle T)
+  => "50/push-eax"
+     "8b/-> *(ebp+" src.stack-offset ") 0/r32/eax"
+     "89/<- *(ebp+" dest.stack-offset ") 0/r32/eax"
+     "8b/-> *(ebp+" src.stack-offset+4 ") 0/r32/eax"
+     "89/<- *(ebp+" dest.stack-offset+4 ") 0/r32/eax"
+     "58/pop-to-eax"
+
+copy-handle-to *dest/reg: (addr handle T), src: (handle T)
+  => "50/push-eax"
+     "8b/-> *(ebp+" src.stack-offset ") 0/r32/eax"
+     "89/<- *" reg " 0/r32/eax"
+     "8b/-> *(ebp+" src.stack-offset+4 ") 0/r32/eax"
+     "89/<- *(" reg "+4) 0/r32/eax"
+     "58/pop-to-eax"
+
+out/reg: (addr T) <- lookup in: (handle T)
+  => # payload_allocid = in->address->allocid
+     "8b/-> *(epb+" (in.stack-offset+4) ") " reg "/r32"
+     "8b/-> *" reg " " reg "/r32"
+     # if (payload_allocid != handle->allocid) abort
+     "39/compare *(ebp+" in.stack-offset ") " reg "/r32"
+     "0f 85/jump-if-!= $lookup:abort/disp32"
+     # return payload
+     "8b/-> *(epb+" (in.stack-offset+4) ") " reg "/r32"
+     "81 0/subop/add %" reg " 4/imm32"  # skip payload->allocid
+
+vim:ft=mu:nowrap:textwidth=0
+
+ + + -- cgit 1.4.1-2-gfad0