diff --git a/Rakefile b/Rakefile index 368abfa..86ca2e1 100644 --- a/Rakefile +++ b/Rakefile @@ -7,8 +7,28 @@ CROSS_GCC = '../riscv32-ilp32d--glibc/bin/riscv32-linux-gcc' SYSROOT = '../riscv32-ilp32d--glibc/riscv32-buildroot-linux-gnu/sysroot' QEMU = 'qemu-riscv32' +def assemble_stage(output, compiler, source) + arguments = [QEMU, '-L', SYSROOT, *compiler] + + puts(arguments * ' ') + puts + Open3.popen2(*arguments) do |qemu_in, qemu_out| + qemu_in.write File.read(*source) + qemu_in.close + + IO.copy_stream qemu_out, output + qemu_out.close + end +end + desc 'Final stage' -task default: 'build/stage2' +task default: ['build/stage2', 'boot/stage2.elna'] do |t| + assembler, exe = t.prerequisites.partition { |prerequisite| prerequisite.end_with? '.elna' } + + File.open File::NULL, 'w' do |output| + assemble_stage output, exe, assembler + end +end directory 'build' @@ -21,18 +41,9 @@ end file 'build/stage2.s' => ['build/stage1', 'boot/stage2.elna'] do |t| assembler, exe = t.prerequisites.partition { |prerequisite| prerequisite.end_with? '.elna' } - arguments = [QEMU, '-L', SYSROOT, *exe] - puts(arguments * ' ') - puts - Open3.popen2(*arguments) do |qemu_in, qemu_out| - qemu_in.write File.read(*assembler) - qemu_in.close - - File.open t.name, 'w' do |output| - IO.copy_stream qemu_out, output - end - qemu_out.close + File.open t.name, 'w' do |output| + assemble_stage output, exe, assembler end end 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. - call _skip_spaces - # Epilogue. - lw ra, 28(sp) - lw s0, 24(sp) - addi sp, sp, 32 - ret + 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 +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.