diff --git a/apps/mu b/apps/mu index b1439126..1d0a6e97 100755 Binary files a/apps/mu and b/apps/mu differ diff --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"