diff --git a/examples/call_ret.mima b/examples/call_ret.mima index b18cb35..e775497 100644 Binary files a/examples/call_ret.mima and b/examples/call_ret.mima differ diff --git a/examples/call_ret_stack.mima b/examples/call_ret_stack.mima index e50c406..a64fbce 100644 Binary files a/examples/call_ret_stack.mima and b/examples/call_ret_stack.mima differ diff --git a/examples/call_ret_stack.mimasm b/examples/call_ret_stack.mimasm index 0a4800f..c0800ed 100644 --- a/examples/call_ret_stack.mimasm +++ b/examples/call_ret_stack.mimasm @@ -17,7 +17,7 @@ main: STV counter ; Since we're top-level, we don't need to (re-)store our RA when calling - CALL sub-a + CALL sub-1 ; set counter bit 1 LDV counter @@ -27,7 +27,7 @@ main: HALT 200: -sub-a: +sub-1: ; Set counter bit 2 LDV counter ADC 0x04 @@ -36,18 +36,18 @@ sub-a: ;; Store the current RA on the stack ; Store the RA at current position of stack pointer LDRA - STVR 0 + STRS 0 ; Move stack pointer by 1 since the stack grew LDSP ADC -1 STSP ; Call the subfunction - CALL sub-b + CALL sub-2 ;; Pop and restore the RA from the stack ; Read RA from the top of the stack - LDVR 1 + LDRS 1 STRA ; Remove top element from stack LDSP @@ -62,7 +62,7 @@ sub-a: RET 300: -sub-b: +sub-2: ; Set counter bit 4 LDV counter ADC 0x10 diff --git a/examples/stack.mima b/examples/stack.mima index 6bec57d..ea6cd3b 100644 Binary files a/examples/stack.mima and b/examples/stack.mima differ diff --git a/examples/stack.mimasm b/examples/stack.mimasm index 95ed0ac..f820b5e 100644 --- a/examples/stack.mimasm +++ b/examples/stack.mimasm @@ -12,8 +12,7 @@ ; Functions take a fixed number of arguments. For this example, all ; values have a size of one word (24 bit). -IAR = caller -RA = 12345 ; to test whether the caller stores and restores the RA correctly +IAR = main SP = 0xfffff FP = 0xfffff @@ -29,78 +28,93 @@ tmp4: LIT 0 tmp5: LIT 0 100: -caller: - ; 1. Push RA onto current stack frame - LDRA - STVR 0 - LDSP - ADC -1 - STSP ; SP offset: 1 +main: + CALL caller + HALT - ; 2. Create a new shared stack frame +200: +caller: + ;; 1. Initialisation + + ; 1.1. Create own stack frame LDFP - STVR 0 + STRS 0 LDSP ADC -1 STSP STFP - ; 3. Push function parameters onto shared stack frame - LDC 5 - STVR 0 - LDC 7 - STVR -1 + ; 2. Push RA onto current stack frame + LDRA + STRS 0 LDSP - ADC -2 - STSP ; SP offset: 2 + ADC -1 + STSP + + ; Do some work here + + ;; 2. Prepare call - ; 4. Create space for return values + ; 2.1. Create a new shared stack frame + LDFP + STRS 0 LDSP - ADC -2 - STSP; SP offset: 4 + ADC -1 + STSP + STFP + + ; 2.2. Write function parameters onto shared stack frame and keep + ; space for return values + LDC 5 + STRF 0 + LDC 7 + STRF -1 + LDFP + ADC -4 ; 2 parameters and 2 return values + STSP ; Now, the shared stack frame looks like this: - ; 4: argument 1 - ; 3: argument 2 - ; 2: return value 1 - ; 1: return value 2 + ; + ; FP offset | Value + ; 0 | argument 1 + ; -1 | argument 2 + ; -2 | return value 1 + ; -3 | return value 2 - ; 5. Call callee + ;; 3. Call callee CALL callee - ; 6. Copy resulting values from the shared stack frame, so we can + ;; 4. Cleanup after call + + ; 4.1. Copy resulting values from the shared stack frame, so we can ; restore our own stack frame - LDVR 2 + LDRF -2 STV tmp1 - LDVR 1 + LDRF -3 STV tmp2 - ; 7. Restore own stack frame + ; 4.2. Restore own stack frame LDFP ADC 1 STSP - LDVR 0 + LDRF 1 STFP - ; 8. Pop and restore RA - LDVR 1 + ; Now, we can use the results stored in tmp1 and tmp2. + ; Do some more work here + + ;; 5. Cleanup before RET + + ; 5.1. Pop and restore RA + LDRS 1 STRA LDSP ADC 1 - STSP ; SP offset: 0 + STSP - ; Now, we can use the results, or put them onto our own stack like so: - LDV tmp1 - STVR 0 - LDV tmp2 - STVR -1 - LDSP - ADC -2 - STSP ; SP offset: 2 - - HALT + RET -500: +300: callee: ; This callee doesn't really need its own stack since all ; calculations did fit into the temporary variables. I still created @@ -109,34 +123,33 @@ callee: ; 1. Create own stack frame LDFP - STVR 0 + STRS 0 LDSP ADC -1 STSP STFP - ; Now, the shared stack frame looks like this: - ; 5: argument 1 - ; 4: argument 2 - ; 3: return value 1 - ; 2: return value 2 - ; 1: previous FP + ; Since we've pushed the old FP to the shared stack frame (which now + ; has length 5) and moved the FP to after that, we've in effect + ; added 5 to the FP offset. This means that the shared stack frame + ; now looks like this: ; - ; The compiler needs to keep track of the offset of the SP within - ; the current stack frame, so that LDVR and STVR have the correct - ; offset when accessing variables inside it (or the previous, shared - ; stack frame). + ; FP offset | Value + ; 5 | argument 1 + ; 4 | argument 2 + ; 3 | return value 1 + ; 2 | return value 2 ; 2. Load arguments into temporary variables - LDVR 5 + LDRF 5 STV tmp1 - LDVR 4 + LDRF 4 STV tmp2 ; 3. Add arguments and put result into return value 1 LDV tmp1 ADD tmp2 - STVR 3 + STRF 3 ; 4. Multiply arguments and put result into return value 2 LDC 0 @@ -162,13 +175,13 @@ callee: callee-loop-end: ; Save the result in return value 2 LDV tmp4 - STVR 2 + STRF 2 ; 5. Restore shared stack frame LDFP ADC 1 STSP - LDVR 0 + LDRF 1 STFP ; And this function is done :)