Implement simple binary expressions

This commit is contained in:
Eugen Wissner 2025-04-26 23:14:38 +02:00
parent fee1781a5b
commit a60e623af5
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
4 changed files with 695 additions and 559 deletions

View File

@ -63,3 +63,35 @@ end
file 'build/stage2b' => ['build/stage2b.s', 'boot/common-boot.s'] do |t| file 'build/stage2b' => ['build/stage2b.s', 'boot/common-boot.s'] do |t|
sh CROSS_GCC, '-nostdlib', '-o', t.name, *t.prerequisites sh CROSS_GCC, '-nostdlib', '-o', t.name, *t.prerequisites
end end
desc 'Print remaining lines to rewrite'
task :statistics do
def is_false_positive(word)
word.start_with?('(*') ||
word.start_with?('*)') ||
('A'..'Z').include?(word[0]) ||
/^[[:alpha:]][[:digit:]]$/.match(word)
end
lines = File.read('boot/stage2.elna')
.split("\n")
.select { |line| line.start_with? "\t" }
.map { |line| line.delete_prefix("\t").split(' ') }
.reject { |words| is_false_positive(words.first) }
.group_by do |words|
if words.first.length < 5
case words.first
when 'goto'
'Statements'
else
words.first
end
else
'Statements'
end
end
lines.each do |key, value|
puts "#{key}: #{value.count}"
end
end

View File

@ -1,4 +1,5 @@
.global _is_alpha, _is_digit, _is_alnum, _is_upper, _is_lower, _write_out, _read_file, exit, _memcmp, _write_error .global _is_alpha, _is_digit, _is_alnum, _is_upper, _is_lower
.global _write_out, _read_file, exit, _memcmp, _write_error, _put_char
.section .rodata .section .rodata
@ -200,6 +201,29 @@ _read_file:
ret ret
# Terminates the program. a0 contains the return code. # Terminates the program. a0 contains the return code.
.type _exit, @function
exit: exit:
li a7, SYS_EXIT li a7, SYS_EXIT
ecall ecall
# Writes a character from a0 into the standard output.
.type _put_char, @function
_put_char:
# Prologue
addi sp, sp, -16
sw ra, 12(sp)
sw s0, 8(sp)
addi s0, sp, 16
sb a0, 4(sp)
li a0, STDOUT
addi a1, sp, 4
li a2, 1
li a7, SYS_WRITE
ecall
# Epilogue.
lw ra, 12(sp)
lw s0, 8(sp)
add sp, sp, 16
ret

View File

