diff options
author | Kartik Agaram <vc@akkartik.com> | 2020-03-11 16:52:37 -0700 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2020-03-11 17:21:59 -0700 |
commit | 28746b36660093dcbf53667f4f67320d278359ea (patch) | |
tree | a3feabc3190234fcb9c2dd8802250c191c53bea2 /101stack_allocate.subx | |
parent | bfb7c601354563498433d22f4dcf3ad4280a7314 (diff) | |
download | mu-28746b36660093dcbf53667f4f67320d278359ea.tar.gz |
6123 - runtime helper for initializing arrays
I built this in 3 phases: a) create a helper in the bootstrap VM to render the state of the stack. b) interactively arrive at the right function (tools/stack_array.subx) c) pull the final solution into the standard library (093stack_allocate.subx) As the final layer says, this may not be the fastest approach for most (or indeed any) Mu programs. Perhaps it's better on balance for the compiler to just emit n/4 `push` instructions. (I'm sure this solution can be optimized further.)
Diffstat (limited to '101stack_allocate.subx')
-rw-r--r-- | 101stack_allocate.subx | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/101stack_allocate.subx b/101stack_allocate.subx new file mode 100644 index 00000000..02ad84f2 --- /dev/null +++ b/101stack_allocate.subx @@ -0,0 +1,62 @@ +# A function which pushes n zeros on the stack. +# Not really useful to call manually. +# The Mu compiler uses it when defining arrays on the stack. + +== code + +#? Entry: +#? # . prologue +#? 89/<- %ebp 4/r32/esp +#? # +#? 68/push 0xfcfdfeff/imm32 +#? b8/copy-to-eax 0x34353637/imm32 +#? $dump-stack0: +#? (push-n-zero-bytes 4) +#? 68/push 0x20/imm32 +#? $dump-stack9: +#? b8/copy-to-eax 1/imm32/exit +#? cd/syscall 0x80/imm8 + +# This is not a regular function, so it won't be idiomatic. +# Registers must be properly restored. +# Registers can be spilled, but that modifies the stack and needs to be +# cleaned up. + +# Overhead: +# 62 + n*6 instructions to push n bytes. +# If we just emitted code to push n zeroes, it would be: +# 5 bytes for 4 zero bytes, so 1.25 bytes per zero. And that's not even +# instructions. +# But on the other hand it would destroy the instruction cache, where this +# approach requires 15 instructions, fixed. + +# n must be positive +push-n-zero-bytes: # n: int +$push-n-zero-bytes:prologue: + 89/<- *Push-n-zero-bytes-ebp 5/r32/ebp # spill ebp without affecting stack + 89/<- %ebp 4/r32/esp +$push-n-zero-bytes:copy-ra: + # -- esp = ebp + 50/push-eax + # -- esp+8 = ebp+4 + # -- esp+4 = ebp + 8b/-> *(esp+4) 0/r32/eax + 2b/subtract *(ebp+4) 4/r32/esp + # -- esp+4+n = ebp + 89/<- *(esp+4) 0/r32/eax + 58/pop-to-eax + # -- esp+n = ebp +$push-n-zero-bytes:bulk-cleaning: + 89/<- *Push-n-zero-bytes-esp 4/r32/esp + 81 0/subop/add *Push-n-zero-bytes-esp 4/imm32 + 81 0/subop/add *(ebp+4) 4/imm32 + (zero-out *Push-n-zero-bytes-esp *(ebp+4)) # n+4 +$push-n-zero-bytes:epilogue: + 8b/-> *Push-n-zero-bytes-ebp 5/r32/ebp # restore spill + c3/return + +== data +Push-n-zero-bytes-ebp: # (addr int) + 0/imm32 +Push-n-zero-bytes-esp: # (addr int) + 0/imm32 |