summaryrefslogtreecommitdiff
path: root/tests/fixtures/frame-pointer.s
diff options
context:
space:
mode:
authorkx <kx@radix-linux.su>2026-10-09 18:00:15 +0300
committerkx <kx@radix-linux.su>2026-10-09 18:00:15 +0300
commit065da3509019b15dd0e678072e6be629e5330bef (patch)
tree69c934c9e786ac048b4fbe8f4c4c5571661521f4 /tests/fixtures/frame-pointer.s
parentd130fe27fa753be02ed76fd9b277aa3c3d928eb9 (diff)
downloadlibmcpu-0.4.0.tar.xz
Version 0.4.00.4.0
Diffstat (limited to 'tests/fixtures/frame-pointer.s')
-rw-r--r--tests/fixtures/frame-pointer.s63
1 files changed, 63 insertions, 0 deletions
diff --git a/tests/fixtures/frame-pointer.s b/tests/fixtures/frame-pointer.s
new file mode 100644
index 0000000..6c6934b
--- /dev/null
+++ b/tests/fixtures/frame-pointer.s
@@ -0,0 +1,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