summaryrefslogtreecommitdiff
path: root/boot/echo-boot.s
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2025-04-24 23:01:12 +0200
committerEugen Wissner <belka@caraus.de>2025-04-24 23:01:12 +0200
commit2e0c958aa30e831ee766efd63f3d6dfa84069e1b (patch)
treeb3ff040c7327a6d01e5711c9bed8a3d2752768fa /boot/echo-boot.s
parentf343296463f8271720cf1e9cb1d45f30c288d872 (diff)
downloadelna-2e0c958aa30e831ee766efd63f3d6dfa84069e1b.tar.gz
Compile procedure calls
Diffstat (limited to 'boot/echo-boot.s')
-rw-r--r--boot/echo-boot.s449
1 files changed, 389 insertions, 60 deletions
diff --git a/boot/echo-boot.s b/boot/echo-boot.s
index 22d59d0..8256bbd 100644
--- a/boot/echo-boot.s
+++ b/boot/echo-boot.s
@@ -11,6 +11,325 @@ source_code: .zero 20480
.section .text
+# Evalutes an expression and saves the result in a0.
+.type _build_expression, @function
+_build_expression:
+ # Prologue.
+ addi sp, sp, -32
+ sw ra, 28(sp)
+ sw s0, 24(sp)
+ addi s0, sp, 32
+
+ call _skip_spaces
+ call _read_token
+ sw s1, 20(sp)
+ sw a0, 16(sp)
+
+ # Integer literal.
+ addi a0, s1, 0
+ lb a0, (a0)
+ call _is_digit
+ bnez a0, .Lbuild_expression_number_literal
+
+ # Named identifier.
+ li t0, 0x202c30 # 0,_
+ sw t0, 12(sp)
+ li t0, 0x6120616c # la a
+ sw t0, 8(sp)
+ addi a0, sp, 8
+ li a1, 7
+ call _write_out
+
+ lw a0, 20(sp)
+ lw a1, 16(sp)
+ call _write_out
+
+ li t0, 0x0a # \n
+ sw t0, 12(sp)
+ addi a0, sp, 12
+ li a1, 1
+ call _write_out
+
+ j .Lbuild_expression_end
+
+.Lbuild_expression_number_literal:
+ li t0, 0x202c30 # 0,_
+ sw t0, 12(sp)
+ li t0, 0x6120696c # li a
+ sw t0, 8(sp)
+ addi a0, sp, 8
+ li a1, 7
+ call _write_out
+
+ lw a0, 20(sp)
+ lw a1, 16(sp)
+ call _write_out
+
+ li t0, 0x0a # \n
+ sw t0, 12(sp)
+ addi a0, sp, 12
+ li a1, 1
+ call _write_out
+
+ j .Lbuild_expression_end
+
+.Lbuild_expression_end:
+ lw a0, 16(sp)
+ add s1, s1, a0
+
+ # Epilogue.
+ lw ra, 28(sp)
+ lw s0, 24(sp)
+ addi sp, sp, 32
+ ret
+
+# Compiles a statement beginning with an identifier.
+#
+# Left values should be variables named "loca n", where n is the offset
+# of the variable on the stack, like loca8 or loca4.
+.type _compile_identifier, @function
+_compile_identifier:
+ # Prologue.
+ addi sp, sp, -32
+ sw ra, 28(sp)
+ sw s0, 24(sp)
+ addi s0, sp, 32
+
+ call _read_token
+
+ # Save the pointer to the identifier and its length on the stack.
+ sw s1, 20(sp)
+ sw a0, 16(sp)
+
+ add s1, s1, a0
+ call _skip_spaces
+ call _read_token
+
+ # Save the pointer and the length of the token following the identifier.
+ sw s1, 12(sp)
+ sw a0, 8(sp)
+
+ add s1, s1, a0 # Skip that token.
+ call _skip_spaces
+
+ li t0, 0x3d3a # :=
+ sw t0, 4(sp)
+ lw a0, 12(sp)
+ lw a1, 8(sp)
+ addi a2, sp, 4
+ call _token_compare
+ beqz a0, .Lcompile_identifier_assign
+
+ /* DEBUG
+ mv a0, s1
+ li a1, 4
+ call _write_error */
+
+ lw t0, 12(sp)
+ lbu t0, (t0)
+ li t1, 0x28 # (
+ beq t0, t1, .Lcompile_identifier_call
+
+ j .Lcompile_identifier_end
+
+.Lcompile_identifier_call:
+ lw a0, 20(sp)
+ lw a1, 16(sp)
+ call _compile_call
+
+ j .Lcompile_identifier_end
+
+.Lcompile_identifier_assign:
+ call _build_expression
+
+ li t0, 0x202c30 # 0,_
+ sw t0, 12(sp)
+ li t0, 0x61207773 # sw a
+ sw t0, 8(sp)
+ addi a0, sp, 8
+ li a1, 7
+ call _write_out
+
+ lw a0, 20(sp)
+ lw a1, 16(sp)
+ addi a0, a0, 4 # Skip the "loca" variable prefix.
+ addi a1, a1, -4 # Skip the "loca" variable prefix.
+ call _write_out
+
+ li t0, 0x0a # \n
+ sw t0, 12(sp)
+ li t0, 0x29707328 # (sp)
+ sw t0, 8(sp)
+ addi a0, sp, 8
+ li a1, 5
+ call _write_out
+
+ j .Lcompile_identifier_end
+
+.Lcompile_identifier_end:
+ # Epilogue.
+ lw ra, 28(sp)
+ lw s0, 24(sp)
+ addi sp, sp, 32
+ ret
+
+# Compiles a procedure call. Expects s1 to point to the first argument.
+# a0 - Pointer to the procedure name.
+# a1 - Length of the procedure name.
+#
+# Returns the procedure result in a0.
+.type _compile_call, @function
+_compile_call:
+ # Prologue.
+ addi sp, sp, -32
+ sw ra, 28(sp)
+ sw s0, 24(sp)
+ addi s0, sp, 32
+
+ sw a0, 20(sp)
+ sw a1, 16(sp)
+ sw zero, 12(sp) # Argument count for a procedure call.
+
+.Lcompile_call_paren:
+ call _skip_spaces
+ call _read_token
+ lbu t0, (s1)
+ li t1, 0x29 # )
+ beq t0, t1, .Lcompile_call_complete
+
+.Lcompile_call_argument:
+ call _build_expression
+
+ li t0, 0x202c30 # 0,_
+ sw t0, 8(sp)
+ li t0, 0x61207773 # sw a
+ sw t0, 4(sp)
+ addi a0, sp, 4
+ li a1, 7
+ call _write_out
+
+ lw t0, 12(sp) # Argument count for a procedure call.
+
+ # Only 8 arguments are supported with a0-a7.
+ # Save all arguments on the stack so they aren't overriden afterwards.
+ # The offset on the stack always has two digits in this case.
+ li t1, -4
+ mul t1, t0, t1
+ addi t1, t1, 84
+ li t2, 10
+ div t3, t1, t2
+ rem t4, t1, t2
+ addi t3, t3, '0'
+ addi t4, t4, '0'
+
+ sw t3, 8(sp)
+ sw t4, 4(sp)
+
+ addi a0, sp, 8
+ li a1, 1
+ call _write_out
+
+ addi a0, sp, 4
+ li a1, 1
+ call _write_out
+
+ li t0, 0x0a # \n
+ sw t0, 8(sp)
+ li t0, 0x29707328 # (sp)
+ sw t0, 4(sp)
+ addi a0, sp, 4
+ li a1, 5
+ call _write_out
+
+ call _skip_spaces
+ call _read_token
+ lbu t0, (s1)
+ li t1, ','
+ bne t0, t1, .Lcompile_call_paren
+
+ lw t0, 12(sp) # Argument count for a procedure call.
+ addi t0, t0, 1
+ sw t0, 12(sp)
+
+ addi s1, s1, 1 # Skip the comma between the arguments.
+ j .Lcompile_call_argument
+
+.Lcompile_call_complete:
+ sw zero, 12(sp)
+
+.Lcompile_call_restore:
+ # Just go through all a0-a7 registers and read them from stack.
+ # If this stack value contains garbage, the procedure just shouldn't use it.
+ lw t0, 12(sp)
+ li t1, 7
+ bgt t0, t1, .Lcompile_call_perform
+
+ li t0, 0x6120776c # lw a
+ sw t0, 4(sp)
+ addi a0, sp, 4
+ li a1, 4
+ call _write_out
+
+ lw t0, 12(sp) # Argument count for a procedure call.
+
+ li t1, -4
+ mul t1, t0, t1
+ addi t1, t1, 84
+ li t2, 10
+ div t3, t1, t2
+ rem t4, t1, t2
+ addi t3, t3, '0'
+ addi t4, t4, '0'
+ addi t0, t0, '0'
+
+ li t5, 0x0a # \n
+ sb t5, 11(sp)
+ li t5, 0x29707328 # (sp)
+ sw t5, 7(sp)
+ sb t4, 6(sp)
+ sb t3, 5(sp)
+ li t5, 0x202c # ,_
+ sh t5, 3(sp)
+ sb t0, 2(sp)
+
+ addi a0, sp, 2
+ li a1, 10
+ call _write_out
+
+ lw t0, 12(sp) # Increment.
+ addi t0, t0, 1
+ sw t0, 12(sp)
+
+ j .Lcompile_call_restore
+
+.Lcompile_call_perform:
+ li t0, 0x20
+ sw t0, 8(sp)
+ li t0, 0x6c6c6163
+ sw t0, 4(sp)
+ addi a0, sp, 4
+ li a1, 5
+ call _write_out
+
+ lw a0, 20(sp)
+ lw a1, 16(sp)
+ call _write_out
+
+ li t0, 0x0a # \n
+ sw t0, 8(sp)
+ addi a0, sp, 8
+ li a1, 1
+ call _write_out
+
+ call _skip_spaces
+ addi s1, s1, 1 # Skip the close paren.
+
+ # Epilogue.
+ lw ra, 28(sp)
+ lw s0, 24(sp)
+ addi sp, sp, 32
+ ret
+
# Reads a token and returns its length in a0.
# _read_token doesn't change s1, it finds the length of the token s1 is pointing to.
.type _read_token, @function
@@ -53,7 +372,7 @@ _read_token:
add t1, s1, t6
lbu a0, (t1) # a0 = Current character.
- call is_alnum
+ call _is_alnum
beqz a0, .Ltoken_character_end
lw t6, 4(sp)
@@ -150,7 +469,7 @@ _compile_assembly:
# Write the source to the standard output.
mv a0, s1
lw a1, 4(sp)
- call write_out
+ call _write_out
lw t0, 4(sp)
add s1, s1, t0
@@ -159,7 +478,7 @@ _compile_assembly:
sb t0, 0(sp)
addi a0, sp, 0
li a1, 1
- call write_out
+ call _write_out
addi s1, s1, 1 # Skip the new line.
@@ -189,7 +508,7 @@ _compile_program:
addi a0, sp, 8
li a1, 15
- call write_out
+ call _write_out
addi s1, s1, 8 # program\n.
@@ -221,14 +540,14 @@ _compile_constant_section:
addi a0, sp, 4
li a1, 17
- call write_out
+ call _write_out
addi s1, s1, 6 # const\n.
.Lcompile_constant_section_item:
call _skip_spaces
lbu a0, (s1)
- call is_upper
+ call _is_upper
beqz a0, .Lcompile_constant_section_end
call _compile_constant
@@ -254,7 +573,7 @@ _compile_constant:
mv a1, a0 # The identifier length from _read_token should be in a1.
mv a0, s1 # Save the identifier pointer before advancing it.
add s1, s1, a1
- call write_out
+ call _write_out
call _skip_spaces
call _read_token
@@ -267,7 +586,7 @@ _compile_constant:
sw t0, 0(sp)
mv a0, sp
li a1, 8
- call write_out
+ call _write_out
call _skip_spaces
call _read_token
@@ -275,13 +594,13 @@ _compile_constant:
mv a1, a0 # The literal length from _read_token should be in a1.
mv a0, s1 # Save the literal pointer before advancing it.
add s1, s1, a1
- call write_out
+ call _write_out
li t0, '\n'
sw t0, 4(sp)
addi a0, sp, 4
li a1, 1
- call write_out
+ call _write_out
# Epilogue.
lw ra, 12(sp)
@@ -309,14 +628,14 @@ _compile_variable_section:
addi a0, sp, 0
li a1, 14
- call write_out
+ call _write_out
addi s1, s1, 4 # var\n.
.Lcompile_variable_section_item:
call _skip_spaces
lbu a0, (s1)
- call is_lower
+ call _is_lower
beqz a0, .Lcompile_variable_section_end
call _compile_variable
@@ -371,11 +690,11 @@ _compile_variable:
sw t0, 8(sp)
addi a0, sp, 8
li a1, 6
- call write_out
+ call _write_out
lw a0, 28(sp)
lw a1, 24(sp)
- call write_out
+ call _write_out
li t0, 0x0a74 # t\n
sw t0, 12(sp)
@@ -385,7 +704,7 @@ _compile_variable:
sw t0, 4(sp)
addi a0, sp, 4
li a1, 10
- call write_out
+ call _write_out
# .size identifier, size
li t0, 0x2065 # e_
@@ -394,32 +713,32 @@ _compile_variable:
sw t0, 8(sp)
addi a0, sp, 8
li a1, 6
- call write_out
+ call _write_out
lw a0, 28(sp)
lw a1, 24(sp)
- call write_out
+ call _write_out
li t0, 0x202c # ,
sw t0, 12(sp)
addi a0, sp, 12
li a1, 2
- call write_out
+ call _write_out
lw a0, 20(sp)
lw a1, 16(sp)
- call write_out
+ call _write_out
li t0, 0x0a # \n
sw t0, 12(sp)
addi a0, sp, 12
li a1, 1
- call write_out
+ call _write_out
# identifier: .zero size
lw a0, 28(sp)
lw a1, 24(sp)
- call write_out
+ call _write_out
li t0, 0x206f7265 # ero_
sw t0, 12(sp)
@@ -427,17 +746,17 @@ _compile_variable:
sw t0, 8(sp)
addi a0, sp, 8
li a1, 8
- call write_out
+ call _write_out
lw a0, 20(sp)
lw a1, 16(sp)
- call write_out
+ call _write_out
li t0, 0x0a # \n
sw t0, 12(sp)
addi a0, sp, 12
li a1, 1
- call write_out
+ call _write_out
# Epilogue.
lw ra, 36(sp)
@@ -466,11 +785,11 @@ _compile_procedure:
sw t0, 8(sp)
addi a0, sp, 8
li a1, 6
- call write_out
+ call _write_out
lw a0, 20(sp)
lw a1, 16(sp)
- call write_out
+ call _write_out
li t0, 0x0a6e6f69 # ion\n
sw t0, 12(sp)
@@ -480,17 +799,17 @@ _compile_procedure:
sw t0, 4(sp)
addi a0, sp, 4
li a1, 12
- call write_out
+ call _write_out
lw a0, 20(sp)
lw a1, 16(sp)
- call write_out
+ call _write_out
li t0, 0x0a3a # :\n
sw t0, 12(sp)
addi a0, sp, 12
li a1, 2
- call write_out
+ call _write_out
call _skip_spaces
addi s1, s1, 1 # Skip opening argument paren.
@@ -521,24 +840,24 @@ _compile_procedure:
sw t0, 12(sp)
addi a0, sp, 12
li a1, 4
- call write_out
+ call _write_out
li t0, 0x2c707320 # _sp,
sw t0, 12(sp)
addi a0, sp, 12
li a1, 4
- call write_out
+ call _write_out
addi a0, sp, 12
li a1, 4
- call write_out
+ call _write_out
li t0, 0x0a36392d # -96\n
sw t0, 12(sp)
addi a0, sp, 12
li a1, 4
- call write_out
+ call _write_out
li t0, 0x0a29 # )\n
sw t0, 12(sp)
@@ -550,7 +869,7 @@ _compile_procedure:
sw t0, 0(sp)
addi a0, sp, 0
li a1, 14
- call write_out
+ call _write_out
li t0, 0x0a29 # )\n
sw t0, 12(sp)
@@ -562,7 +881,7 @@ _compile_procedure:
sw t0, 0(sp)
addi a0, sp, 0
li a1, 14
- call write_out
+ call _write_out
li t0, 0x0a363920 # _96\n
sw t0, 12(sp)
@@ -574,7 +893,7 @@ _compile_procedure:
sw t0, 0(sp)
addi a0, sp, 0
li a1, 16
- call write_out
+ call _write_out
# Generate the body of the procedure.
.Lcompile_procedure_body:
@@ -586,7 +905,7 @@ _compile_procedure:
mv a0, s1
addi a1, sp, 8
li a2, 4
- call memcmp
+ call _memcmp
beqz a0, .Lcompile_procedure_end
@@ -608,7 +927,7 @@ _compile_procedure:
sw t0, 0(sp)
addi a0, sp, 0
li a1, 14
- call write_out
+ call _write_out
li t0, 0x0a29 # )\n
sw t0, 12(sp)
@@ -620,36 +939,36 @@ _compile_procedure:
sw t0, 0(sp)
addi a0, sp, 0
li a1, 14
- call write_out
+ call _write_out
li t0, 0x69646461 # addi
sw t0, 12(sp)
addi a0, sp, 12
li a1, 4
- call write_out
+ call _write_out
li t0, 0x2c707320 # _sp,
sw t0, 12(sp)
addi a0, sp, 12
li a1, 4
- call write_out
+ call _write_out
addi a0, sp, 12
li a1, 4
- call write_out
+ call _write_out
li t0, 0x0a3639 # 96\n
sw t0, 12(sp)
addi a0, sp, 12
li a1, 3
- call write_out
+ call _write_out
li t0, 0x0a746572 # ret\n
sw t0, 12(sp)
addi a0, sp, 12
li a1, 4
- call write_out
+ call _write_out
# Epilogue.
lw ra, 28(sp)
@@ -726,7 +1045,7 @@ _compile_line:
mv a0, s1
addi a1, sp, 12
li a2, 8
- call memcmp
+ call _memcmp
beqz a0, .Lcompile_line_program
li t0, 0x0a74 # t\n
@@ -736,7 +1055,7 @@ _compile_line:
mv a0, s1
addi a1, sp, 12
li a2, 6
- call memcmp
+ call _memcmp
beqz a0, .Lcompile_line_const
li t0, 0x0a726176 # var\n
@@ -744,7 +1063,7 @@ _compile_line:
mv a0, s1
addi a1, sp, 16
li a2, 4
- call memcmp
+ call _memcmp
beqz a0, .Lcompile_line_var
li t0, 0x20 # _
@@ -754,7 +1073,7 @@ _compile_line:
mv a0, s1
addi a1, sp, 12
li a2, 5
- call memcmp
+ call _memcmp
beqz a0, .Lcompile_line_procedure
li t0, 0x0a6e # n\n
@@ -764,7 +1083,7 @@ _compile_line:
mv a0, s1
addi a1, sp, 12
li a2, 6
- call memcmp
+ call _memcmp
beqz a0, .Lcompile_line_begin
li t0, 0x2e646e65 # end.
@@ -772,11 +1091,27 @@ _compile_line:
mv a0, s1
addi a1, sp, 16
li a2, 4
- call memcmp
+ call _memcmp
beqz a0, .Lcompile_line_exit
+ li t0, 0x61636f6c # loca
+ sw t0, 16(sp)
+ mv a0, s1
+ addi a1, sp, 16
+ li a2, 4
+ call _memcmp
+ beqz a0, .Lcompile_line_identifier
+
+ lbu t0, (s1)
+ li t1, '_'
+ beq t0, t1, .Lcompile_line_identifier
+
j .Lcompile_line_unchanged # Else.
+.Lcompile_line_identifier:
+ call _compile_identifier
+ j .Lcompile_line_section
+
.Lcompile_line_exit:
call _compile_exit
j .Lcompile_line_section
@@ -796,12 +1131,6 @@ _compile_line:
j .Lcompile_line_end
.Lcompile_line_var:
-
- /* DEBUG
- mv a0, s1
- li a1, 20
- call write_error */
-
call _compile_variable_section
j .Lcompile_line_section
@@ -853,7 +1182,7 @@ _compile_text_section:
addi a0, sp, 0
li a1, 15
- call write_out
+ call _write_out
# Epilogue.
lw ra, 20(sp)
@@ -888,7 +1217,7 @@ _compile_entry_point:
sw t0, 24(sp)
addi a0, sp, 24
li a1, 32
- call write_out
+ call _write_out
addi s1, s1, 6 # Skip begin\n.
@@ -925,7 +1254,7 @@ _compile_exit:
sw t0, 28(sp)
addi a0, sp, 28
li a1, 25
- call write_out
+ call _write_out
addi s1, s1, 4 # Skip end.
call _skip_spaces # Read the possible new line at the end of the file.
@@ -986,7 +1315,7 @@ _start:
la a0, source_code
la a1, SOURCE_BUFFER_SIZE # Buffer size.
lw a1, (a1)
- call read_file
+ call _read_file
la s1, source_code # s1 = Source code position.
call _compile