about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xapps/mubin593809 -> 594611 bytes
-rw-r--r--apps/mu.subx79
-rw-r--r--mu.md3
-rw-r--r--mu_instructions2
4 files changed, 70 insertions, 14 deletions
diff --git a/apps/mu b/apps/mu
index b1439126..1d0a6e97 100755
--- a/apps/mu
+++ b/apps/mu
Binary files differdiff --git a/apps/mu.subx b/apps/mu.subx
index 4e8c6721..91825443 100644
--- a/apps/mu.subx
+++ b/apps/mu.subx
@@ -3620,19 +3620,21 @@ test-convert-function-with-byte-operations:
     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-function-with-byte-operations/8")
     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"                  "F - test-convert-function-with-byte-operations/9")
     (check-next-stream-line-equal _test-output-stream "    8a/byte-> %eax 0x00000001/r32"           "F - test-convert-function-with-byte-operations/10")
-    (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/11")
-    (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/12")
-    (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/13")
-    (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/14")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/15")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/16")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/17")
-    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/18")
-    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/19")
-    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/20")
-    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/21")
-    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/22")
-    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/23")
+    (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/11")
+    (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/12")
+    (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/13")
+    (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/14")
+    (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/15")
+    (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/16")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/17")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/18")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/19")
+    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/20")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/21")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/22")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/23")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/24")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/25")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -28302,6 +28304,16 @@ emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (ad
     8b/-> *(ebp+0xc) 1/r32/ecx
     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
     89/<- %ecx 0/r32/eax
+    # copy byte (can be a primitive except we need to emit a second instruction)
+    {
+      # if (!string-equal?(stmt->operation, "copy-byte")) break
+      (string-equal? %ecx "copy-byte")  # => eax
+      3d/compare-eax-and 0/imm32
+      0f 84/jump-if-= break/disp32
+      (translate-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
+      e9/jump $emit-subx-stmt:end/disp32
+    }
+    # copy-byte-to can be a primitive; writes to memory don't need to clear surrounding bytes
     # array size
     {
       # if (!string-equal?(stmt->operation, "length")) break
@@ -28751,6 +28763,47 @@ $emit-divide-by-shift-right:end:
     5d/pop-to-ebp
     c3/return
 
+translate-mu-copy-byte-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+    50/push-eax
+    56/push-esi
+    # esi = stmt
+    8b/-> *(ebp+0xc) 6/r32/esi
+    #
+    (emit-indent *(ebp+8) *Curr-block-depth)
+    (write-buffered *(ebp+8) "8a/byte->")
+    # emit stmt->inouts[0]
+    (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
+    (emit-subx-var-as-rm32 *(ebp+8) %eax)
+    # emit /r32 for stmt->outputs[0]->register
+    (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
+    (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
+    (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
+    (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
+    (write-buffered *(ebp+8) Space)
+    (write-int32-hex-buffered *(ebp+8) *eax)
+    (write-buffered *(ebp+8) "/r32\n")
+    # clear rest of register
+    (emit-indent *(ebp+8) *Curr-block-depth)
+    (write-buffered *(ebp+8) "81 4/subop/and %")
+    8b/-> *(ebp+0xc) 0/r32/eax
+    (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
+    (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
+    (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
+    (write-buffered *(ebp+8) %eax)
+    (write-buffered *(ebp+8) " 0xff/imm32\n")
+$translate-mu-copy-byte-stmt:end:
+    # . restore registers
+    5e/pop-to-esi
+    58/pop-to-eax
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 # a little different from other translate- functions; notice the extra 'fn' argument
 translate-mu-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
     # . prologue
diff --git a/mu.md b/mu.md
index b342aa6c..a990bc0c 100644
--- a/mu.md
+++ b/mu.md
@@ -685,7 +685,8 @@ enforce type- and memory-safety, I was forced to carve out a few exceptions:
 * the `length` instruction on arrays, for translating the array size in bytes
   into the number of elements.
 * the `lookup` instruction on handles, for validating fat-pointer metadata
-* `var` instructions, for initializing memory
+* `var` instructions, to initialize memory
+* byte copies, to initialize memory
 
 If you're curious, [the compiler summary page](http://akkartik.github.io/mu/html/mu_instructions.html)
 has the complete nitty-gritty on how each instruction is implemented. Including
diff --git a/mu_instructions b/mu_instructions
index ba8dd2cf..7c3d8d6c 100644
--- a/mu_instructions
+++ b/mu_instructions
@@ -115,7 +115,9 @@ copy-to var, n                    => "c7 0/subop/copy *(ebp+" var.stack-offset "
 copy-to *var/reg, n               => "c7 0/subop/copy *" reg " " n "/imm32"
 
 var/reg <- copy-byte var2/reg2    => "8a/byte-> %" reg2 " " reg "/r32"
+                                     "81 4/subop/and %" reg " 0xff/imm32"
 var/reg <- copy-byte *var2/reg2   => "8a/byte-> *" reg2 " " reg "/r32"
+                                     "81 4/subop/and %" reg " 0xff/imm32"
 copy-byte-to *var1/reg1, var2/reg2  => "88/byte<- *" reg1 " " reg2 "/r32"
 
 compare var1, var2/reg2           => "39/compare *(ebp+" var1.stack-offset ") " reg2 "/r32"