Implement if statements
This commit is contained in:
240
boot/stage1.s
240
boot/stage1.s
@@ -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
|
||||
|
Reference in New Issue
Block a user