Implement if statements
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,2 +1,3 @@
 | 
			
		||||
/build/
 | 
			
		||||
a.out
 | 
			
		||||
/vendor/
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								Gemfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Gemfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
source 'https://rubygems.org'
 | 
			
		||||
 | 
			
		||||
gem 'term-ansicolor', '~> 1.2'
 | 
			
		||||
gem 'rake', '~> 13.2'
 | 
			
		||||
							
								
								
									
										22
									
								
								Gemfile.lock
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								Gemfile.lock
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
GEM
 | 
			
		||||
  remote: https://rubygems.org/
 | 
			
		||||
  specs:
 | 
			
		||||
    bigdecimal (3.1.9)
 | 
			
		||||
    rake (13.2.1)
 | 
			
		||||
    sync (0.5.0)
 | 
			
		||||
    term-ansicolor (1.11.2)
 | 
			
		||||
      tins (~> 1.0)
 | 
			
		||||
    tins (1.38.0)
 | 
			
		||||
      bigdecimal
 | 
			
		||||
      sync
 | 
			
		||||
 | 
			
		||||
PLATFORMS
 | 
			
		||||
  ruby
 | 
			
		||||
  x86_64-linux
 | 
			
		||||
 | 
			
		||||
DEPENDENCIES
 | 
			
		||||
  rake (~> 13.2)
 | 
			
		||||
  term-ansicolor (~> 1.2)
 | 
			
		||||
 | 
			
		||||
BUNDLED WITH
 | 
			
		||||
   2.6.7
 | 
			
		||||
							
								
								
									
										10
									
								
								Rakefile
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								Rakefile
									
									
									
									
									
								
							@@ -1,5 +1,8 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'open3'
 | 
			
		||||
require 'rake/clean'
 | 
			
		||||
require 'term/ansicolor'
 | 
			
		||||
 | 
			
		||||
CLOBBER.include 'build'
 | 
			
		||||
 | 
			
		||||
@@ -10,7 +13,7 @@ QEMU = 'qemu-riscv32'
 | 
			
		||||
def assemble_stage(output, compiler, source)
 | 
			
		||||
  arguments = [QEMU, '-L', SYSROOT, *compiler]
 | 
			
		||||
 | 
			
		||||
  puts(arguments * ' ')
 | 
			
		||||
  puts Term::ANSIColor.green(arguments * ' ')
 | 
			
		||||
  puts
 | 
			
		||||
  Open3.popen2(*arguments) do |qemu_in, qemu_out|
 | 
			
		||||
    qemu_in.write File.read(*source)
 | 
			
		||||
@@ -27,7 +30,7 @@ task default: ['build/stage2b', 'build/stage2b.s', 'boot/stage2.elna'] do |t|
 | 
			
		||||
 | 
			
		||||
  cat_arguments = ['cat', source]
 | 
			
		||||
  compiler_arguments = [QEMU, '-L', SYSROOT, exe]
 | 
			
		||||
  diff_arguments = ['diff', '-Nur', previous_output, '-']
 | 
			
		||||
  diff_arguments = ['diff', '-Nur', '--text', previous_output, '-']
 | 
			
		||||
  Open3.pipeline(cat_arguments, compiler_arguments, diff_arguments)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@@ -70,7 +73,8 @@ task :statistics do
 | 
			
		||||
    word.start_with?('(*') ||
 | 
			
		||||
      word.start_with?('*)') ||
 | 
			
		||||
      ('A'..'Z').include?(word[0]) ||
 | 
			
		||||
      /^[[:alpha:]][[:digit:]]$/.match(word)
 | 
			
		||||
      /^[[:alpha:]][[:digit:]]$/.match(word) ||
 | 
			
		||||
      ['end', 'if'].include?(word)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  lines = File.read('boot/stage2.elna')
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
.global _is_alpha, _is_digit, _is_alnum, _is_upper, _is_lower
 | 
			
		||||
.global _write_out, _read_file, exit, _memcmp, _write_error, _put_char
 | 
			
		||||
