Implement if statements
This commit is contained in:
340
boot/stage2.elna
340
boot/stage2.elna
@@ -14,6 +14,9 @@ type checking.
|
||||
hexadecimal format).
|
||||
|
||||
- Comments are accepted only at the end of a line.
|
||||
|
||||
- Return can be used only as the last statement of a procedure. It
|
||||
doesn't actually return, but sets a0 to the appropriate value.
|
||||
*)
|
||||
program
|
||||
|
||||
@@ -36,7 +39,7 @@ begin
|
||||
end
|
||||
|
||||
proc _build_binary_expression()
|
||||
var loca0, loca4, loca8: Word
|
||||
var loca0, loca4, loca8, loca20: Word
|
||||
begin
|
||||
_build_expression(0)
|
||||
|
||||
@@ -44,8 +47,7 @@ begin
|
||||
loca8 := 0x0a316120 (* _a1\n *)
|
||||
|
||||
_skip_spaces()
|
||||
call _read_token
|
||||
sw a0, 20(sp)
|
||||
loca20 := _read_token()
|
||||
|
||||
li t0, 0x26 # &
|
||||
sw t0, 16(sp)
|
||||
@@ -87,6 +89,14 @@ begin
|
||||
call _token_compare
|
||||
beqz a0, .L_build_binary_expression_minus
|
||||
|
||||
li t0, 0x2a # *
|
||||
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
|
||||
|
||||
goto .Lbuild_binary_expression_end
|
||||
|
||||
.L_build_binary_expression_equal
|
||||
@@ -146,6 +156,19 @@ begin
|
||||
_write_out(@loca4, 4)
|
||||
_write_out(@loca8, 4)
|
||||
|
||||
goto .Lbuild_binary_expression_end
|
||||
|
||||
.L_build_binary_expression_product
|
||||
_advance(1) (* Skip *. *)
|
||||
_build_expression(1)
|
||||
loca0 := 0x6c756d (* mul *)
|
||||
_write_out(@loca0, 3)
|
||||
_write_out(@loca4, 4)
|
||||
_write_out(@loca4, 4)
|
||||
_write_out(@loca8, 4)
|
||||
|
||||
goto .Lbuild_binary_expression_end
|
||||
|
||||
.Lbuild_binary_expression_end
|
||||
end
|
||||
|
||||
@@ -156,28 +179,30 @@ a0 - X in aX, the register number to save the result.
|
||||
*)
|
||||
proc _build_expression()
|
||||
var
|
||||
loca20, loca28, loca8: Word
|
||||
loca24: ^Byte
|
||||
loca0, loca20, loca28, loca8: Word
|
||||
loca24, loca4: ^Byte
|
||||
begin
|
||||
addi a0, a0, '0' # Make the register number to a character.
|
||||
sw a0, 28(sp) # And save it.
|
||||
(* Make the register number to a character and save it. *)
|
||||
loca28 := loca84 + 0x30 (* 0 *)
|
||||
|
||||
_skip_spaces()
|
||||
loca20 := _read_token()
|
||||
loca24 := _current()
|
||||
|
||||
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)
|
||||
call _is_digit
|
||||
bnez a0, .Lbuild_expression_literal
|
||||
loca0 := _front()
|
||||
if _is_digit(loca0) then
|
||||
goto .Lbuild_expression_literal
|
||||
end
|
||||
|
||||
addi a0, s1, 0
|
||||
lbu a0, (a0)
|
||||
lbu a0, (s1)
|
||||
li t0, '_'
|
||||
beq a0, t0, .Lbuild_expression_call
|
||||
|
||||
@@ -200,6 +225,19 @@ begin
|
||||
|
||||
goto .Lbuild_expression_advance
|
||||
|
||||
.Lbuild_expression_negate
|
||||
_advance(1) (* Skip the -. *)
|
||||
_build_expression(0)
|
||||
|
||||
loca8 := 0x2067656e (* neg_ *)
|
||||
_write_out(@loca8, 4)
|
||||
loca8 := 0x202c3061 (* a0,_ *)
|
||||
_write_out(@loca8, 4)
|
||||
loca8 := 0x0a3061 (* a0,_ *)
|
||||
_write_out(@loca8, 3)
|
||||
|
||||
goto .Lbuild_expression_advance
|
||||
|
||||
.Lbuild_expression_address
|
||||
loca8 := 0x69646461 (* addi *)
|
||||
_write_out(@loca8, 4)
|
||||
@@ -216,40 +254,28 @@ begin
|
||||
loca24 := _current()
|
||||
loca20 := _read_token()
|
||||
|
||||
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
|
||||
(* Skip the "loca" variable prefix. *)
|
||||
loca4 := loca24 + 4
|
||||
loca0 := loca20 - 4
|
||||
_write_out(loca4, loca0)
|
||||
|
||||
_put_char(0xa)
|
||||
|
||||
goto .Lbuild_expression_advance
|
||||
|
||||
.Lbuild_expression_identifier
|
||||
lw t1, 28(sp)
|
||||
li t0, 0x00202c00 # \0,_
|
||||
or t0, t0, t1
|
||||
sw t0, 8(sp)
|
||||
li t0, 0x6120776c # lw a
|
||||
sw t0, 4(sp)
|
||||
addi a0, sp, 4
|
||||
li a1, 7
|
||||
call _write_out
|
||||
loca8 := 0x6120776c (* lw a *)
|
||||
_write_out(@loca8, 4)
|
||||
loca8 := 0x00202c00 or loca28 # \0,_
|
||||
_write_out(@loca8, 3)
|
||||
|
||||
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
|
||||
loca4 := loca24 + 4
|
||||
loca0 := loca20 - 4
|
||||
_write_out(loca4, loca0) (* Skip the "loca" variable prefix. *)
|
||||
|
||||
li t0, 0x0a # \n
|
||||
sw t0, 8(sp)
|
||||
li t0, 0x29707328 # (sp)
|
||||
sw t0, 4(sp)
|
||||
addi a0, sp, 4
|
||||
li a1, 5
|
||||
call _write_out
|
||||
loca8 := 0x29707328 (* (sp) *)
|
||||
_write_out(@loca8, 4)
|
||||
_put_char(0x0a) (* \n *)
|
||||
|
||||
goto .Lbuild_expression_advance
|
||||
|
||||
@@ -261,18 +287,13 @@ begin
|
||||
goto .Lbuild_expression_end
|
||||
|
||||
.Lbuild_expression_literal
|
||||
lw t1, 28(sp)
|
||||
li t0, 0x00202c00 # \0,_
|
||||
or t0, t0, t1
|
||||
sw t0, 8(sp)
|
||||
li t0, 0x6120696c # li a
|
||||
sw t0, 4(sp)
|
||||
addi a0, sp, 4
|
||||
li a1, 7
|
||||
call _write_out
|
||||
loca8 := 0x6120696c (* li a *)
|
||||
_write_out(@loca8, 4)
|
||||
loca8 := 0x00202c00 or loca28 (* \0,_ *)
|
||||
_write_out(@loca8, 3)
|
||||
|
||||
_write_out(loca24, loca20)
|
||||
_put_char(0x0a) # \n
|
||||
_put_char(0x0a) (* \n *)
|
||||
|
||||
goto .Lbuild_expression_advance
|
||||
|
||||
@@ -335,11 +356,9 @@ begin
|
||||
loca0 := 0x202c30 (* 0,_ *)
|
||||
_write_out(@loca0, 3)
|
||||
|
||||
lw a0, 20(sp)
|
||||
lw a1, 16(sp)
|
||||
addi a0, a0, 4 # Skip the "loca" variable prefix.
|
||||
addi a1, a1, -4 # Skip the "loca" variable prefix.
|
||||
call _write_out
|
||||
loca20 := loca20 + 4
|
||||
loca16 := loca16 - 4
|
||||
_write_out(loca20, loca16)
|
||||
|
||||
loca0 := 0x29707328 (* (sp) *)
|
||||
_write_out(@loca0, 4)
|
||||
@@ -359,7 +378,7 @@ Returns the procedure result in a0.
|
||||
*)
|
||||
proc _compile_call(loca84: ^Byte, loca80: Word)
|
||||
var
|
||||
loca0, loca12: Word
|
||||
loca0, loca4, loca12: Word
|
||||
begin
|
||||
loca12 := 0 (* Argument count for a procedure call. *)
|
||||
|
||||
@@ -377,49 +396,24 @@ begin
|
||||
loca0 := 0x202c30 (* 0,_ *)
|
||||
_write_out(@loca0, 3)
|
||||
|
||||
lw t0, 12(sp) # Argument count for a procedure 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'
|
||||
loca0 := -4 * loca12
|
||||
loca0 := loca0 + 60
|
||||
_printi(loca0)
|
||||
|
||||
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 t0, 0x0a # \n
|
||||
sw t0, 8(sp)
|
||||
li t0, 0x29707328 # (sp)
|
||||
sw t0, 4(sp)
|
||||
addi a0, sp, 4
|
||||
li a1, 5
|
||||
call _write_out
|
||||
loca0 := 0x29707328 (* (sp) *)
|
||||
_write_out(@loca0, 4)
|
||||
_put_char(0x0a) (* \n *)
|
||||
|
||||
_skip_spaces()
|
||||
lbu t0, (s1)
|
||||
li t1, ','
|
||||
bne t0, t1, .Lcompile_call_paren
|
||||
|
||||
lw t0, 12(sp) # Argument count for a procedure call.
|
||||
addi t0, t0, 1
|
||||
sw t0, 12(sp)
|
||||
loca12 := loca12 + 1 (* Argument count for a procedure call. *)
|
||||
|
||||
_advance(1) (* Skip the comma between the arguments. *)
|
||||
goto .Lcompile_call_argument
|
||||
@@ -432,47 +426,62 @@ begin
|
||||
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
|
||||
loca0 := 0x6120776c (* lw a *)
|
||||
(* lw a0, 60(sp) *)
|
||||
_write_out(@loca0, 4)
|
||||
loca4 := 0x36202c30 (* 0, 6 *)
|
||||
_write_out(@loca4, 4)
|
||||
loca4 := 0x70732830 (* 0(sp *)
|
||||
_write_out(@loca4, 4)
|
||||
loca4 := 0x0a29 (* )\n *)
|
||||
_write_out(@loca4, 2)
|
||||
|
||||
li t0, 0x6120776c # lw a
|
||||
sw t0, 4(sp)
|
||||
addi a0, sp, 4
|
||||
li a1, 4
|
||||
call _write_out
|
||||
(* lw a1, 56(sp) *)
|
||||
_write_out(@loca0, 4)
|
||||
loca4 := 0x35202c31 (* 1, 5 *)
|
||||
_write_out(@loca4, 4)
|
||||
loca4 := 0x70732836 (* 6(sp *)
|
||||
_write_out(@loca4, 4)
|
||||
loca4 := 0x0a29 (* )\n *)
|
||||
_write_out(@loca4, 2)
|
||||
|
||||
lw t0, 12(sp) # Argument count for a procedure call.
|
||||
(* lw a2, 52(sp) *)
|
||||
_write_out(@loca0, 4)
|
||||
loca4 := 0x35202c32 (* 2, 5 *)
|
||||
_write_out(@loca4, 4)
|
||||
loca4 := 0x70732832 (* 2(sp *)
|
||||
_write_out(@loca4, 4)
|
||||
loca4 := 0x0a29 (* )\n *)
|
||||
_write_out(@loca4, 2)
|
||||
|
||||
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'
|
||||
(* lw a3, 48(sp) *)
|
||||
_write_out(@loca0, 4)
|
||||
loca4 := 0x34202c33 (* 3, 4 *)
|
||||
_write_out(@loca4, 4)
|
||||
loca4 := 0x70732838 (* 8(sp *)
|
||||
_write_out(@loca4, 4)
|
||||
loca4 := 0x0a29 (* )\n *)
|
||||
_write_out(@loca4, 2)
|
||||
|
||||
li t5, 0x0a # \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)
|
||||
(* lw a4, 44(sp) *)
|
||||
_write_out(@loca0, 4)
|
||||
loca4 := 0x34202c34 (* 4, 4 *)
|
||||
_write_out(@loca4, 4)
|
||||
loca4 := 0x70732834 (* 4(sp *)
|
||||
_write_out(@loca4, 4)
|
||||
loca4 := 0x0a29 (* )\n *)
|
||||
_write_out(@loca4, 2)
|
||||
|
||||
addi a0, sp, 2
|
||||
li a1, 10
|
||||
call _write_out
|
||||
(* lw a5, 40(sp) *)
|
||||
_write_out(@loca0, 4)
|
||||
loca4 := 0x34202c35 (* 5, 4 *)
|
||||
_write_out(@loca4, 4)
|
||||
loca4 := 0x70732830 (* 0(sp *)
|
||||
_write_out(@loca4, 4)
|
||||
loca4 := 0x0a29 (* )\n *)
|
||||
_write_out(@loca4, 2)
|
||||
|
||||
loca12 := loca12 + 1
|
||||
goto .Lcompile_call_restore
|
||||
|
||||
.Lcompile_call_perform
|
||||
loca0 := 0x6c6c6163
|
||||
loca0 := 0x6c6c6163 (* call *)
|
||||
_write_out(@loca0, 4)
|
||||
_put_char(0x20) (* _ *)
|
||||
|
||||
@@ -532,6 +541,9 @@ begin
|
||||
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. *)
|
||||
@@ -1125,6 +1137,61 @@ begin
|
||||
_build_binary_expression()
|
||||
end
|
||||
|
||||
proc _compile_if()
|
||||
var
|
||||
loca8, loca12, loca16, loca20: Word
|
||||
loca4: ^Byte
|
||||
begin
|
||||
_advance(2) (* Skip the if. *)
|
||||
_skip_spaces()
|
||||
|
||||
_build_binary_expression()
|
||||
|
||||
_skip_spaces()
|
||||
_advance(4) (* Skip the then. *)
|
||||
|
||||
loca20 := 0x00646e65 (* if end marker and newline. *)
|
||||
loca16 := 0x66694c2e (* Label prefix ".Lif". *)
|
||||
|
||||
loca12 := 0x7a716562 (* beqz *)
|
||||
_write_out(@loca12, 4)
|
||||
loca12 := 0x2c306120 (* _a0, *)
|
||||
_write_out(@loca12, 4)
|
||||
_put_char(0x20) (* _ *)
|
||||
|
||||
(* Write the label *)
|
||||
_write_out(@loca16, 4)
|
||||
mv a0, s2
|
||||
call _printi
|
||||
|
||||
_put_char(0x0a) (* \n *)
|
||||
|
||||
.Lcompile_if_loop
|
||||
_skip_spaces()
|
||||
loca12 := _read_token()
|
||||
|
||||
loca4 := _current()
|
||||
loca8 := _token_compare(loca4, loca12, @loca20)
|
||||
|
||||
if loca8 then
|
||||
loca12 := _read_line()
|
||||
_compile_line(loca12, 1)
|
||||
|
||||
goto .Lcompile_if_loop
|
||||
end
|
||||
|
||||
(* Write the label *)
|
||||
_write_out(@loca16, 4)
|
||||
mv a0, s2
|
||||
call _printi
|
||||
|
||||
loca12 := 0x0a3a0a3a (* :\n:\n *)
|
||||
_write_out(@loca12, 2)
|
||||
|
||||
addi s2, s2, 1 # Increment the label counter.
|
||||
_advance(4) (* Skip the end with newline. *)
|
||||
end
|
||||
|
||||
(*
|
||||
Parameters:
|
||||
a0 - Line length.
|
||||
@@ -1234,6 +1301,14 @@ begin
|
||||
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
|
||||
@@ -1242,6 +1317,10 @@ begin
|
||||
|
||||
goto .Lcompile_line_unchanged (* Else. *)
|
||||
|
||||
.Lcompile_line_if:
|
||||
_compile_if()
|
||||
goto .Lcompile_line_section
|
||||
|
||||
.Lcompile_line_label
|
||||
_compile_label(loca84)
|
||||
goto .Lcompile_line_section
|
||||
@@ -1409,7 +1488,9 @@ begin
|
||||
end
|
||||
|
||||
proc _compile()
|
||||
var loca0, loca4: Word
|
||||
var
|
||||
loca0, loca4: Word
|
||||
loca8: Bool
|
||||
begin
|
||||
loca4 := 0 (* Whether the text section header was already emitted. *)
|
||||
|
||||
@@ -1419,15 +1500,11 @@ begin
|
||||
|
||||
_skip_indentation()
|
||||
loca0 := _read_line()
|
||||
lw a0, 0(sp)
|
||||
lw a1, 4(sp)
|
||||
call _compile_line
|
||||
loca8 := _compile_line(loca0, loca4)
|
||||
|
||||
beqz a0, .Lcompile_do
|
||||
(* Update whether the text section header was already emitted. *)
|
||||
lw t0, 4(sp)
|
||||
or t0, t0, a0
|
||||
sw t0, 4(sp)
|
||||
loca4 := loca4 or loca8
|
||||
|
||||
goto .Lcompile_do
|
||||
.Lcompile_end
|
||||
@@ -1460,5 +1537,6 @@ begin
|
||||
call _read_file
|
||||
|
||||
la s1, source_code # s1 = Source code position.
|
||||
li s2, 1
|
||||
_compile()
|
||||
end.
|
||||
|
Reference in New Issue
Block a user