7286 - mu.subx: isolate bytes from previous values

This commit is contained in:
Kartik Agaram 2020-11-27 00:00:40 -08:00
parent c165b0be5a
commit 125bfde435
4 changed files with 70 additions and 14 deletions

BIN
apps/mu

Binary file not shown.

View File

@ -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

3
mu.md
View File

@ -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

View File

@ -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"