diff options
| author | Eugen Wissner <belka@caraus.de> | 2025-08-28 22:45:42 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2025-08-30 01:29:00 +0200 |
| commit | 627975775c941130975ce0f9dbef08c723e69794 (patch) | |
| tree | 0f7f4c2c6d83420262d89ff720e6435a67410c9a /boot/stage2.elna | |
| parent | e614d43ea9af078301d538fcddb19e83eed7e879 (diff) | |
| download | elna-627975775c941130975ce0f9dbef08c723e69794.tar.gz | |
Start over
Diffstat (limited to 'boot/stage2.elna')
| -rw-r--r-- | boot/stage2.elna | 2056 |
1 files changed, 759 insertions, 1297 deletions
diff --git a/boot/stage2.elna b/boot/stage2.elna index b4f359e..a9de48d 100644 --- a/boot/stage2.elna +++ b/boot/stage2.elna @@ -1,1393 +1,855 @@ -program +# This Source Code Form is subject to the terms of the Mozilla Public License, +# v. 2.0. If a copy of the MPL was not distributed with this file, You can +# obtain one at https://mozilla.org/MPL/2.0/. -import dummy +# Stage2 compiler. +# +# It supports declaring and calling procedures without arguments. +# A procedure name should start with an underscore. -var - source_code: [81920]Byte +.section .rodata -proc _compile_import() -var loca0: Word -begin - _advance(6); - _skip_spaces(); - loca0 := _read_token(); - _advance(loca0) -end - -proc _build_binary_expression() -var - loca0: Word - loca4: Word - loca8: Word - loca12: ^Byte - loca16: Word - loca20: Word - loca24: Bool -begin - _build_expression(0); - - loca4 := 0x2c306120; - loca8 := 0x0a316120; - - _skip_spaces(); - loca20 := _read_token(); - loca12 := _current(); - - loca16 := 0x26; - loca24 := _token_compare(loca12, loca20, @loca16); - if loca24 = 0 then - goto .L_build_binary_expression_and - end; - - loca16 := 0x726f; - loca24 := _token_compare(loca12, loca20, @loca16); - if loca24 = 0 then - goto .L_build_binary_expression_or - end; - - loca16 := 0x3d; - loca24 := _token_compare(loca12, loca20, @loca16); - if loca24 = 0 then - goto .L_build_binary_expression_equal - end; - - loca16 := 0x2b; - loca24 := _token_compare(loca12, loca20, @loca16); - if loca24 = 0 then - goto .L_build_binary_expression_plus - end; - - loca16 := 0x2d; - loca24 := _token_compare(loca12, loca20, @loca16); - if loca24 = 0 then - goto .L_build_binary_expression_minus - end; - - loca16 := 0x2a; - loca24 := _token_compare(loca12, loca20, @loca16); - if loca24 = 0 then - goto .L_build_binary_expression_product - end; - - goto .Lbuild_binary_expression_end; - - .L_build_binary_expression_equal; - _advance(1); - _build_expression(1); - - loca0 := 0x627573; - _write_s(3, @loca0); - _write_s(4, @loca4); - _write_s(4, @loca4); - _write_s(4, @loca8); - - loca0 := 0x7a716573; - _write_s(4, @loca0); - _write_s(4, @loca4); - _write_s(3, @loca4); - _write_c(0x0a); - - goto .Lbuild_binary_expression_end; - - .L_build_binary_expression_and; - _advance(1); - _build_expression(1); - loca0 := 0x646e61; - _write_s(3, @loca0); - _write_s(4, @loca4); - _write_s(4, @loca4); - _write_s(4, @loca8); - - goto .Lbuild_binary_expression_end; - - .L_build_binary_expression_or; - _advance(2); - _build_expression(1); - loca0 := 0x726f; - _write_s(2, @loca0); - _write_s(4, @loca4); - _write_s(4, @loca4); - _write_s(4, @loca8); - - goto .Lbuild_binary_expression_end; - - .L_build_binary_expression_plus; - _advance(1); - _build_expression(1); - loca0 := 0x646461; - _write_s(3, @loca0); - _write_s(4, @loca4); - _write_s(4, @loca4); - _write_s(4, @loca8); - - goto .Lbuild_binary_expression_end; - - .L_build_binary_expression_minus; - _advance(1); - _build_expression(1); - loca0 := 0x627573; - _write_s(3, @loca0); - _write_s(4, @loca4); - _write_s(4, @loca4); - _write_s(4, @loca8); - - goto .Lbuild_binary_expression_end; - - .L_build_binary_expression_product; - _advance(1); - _build_expression(1); - loca0 := 0x6c756d; - _write_s(3, @loca0); - _write_s(4, @loca4); - _write_s(4, @loca4); - _write_s(4, @loca8); - - goto .Lbuild_binary_expression_end; - - .Lbuild_binary_expression_end -end - -proc _compile_identifier_expression(loca84: Word, loca80: Byte) -var - loca0: Word - loca4: ^Byte - loca8: Word - loca12: Bool - loca16: Word - loca20: Word - loca24: ^Byte - loca28: Byte +.type keyword_equ, @object +keyword_equ: .ascii ".equ" +.equ KEYWORD_EQU_SIZE, 4 + +.type keyword_section, @object +keyword_section: .ascii ".section" +.equ KEYWORD_SECTION_SIZE, 8 + +.type keyword_type, @object +keyword_type: .ascii ".type" +.equ KEYWORD_TYPE_SIZE, 5 + +.type keyword_ret, @object +keyword_ret: .ascii "ret" +.equ KEYWORD_RET_SIZE, 3 + +.type keyword_global, @object +keyword_global: .ascii ".globl" +.equ KEYWORD_GLOBAL_SIZE, 6 + +.type keyword_proc, @object +keyword_proc: .ascii "proc " +.equ KEYWORD_PROC_SIZE, 5 + +.type keyword_end, @object +keyword_end: .ascii "end" +.equ KEYWORD_END_SIZE, 3 + +.type keyword_begin, @object +keyword_begin: .ascii "begin" +.equ KEYWORD_BEGIN_SIZE, 5 + +.type keyword_var, @object +keyword_var: .ascii "var" +.equ KEYWORD_VAR_SIZE, 3 + +.type asm_prologue, @object +asm_prologue: .string "\taddi sp, sp, -32\n\tsw ra, 28(sp)\n\tsw s0, 24(sp)\n\taddi s0, sp, 32\n" + +.type asm_epilogue, @object +asm_epilogue: .string "\tlw ra, 28(sp)\n\tlw s0, 24(sp)\n\taddi sp, sp, 32\n\tret\n" + +.type asm_type_directive, @object +asm_type_directive: .string ".type " + +.type asm_type_function, @object +asm_type_function: .string ", @function\n" + +.type asm_colon, @object +asm_colon: .string ":\n" + +.type asm_call, @object +asm_call: .string "\tcall " + +.type asm_j, @object +asm_j: .string "\tj " + +.type asm_li, @object +asm_li: .string "\tli " + +.type asm_lw, @object +asm_lw: .string "\tlw " + +.type asm_t0, @object +asm_t0: .string "t0" + +.type asm_a0, @object +asm_a0: .string "a0" + +.type asm_comma, @object +asm_comma: .string ", " + +.type asm_sp, @object +asm_sp: .string "(sp)" + +.section .bss + +.equ SOURCE_BUFFER_SIZE, 81920 +.type source_code, @object +source_code: .zero SOURCE_BUFFER_SIZE + +.section .data + +.type source_code_position, @object +source_code_position: .word source_code + +.section .text + +# Reads standard input into a buffer. +# a0 - Buffer pointer. +# a1 - Buffer size. +# +# Returns the amount of bytes written in a0. +proc _read_file(); begin - loca24 := _current(); - loca0 := 0x61636f6c; - loca0 := _memcmp(@loca0, loca24, 4); - - if loca0 = 0 then - loca8 := 0x6120776c; - _write_s(4, @loca8); - loca8 := 0x00202c00 or loca80; - _write_s(3, @loca8); - - loca4 := loca24 + 4; - loca0 := loca84 - 4; - _write_s(loca0, loca4); - - loca8 := 0x29707328; - _write_s(4, @loca8); - _write_c(0x0a); - - goto .Lcompile_identifier_expression_end - end; - loca0 := _front(loca24); - loca8 := loca84 = 2; - loca12 := loca0 = 0x73; - if loca8 & loca12 then - loca8 := 0x6120766d; - _write_s(4, @loca8); - loca8 := 0x00202c00 or loca80; - _write_s(3, @loca8); - _write_s(loca84, loca24); - _write_c(0x0a); - - goto .Lcompile_identifier_expression_end - end; - - loca8 := 0x6120616c; - _write_s(4, @loca8); - loca8 := 0x00202c00 or loca80; - _write_s(3, @loca8); - - _write_s(loca84, loca24); - _write_c(0x0a); - - if _is_upper(loca0) then - loca8 := 0x6120776c; - _write_s(4, @loca8); - loca8 := 0x28202c00 or loca28; - _write_s(4, @loca8); - _write_c(0x61); - _write_c(loca28); - _write_c(0x29); - _write_c(0x0a); - - goto .Lcompile_identifier_expression_end - end; - - .Lcompile_identifier_expression_end -end - -proc _build_expression(loca84: Word) -var - loca0: Word - loca4: ^Byte - loca8: Word - loca12: Word - loca16: Word - loca20: Word - loca24: ^Byte - loca28: Word + mv a2, a1 + mv a1, a0 + # STDIN. + li a0, 0 + li a7, 63 # SYS_READ. + ecall +end; + +# Writes to the standard output. +# +# Parameters: +# a0 - Buffer. +# a1 - Buffer length. +proc _write(); begin - loca28 := loca84 + 0x30; - - _skip_spaces(); - loca20 := _read_token(); - loca24 := _current(); - loca0 := _front(loca24); - - if loca0 = 0x2d then - goto .Lbuild_expression_negate - end; - - if loca0 = 0x40 then - goto .Lbuild_expression_address - end; - - if _is_digit(loca0) then - goto .Lbuild_expression_literal - end; - - if loca0 = 0x5f then - goto .Lbuild_expression_call - end; - - _compile_identifier_expression(loca20, loca28); - goto .Lbuild_expression_advance; - - .Lbuild_expression_negate; - _advance(1); - _build_expression(0); - - loca8 := 0x2067656e; - _write_s(4, @loca8); - loca8 := 0x202c3061; - _write_s(4, @loca8); - loca8 := 0x0a3061; - _write_s(3, @loca8); - - goto .Lbuild_expression_advance; - - .Lbuild_expression_address; - loca8 := 0x69646461; - _write_s(4, @loca8); - loca8 := 0x6120; - _write_s(2, @loca8); - _write_c(loca28); - loca8 := 0x7073202c; - _write_s(4, @loca8); - loca8 := 0x202c; - _write_s(2, @loca8); - - _advance(1); - _skip_spaces(); - loca24 := _current(); - loca20 := _read_token(); - - loca4 := loca24 + 4; - loca0 := loca20 - 4; - _write_s(loca0, loca4); - - _write_c(0xa); - - goto .Lbuild_expression_advance; - - .Lbuild_expression_call; - _advance(loca20); - _advance(1); - _compile_call(loca24, loca20); - - goto .Lbuild_expression_end; - - .Lbuild_expression_literal; - loca8 := 0x6120696c; - _write_s(4, @loca8); - loca8 := 0x00202c00 or loca28; - _write_s(3, @loca8); - - _write_s(loca20, loca24); - _write_c(0x0a); - - goto .Lbuild_expression_advance; - - .Lbuild_expression_advance; - _advance(loca20); - - .Lbuild_expression_end -end - -proc _compile_designator_expression(loca84: ^Byte, loca80: Word) -var - loca0: Word - loca4: Int - loca8: Char - loca12: Bool - loca16: Bool + mv a2, a1 + mv a1, a0 + # STDOUT. + li a0, 1 + li a7, 64 # SYS_WRITE. + ecall +end; + +# Writes a character from a0 into the standard output. +proc _write_c(); begin - loca0 := 0x61636f6c; - loca4 := _memcmp(@loca0, loca84, 4); - - if loca4 = 0 then - loca0 := 0x61207773; - _write_s(4, @loca0); - loca0 := 0x202c30; - _write_s(3, @loca0); - - loca84 := loca84 + 4; - loca80 := loca80 - 4; - _write_s(loca80, loca84); - - loca0 := 0x29707328; - _write_s(4, @loca0); - _write_c(0x0a); - - goto .Lcompile_designator_expression_end - end; - loca8 := _front(loca84); - loca12 := loca8 = 0x73; - loca16 := loca80 = 2; - if loca12 & loca16 then - loca0 := 0x20766d; - _write_s(3, @loca0); - _write_s(loca80, loca84); - loca0 := 0x3061202c; - _write_s(4, @loca0); - _write_c(0x0a); - - goto .Lcompile_designator_expression_end - end; - - .Lcompile_designator_expression_end -end - -proc _compile_identifier() -var - loca0: Word - loca4: Bool - loca8: Word - loca12: ^Byte - loca16: Word - loca20: ^Byte + sb a0, 20(sp) + addi a0, sp, 20 + li a1, 1 + _write(); +end; + +# Write null terminated string. +# +# Parameters: +# a0 - String. +proc _write_z(); begin - loca20 := _current(); - loca16 := _read_token(); + sw a0, 20(sp) - _advance(loca16); - _skip_spaces(); +.write_z_loop: + # Check for 0 character. + lb a0, (a0) + beqz a0, .write_z_end - loca12 := _current(); - loca8 := _read_token(); + # Print a character. + lw a0, 20(sp) + lb a0, (a0) + _write_c(); - _advance(loca8); - _skip_spaces(); + # Advance the input string by one byte. + lw a0, 20(sp) + addi a0, a0, 1 + sw a0, 20(sp) - loca0 := 0x3d3a; - loca4 := _token_compare(loca12, loca8, @loca0); - if loca4 = 0 then - _build_binary_expression(); - _compile_designator_expression(loca20, loca16); + j .write_z_loop - goto .Lcompile_identifier_end - end; - if _front(loca12) = 0x28 then - _compile_call(loca20, loca16); +.write_z_end: +end; - goto .Lcompile_identifier_end - end; +# Detects if a0 is an uppercase character. Sets a0 to 1 if so, otherwise to 0. +proc _is_upper(); +begin + li t0, 'A' - 1 + sltu t1, t0, a0 # t1 = a0 >= 'A' - .Lcompile_identifier_end -end + sltiu t2, a0, 'Z' + 1 # t2 = a0 <= 'Z' + and a0, t1, t2 # t1 = a0 >= 'A' & a0 <= 'Z' +end; -proc _compile_call(loca84: ^Byte, loca80: Word) -var - loca0: Word - loca4: Word - loca8: ^Byte - loca12: Word +# Detects if a0 is an lowercase character. Sets a0 to 1 if so, otherwise to 0. +proc _is_lower(); begin - loca12 := 0; - - .Lcompile_call_paren; - _skip_spaces(); - loca8 := _current(); - if _front(loca8) = 0x29 then - goto .Lcompile_call_complete - end; - - .Lcompile_call_argument; - _build_expression(0); - - loca0 := 0x61207773; - _write_s(4, @loca0); - loca0 := 0x202c30; - _write_s(3, @loca0); - - loca0 := -4 * loca12; - loca0 := loca0 + 60; - _write_i(loca0); - - loca0 := 0x29707328; - _write_s(4, @loca0); - _write_c(0x0a); - - _skip_spaces(); - loca8 := _current(); - loca0 := _front(loca8) = 0x2c; - if loca0 = 0 then - goto .Lcompile_call_paren - end; - - loca12 := loca12 + 1; - - _advance(1); - goto .Lcompile_call_argument; - - .Lcompile_call_complete; - loca12 := 0; - - .Lcompile_call_restore; - - loca0 := 0x6120776c; - _write_s(4, @loca0); - loca4 := 0x36202c30; - _write_s(4, @loca4); - loca4 := 0x70732830; - _write_s(4, @loca4); - loca4 := 0x0a29; - _write_s(2, @loca4); - - _write_s(4, @loca0); - loca4 := 0x35202c31; - _write_s(4, @loca4); - loca4 := 0x70732836; - _write_s(4, @loca4); - loca4 := 0x0a29; - _write_s(2, @loca4); - - _write_s(4, @loca0); - loca4 := 0x35202c32; - _write_s(4, @loca4); - loca4 := 0x70732832; - _write_s(4, @loca4); - loca4 := 0x0a29; - _write_s(2, @loca4); - - _write_s(4, @loca0); - loca4 := 0x34202c33; - _write_s(4, @loca4); - loca4 := 0x70732838; - _write_s(4, @loca4); - loca4 := 0x0a29; - _write_s(2, @loca4); - - _write_s(4, @loca0); - loca4 := 0x34202c34; - _write_s(4, @loca4); - loca4 := 0x70732834; - _write_s(4, @loca4); - loca4 := 0x0a29; - _write_s(2, @loca4); - - _write_s(4, @loca0); - loca4 := 0x34202c35; - _write_s(4, @loca4); - loca4 := 0x70732830; - _write_s(4, @loca4); - loca4 := 0x0a29; - _write_s(2, @loca4); - - loca0 := 0x6c6c6163; - _write_s(4, @loca0); - _write_c(0x20); - - _write_s(loca80, loca84); - _write_c(0x0a); - - _skip_spaces(); - _advance(1) -end - -proc _read_token() -var - loca0: Word - loca4: Word - loca8: ^Byte + li t0, 'a' - 1 + sltu t2, t0, a0 # t2 = a0 >= 'a' + + sltiu t3, a0, 'z' + 1 # t3 = a0 <= 'z' + and a0, t2, t3 # t2 = a0 >= 'a' & a0 <= 'z' +end; + +# Detects if the passed character is a 7-bit alpha character or an underscore. +# +# Paramters: +# a0 - Tested character. +# +# Sets a0 to 1 if the character is an alpha character or underscore, sets it to 0 otherwise. +proc _is_alpha(); begin - loca8 := _current(); - loca0 := _front(loca8); - loca4 := 0; - - if loca0 = 0x2e then - goto .Ltoken_character_single - end; - - if loca0 = 0x2c then - goto .Ltoken_character_single - end; - - if loca0 = 0x3a then - goto .Ltoken_character_colon - end; - - if loca0 = 0x3b then - goto .Ltoken_character_single - end; - - if loca0 = 0x28 then - goto .Ltoken_character_single - end; - - if loca0 = 0x29 then - goto .Ltoken_character_single - end; - - if loca0 = 0x5b then - goto .Ltoken_character_single - end; - - if loca0 = 0x5d then - goto .Ltoken_character_single - end; - - if loca0 = 0x5e then - goto .Ltoken_character_single - end; - - if loca0 = 0x26 then - goto .Ltoken_character_single - end; - - if loca0 = 0x3d then - goto .Ltoken_character_single - end; - - if loca0 = 0x2b then - goto .Ltoken_character_single - end; - - if loca0 = 0x2d then - goto .Ltoken_character_single - end; - - if loca0 = 0x2a then - goto .Ltoken_character_single - end; - - if loca0 = 0x40 then - goto .Ltoken_character_single - end; - - .Ltoken_character_loop_do; - loca0 := loca8 + loca4; - loca0 := _front(loca0); - - if _is_alnum(loca0) then - loca4 := loca4 + 1; - goto .Ltoken_character_loop_do; - - .Ltoken_character_single; - loca4 := loca4 + 1; - goto .Ltoken_character_end; - - .Ltoken_character_colon; - loca0 := loca8 + 1; - loca0 := _front(loca0); - loca4 := loca4 + 1; - - if loca0 = 0x3d then - goto .Ltoken_character_single - end - end; - .Ltoken_character_end; - return loca4 -end - -proc _skip_spaces() -var - loca0: Byte - loca4: ^Byte + sw a0, 20(sp) + + _is_upper(); + sw a0, 16(sp) + + lw a0, 20(sp) + _is_lower(); + + lw t0, 20(sp) + xori t1, t0, '_' + seqz t1, t1 + + lw t0, 16(sp) + or a0, a0, t0 + or a0, a0, t1 +end; + +# Detects whether the passed character is a digit +# (a value between 0 and 9). +# +# Parameters: +# a0 - Exemined value. +# +# Sets a0 to 1 if it is a digit, to 0 otherwise. +proc _is_digit(); begin - .Lspace_loop_do; - loca4 := _current(); - loca0 := _front(loca4); - - if loca0 = 0x20 then - goto .Lspace_loop_repeat - end; - if loca0 = 0x09 then - goto .Lspace_loop_repeat - end; - if loca0 = 0x0a then - goto .Lspace_loop_repeat - end; - if loca0 = 0x0d then - goto .Lspace_loop_repeat - end; - - goto .Lspace_loop_end; - .Lspace_loop_repeat; - _advance(1); - goto .Lspace_loop_do; - - .Lspace_loop_end -end - -proc _compile_assembly(loca84: Word) -var loca0: ^Byte + li t0, '0' - 1 + sltu t1, t0, a0 # t1 = a0 >= '0' + + sltiu t2, a0, '9' + 1 # t2 = a0 <= '9' + + and a0, t1, t2 +end; + +# Reads the next token. +# +# Returns token length in a0. +proc _read_token(); begin - loca0 := _current(); + la t0, source_code_position # Token pointer. + lw t0, (t0) + sw t0, 20(sp) # Current token position. + sw zero, 16(sp) # Token length. + +.read_token_loop: + lb t0, (t0) # Current character. + + # First we try to read a derictive. + # A derictive can contain a dot and characters. + li t1, '.' + beq t0, t1, .read_token_next + + lw a0, 20(sp) + lb a0, (a0) + _is_alpha(); + bnez a0, .read_token_next + + lw a0, 20(sp) + lb a0, (a0) + _is_digit(); + bnez a0, .read_token_next + + j .read_token_end + +.read_token_next: + # Advance the source code position and token length. + lw t0, 16(sp) + addi t0, t0, 1 + sw t0, 16(sp) + + lw t0, 20(sp) + addi t0, t0, 1 + sw t0, 20(sp) + + j .read_token_loop + +.read_token_end: + lw a0, 16(sp) +end; + +# a0 - First pointer. +# a1 - Second pointer. +# a2 - The length to compare. +# +# Returns 0 in a0 if memory regions are equal. +proc _memcmp(); +begin + mv t0, a0 + li a0, 0 - _write_s(loca84, loca0); - _advance(loca84); +.Lmemcmp_loop: + beqz a2, .Lmemcmp_end - _write_c(0xa); + lbu t1, (t0) + lbu t2, (a1) + sub a0, t1, t2 - _advance(1) -end + bnez a0, .Lmemcmp_end -proc _compile_program() -var loca0: Word -begin - loca0 := 0x6f6c672e; - _write_s(4, @loca0); - loca0 := 0x206c6162; - _write_s(4, @loca0); - loca0 := 0x6174735f; - _write_s(4, @loca0); - loca0 := 0x0a7472; - _write_s(3, @loca0); - - _advance(8) -end - -proc _compile_variable_section() -var - loca0: Word - loca4: ^Byte + addi t0, t0, 1 + addi a1, a1, 1 + addi a2, a2, -1 + + j .Lmemcmp_loop + +.Lmemcmp_end: +end; + +# Advances the token stream by a0 bytes. +proc _advance_token(); begin - loca0 := 0x6365732e; - _write_s(4, @loca0); - loca0 := 0x6e6f6974; - _write_s(4, @loca0); - loca0 := 0x73622e20; - _write_s(4, @loca0); - loca0 := 0x0a73; - _write_s(2, @loca0); - - _advance(4); - - .Lcompile_variable_section_item; - _skip_spaces(); - loca4 := _current(); - - loca0 := 0x636f7270; - loca0 := _memcmp(@loca0, loca4, 4); - - if loca0 = 0 then - goto .Lcompile_variable_section_end - end; - _compile_variable(); - goto .Lcompile_variable_section_item; - - .Lcompile_variable_section_end -end - -proc _compile_variable() -var - loca0: Word - loca4: Word - loca8: Word - loca12: Word - loca16: ^Byte - loca20: Word - loca24: Word - loca28: ^Byte + # Skip the .equ directive. + la t0, source_code_position + lw t1, (t0) + add t1, t1, a0 + sw t1, (t0) +end; + +# Prints the current token. +# +# Parameters: +# a0 - Token length. +# +# Returns a0 unchanged. +proc _write_token(); begin - loca24 := _read_token(); - loca28 := _current(); + sw a0, 20(sp) - _advance(loca24); + la a0, source_code_position + lw a0, (a0) + lw a1, 20(sp) + _write(); - _skip_spaces(); - _advance(1); + lw a0, 20(sp) +end; - _skip_spaces(); - _advance(1); +proc _compile_section(); +begin + # Print and skip the .section directive and a space after it. + li a0, KEYWORD_SECTION_SIZE + 1 + _write_token(); + _advance_token(); - loca16 := _read_token(); - loca20 := _current(); - _advance(loca16); + # Read the section name. + _read_token(); + addi a0, a0, 1 - _skip_spaces(); - _advance(1); + _write_token(); + _advance_token(); +end; - _skip_spaces(); - loca0 := _read_token(); - _advance(loca0); +# Prints and skips a line. +proc _skip_comment(); +begin + la t0, source_code_position + lw t1, (t0) - loca0 := 0x7079742e; - _write_s(4, @loca0); - loca0 := 0x2065; - _write_s(2, @loca0); +.skip_comment_loop: + # Check for newline character. + lb t2, (t1) + li t3, '\n' + beq t2, t3, .skip_comment_end - _write_s(loca24, loca28); + # Advance the input string by one byte. + addi t1, t1, 1 + sw t1, (t0) - loca0 := 0x6f40202c; - _write_s(4, @loca0); - loca0 := 0x63656a62; - _write_s(4, @loca0); - loca0 := 0x0a74; - _write_s(2, @loca0); + j .skip_comment_loop - loca0 := 0x7a69732e; - _write_s(4, @loca0); - loca0 := 0x2065; - _write_s(2, @loca0); +.skip_comment_end: + # Skip the newline. + addi t1, t1, 1 + sw t1, (t0) +end; - _write_s(loca24, loca28); +# Prints and skips a line. +proc _compile_line(); +begin +.compile_line_loop: + la a0, source_code_position + lw a1, (a0) - loca0 := 0x202c; - _write_s(2, @loca0); + lb t0, (a1) + li t1, '\n' + beq t0, t1, .compile_line_end - _write_s(loca16, loca20); - _write_c(0x0a); + # Print a character. + lw a0, (a1) + _write_c(); - _write_s(loca24, loca28); + # Advance the input string by one byte. + li a0, 1 + _advance_token(); - loca0 := 0x7a2e203a; - _write_s(4, @loca0); - loca0 := 0x206f7265; - _write_s(4, @loca0); + j .compile_line_loop - _write_s(loca16, loca20); +.compile_line_end: + li a0, '\n' + _write_c(); - _write_c(0x0a) -end + li a0, 1 + _advance_token(); +end; -proc _compile_procedure() -var - loca0: Word - loca4: Word - loca8: Word - loca12: Word - loca16: Word - loca20: ^Byte - loca24: ^Byte +proc _compile_integer_literal(); begin - _advance(5); - loca16 := _read_token(); - loca20 := _current(); - _advance(loca16); - - loca0 := 0x7079742e; - _write_s(4, @loca0); - loca0 := 0x2065; - _write_s(2, @loca0); - - _write_s(loca16, loca20); - - loca0 := 0x6640202c; - _write_s(4, @loca0); - loca0 := 0x74636e75; - _write_s(4, @loca0); - loca0 := 0x0a6e6f69; - _write_s(4, @loca0); - - _write_s(loca16, loca20); - - loca0 := 0x0a3a; - _write_s(2, @loca0); - - _skip_spaces(); - _advance(1); - _skip_spaces(); - _advance(1); - - loca12 := 0x6e; - loca8 := 0x69676562; - - .Lcompile_procedure_begin; - _skip_spaces(); - loca0 := _read_token(); - - loca24 := _current(); - _advance(loca0); - loca0 := _token_compare(loca24, loca0, @loca8); - - if loca0 = 1 then - goto .Lcompile_procedure_begin - end; - - loca0 := 0x69646461; - _write_s(4, @loca0); - - loca0 := 0x2c707320; - _write_s(4, @loca0); - _write_s(4, @loca0); - - loca0 := 0x0a36392d; - _write_s(4, @loca0); - - loca0 := 0x72207773; - _write_s(4, @loca0); - loca0 := 0x39202c61; - _write_s(4, @loca0); - loca0 := 0x70732832; - _write_s(4, @loca0); - loca0 := 0x0a29; - _write_s(2, @loca0); - - loca0 := 0x73207773; - _write_s(4, @loca0); - loca0 := 0x38202c30; - _write_s(4, @loca0); - loca0 := 0x70732838; - _write_s(4, @loca0); - loca0 := 0x0a29; - _write_s(2, @loca0); - - loca0 := 0x69646461; - _write_s(4, @loca0); - loca0 := 0x2c307320; - _write_s(4, @loca0); - loca0 := 0x2c707320; - _write_s(4, @loca0); - loca0 := 0x0a363920; - _write_s(4, @loca0); - - loca0 := 0x61207773; - _write_s(4, @loca0); - loca4 := 0x38202c30; - _write_s(4, @loca4); - loca8 := 0x70732834; - _write_s(4, @loca8); - loca12 := 0x0a29; - _write_s(2, @loca12); - - _write_s(4, @loca0); - loca4 := 0x38202c31; - _write_s(4, @loca4); - loca8 := 0x70732830; - _write_s(4, @loca8); - _write_s(2, @loca12); - - _write_s(4, @loca0); - loca4 := 0x37202c32; - _write_s(4, @loca4); - loca8 := 0x70732836; - _write_s(4, @loca8); - _write_s(2, @loca12); - - _write_s(4, @loca0); - loca4 := 0x37202c33; - _write_s(4, @loca4); - loca8 := 0x70732832; - _write_s(4, @loca8); - _write_s(2, @loca12); - - _write_s(4, @loca0); - loca4 := 0x36202c34; - _write_s(4, @loca4); - loca8 := 0x70732838; - _write_s(4, @loca8); - _write_s(2, @loca12); - - _write_s(4, @loca0); - loca4 := 0x36202c35; - _write_s(4, @loca4); - loca8 := 0x70732838; - _write_s(4, @loca8); - _write_s(2, @loca12); - - .Lcompile_procedure_body; - _skip_spaces(); - loca12 := _read_line(); - loca8 := 0x0a646e65; - loca24 := _current(); - loca8 := _memcmp(loca24, @loca8, 4); - - if loca8 = 0 then - goto .Lcompile_procedure_end - end; - - _compile_line(loca12); - goto .Lcompile_procedure_body; - - .Lcompile_procedure_end; - _advance(4); - - loca0 := 0x7220776c; - _write_s(4, @loca0); - loca0 := 0x39202c61; - _write_s(4, @loca0); - loca0 := 0x70732832; - _write_s(4, @loca0); - loca0 := 0x0a29; - _write_s(2, @loca0); - - loca0 := 0x7320776c; - _write_s(4, @loca0); - loca0 := 0x38202c30; - _write_s(4, @loca0); - loca0 := 0x70732838; - _write_s(4, @loca0); - loca0 := 0x0a29; - _write_s(2, @loca0); - - loca0 := 0x69646461; - _write_s(4, @loca0); - - loca0 := 0x2c707320; - _write_s(4, @loca0); - _write_s(4, @loca0); - - loca0 := 0x0a3639; - _write_s(4, @loca0); - - loca0 := 0x0a746572; - _write_s(4, @loca0) -end - -proc _token_compare(loca84: ^Byte, loca80: Word, loca76: ^Byte) -var - loca0: Bool - loca4: Byte - loca8: Word - loca12: Byte + la a0, asm_li + _write_z(); + + la a0, asm_a0 + _write_z(); + + la a0, asm_comma + _write_z(); + + _read_token(); + _write_token(); + _advance_token(); + + li a0, '\n' + _write_c(); +end; + +proc _compile_character_literal(); begin - .Ltoken_compare_loop; - loca4 := _front(loca76); - - loca8 := loca4 or loca80; - if loca8 = 0 then - goto .Ltoken_compare_equal - end; - if loca80 = 0 then - goto .Ltoken_compare_not_equal - end; - if loca4 = 0 then - goto .Ltoken_compare_not_equal - end; - loca12 := _front(loca84); - if loca4 = loca12 then - goto .Ltoken_compare_continue - end; - goto .Ltoken_compare_not_equal; - - .Ltoken_compare_continue; - - loca84 := loca84 + 1; - loca80 := loca80 - 1; - loca76 := loca76 + 1; - goto .Ltoken_compare_loop; - - .Ltoken_compare_not_equal; - loca0 := 1; - goto .Ltoken_compare_end; - - .Ltoken_compare_equal; - loca0 := 0; - - .Ltoken_compare_end; - return loca0 -end - -proc _compile_goto() -var - loca0: Word - loca4: Word - loca8: ^Byte + la a0, asm_li + _write_z(); + + la a0, asm_a0 + _write_z(); + + la a0, asm_comma + _write_z(); + +.compile_character_literal_loop: + la a0, source_code_position + lw a0, (a0) + li a1, 1 + _write(); + li a0, 1 + _advance_token(); + + la t0, source_code_position + lw t0, (t0) + lb a0, (t0) + li t1, '\'' + beq a0, t1, .compile_character_literal_end + + j .compile_character_literal_loop + +.compile_character_literal_end: + li a0, '\'' + _write_c(); + + li a0, '\n' + _write_c(); + + li a0, 1 + _advance_token(); +end; + +proc _compile_variable_expression(); begin - _advance(4); + la a0, asm_lw + _write_z(); + + la a0, asm_a0 + _write_z(); - loca0 := 0x206a; - _write_s(2, @loca0); + la a0, asm_comma + _write_z(); - _skip_spaces(); - loca8 := _current(); - _advance(1); + la a0, source_code_position + lw a0, (a0) + addi a0, a0, 1 + li a1, 2 + _write(); - loca0 := _read_token(); - _advance(loca0); - loca0 := loca0 + 1; - _write_s(loca0, loca8); + la a0, asm_sp + _write_z(); - _advance(1); - _write_c(0x0a) -end + li a0, '\n' + _write_c(); -proc _compile_label(loca84: Word) -var - loca0: Word - loca4: Word - loca8: ^Byte + li a0, 3 + _advance_token(); + +end; + +proc _compile_expression(); begin - loca0 := _current(); + la t0, source_code_position + lw t0, (t0) + lb a0, (t0) - loca0 := loca0 + loca84; - loca0 := loca0 - 1; - loca4 := loca84; + li t1, '\'' + beq a0, t1, .compile_expression_character_literal - loca0 := _front(loca0); - if loca0 = 0x3b then - loca4 := loca4 - 1 - end; - loca8 := _current(); - _write_s(loca4, loca8); + li t1, 'v' + beq a0, t1, .compile_expression_variable - _write_c(0x3a); - _write_c(0x0a); + _is_digit(); + bnez a0, .compile_expression_integer_literal - _advance(loca84) -end + j .compile_expression_end -proc _compile_return() -begin - _advance(6); - _skip_spaces(); - _build_binary_expression() -end - -proc _compile_if() -var - loca0: Word - loca4: ^Byte - loca8: Word - loca12: Word - loca16: Word - loca20: Word - loca24: Word -begin - _advance(2); - _skip_spaces(); +.compile_expression_character_literal: + _compile_character_literal(); + j .compile_expression_end + +.compile_expression_integer_literal: + _compile_integer_literal(); + j .compile_expression_end + +.compile_expression_variable: + _compile_variable_expression(); + j .compile_expression_end; - _build_binary_expression(); +.compile_expression_end: +end; - _skip_spaces(); - _advance(4); +proc _compile_call(); +begin + _read_token(); + sw a0, 20(sp) + la t0, source_code_position + lw t0, (t0) + sw t0, 16(sp) - loca20 := 0x00646e65; - loca16 := 0x66694c2e; + # Skip the identifier and left paren. + addi a0, a0, 1 + _advance_token(); - loca12 := 0x7a716562; - _write_s(4, @loca12); - loca12 := 0x2c306120; - _write_s(4, @loca12); - _write_c(0x20); + la t0, source_code_position + lw t0, (t0) + lb t0, (t0) - loca24 := _label_counter(1); - _write_s(4, @loca16); - _write_i(loca24); + li t1, ')' + beq t0, t1, .compile_call_finalize - _write_c(0x0a); + _compile_expression(); - .Lcompile_if_loop; - _skip_spaces(); - loca12 := _read_token(); +.compile_call_finalize: + la a0, asm_call + _write_z(); - loca4 := _current(); - loca8 := _token_compare(loca4, loca12, @loca20); + lw a0, 16(sp) + lw a1, 20(sp) + _write(); - if loca8 then - loca12 := _read_line(); - _compile_line(loca12, 1); + # Skip the right paren. + li a0, 1 + _advance_token(); +end; - goto .Lcompile_if_loop - end; +proc _compile_goto(); +begin + li a0, 5 + _advance_token(); - _write_s(4, @loca16); - _write_i(loca24); + _read_token(); + sw a0, 20(sp) - loca12 := 0x0a3a0a3a; - _write_s(2, @loca12); + la a0, asm_j + _write_z(); - _advance(4) -end + lw a0, 20(sp) + _write_token(); + _advance_token(); +end; -proc _compile_line(loca84: Word, loca80: Bool) -var - loca0: Char - loca4: Int - loca8: Bool - loca12: Word - loca16: ^Byte +proc _compile_statement(); begin - if loca84 = 0 then - goto .Lcompile_line_empty - end; - - loca16 := _current(); - loca0 := _front(loca16); - - loca12 := 0x676f7270; - loca4 := _memcmp(loca16, @loca12, 4); - if loca4 = 0 then - goto .Lcompile_line_program - end; - - loca12 := 0x0a726176; - loca4 := _memcmp(loca16, @loca12, 4); - if loca4 = 0 then - goto .Lcompile_line_var - end; - - loca12 := 0x636f7270; - loca4 := _memcmp(loca16, @loca12, 4); - if loca4 = 0 then - goto .Lcompile_line_procedure - end; - - loca12 := 0x69676562; - loca4 := _memcmp(loca16, @loca12, 4); - if loca4 = 0 then - goto .Lcompile_line_begin - end; - - loca12 := 0x2e646e65; - loca4 := _memcmp(loca16, @loca12, 4); - if loca4 = 0 then - goto .Lcompile_line_exit - end; - - loca12 := 0x61636f6c; - loca4 := _memcmp(loca16, @loca12, 4); - if loca4 = 0 then - goto .Lcompile_line_identifier - end; - loca4 := _front(loca16); - if loca4 = 0x73 then - goto .Lcompile_line_identifier - end; - - loca12 := 0x6f706d69; - loca4 := _memcmp(loca16, @loca12, 4); - if loca4 = 0 then - goto .Lcompile_line_import - end; - - loca12 := 0x6f746f67; - loca4 := _memcmp(loca16, @loca12, 4); - if loca4 = 0 then - goto .Lcompile_line_goto - end; - - loca12 := 0x75746572; - loca4 := _memcmp(loca16, @loca12, 4); - if loca4 = 0 then - goto .Lcompile_line_return - end; - - loca12 := 0x6669; - loca4 := _memcmp(loca16, @loca12, 2); - if loca4 = 0 then - goto .Lcompile_line_if - end; - - if loca0 = 0x2e then - goto .Lcompile_line_label - end; - if loca0 = 0x5f then - goto .Lcompile_line_identifier - end; - goto .Lcompile_line_unchanged; - - .Lcompile_line_if; - _compile_if(); - goto .Lcompile_line_section; - - .Lcompile_line_label; - _compile_label(loca84); - goto .Lcompile_line_section; - - .Lcompile_line_return; - _compile_return(); - goto .Lcompile_line_section; - - .Lcompile_line_goto; + # This is a call if the statement starts with an underscore. + la t0, source_code_position + lw t0, (t0) + # First character after alignment tab. + addi t0, t0, 1 + lb t0, (t0) + + li t1, '_' + beq t0, t1, .compile_statement_call + + li t1, 'g' + beq t0, t1, .compile_statement_goto + + _compile_line(); + j .compile_statement_end + +.compile_statement_call: + li a0, 1 + _advance_token(); + _compile_call(); + + j .compile_statement_semicolon + +.compile_statement_goto: + li a0, 1 + _advance_token(); _compile_goto(); - goto .Lcompile_line_section; - - .Lcompile_line_import; - _compile_import(); - goto .Lcompile_line_section; - - .Lcompile_line_identifier; - _compile_identifier(); - goto .Lcompile_line_section; - - .Lcompile_line_exit; - _compile_exit(); - goto .Lcompile_line_section; - - .Lcompile_line_begin; - - if loca80 = 1 then - goto .Lcompile_line_compile_entry - end; - _compile_text_section(); - .Lcompile_line_compile_entry; - _compile_entry_point(); - loca8 := 1; - goto .Lcompile_line_end; - - .Lcompile_line_procedure; - if loca80 = 1 then - goto .Lcompile_line_compile_procedure - end; - _compile_text_section(); - .Lcompile_line_compile_procedure; - _compile_procedure(); - loca8 := 1; - goto .Lcompile_line_end; - .Lcompile_line_var; - _compile_variable_section(); - goto .Lcompile_line_section; + j .compile_statement_semicolon - .Lcompile_line_program; - _compile_program(); - goto .Lcompile_line_section; +.compile_statement_semicolon: + li a0, 2 + _advance_token(); - .Lcompile_line_empty; - _advance(1); - goto .Lcompile_line_section; + li a0, '\n' + _write_c(); - .Lcompile_line_unchanged; - _compile_assembly(loca84); - goto .Lcompile_line_section; +.compile_statement_end: +end; - .Lcompile_line_section; - loca8 := 0; +proc _compile_procedure_body(); +begin +.compile_procedure_body_loop: + la a0, source_code_position + lw a0, (a0) + la a1, keyword_end + li a2, KEYWORD_END_SIZE + _memcmp(); + + beqz a0, .compile_procedure_body_epilogue - .Lcompile_line_end; - _skip_spaces(); + _compile_statement(); + j .compile_procedure_body_loop - return loca8 -end +.compile_procedure_body_epilogue: +end; -proc _compile_text_section() -var loca0: Word +proc _compile_procedure(); begin - loca0 := 0x6365732e; - _write_s(4, @loca0); - loca0 := 0x6e6f6974; - _write_s(4, @loca0); - loca0 := 0x65742e20; - _write_s(4, @loca0); - loca0 := 0x0a7478; - _write_s(3, @loca0) -end - -proc _compile_entry_point() -var loca0: Word + # Skip "proc ". + li a0, KEYWORD_PROC_SIZE + _advance_token(); + + _read_token(); + sw a0, 20(sp) # Save the procedure name length. + + # Write .type _procedure_name, @function. + la a0, asm_type_directive + _write_z(); + + lw a0, 20(sp) + _write_token(); + + la a0, asm_type_function + _write_z(); + + # Write procedure label, _procedure_name: + lw a0, 20(sp) + _write_token(); + + la a0, asm_colon + _write_z(); + + # Skip the function name and trailing parens, semicolon, "begin" and newline. + lw a0, 20(sp) + addi a0, a0, KEYWORD_BEGIN_SIZE + 1 + 4 + _advance_token(); + + la a0, asm_prologue + _write_z(); + + _compile_procedure_body(); + + # Write the epilogue. + la a0, asm_epilogue + _write_z(); + + li a0, KEYWORD_END_SIZE + 2 + _advance_token(); +end; + +proc _compile_type(); begin - loca0 := 0x7079742e; - _write_s(4, @loca0); - loca0 := 0x735f2065; - _write_s(4, @loca0); - loca0 := 0x74726174; - _write_s(4, @loca0); - loca0 := 0x6640202c; - _write_s(4, @loca0); - loca0 := 0x74636e75; - _write_s(4, @loca0); - loca0 := 0x0a6e6f69; - _write_s(4, @loca0); - loca0 := 0x6174735f; - _write_s(4, @loca0); - loca0 := 0x0a3a7472; - _write_s(4, @loca0); - - _advance(6) -end - -proc _compile_exit() -var loca0: Word + # Print and skip the .type directive and a space after it. + li a0, KEYWORD_TYPE_SIZE + 1 + _write_token(); + _advance_token(); + + # Read and print the symbol name. + _read_token(); + sw a0, 20(sp) + + # Print and skip the symbol name, comma, space and @. + lw a0, 20(sp) + addi a0, a0, 3 + _write_token(); + _advance_token(); + + # Read the symbol type. + _read_token(); + sw a0, 16(sp) + la t0, source_code_position + lw t0, (t0) + sw t0, 12(sp) + + # Print the symbol type and newline. + lw a0, 16(sp) + addi a0, a0, 1 + _write_token(); + _advance_token(); + + # Write the object definition itself. + _compile_line(); + +.compile_type_end: +end; + +proc _compile_equ(); begin - loca0 := 0x6120696c; - _write_s(4, @loca0); - loca0 := 0x30202c30; - _write_s(4, @loca0); - loca0 := 0x20696c0a; - _write_s(4, @loca0); - loca0 := 0x202c3761; - _write_s(4, @loca0); - loca0 := 0x650a3339; - _write_s(4, @loca0); - loca0 := 0x6c6c6163; - _write_s(4, @loca0); - loca0 := 0x0a; - _write_s(1, @loca0); - - _advance(4); - _skip_spaces() -end - -proc _read_line() -var - loca0: ^Byte - loca4: Byte + # Print and skip the .equ directive and a space after it. + li a0, KEYWORD_EQU_SIZE + 1 + _write_token(); + _advance_token(); + + # Read and print the constant name. + _read_token(); + sw a0, 20(sp) + + # Print and skip the constant name, comma and space. + lw a0, 20(sp) + addi a0, a0, 2 + _write_token(); + _advance_token(); + + # Read the constant value. + _read_token(); + sw a0, 16(sp) + + # Print and skip the constant value and newline. + lw a0, 16(sp) + addi a0, a0, 1 + _write_token(); + _advance_token(); +end; + +proc _skip_newlines(); begin - loca0 := _current(); - - .Lread_line_do; - loca4 := _front(loca0); - if loca4 = 0 then - goto .Lread_line_end - end; - if loca4 = 0x0a then - goto .Lread_line_end - end; - loca0 := loca0 + 1; - goto .Lread_line_do; - - .Lread_line_end; - loca4 := _current(); - return loca0 - loca4 -end - -proc _compile() -var - loca0: Word - loca4: Word - loca8: Bool - loca12: Char - loca16: ^Byte + # Skip newlines. + la t0, source_code_position + lw t1, (t0) + +.skip_newlines_loop: + lb t2, (t1) + li t3, '\n' + bne t2, t3, .skip_newlines_end + beqz t2, .skip_newlines_end + + addi t1, t1, 1 + sw t1, (t0) + + j .skip_newlines_loop + +.skip_newlines_end: +end; + +# Process the source code and print the generated code. +proc _compile(); begin - loca4 := 0; +.compile_loop: + _skip_newlines(); - .Lcompile_do; - loca16 := _current(); - loca12 := _front(loca16); + la t0, source_code_position + lw t0, (t0) + lb t0, (t0) + beqz t0, .compile_end + li t1, '#' + beq t0, t1, .compile_comment - if loca12 = 0 then - goto .Lcompile_end - end; + la a0, source_code_position + lw a0, (a0) + la a1, keyword_equ + li a2, KEYWORD_EQU_SIZE + _memcmp(); - _skip_spaces(); - loca0 := _read_line(); - loca8 := _compile_line(loca0, loca4); + beqz a0, .compile_equ - if loca8 = 0 then - goto .Lcompile_do - end; - loca4 := loca4 or loca8; + la a0, source_code_position + lw a0, (a0) + la a1, keyword_section + li a2, KEYWORD_SECTION_SIZE + _memcmp(); - goto .Lcompile_do; - .Lcompile_end -end + beqz a0, .compile_section -proc _front(loca84: ^Word) -begin - return _get(loca84) & 0xff -end + la a0, source_code_position + lw a0, (a0) + la a1, keyword_type + li a2, KEYWORD_TYPE_SIZE + _memcmp(); -proc _main() -begin - _read_file(source_code, 81920); + beqz a0, .compile_type + + la a0, source_code_position + lw a0, (a0) + la a1, keyword_proc + li a2, KEYWORD_PROC_SIZE + _memcmp(); + + beqz a0, .compile_procedure + + la a0, source_code_position + lw a0, (a0) + la a1, keyword_global + li a2, KEYWORD_GLOBAL_SIZE + _memcmp(); + + beqz a0, .compile_global + # Not a known token, exit. + j .compile_end + +.compile_equ: + _compile_equ(); + + j .compile_loop + +.compile_section: + _compile_section(); + + j .compile_loop + +.compile_type: + _compile_type(); + + j .compile_loop + +.compile_global: + _compile_line(); + + j .compile_loop + +.compile_comment: + _skip_comment(); + + j .compile_loop + +.compile_procedure: + _compile_procedure(); + + j .compile_loop - _label_counter(0) -end +.compile_end: +end; +# Entry point. +.globl _start +proc _start(); begin - _main(); - _compile() -end. + # Read the source from the standard input. + la a0, source_code + li a1, SOURCE_BUFFER_SIZE # Buffer size. + _read_file(); + _compile(); + + # Call exit. + li a0, 0 # Use 0 return code. + li a7, 93 # SYS_EXIT. + ecall +end; |
