summaryrefslogtreecommitdiff
path: root/tests/fixtures/frame-pointer.s
blob: 6c6934be4dd59ce6f7c64e5cc98be52635b61e80 (plain)
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