I need to be able to return values from functions. So I had to make a change.
I could have used a "return" statement, but decided instead to extend the function arguments to include "inout" parameters instead.
This allows me to return zero or more value from a function call by marking the relevant params as "out". Technically are "inout" when marked in this manner.
Below I pass 'A' into the call tree and the value is incremented in the function 'depth2' changing it to a 'B'; which we expect to be printed once control returns to the main function.
fun depth2(b1 out) {
var b1 = b1 + 1;
}
fun depth1(a1 out) {
depth2(a1)
}
fun main() {
var arg1 = 'A';
depth1(arg1)
putchar(arg1)
}
The Assembler is shown below.
Everything wth a ';' is a comment so there are 36 instructions to implement the above program.
The "EQU" block defined constants for the addresses in RAM for temporary values and for function arguments and also variables used in the program.
The names of these constants map to the static path in the program where the variable can be found.
No stack is used at the moment so all calls and return addresses are recorded in RAM variables allocated to each function. What this aproach means is that the execution is fast at the expense of not being able to safely have functions called recursuvely; ie no "reentrant" functions.
If I retain this calling convention as the default and call it the "variable" calling conventions, then I can introduce a second calling convention called "stack" for those few cases where reentrant functions are needed. The function declaration would signal when it wants one or the other.
root_function_depth2___VAR_RETURN_HI: EQU 0
root_function_depth2___VAR_RETURN_LO: EQU 1
root_function_depth2___VAR_b1: EQU 2
root_function_depth1___VAR_RETURN_HI: EQU 3
root_function_depth1___VAR_RETURN_LO: EQU 4
root_function_depth1___VAR_a1: EQU 5
root_function_depth1___VAR_blkExprs2: EQU 6
root_function_main___VAR_RETURN_HI: EQU 7
root_function_main___VAR_RETURN_LO: EQU 8
root_function_main___VAR_arg1: EQU 9
root_function_main___VAR_blkExprs2: EQU 10
0 PCHITMP = < :ROOT________main_start
1 PC = > :ROOT________main_start
; (0) ENTER root_function_depth2 @ function
root_function_depth2___LABEL_START:
; (1) ENTER root_function_depth2 @ statementEqVarOpConst
2 REGA = [:root_function_depth2___VAR_b1]
3 REGA = REGA + 1
4 [:root_function_depth2___VAR_b1] = REGA
; (1) EXIT root_function_depth2 @ statementEqVarOpConst
5 PCHITMP = [:root_function_depth2___VAR_RETURN_HI]
6 PC = [:root_function_depth2___VAR_RETURN_LO]
; (0) EXIT root_function_depth2 @ function
; (0) ENTER root_function_depth1 @ function
root_function_depth1___LABEL_START:
; (1) ENTER root_function_depth1 @ functionCall
; (2) ENTER root_function_depth1 @ blkExprs
; (3) ENTER root_function_depth1 @ blkVar
7 REGA = [:root_function_depth1___VAR_a1]
; (3) EXIT root_function_depth1 @ blkVar
; assign clause 1 result to [:root_function_depth1___VAR_blkExprs2] = a1
8 [:root_function_depth1___VAR_blkExprs2] = REGA
; assigning result back to REGA
9 REGA = [:root_function_depth1___VAR_blkExprs2]
; (2) EXIT root_function_depth1 @ blkExprs
10 [:root_function_depth2___VAR_b1] = REGA
; set return address variables
11 [:root_function_depth2___VAR_RETURN_HI] = < :root_function_depth1___LABEL_RETURN_1
12 [:root_function_depth2___VAR_RETURN_LO] = > :root_function_depth1___LABEL_RETURN_1
; do jump to function 'depth2''
13 PCHITMP = < :root_function_depth2___LABEL_START
14 PC = > :root_function_depth2___LABEL_START
; return location
root_function_depth1___LABEL_RETURN_1:
15 REGA = [:root_function_depth2___VAR_b1]
16 [:root_function_depth1___VAR_a1] = REGA
; (1) EXIT root_function_depth1 @ functionCall
17 PCHITMP = [:root_function_depth1___VAR_RETURN_HI]
18 PC = [:root_function_depth1___VAR_RETURN_LO]
; (0) EXIT root_function_depth1 @ function
; (0) ENTER root_function_main @ function
ROOT________main_start:
root_function_main___LABEL_START:
; (1) ENTER root_function_main @ statementVar
19 [:root_function_main___VAR_arg1] = 65
; (1) EXIT root_function_main @ statementVar
; (1) ENTER root_function_main @ functionCall
; (2) ENTER root_function_main @ blkExprs
; (3) ENTER root_function_main @ blkVar
20 REGA = [:root_function_main___VAR_arg1]
; (3) EXIT root_function_main @ blkVar
; assign clause 1 result to [:root_function_main___VAR_blkExprs2] = arg1
21 [:root_function_main___VAR_blkExprs2] = REGA
; assigning result back to REGA
22 REGA = [:root_function_main___VAR_blkExprs2]
; (2) EXIT root_function_main @ blkExprs
23 [:root_function_depth1___VAR_a1] = REGA
; set return address variables
24 [:root_function_depth1___VAR_RETURN_HI] = < :root_function_main___LABEL_RETURN_2
25 [:root_function_depth1___VAR_RETURN_LO] = > :root_function_main___LABEL_RETURN_2
; do jump to function 'depth1''
26 PCHITMP = < :root_function_depth1___LABEL_START
27 PC = > :root_function_depth1___LABEL_START
; return location
root_function_main___LABEL_RETURN_2:
28 REGA = [:root_function_depth1___VAR_a1]
29 [:root_function_main___VAR_arg1] = REGA
; (1) EXIT root_function_main @ functionCall
; (1) ENTER root_function_main_putcharN_arg1_ @ statementPutcharName
root_function_main_putcharN_arg1____LABEL_wait_3:
30 PCHITMP = <:root_function_main_putcharN_arg1____LABEL_transmit_4
31 PC = >:root_function_main_putcharN_arg1____LABEL_transmit_4 _DO
32 PCHITMP = <:root_function_main_putcharN_arg1____LABEL_wait_3
33 PC = <:root_function_main_putcharN_arg1____LABEL_wait_3
root_function_main_putcharN_arg1____LABEL_transmit_4:
34 UART = [:root_function_main___VAR_arg1]
; (1) EXIT root_function_main_putcharN_arg1_ @ statementPutcharName
35 PCHITMP = <:root_end
36 PC = >:root_end
; (0) EXIT root_function_main @ function
; (0) ENTER root @ comment
; // END COMMAND
; (0) EXIT root @ comment
root_end:
37 END
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.