@ -16,6 +16,14 @@ prologue: .ascii "addi sp, sp, -96\nsw ra, 92(sp)\nsw s0, 88(sp)\naddi s0, sp, 9
.equ PROLOGUE_SIZE, . - prologue .equ PROLOGUE_SIZE, . - prologue
epilogue: .ascii "lw ra, 92(sp)\nlw s0, 88(sp)\naddi sp, sp, 96\nret\n" epilogue: .ascii "lw ra, 92(sp)\nlw s0, 88(sp)\naddi sp, sp, 96\nret\n"
.equ EPILOGUE_SIZE, . - epilogue .equ EPILOGUE_SIZE, . - epilogue
asm_exit: .ascii "li a0, 0\nli a7, 93\necall\n"
.equ ASM_EXIT_SIZE, . - asm_exit
asm_start: .ascii ".type _start, @function\n_start:\n"
.equ ASM_START_SIZE, . - asm_start
asm_and_a0_a1: .ascii "and a0, a0, a1\n"
.equ ASM_AND_A0_A1_SIZE, . - asm_and_a0_a1
asm_or_a0_a1: .ascii "or a0, a0, a1\n"
.equ ASM_OR_A0_A1_SIZE, . - asm_or_a0_a1
.section .bss .section .bss
.type source_code, @object .type source_code, @object
@ -67,6 +75,14 @@ _build_binary_expression:
call _token_compare call _token_compare
beqz a0, .L_build_binary_expression_and beqz a0, .L_build_binary_expression_and
li t0, 0x726f # or
sw t0, 16(sp)
mv a0, s1
lw a1, 20(sp)
addi a2, sp, 16
call _token_compare
beqz a0, .L_build_binary_expression_or
li t0, 0x3d # = li t0, 0x3d # =
sw t0, 16(sp) sw t0, 16(sp)
mv a0, s1 mv a0, s1
@ -75,11 +91,6 @@ _build_binary_expression:
call _token_compare call _token_compare
beqz a0, .L_build_binary_expression_equal beqz a0, .L_build_binary_expression_equal
/* DEBUG
mv a0, s1
li a1, 8
call _write_error */
j .Lbuild_binary_expression_end j .Lbuild_binary_expression_end
.L_build_binary_expression_equal: .L_build_binary_expression_equal:
@ -114,16 +125,18 @@ _build_binary_expression:
addi s1, s1, 1 # Skip &. addi s1, s1, 1 # Skip &.
li a0, 1 li a0, 1
call _build_expression call _build_expression
li t0, 0x0a3161 # a1\n la a0, asm_and_a0_a1
sw t0, 16(sp) li a1, ASM_AND_A0_A1_SIZE
li t0, 0x202c3061 # a0,_ call _write_out
sw t0, 12(sp)
li t0, 0x202c3061 # a0,_ j .Lbuild_binary_expression_end
sw t0, 8(sp)
li t0, 0x20646e61 # and_ .L_build_binary_expression_or:
sw t0, 4(sp) addi s1, s1, 2 # Skip or.
addi a0, sp, 4 li a0, 1
li a1, 15 call _build_expression
la a0, asm_or_a0_a1
li a1, ASM_OR_A0_A1_SIZE
call _write_out call _write_out
j .Lbuild_binary_expression_end j .Lbuild_binary_expression_end
@ -141,20 +154,24 @@ _build_binary_expression:
.type _build_expression, @function .type _build_expression, @function
_build_expression: _build_expression:
# Prologue. # Prologue.
addi sp, sp, -32 addi sp, sp, -40
sw ra, 28(sp) sw ra, 36(sp)
sw s0, 24(sp) sw s0, 32(sp)
addi s0, sp, 32 addi s0, sp, 40
addi a0, a0, '0' # Make the register number to a character. addi a0, a0, '0' # Make the register number to a character.
sw a0, 20(sp) # And save it. sw a0, 28(sp) # And save it.
call _skip_spaces call _skip_spaces
call _read_token call _read_token
sw s1, 16(sp) sw s1, 24(sp)
sw a0, 12(sp) sw a0, 20(sp)
addi a0, s1, 0
lbu a0, (a0)
li t0, '@'
beq a0, t0, .Lbuild_expression_address
# Integer literal.
addi a0, s1, 0 addi a0, s1, 0
lbu a0, (a0) lbu a0, (a0)
call _is_digit call _is_digit
@ -162,7 +179,7 @@ _build_expression:
addi a0, s1, 0 addi a0, s1, 0
lbu a0, (a0) lbu a0, (a0)
li t0, 0x5f # _ li t0, '_'
beq a0, t0, .Lbuild_expression_call beq a0, t0, .Lbuild_expression_call
li t0, 0x61636f6c # loca li t0, 0x61636f6c # loca
@ -174,7 +191,7 @@ _build_expression:
beqz a0, .Lbuild_expression_identifier beqz a0, .Lbuild_expression_identifier
# Named identifier. # Named identifier.
lw t1, 20(sp) lw t1, 28(sp)
li t0, 0x00202c00 # \0,_ li t0, 0x00202c00 # \0,_
or t0, t0, t1 or t0, t0, t1
sw t0, 8(sp) sw t0, 8(sp)
@ -184,48 +201,80 @@ _build_expression:
li a1, 7 li a1, 7
call _write_out call _write_out
lw a0, 16(sp) lw a0, 24(sp)
lw a1, 12(sp) lw a1, 20(sp)
call _write_out
li a0, '\n'
call _put_char
j .Lbuild_expression_advance
.Lbuild_expression_address:
lw t1, 28(sp)
li t0, 0x20 # _
sw t0, 16(sp)
li t0, 0x2c707320 # _sp,
sw t0, 12(sp)
li t0, 0x2c006120 # _a\0,
sw t0, 8(sp)
sb t1, 10(sp)
li t0, 0x69646461 # addi
sw t0, 4(sp)
addi a0, sp, 4
li a1, 13
call _write_out
addi s1, s1, 1 # Skip @.
call _skip_spaces
call _read_token
sw s1, 24(sp)
sw a0, 20(sp)
lw a0, 24(sp)
lw a1, 20(sp)
addi a0, a0, 4 # Skip the "loca" variable prefix.
addi a1, a1, -4 # Skip the "loca" variable prefix.
call _write_out call _write_out
li t0, 0x0a # \n li t0, 0x0a # \n
sw t0, 8(sp) sw t0, 16(sp)
addi a0, sp, 8 addi a0, sp, 16
li a1, 1 li a1, 1
call _write_out call _write_out
j .Lbuild_expression_advance j .Lbuild_expression_advance
.Lbuild_expression_identifier: .Lbuild_expression_identifier:
lw t1, 20(sp) lw t1, 28(sp)
li t0, 0x00202c00 # \0,_ li t0, 0x00202c00 # \0,_
or t0, t0, t1 or t0, t0, t1
sw t0, 8(sp) sw t0, 16(sp)
li t0, 0x6120776c # lw a li t0, 0x6120776c # lw a
sw t0, 4(sp) sw t0, 12(sp)
addi a0, sp, 4 addi a0, sp, 12
li a1, 7 li a1, 7
call _write_out call _write_out
lw a0, 16(sp) lw a0, 24(sp)
lw a1, 12(sp) lw a1, 20(sp)
addi a0, a0, 4 # Skip the "loca" variable prefix. addi a0, a0, 4 # Skip the "loca" variable prefix.
addi a1, a1, -4 # Skip the "loca" variable prefix. addi a1, a1, -4 # Skip the "loca" variable prefix.
call _write_out call _write_out
li t0, 0x0a # \n li t0, 0x0a # \n
sw t0, 8(sp) sw t0, 16(sp)
li t0, 0x29707328 # (sp) li t0, 0x29707328 # (sp)
sw t0, 4(sp) sw t0, 12(sp)
addi a0, sp, 4 addi a0, sp, 12
li a1, 5 li a1, 5
call _write_out call _write_out
j .Lbuild_expression_advance j .Lbuild_expression_advance
.Lbuild_expression_call: .Lbuild_expression_call:
lw a0, 16(sp) lw a0, 24(sp)
lw a1, 12(sp) lw a1, 20(sp)
add s1, s1, a1 add s1, s1, a1
addi s1, s1, 1 addi s1, s1, 1
call _compile_call call _compile_call
@ -233,37 +282,34 @@ _build_expression:
j .Lbuild_expression_end j .Lbuild_expression_end
.Lbuild_expression_literal: .Lbuild_expression_literal:
lw t1, 20(sp) lw t1, 28(sp)
li t0, 0x00202c00 # \0,_ li t0, 0x00202c00 # \0,_
or t0, t0, t1 or t0, t0, t1
sw t0, 8(sp) sw t0, 16(sp)
li t0, 0x6120696c # li a li t0, 0x6120696c # li a
sw t0, 4(sp) sw t0, 12(sp)
addi a0, sp, 4 addi a0, sp, 12
li a1, 7 li a1, 7
call _write_out call _write_out
lw a0, 16(sp) lw a0, 24(sp)
lw a1, 12(sp) lw a1, 20(sp)
call _write_out call _write_out
li t0, 0x0a # \n li a0, '\n'
sw t0, 8(sp) call _put_char
addi a0, sp, 8
li a1, 1
call _write_out
j .Lbuild_expression_advance j .Lbuild_expression_advance
.Lbuild_expression_advance: .Lbuild_expression_advance:
lw a0, 12(sp) lw a0, 20(sp)
add s1, s1, a0 add s1, s1, a0
.Lbuild_expression_end: .Lbuild_expression_end:
# Epilogue. # Epilogue.
lw ra, 28(sp) lw ra, 36(sp)
lw s0, 24(sp) lw s0, 32(sp)
addi sp, sp, 32 addi sp, sp, 40
ret ret
# Compiles a statement beginning with an identifier. # Compiles a statement beginning with an identifier.
@ -554,6 +600,9 @@ _read_token:
li t1, '=' li t1, '='
beq t0, t1, .Ltoken_character_single beq t0, t1, .Ltoken_character_single
li t1, '@'
beq t0, t1, .Ltoken_character_single
# Expect an identifier or a number. # Expect an identifier or a number.
.Ltoken_character_loop_do: .Ltoken_character_loop_do:
lw t6, 4(sp) lw t6, 4(sp)
@ -638,8 +687,50 @@ _skip_indentation:
# a0 - Line length. # a0 - Line length.
.type _skip_comment, @function .type _skip_comment, @function
_skip_comment: _skip_comment:
add s1, s1, a0 # Prologue.
addi s1, s1, 1 # Skip the new line. addi sp, sp, -16
sw ra, 12(sp)
sw s0, 8(sp)
addi s0, sp, 16
/* DEBUG
mv a0, s1
li a1, 8
call _write_error */
# Check whether this is a comment.
li t0, 0x2a28 # (*
sw t0, 4(sp)
addi a0, sp, 4
mv a1, s1
li a2, 2
call _memcmp
bnez a0, .Lskip_comment_end
addi s1, s1, 2 # Skip (*.
li t0, 0x292a # *)
sw t0, 4(sp)
.Lskip_comment_loop:
addi a0, sp, 4
mv a1, s1
li a2, 2
call _memcmp
beqz a0, .Lskip_comment_close
addi s1, s1, 1
j .Lskip_comment_loop
.Lskip_comment_close:
addi s1, s1, 2 # Skip *).
.Lskip_comment_end:
# Epilogue.
lw ra, 12(sp)
lw s0, 8(sp)
addi sp, sp, 16
ret ret
# Parameters: # Parameters:
@ -662,11 +753,8 @@ _compile_assembly:
lw t0, 4(sp) lw t0, 4(sp)
add s1, s1, t0 add s1, s1, t0
li t0, '\n' li a0, '\n'
sb t0, 0(sp) call _put_char
addi a0, sp, 0
li a1, 1
call _write_out
addi s1, s1, 1 # Skip the new line. addi s1, s1, 1 # Skip the new line.
@ -742,7 +830,6 @@ _compile_constant:
call _write_out call _write_out
call _skip_spaces call _skip_spaces
call _read_token
addi s1, s1, 2 # Skip the assignment sign. addi s1, s1, 2 # Skip the assignment sign.
# : .long # : .long
@ -762,11 +849,8 @@ _compile_constant:
add s1, s1, a1 add s1, s1, a1
call _write_out call _write_out
li t0, '\n' li a0, '\n'
sw t0, 4(sp) call _put_char
addi a0, sp, 4
li a1, 1
call _write_out
# Epilogue. # Epilogue.
lw ra, 12(sp) lw ra, 12(sp)
@ -1234,7 +1318,7 @@ _compile_line:
beqz a0, .Lcompile_line_empty # Skip an empty line. beqz a0, .Lcompile_line_empty # Skip an empty line.
lbu t0, (s1) lbu t0, (s1)
li t1, '#' li t1, '('
beq t0, t1, .Lcompile_line_comment beq t0, t1, .Lcompile_line_comment
li t0, 0x0a6d6172 # ram\n li t0, 0x0a6d6172 # ram\n
@ -1396,6 +1480,11 @@ _compile_line:
mv a0, zero mv a0, zero
.Lcompile_line_end: .Lcompile_line_end:
sw a0, 12(sp)
call _skip_spaces
call _skip_comment
lw a0, 12(sp)
# Epilogue. # Epilogue.
lw ra, 28(sp) lw ra, 28(sp)
lw s0, 24(sp) lw s0, 24(sp)
@ -1406,94 +1495,61 @@ _compile_line:
.type _compile_text_section, @function .type _compile_text_section, @function
_compile_text_section: _compile_text_section:
# Prologue. # Prologue.
addi sp, sp, -24 addi sp, sp, -8
sw ra, 20(sp) sw ra, 4(sp)
sw s0, 16(sp) sw s0, 0(sp)
addi s0, sp, 24 addi s0, sp, 8
la a0, section_text la a0, section_text
li a1, SECTION_TEXT_SIZE li a1, SECTION_TEXT_SIZE
call _write_out call _write_out
# Epilogue. # Epilogue.
lw ra, 20(sp) lw ra, 4(sp)
lw s0, 16(sp) lw s0, 0(sp)
addi sp, sp, 24 addi sp, sp, 8
ret ret
.type _compile_entry_point, @function .type _compile_entry_point, @function
_compile_entry_point: _compile_entry_point:
# Prologue. # Prologue.
addi sp, sp, -64 addi sp, sp, -8
sw ra, 60(sp) sw ra, 4(sp)
sw s0, 56(sp) sw s0, 0(sp)
addi s0, sp, 64 addi s0, sp, 8
# .type _start, @function # .type _start, @function
li t0, 0x0a3a7472 # rt:\n la a0, asm_start
sw t0, 52(sp) li a1, ASM_START_SIZE
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 call _write_out
addi s1, s1, 6 # Skip begin\n. addi s1, s1, 6 # Skip begin\n.
# Epilogue. # Epilogue.
lw ra, 60(sp) lw ra, 4(sp)
lw s0, 56(sp) lw s0, 0(sp)
addi sp, sp, 64 addi sp, sp, 8
ret ret
.type _compile_exit, @function .type _compile_exit, @function
_compile_exit: _compile_exit:
# Prologue. # Prologue.
addi sp, sp, -64 addi sp, sp, -8
sw ra, 60(sp) sw ra, 4(sp)
sw s0, 56(sp) sw s0, 0(sp)
addi s0, sp, 64 addi s0, sp, 8
# li a0, 0 la a0, asm_exit
# li a7, SYS_EXIT li a1, ASM_EXIT_SIZE
# 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 call _write_out
addi s1, s1, 4 # Skip end. addi s1, s1, 4 # Skip end.
call _skip_spaces # Read the possible new line at the end of the file. call _skip_spaces # Read the possible new line at the end of the file.
# Epilogue. # Epilogue.
lw ra, 60(sp) lw ra, 4(sp)
lw s0, 56(sp) lw s0, 0(sp)
addi sp, sp, 64 addi sp, sp, 8
ret ret
# Finds the end of the line and returns its length in a0. # Finds the end of the line and returns its length in a0.

File diff suppressed because it is too large Load Diff