diff options
Diffstat (limited to 'tests/fixtures/frame-pointer.s')
| -rw-r--r-- | tests/fixtures/frame-pointer.s | 63 |
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 |
