diff options
| author | Eugen Wissner <belka@caraus.de> | 2025-04-24 23:01:12 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2025-04-24 23:01:12 +0200 |
| commit | 2e0c958aa30e831ee766efd63f3d6dfa84069e1b (patch) | |
| tree | b3ff040c7327a6d01e5711c9bed8a3d2752768fa /boot/echo-boot.s | |
| parent | f343296463f8271720cf1e9cb1d45f30c288d872 (diff) | |
| download | elna-2e0c958aa30e831ee766efd63f3d6dfa84069e1b.tar.gz | |
Compile procedure calls
Diffstat (limited to 'boot/echo-boot.s')
| -rw-r--r-- | boot/echo-boot.s | 449 |
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 |
