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
63
|
; Build/run from examples/:
; ../utils/mcpu-as -o frame-pointer.o frame-pointer.s
; ../utils/mcpu-ld --stack-size=512 -o frame-pointer frame-pointer.o
; ../utils/mcpu-run --int-reg=r64@0x00008 frame-pointer
;
; Expected output: 42
;
; LibCPU optional frame-pointer and dynamic STACK allocation example.
;
; demo(5) builds a fixed frame, creates a 24-byte dynamic object below it,
; accesses a fixed local through FP while SP is moving, and returns 42 in
; the canonical r64 return register.
.text
_start_life:
LDI r64@0x00000, 5
ADJSP -16 ; 16-byte ABI argument block
STSP 0, r64@0x00000
CALL demo
ADJSP 16
MOV r64@0x00008, r64@0x7fff8
HALT
demo:
PUSHFP
SETFP
ADJSP -16
; First explicit argument. With FP in use the layout is:
; FP+0 saved caller FP
; FP+8 return PC
; FP+16 first explicit argument
LDFP r64@0x00100, 16
; Fixed local at FP-8.
STFP -8, r64@0x00100
LEAFP r64@0x00108, -8
; Save the current stack top as a dynamic-scope mark.
LEASP r64@0x00110, 0
; Dynamically reserve 24 bytes: new_SP = old_SP - 24.
LDI r64@0x00118, 24
PSUB r64@0x00120, r64@0x00110, r64@0x00118
SETSP r64@0x00120
; Put 37 in the dynamic object at current SP.
LDI r64@0x00128, 37
LEASP r64@0x00130, 0
STOREP r64@0x00130, r64@0x00128
; FP-relative access is stable although SP moved dynamically.
LDFP r64@0x00138, -8
LOADP r64@0x00140, r64@0x00130
IADD r64@0x7fff8, r64@0x00138, r64@0x00140
; Restore the nested dynamic scope explicitly.
SETSP r64@0x00110
; Destroy the complete frame below FP, restore caller FP and return.
RESTSP
POPFP
RET
|