Implement if statements

This commit is contained in:
2025-04-29 00:55:20 +02:00
parent 963d32e8d1
commit 9c66cec171
7 changed files with 476 additions and 213 deletions

View File

@@ -1,5 +1,8 @@
.global _start # Program entry point.
# Global variables or registers.
# s1 - Contains the current position in the source text.
# s2 - Label counter.
.equ SOURCE_BUFFER_SIZE, 81920
@@ -29,10 +32,17 @@ asm_add_a0_a1: .ascii "add a0, a0, a1\n"
.equ ASM_ADD_A0_A1_SIZE, . - asm_add_a0_a1
asm_sub_a0_a1: .ascii "sub a0, a0, a1\n"
.equ ASM_SUB_A0_A1_SIZE, . - asm_sub_a0_a1
asm_mul_a0_a1: .ascii "mul a0, a0, a1\n"
.equ ASM_MUL_A0_A1_SIZE, . - asm_mul_a0_a1
asm_seqz_a0: .ascii "seqz a0, a0\n"
.equ ASM_SEQZ_A0_SIZE, . - asm_seqz_a0
asm_neg_a0: .ascii "neg a0, a0\n"
.equ ASM_NEG_A0_SIZE, . - asm_neg_a0
asm_type: .ascii ".type "
.equ ASM_TYPE_SIZE, . - asm_type
asm_restore_parameters:
.ascii "lw a0, 60(sp)\nlw a1, 56(sp)\nlw a2, 52(sp)\nlw a3, 48(sp)\nlw a4, 44(sp)\nlw a5, 40(sp)\n"
.equ ASM_RESTORE_PARAMETERS_SIZE, . - asm_restore_parameters
.section .bss
.type source_code, @object
@@ -116,6 +126,14 @@ _build_binary_expression:
call _token_compare
beqz a0, .L_build_binary_expression_minus
li t0, '*'
sw t0, 16(sp)
mv a0, s1
lw a1, 20(sp)
addi a2, sp, 16
call _token_compare
beqz a0, .L_build_binary_expression_product
j .Lbuild_binary_expression_end
.L_build_binary_expression_equal:
@@ -172,6 +190,16 @@ _build_binary_expression:
j .Lbuild_binary_expression_end
.L_build_binary_expression_product:
addi s1, s1, 1 # Skip *.
li a0, 1
call _build_expression
la a0, asm_mul_a0_a1
li a1, ASM_MUL_A0_A1_SIZE
call _write_out
j .Lbuild_binary_expression_end
.Lbuild_binary_expression_end:
# Epilogue.
lw ra, 28(sp)
@@ -198,18 +226,19 @@ _build_expression:
sw s1, 24(sp)
sw a0, 20(sp)
addi a0, s1, 0
lbu a0, (a0)
lbu a0, (s1)
li t0, '-'
beq a0, t0, .Lbuild_expression_negate
lbu a0, (s1)
li t0, '@'
beq a0, t0, .Lbuild_expression_address
addi a0, s1, 0
lbu a0, (a0)
lbu a0, (s1)
call _is_digit
bnez a0, .Lbuild_expression_literal
addi a0, s1, 0
lbu a0, (a0)
lbu a0, (s1)
li t0, '_'
beq a0, t0, .Lbuild_expression_call
@@ -241,6 +270,17 @@ _build_expression:
j .Lbuild_expression_advance
.Lbuild_expression_negate:
addi s1, s1, 1 # Skip the -.
mv a0, zero
call _build_expression
la a0, asm_neg_a0
li a1, ASM_NEG_A0_SIZE
call _write_out
j .Lbuild_expression_advance
.Lbuild_expression_address:
lw t1, 28(sp)
li t0, 0x20 # _
@@ -464,26 +504,10 @@ _compile_call:
# Only 6 arguments are supported with a0-a5.
# Save all arguments on the stack so they aren't overriden afterwards.
# The offset on the stack always has two digits in this case.
li t1, -4
mul t1, t0, t1
addi t1, t1, 60
li t2, 10
div t3, t1, t2
rem t4, t1, t2
addi t3, t3, '0'
addi t4, t4, '0'
sw t3, 8(sp)
sw t4, 4(sp)
addi a0, sp, 8
li a1, 1
call _write_out
addi a0, sp, 4
li a1, 1
call _write_out
li a0, -4
mul a0, t0, a0
addi a0, a0, 60
call _printi
li t0, '\n'
sw t0, 8(sp)
@@ -511,52 +535,14 @@ _compile_call:
.Lcompile_call_restore:
# Just go through all a0-a5 registers and read them from stack.
# If this stack value contains garbage, the procedure just shouldn't use it.
lw t0, 12(sp)
li t1, 5
bgt t0, t1, .Lcompile_call_perform
li t0, 0x6120776c # lw a
sw t0, 4(sp)
addi a0, sp, 4
li a1, 4
la a0, asm_restore_parameters
li a1, ASM_RESTORE_PARAMETERS_SIZE
call _write_out
lw t0, 12(sp) # Argument count for a procedure call.
li t1, -4
mul t1, t0, t1
addi t1, t1, 60
li t2, 10
div t3, t1, t2
rem t4, t1, t2
addi t3, t3, '0'
addi t4, t4, '0'
addi t0, t0, '0'
li t5, '\n'
sb t5, 11(sp)
li t5, 0x29707328 # (sp)
sw t5, 7(sp)
sb t4, 6(sp)
sb t3, 5(sp)
li t5, 0x202c # ,_
sh t5, 3(sp)
sb t0, 2(sp)
addi a0, sp, 2
li a1, 10
call _write_out
lw t0, 12(sp) # Increment.
addi t0, t0, 1
sw t0, 12(sp)
j .Lcompile_call_restore
.Lcompile_call_perform:
li t0, 0x20
sw t0, 8(sp)
li t0, 0x6c6c6163
li t0, 0x6c6c6163 # call
sw t0, 4(sp)
addi a0, sp, 4
li a1, 5
@@ -566,11 +552,8 @@ _compile_call:
lw a1, 16(sp)
call _write_out
li t0, '\n'
sw t0, 8(sp)
addi a0, sp, 8
li a1, 1
call _write_out
li a0, '\n'
call _put_char
call _skip_spaces
addi s1, s1, 1 # Skip the close paren.
@@ -633,6 +616,9 @@ _read_token:
li t1, '-'
beq t0, t1, .Ltoken_character_single
li t1, '*'
beq t0, t1, .Ltoken_character_single
li t1, '@'
beq t0, t1, .Ltoken_character_single
# Expect an identifier or a number.
@@ -1325,6 +1311,97 @@ _compile_return:
addi sp, sp, 16
ret
.type _compile_if, @function
_compile_if:
# Prologue.
addi sp, sp, -32
sw ra, 28(sp)
sw s0, 24(sp)
addi s0, sp, 32
addi s1, s1, 2 # Skip the if.
call _skip_spaces
call _build_binary_expression
call _skip_spaces
addi s1, s1, 4 # Skip the then.
# if end marker.
li t0, 0x00646e65 # end\0
sw t0, 20(sp)
# Label prefix.
li t0, 0x66694c2e # .Lif
sw t0, 16(sp)
li t0, 0x202c3061 # a0,_
sw t0, 12(sp)
li t0, 0x207a7165 # eqz_
sw t0, 8(sp)
li t0, 0x62626262 # bbbb
sb t0, 7(sp)
addi a0, sp, 7
li a1, 13
call _write_out
# Write the label counter.
mv a0, s2
call _printi
li a0, '\n'
call _put_char
.Lcompile_if_loop:
/* DEBUG
mv a0, s1
li a1, 6
call _write_error
call _divide_by_zero_error */
call _skip_spaces
call _read_token
mv a1, a0
mv a0, s1
addi a2, sp, 20
call _token_compare
beqz a0, .Lcompile_if_end
call _read_line
li a1, 1
call _compile_line
j .Lcompile_if_loop
.Lcompile_if_end:
# Write the label prefix.
addi a0, sp, 16
li a1, 4
call _write_out
# Write the label counter.
mv a0, s2
call _printi
# Finalize the label.
li t0, 0x0a3a0a3a # :\n:\n
sh t0, 12(sp)
addi a0, sp, 12
li a1, 2
call _write_out
addi s2, s2, 1 # Increment the label counter.
addi s1, s1, 4 # Skip the end with newline.
# Epilogue.
lw ra, 28(sp)
lw s0, 24(sp)
addi sp, sp, 32
ret
# Parameters:
# a0 - Line length.
# a1 - Whether the section header was already emitted. If not it should be
@@ -1442,6 +1519,14 @@ _compile_line:
call _memcmp
beqz a0, .Lcompile_line_return
li t0, 0x6669 # if
sw t0, 12(sp)
mv a0, s1
addi a1, sp, 12
li a2, 2
call _memcmp
beqz a0, .Lcompile_line_if
lbu t0, (s1)
li t1, '.'
beq t0, t1, .Lcompile_line_label
@@ -1450,16 +1535,16 @@ _compile_line:
j .Lcompile_line_unchanged # Else.
.Lcompile_line_if:
call _compile_if
j .Lcompile_line_section
.Lcompile_line_label:
lw a0, 20(sp)
call _compile_label
j .Lcompile_line_section
.Lcompile_line_return:
/* DEBUG
mv a0, s1
li a1, 6
call _write_error */
call _compile_return
j .Lcompile_line_section
@@ -1659,9 +1744,10 @@ _start:
li a1, SOURCE_BUFFER_SIZE # Buffer size.
call _read_file
li s2, 1
la s1, source_code # s1 = Source code position.
call _compile
# Call exit.
li a0, 0 # Use 0 return code.
call exit
call _exit