blob: 02ad84f2325652534c8cface81649063ce880bc7 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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
|