summaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2025-04-23 23:16:00 +0200
committerEugen Wissner <belka@caraus.de>2025-04-23 23:16:00 +0200
commitf343296463f8271720cf1e9cb1d45f30c288d872 (patch)
tree24aaa3124762ed64bb754475c03cc5e5736e2bec /boot
parent5aaf9ded3646f5312e26fc7b3502f141c2e556f5 (diff)
downloadelna-f343296463f8271720cf1e9cb1d45f30c288d872.tar.gz
Compile procedure headers
Diffstat (limited to 'boot')
-rw-r--r--boot/echo-boot.s359
-rw-r--r--boot/stage2.elna506
2 files changed, 692 insertions, 173 deletions
diff --git a/boot/echo-boot.s b/boot/echo-boot.s
index a8faecb..22d59d0 100644
--- a/boot/echo-boot.s
+++ b/boot/echo-boot.s
@@ -188,7 +188,7 @@ _compile_program:
sw t0, 8(sp)
addi a0, sp, 8
- li a1, 16
+ li a1, 15
call write_out
addi s1, s1, 8 # program\n.
@@ -496,7 +496,160 @@ _compile_procedure:
addi s1, s1, 1 # Skip opening argument paren.
call _skip_spaces
addi s1, s1, 1 # Skip closing argument paren.
+
+ li t0, 0x6e # n
+ sw t0, 12(sp)
+ li t0, 0x69676562 # begi
+ sw t0, 8(sp)
+
+ # Skip all declarations until we find the "begin" keyword, denoting the
+ # beginning of the procedure body.
+.Lcompile_procedure_begin:
call _skip_spaces
+ call _read_token
+
+ mv a1, a0
+ mv a0, s1
+ addi a2, sp, 8
+ add s1, s1, a1
+ call _token_compare
+
+ bnez a0, .Lcompile_procedure_begin
+
+ # Generate the procedure prologue with a predefined stack size.
+ li t0, 0x69646461 # addi
+ sw t0, 12(sp)
+ addi a0, sp, 12
+ li a1, 4
+ call write_out
+
+ li t0, 0x2c707320 # _sp,
+ sw t0, 12(sp)
+
+ addi a0, sp, 12
+ li a1, 4
+ call write_out
+
+ addi a0, sp, 12
+ li a1, 4
+ call write_out
+
+ li t0, 0x0a36392d # -96\n
+ sw t0, 12(sp)
+ addi a0, sp, 12
+ li a1, 4
+ call write_out
+
+ li t0, 0x0a29 # )\n
+ sw t0, 12(sp)
+ li t0, 0x70732832 # 2(sp
+ sw t0, 8(sp)
+ li t0, 0x39202c61 # a, 9
+ sw t0, 4(sp)
+ li t0, 0x72207773 # sw r
+ sw t0, 0(sp)
+ addi a0, sp, 0
+ li a1, 14
+ call write_out
+
+ li t0, 0x0a29 # )\n
+ sw t0, 12(sp)
+ li t0, 0x70732838 # 2(sp
+ sw t0, 8(sp)
+ li t0, 0x38202c30 # 0, 8
+ sw t0, 4(sp)
+ li t0, 0x73207773 # sw s
+ sw t0, 0(sp)
+ addi a0, sp, 0
+ li a1, 14
+ call write_out
+
+ li t0, 0x0a363920 # _96\n
+ sw t0, 12(sp)
+ li t0, 0x2c707320 # _sp,
+ sw t0, 8(sp)
+ li t0, 0x2c307320 # _s0,
+ sw t0, 4(sp)
+ li t0, 0x69646461 # addi
+ sw t0, 0(sp)
+ addi a0, sp, 0
+ li a1, 16
+ call write_out
+
+ # Generate the body of the procedure.
+.Lcompile_procedure_body:
+ call _skip_indentation
+ call _read_line
+ sw a0, 12(sp)
+ li t0, 0x0a646e65 # end\n
+ sw t0, 8(sp)
+ mv a0, s1
+ addi a1, sp, 8
+ li a2, 4
+ call memcmp
+
+ beqz a0, .Lcompile_procedure_end
+
+ lw a0, 12(sp)
+ call _compile_line
+ j .Lcompile_procedure_body
+
+.Lcompile_procedure_end:
+ add s1, s1, 4 # Skip end\n.
+
+ # Generate the procedure epilogue with a predefined stack size.
+ li t0, 0x0a29 # )\n
+ sw t0, 12(sp)
+ li t0, 0x70732832 # 2(sp
+ sw t0, 8(sp)
+ li t0, 0x39202c61 # a, 9
+ sw t0, 4(sp)
+ li t0, 0x7220776c # lw r
+ sw t0, 0(sp)
+ addi a0, sp, 0
+ li a1, 14
+ call write_out
+
+ li t0, 0x0a29 # )\n
+ sw t0, 12(sp)
+ li t0, 0x70732838 # 2(sp
+ sw t0, 8(sp)
+ li t0, 0x38202c30 # 0, 8
+ sw t0, 4(sp)
+ li t0, 0x7320776c # lw s
+ sw t0, 0(sp)
+ addi a0, sp, 0
+ li a1, 14
+ call write_out
+
+ li t0, 0x69646461 # addi
+ sw t0, 12(sp)
+ addi a0, sp, 12
+ li a1, 4
+ call write_out
+
+ li t0, 0x2c707320 # _sp,
+ sw t0, 12(sp)
+
+ addi a0, sp, 12
+ li a1, 4
+ call write_out
+
+ addi a0, sp, 12
+ li a1, 4
+ call write_out
+
+ li t0, 0x0a3639 # 96\n
+ sw t0, 12(sp)
+ addi a0, sp, 12
+ li a1, 3
+ call write_out
+
+ li t0, 0x0a746572 # ret\n
+ sw t0, 12(sp)
+ addi a0, sp, 12
+ li a1, 4
+ call write_out
# Epilogue.
lw ra, 28(sp)
@@ -504,8 +657,52 @@ _compile_procedure:
addi sp, sp, 32
ret
+# Compares two string, which of one has a length, the other one is null-terminated.
+#
+# a0 - The address of the token string.
+# a1 - The length of the string in a0.
+# a2 - The address of the null-terminated string.
+#
+# If the strings match sets a0 to 0, otherwise sets it to 1.
+.type _token_compare, @function
+_token_compare:
+ addi t0, a0, 0
+ addi t1, a1, 0
+ addi t2, a2, 0
+
+.Ltoken_compare_loop:
+ lbu t3, (t2)
+
+ # Will only be 0 if the current character in the null terminated string is \0 and the remaining length of the
+ # another string is 0.
+ or t4, t3, t1
+ beqz t4, .Ltoken_compare_equal
+
+ beqz t1, .Ltoken_compare_not_equal
+ beqz t3, .Ltoken_compare_not_equal
+
+ lbu t4, (t0)
+ bne t3, t4, .Ltoken_compare_not_equal
+
+ addi t0, t0, 1
+ addi t1, t1, -1
+ addi t2, t2, 1
+ j .Ltoken_compare_loop
+
+.Ltoken_compare_not_equal:
+ li a0, 1
+ j .Ltoken_compare_end
+
+.Ltoken_compare_equal:
+ li a0, 0
+
+.Ltoken_compare_end:
+ ret
+
# Parameters:
# a0 - Line length.
+# Returns 1 in a0 if the parsed line contained a text section element such a
+# procedure or the program entry point. Otherwise sets a0 to 0.
.type _compile_line, @function
_compile_line:
# Prologue.
@@ -560,14 +757,42 @@ _compile_line:
call memcmp
beqz a0, .Lcompile_line_procedure
+ li t0, 0x0a6e # n\n
+ sw t0, 16(sp)
+ li t0, 0x69676562 # begi
+ sw t0, 12(sp)
+ mv a0, s1
+ addi a1, sp, 12
+ li a2, 6
+ call memcmp
+ beqz a0, .Lcompile_line_begin
+
+ li t0, 0x2e646e65 # end.
+ sw t0, 16(sp)
+ mv a0, s1
+ addi a1, sp, 16
+ li a2, 4
+ call memcmp
+ beqz a0, .Lcompile_line_exit
+
j .Lcompile_line_unchanged # Else.
+.Lcompile_line_exit:
+ call _compile_exit
+ j .Lcompile_line_section
+
+.Lcompile_line_begin:
+ call _compile_entry_point
+ li a0, 1
+ j .Lcompile_line_end
+
.Lcompile_line_const:
call _compile_constant_section
- j .Lcompile_line_end
+ j .Lcompile_line_section
.Lcompile_line_procedure:
call _compile_procedure
+ li a0, 1
j .Lcompile_line_end
.Lcompile_line_var:
@@ -578,25 +803,28 @@ _compile_line:
call write_error */
call _compile_variable_section
- j .Lcompile_line_end
+ j .Lcompile_line_section
.Lcompile_line_program:
call _compile_program
- j .Lcompile_line_end
+ j .Lcompile_line_section
.Lcompile_line_comment:
lw a0, 20(sp)
call _skip_comment
- j .Lcompile_line_end
+ j .Lcompile_line_section
.Lcompile_line_empty:
addi s1, s1, 1
- j .Lcompile_line_end
+ j .Lcompile_line_section
.Lcompile_line_unchanged:
lw a0, 20(sp)
call _compile_assembly
- j .Lcompile_line_end
+ j .Lcompile_line_section
+
+.Lcompile_line_section:
+ mv a0, zero
.Lcompile_line_end:
# Epilogue.
@@ -605,6 +833,109 @@ _compile_line:
addi sp, sp, 32
ret
+.type _compile_text_section, @function
+_compile_text_section:
+ # Prologue.
+ addi sp, sp, -24
+ sw ra, 20(sp)
+ sw s0, 16(sp)
+ addi s0, sp, 24
+
+ # .section .text
+ li t0, 0x0a7478 # xt\n
+ sw t0, 12(sp)
+ li t0, 0x65742e20 # _.te
+ sw t0, 8(sp)
+ li t0, 0x6e6f6974 # tion
+ sw t0, 4(sp)
+ li t0, 0x6365732e # .sec
+ sw t0, 0(sp)
+
+ addi a0, sp, 0
+ li a1, 15
+ call write_out
+
+ # Epilogue.
+ lw ra, 20(sp)
+ lw s0, 16(sp)
+ addi sp, sp, 24
+ ret
+
+.type _compile_entry_point, @function
+_compile_entry_point:
+ # Prologue.
+ addi sp, sp, -64
+ sw ra, 60(sp)
+ sw s0, 56(sp)
+ addi s0, sp, 64
+
+ # .type _start, @function
+ li t0, 0x0a3a7472 # rt:\n
+ sw t0, 52(sp)
+ li t0, 0x6174735f # _sta
+ sw t0, 48(sp)
+ li t0, 0x0a6e6f69 # ion\n
+ sw t0, 44(sp)
+ li t0, 0x74636e75 # unct
+ sw t0, 40(sp)
+ li t0, 0x6640202c # , @f
+ sw t0, 36(sp)
+ li t0, 0x74726174 # tart
+ sw t0, 32(sp)
+ li t0, 0x735f2065 # e _s
+ sw t0, 28(sp)
+ li t0, 0x7079742e # .typ
+ sw t0, 24(sp)
+ addi a0, sp, 24
+ li a1, 32
+ call write_out
+
+ addi s1, s1, 6 # Skip begin\n.
+
+ # Epilogue.
+ lw ra, 60(sp)
+ lw s0, 56(sp)
+ addi sp, sp, 64
+ ret
+
+.type _compile_exit, @function
+_compile_exit:
+ # Prologue.
+ addi sp, sp, -64
+ sw ra, 60(sp)
+ sw s0, 56(sp)
+ addi s0, sp, 64
+
+ # li a0, 0
+ # li a7, SYS_EXIT
+ # ecall
+ li t0, 0x0a # \n
+ sw t0, 52(sp)
+ li t0, 0x6c6c6163 # call
+ sw t0, 48(sp)
+ li t0, 0x650a3339 # 93\ne
+ sw t0, 44(sp)
+ li t0, 0x202c3761 # a7,_
+ sw t0, 40(sp)
+ li t0, 0x20696c0a # \nli_
+ sw t0, 36(sp)
+ li t0, 0x30202c30 # 0, 0
+ sw t0, 32(sp)
+ li t0, 0x6120696c # li a
+ sw t0, 28(sp)
+ addi a0, sp, 28
+ li a1, 25
+ call write_out
+
+ addi s1, s1, 4 # Skip end.
+ call _skip_spaces # Read the possible new line at the end of the file.
+
+ # Epilogue.
+ lw ra, 60(sp)
+ lw s0, 56(sp)
+ addi sp, sp, 64
+ ret
+
# Finds the end of the line and returns its length in a0.
.type _read_line, @function
_read_line:
@@ -626,10 +957,10 @@ _read_line:
.type _compile, @function
_compile:
# Prologue.
- addi sp, sp, -8
- sw ra, 4(sp)
- sw s0, 0(sp)
- addi s0, sp, 8
+ addi sp, sp, -16
+ sw ra, 12(sp)
+ sw s0, 8(sp)
+ addi s0, sp, 16
.Lcompile_do:
lbu t0, (s1) # t0 = Current character.
@@ -643,9 +974,9 @@ _compile:
.Lcompile_end:
# Epilogue.
- lw ra, 4(sp)
- lw s0, 0(sp)
- addi sp, sp, 8
+ lw ra, 12(sp)
+ lw s0, 8(sp)
+ addi sp, sp, 16
ret
# Entry point.
diff --git a/boot/stage2.elna b/boot/stage2.elna
index 4338ad8..e954762 100644
--- a/boot/stage2.elna
+++ b/boot/stage2.elna
@@ -12,12 +12,7 @@ var
# 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.
proc _read_token()
- # Prologue.
- addi sp, sp, -16
- sw ra, 12(sp)
- sw s0, 8(sp)
- addi s0, sp, 16
-
+begin
lbu t0, (s1) # t0 = Current character.
sw zero, 4(sp)
@@ -76,16 +71,11 @@ proc _read_token()
.Ltoken_character_end:
lw a0, 4(sp)
-
- # Epilogue.
- lw ra, 12(sp)
- lw s0, 8(sp)
- addi sp, sp, 16
- ret
+end
# Skips the spaces till the next non space character.
-.type _skip_spaces, @function
-_skip_spaces:
+proc _skip_spaces()
+begin
.Lspace_loop_do:
lbu t0, (s1) # t0 = Current character.
@@ -104,11 +94,11 @@ _skip_spaces:
j .Lspace_loop_do
.Lspace_loop_end:
- ret
+end
# Skips tabs at the line beginning.
-.type _skip_indentation, @function
-_skip_indentation:
+proc _skip_indentation()
+begin
.Lskip_indentation_do:
lbu t0, (s1)
@@ -122,26 +112,20 @@ _skip_indentation:
j .Lskip_indentation_do
.Lskip_indentation_end:
- ret
+end
# Parameters:
# a0 - Line length.
-.type _skip_comment, @function
-_skip_comment:
+proc _skip_comment()
+begin
add s1, s1, a0
addi s1, s1, 1 # Skip the new line.
- ret
+end
# Parameters:
# a0 - Line length.
-.type _compile_assembly, @function
-_compile_assembly:
- # Prologue.
- addi sp, sp, -16
- sw ra, 12(sp)
- sw s0, 8(sp)
- addi s0, sp, 16
-
+proc _compile_assembly()
+begin
sw a0, 4(sp) # a0 - Line length.
# Write the source to the standard output.
@@ -159,21 +143,10 @@ _compile_assembly:
call write_out
addi s1, s1, 1 # Skip the new line.
+end
- # Epilogue.
- lw ra, 12(sp)
- lw s0, 8(sp)
- addi sp, sp, 16
- ret
-
-.type _compile_program, @function
-_compile_program:
- # Prologue.
- addi sp, sp, -32
- sw ra, 28(sp)
- sw s0, 24(sp)
- addi s0, sp, 32
-
+proc _compile_program()
+begin
# .global _start
li t0, 0x0a7472 # rt\n
sw t0, 20(sp)
@@ -185,25 +158,14 @@ _compile_program:
sw t0, 8(sp)
addi a0, sp, 8
- li a1, 16
+ li a1, 15
call write_out
addi s1, s1, 8 # program\n.
+end
- # Epilogue.
- lw ra, 28(sp)
- lw s0, 24(sp)
- addi sp, sp, 32
- ret
-
-.type _compile_constant_section, @function
-_compile_constant_section:
- # Prologue.
- addi sp, sp, -32
- sw ra, 28(sp)
- sw s0, 24(sp)
- addi s0, sp, 32
-
+proc _compile_constant_section()
+begin
# .section .rodata
li t0, 0x0a # \n
sw t0, 20(sp)
@@ -232,20 +194,10 @@ _compile_constant_section:
j .Lcompile_constant_section_item
.Lcompile_constant_section_end:
- # Epilogue.
- lw ra, 28(sp)
- lw s0, 24(sp)
- addi sp, sp, 32
- ret
-
-.type _compile_constant, @function
-_compile_constant:
- # Prologue.
- addi sp, sp, -16
- sw ra, 12(sp)
- sw s0, 8(sp)
- addi s0, sp, 16
+end
+proc _compile_constant()
+begin
call _read_token
mv a1, a0 # The identifier length from _read_token should be in a1.
@@ -279,21 +231,10 @@ _compile_constant:
addi a0, sp, 4
li a1, 1
call write_out
+end
- # Epilogue.
- lw ra, 12(sp)
- lw s0, 8(sp)
- addi sp, sp, 16
- ret
-
-.type _compile_variable_section, @function
-_compile_variable_section:
- # Prologue.
- addi sp, sp, -24
- sw ra, 20(sp)
- sw s0, 16(sp)
- addi s0, sp, 24
-
+proc _compile_variable_section()
+begin
# .section .bss
li t0, 0x0a73 # s\n
sw t0, 12(sp)
@@ -320,20 +261,10 @@ _compile_variable_section:
j .Lcompile_variable_section_item
.Lcompile_variable_section_end:
- # Epilogue.
- lw ra, 20(sp)
- lw s0, 16(sp)
- addi sp, sp, 24
- ret
-
-.type _compile_variable, @function
-_compile_variable:
- # Prologue.
- addi sp, sp, -40
- sw ra, 36(sp)
- sw s0, 32(sp)
- addi s0, sp, 40
+end
+proc _compile_variable()
+begin
call _read_token
# Save the identifier on the stack since it should emitted multiple times.
@@ -435,21 +366,10 @@ _compile_variable:
addi a0, sp, 12
li a1, 1
call write_out
+end
- # Epilogue.
- lw ra, 36(sp)
- lw s0, 32(sp)
- addi sp, sp, 40
- ret
-
-.type _compile_procedure, @function
-_compile_procedure:
- # Prologue.
- addi sp, sp, -32
- sw ra, 28(sp)
- sw s0, 24(sp)
- addi s0, sp, 32
-
+proc _compile_procedure()
+begin
addi s1, s1, 5 # Skip proc_
call _read_token
sw s1, 20(sp)
@@ -493,24 +413,210 @@ _compile_procedure:
addi s1, s1, 1 # Skip opening argument paren.
call _skip_spaces
addi s1, s1, 1 # Skip closing argument paren.
+
+ li t0, 0x6e # n
+ sw t0, 12(sp)
+ li t0, 0x69676562 # begi
+ sw t0, 8(sp)
+
+ # Skip all declarations until we find the "begin" keyword, denoting the
+ # beginning of the procedure body.
+.Lcompile_procedure_begin:
call _skip_spaces
+ call _read_token
- # Epilogue.
- lw ra, 28(sp)
- lw s0, 24(sp)
- addi sp, sp, 32
- ret
+ mv a1, a0
+ mv a0, s1
+ addi a2, sp, 8
+ add s1, s1, a1
+ call _token_compare
+
+ bnez a0, .Lcompile_procedure_begin
+
+ # Generate the procedure prologue with a predefined stack size.
+ li t0, 0x69646461 # addi
+ sw t0, 12(sp)
+ addi a0, sp, 12
+ li a1, 4
+ call write_out
+
+ li t0, 0x2c707320 # _sp,
+ sw t0, 12(sp)
+
+ addi a0, sp, 12
+ li a1, 4
+ call write_out
+
+ addi a0, sp, 12
+ li a1, 4
+ call write_out
+
+ li t0, 0x0a36392d # -96\n
+ sw t0, 12(sp)
+ addi a0, sp, 12
+ li a1, 4
+ call write_out
+
+ li t0, 0x0a29 # )\n
+ sw t0, 12(sp)
+ li t0, 0x70732832 # 2(sp
+ sw t0, 8(sp)
+ li t0, 0x39202c61 # a, 9
+ sw t0, 4(sp)
+ li t0, 0x72207773 # sw r
+ sw t0, 0(sp)
+ addi a0, sp, 0
+ li a1, 14
+ call write_out
+
+ li t0, 0x0a29 # )\n
+ sw t0, 12(sp)
+ li t0, 0x70732838 # 2(sp
+ sw t0, 8(sp)
+ li t0, 0x38202c30 # 0, 8
+ sw t0, 4(sp)
+ li t0, 0x73207773 # sw s
+ sw t0, 0(sp)
+ addi a0, sp, 0
+ li a1, 14
+ call write_out
+
+ li t0, 0x0a363920 # _96\n
+ sw t0, 12(sp)
+ li t0, 0x2c707320 # _sp,
+ sw t0, 8(sp)
+ li t0, 0x2c307320 # _s0,
+ sw t0, 4(sp)
+ li t0, 0x69646461 # addi
+ sw t0, 0(sp)
+ addi a0, sp, 0
+ li a1, 16
+ call write_out
+
+ # Generate the body of the procedure.
+.Lcompile_procedure_body:
+ call _skip_indentation
+ call _read_line
+ sw a0, 12(sp)
+ li t0, 0x0a646e65 # end\n
+ sw t0, 8(sp)
+ mv a0, s1
+ addi a1, sp, 8
+ li a2, 4
+ call memcmp
+
+ beqz a0, .Lcompile_procedure_end
+
+ lw a0, 12(sp)
+ call _compile_line
+ j .Lcompile_procedure_body
+
+.Lcompile_procedure_end:
+ add s1, s1, 4 # Skip end\n.
+
+ # Generate the procedure epilogue with a predefined stack size.
+ li t0, 0x0a29 # )\n
+ sw t0, 12(sp)
+ li t0, 0x70732832 # 2(sp
+ sw t0, 8(sp)
+ li t0, 0x39202c61 # a, 9
+ sw t0, 4(sp)
+ li t0, 0x7220776c # lw r
+ sw t0, 0(sp)
+ addi a0, sp, 0
+ li a1, 14
+ call write_out
+
+ li t0, 0x0a29 # )\n
+ sw t0, 12(sp)
+ li t0, 0x70732838 # 2(sp
+ sw t0, 8(sp)
+ li t0, 0x38202c30 # 0, 8
+ sw t0, 4(sp)
+ li t0, 0x7320776c # lw s
+ sw t0, 0(sp)
+ addi a0, sp, 0
+ li a1, 14
+ call write_out
+
+ li t0, 0x69646461 # addi
+ sw t0, 12(sp)
+ addi a0, sp, 12
+ li a1, 4
+ call write_out
+
+ li t0, 0x2c707320 # _sp,
+ sw t0, 12(sp)
+
+ addi a0, sp, 12
+ li a1, 4
+ call write_out
+
+ addi a0, sp, 12
+ li a1, 4
+ call write_out
+
+ li t0, 0x0a3639 # 96\n
+ sw t0, 12(sp)
+ addi a0, sp, 12
+ li a1, 3
+ call write_out
+
+ li t0, 0x0a746572 # ret\n
+ sw t0, 12(sp)
+ addi a0, sp, 12
+ li a1, 4
+ call write_out
+end
+
+# Compares two string, which of one has a length, the other one is null-terminated.
+#
+# a0 - The address of the token string.
+# a1 - The length of the string in a0.
+# a2 - The address of the null-terminated string.
+#
+# If the strings match sets a0 to 0, otherwise sets it to 1.
+proc _token_compare()
+begin
+ addi t0, a0, 0
+ addi t1, a1, 0
+ addi t2, a2, 0
+
+.Ltoken_compare_loop:
+ lbu t3, (t2)
+
+ # Will only be 0 if the current character in the null terminated string is \0 and the remaining length of the
+ # another string is 0.
+ or t4, t3, t1
+ beqz t4, .Ltoken_compare_equal
+
+ beqz t1, .Ltoken_compare_not_equal
+ beqz t3, .Ltoken_compare_not_equal
+
+ lbu t4, (t0)
+ bne t3, t4, .Ltoken_compare_not_equal
+
+ addi t0, t0, 1
+ addi t1, t1, -1
+ addi t2, t2, 1
+ j .Ltoken_compare_loop
+
+.Ltoken_compare_not_equal:
+ li a0, 1
+ j .Ltoken_compare_end
+
+.Ltoken_compare_equal:
+ li a0, 0
+
+.Ltoken_compare_end:
+end
# Parameters:
# a0 - Line length.
-.type _compile_line, @function
-_compile_line:
- # Prologue.
- addi sp, sp, -32
- sw ra, 28(sp)
- sw s0, 24(sp)
- addi s0, sp, 32
-
+# Returns 1 in a0 if the parsed line contained a text section element such a
+# procedure or the program entry point. Otherwise sets a0 to 0.
+proc _compile_line()
+begin
sw a0, 20(sp) # a0 - Line length.
beqz a0, .Lcompile_line_empty # Skip an empty line.
@@ -557,14 +663,42 @@ _compile_line:
call memcmp
beqz a0, .Lcompile_line_procedure
+ li t0, 0x0a6e # n\n
+ sw t0, 16(sp)
+ li t0, 0x69676562 # begi
+ sw t0, 12(sp)
+ mv a0, s1
+ addi a1, sp, 12
+ li a2, 6
+ call memcmp
+ beqz a0, .Lcompile_line_begin
+
+ li t0, 0x2e646e65 # end.
+ sw t0, 16(sp)
+ mv a0, s1
+ addi a1, sp, 16
+ li a2, 4
+ call memcmp
+ beqz a0, .Lcompile_line_exit
+
j .Lcompile_line_unchanged # Else.
+.Lcompile_line_exit:
+ call _compile_exit
+ j .Lcompile_line_section
+
+.Lcompile_line_begin:
+ call _compile_entry_point
+ li a0, 1
+ j .Lcompile_line_end
+
.Lcompile_line_const:
call _compile_constant_section
- j .Lcompile_line_end
+ j .Lcompile_line_section
.Lcompile_line_procedure:
call _compile_procedure
+ li a0, 1
j .Lcompile_line_end
.Lcompile_line_var:
@@ -575,36 +709,105 @@ _compile_line:
call write_error */
call _compile_variable_section
- j .Lcompile_line_end
+ j .Lcompile_line_section
.Lcompile_line_program:
call _compile_program
- j .Lcompile_line_end
+ j .Lcompile_line_section
.Lcompile_line_comment:
lw a0, 20(sp)
call _skip_comment
- j .Lcompile_line_end
+ j .Lcompile_line_section
.Lcompile_line_empty:
addi s1, s1, 1
- j .Lcompile_line_end
+ j .Lcompile_line_section
.Lcompile_line_unchanged:
lw a0, 20(sp)
call _compile_assembly
- j .Lcompile_line_end
+ j .Lcompile_line_section
+
+.Lcompile_line_section:
+ mv a0, zero
.Lcompile_line_end:
- # Epilogue.
- lw ra, 28(sp)
- lw s0, 24(sp)
- addi sp, sp, 32
- ret
+end
+
+proc _compile_text_section()
+begin
+ # .section .text
+ li t0, 0x0a7478 # xt\n
+ sw t0, 12(sp)
+ li t0, 0x65742e20 # _.te
+ sw t0, 8(sp)
+ li t0, 0x6e6f6974 # tion
+ sw t0, 4(sp)
+ li t0, 0x6365732e # .sec
+ sw t0, 0(sp)
+
+ addi a0, sp, 0
+ li a1, 15
+ call write_out
+end
+
+proc _compile_entry_point()
+begin
+ # .type _start, @function
+ li t0, 0x0a3a7472 # rt:\n
+ sw t0, 52(sp)
+ li t0, 0x6174735f # _sta
+ sw t0, 48(sp)
+ li t0, 0x0a6e6f69 # ion\n
+ sw t0, 44(sp)
+ li t0, 0x74636e75 # unct
+ sw t0, 40(sp)
+ li t0, 0x6640202c # , @f
+ sw t0, 36(sp)
+ li t0, 0x74726174 # tart
+ sw t0, 32(sp)
+ li t0, 0x735f2065 # e _s
+ sw t0, 28(sp)
+ li t0, 0x7079742e # .typ
+ sw t0, 24(sp)
+ addi a0, sp, 24
+ li a1, 32
+ call write_out
+
+ addi s1, s1, 6 # Skip begin\n.
+end
+
+proc _compile_exit()
+begin
+ # li a0, 0
+ # li a7, SYS_EXIT
+ # ecall
+ li t0, 0x0a # \n
+ sw t0, 52(sp)
+ li t0, 0x6c6c6163 # call
+ sw t0, 48(sp)
+ li t0, 0x650a3339 # 93\ne
+ sw t0, 44(sp)
+ li t0, 0x202c3761 # a7,_
+ sw t0, 40(sp)
+ li t0, 0x20696c0a # \nli_
+ sw t0, 36(sp)
+ li t0, 0x30202c30 # 0, 0
+ sw t0, 32(sp)
+ li t0, 0x6120696c # li a
+ sw t0, 28(sp)
+ addi a0, sp, 28
+ li a1, 25
+ call write_out
+
+ addi s1, s1, 4 # Skip end.
+ call _skip_spaces # Read the possible new line at the end of the file.
+end
# Finds the end of the line and returns its length in a0.
-.type _read_line, @function
-_read_line:
+proc _read_line()
+begin
mv t0, s1 # Local position in the source text.
.Lread_line_do:
@@ -618,16 +821,10 @@ _read_line:
.Lread_line_end:
sub a0, t0, s1 # Return the line length.
- ret
-
-.type _compile, @function
-_compile:
- # Prologue.
- addi sp, sp, -8
- sw ra, 4(sp)
- sw s0, 0(sp)
- addi s0, sp, 8
+end
+proc _compile()
+begin
.Lcompile_do:
lbu t0, (s1) # t0 = Current character.
beqz t0, .Lcompile_end # Exit the loop on the NUL character.
@@ -638,16 +835,10 @@ _compile:
j .Lcompile_do
.Lcompile_end:
-
- # Epilogue.
- lw ra, 4(sp)
- lw s0, 0(sp)
- addi sp, sp, 8
- ret
+end
# Entry point.
-.type _start, @function
-_start:
+begin
# Read the source from the standard input.
la a0, source_code
la a1, SOURCE_BUFFER_SIZE # Buffer size.
@@ -656,7 +847,4 @@ _start:
la s1, source_code # s1 = Source code position.
call _compile
-
- # Call exit.
- li a0, 0 # Use 0 return code.
- call exit
+end.