.global _write_out, _read_file, _memcmp, _write_error, _put_char, _printi
 | 
			
		||||
.global _divide_by_zero_error, _exit
 | 
			
		||||
 | 
			
		||||
.section .rodata
 | 
			
		||||
 | 
			
		||||
@@ -119,6 +120,13 @@ _is_alpha:
 | 
			
		||||
	addi sp, sp, 16
 | 
			
		||||
	ret
 | 
			
		||||
 | 
			
		||||
# 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.
 | 
			
		||||
.type _is_digit, @function
 | 
			
		||||
_is_digit:
 | 
			
		||||
	li t0, '0' - 1
 | 
			
		||||
@@ -201,10 +209,68 @@ _read_file:
 | 
			
		||||
	ret
 | 
			
		||||
 | 
			
		||||
# Terminates the program. a0 contains the return code.
 | 
			
		||||
#
 | 
			
		||||
# Parameters:
 | 
			
		||||
# a0 - Status code.
 | 
			
		||||
.type _exit, @function
 | 
			
		||||
exit:
 | 
			
		||||
_exit:
 | 
			
		||||
	li a7, SYS_EXIT
 | 
			
		||||
	ecall
 | 
			
		||||
	# ret
 | 
			
		||||
 | 
			
		||||
.type _divide_by_zero_error, @function
 | 
			
		||||
_divide_by_zero_error:
 | 
			
		||||
    addi a7, zero, 172 # getpid
 | 
			
		||||
    ecall
 | 
			
		||||
 | 
			
		||||
    addi a1, zero, 8 # SIGFPE
 | 
			
		||||
    addi a7, zero, 129 # kill
 | 
			
		||||
    ecall
 | 
			
		||||
    ret
 | 
			
		||||
 | 
			
		||||
# a0 - Whole number.
 | 
			
		||||
# t1 - Constant 10.
 | 
			
		||||
# a1 - Local buffer.
 | 
			
		||||
# t2 - Current character.
 | 
			
		||||
# t3 - Whether the number is negative.
 | 
			
		||||
.type printi, @function
 | 
			
		||||
_printi:
 | 
			
		||||
    addi sp, sp, -16
 | 
			
		||||
    sw s0, 0(sp)
 | 
			
		||||
    sw ra, 4(sp)
 | 
			
		||||
    addi s0, sp, 16
 | 
			
		||||
    addi t1, zero, 10
 | 
			
		||||
    addi a1, s0, -1
 | 
			
		||||
 | 
			
		||||
    addi t3, zero, 0
 | 
			
		||||
    bge a0, zero, .digit10
 | 
			
		||||
    addi t3, zero, 1
 | 
			
		||||
    sub a0, zero, a0
 | 
			
		||||
 | 
			
		||||
.digit10:
 | 
			
		||||
    rem t2, a0, t1
 | 
			
		||||
    addi t2, t2, '0'
 | 
			
		||||
    sb t2, 0(a1)
 | 
			
		||||
    div a0, a0, t1
 | 
			
		||||
    addi a1, a1, -1
 | 
			
		||||
    bne zero, a0, .digit10
 | 
			
		||||
 | 
			
		||||
    beq zero, t3, .write_call
 | 
			
		||||
    addi t2, zero, '-'
 | 
			
		||||
    sb t2, 0(a1)
 | 
			
		||||
    addi a1, a1, -1
 | 
			
		||||
 | 
			
		||||
.write_call:
 | 
			
		||||
    addi a0, zero, 1
 | 
			
		||||
    addi a1, a1, 1
 | 
			
		||||
    sub a2, s0, a1
 | 
			
		||||
    addi a7, zero, 64 # write
 | 
			
		||||
    ecall
 | 
			
		||||
 | 
			
		||||
    lw s0, 0(sp)
 | 
			
		||||
    lw ra, 4(sp)
 | 
			
		||||
    addi sp, sp, 16
 | 
			
		||||
    ret
 | 
			
		||||
 | 
			
		||||
# Writes a character from a0 into the standard output.
 | 
			
		||||
.type _put_char, @function
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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