Implement arithmetic negation
This commit is contained in:
		
							
								
								
									
										9
									
								
								Rakefile
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								Rakefile
									
									
									
									
									
								
							| @@ -6,7 +6,6 @@ | |||||||
| require 'open3' | require 'open3' | ||||||
| require 'rake/clean' | require 'rake/clean' | ||||||
|  |  | ||||||
| CROSS_GCC = '../eugenios/build/rootfs/bin/riscv32-unknown-linux-gnu-gcc' |  | ||||||
| SYSROOT = '../eugenios/build/sysroot' | SYSROOT = '../eugenios/build/sysroot' | ||||||
| QEMU = 'qemu-riscv32' | QEMU = 'qemu-riscv32' | ||||||
| STAGES = Dir.glob('boot/stage*.elna').collect { |stage| File.basename stage, '.elna' }.sort | STAGES = Dir.glob('boot/stage*.elna').collect { |stage| File.basename stage, '.elna' }.sort | ||||||
| @@ -16,6 +15,10 @@ CLEAN.include 'build/boot', 'build/valid' | |||||||
| directory 'build/boot' | directory 'build/boot' | ||||||
| directory 'build/valid' | directory 'build/valid' | ||||||
|  |  | ||||||
|  | def compile(input, output) | ||||||
|  |   sh ENV.fetch('CC', 'gcc'), '-nostdlib', '-o', output, input | ||||||
|  | end | ||||||
|  |  | ||||||
| task default: :boot | task default: :boot | ||||||
|  |  | ||||||
| desc 'Final stage' | desc 'Final stage' | ||||||
| @@ -47,7 +50,7 @@ end | |||||||
| rule /^build\/[[:alpha:]]+\/stage[[:digit:]]+$/ => ->(match) { | rule /^build\/[[:alpha:]]+\/stage[[:digit:]]+$/ => ->(match) { | ||||||
|   "#{match}.s" |   "#{match}.s" | ||||||
| } do |t| | } do |t| | ||||||
|   sh CROSS_GCC, '-nostdlib', '-o', t.name, *t.prerequisites |   compile(*t.prerequisites, t.name) | ||||||
| end | end | ||||||
|  |  | ||||||
| STAGES.each do |stage| | STAGES.each do |stage| | ||||||
| @@ -91,5 +94,5 @@ end | |||||||
| file 'build/boot/stage1' => ['build/boot', 'boot/stage1.s'] do |t| | file 'build/boot/stage1' => ['build/boot', 'boot/stage1.s'] do |t| | ||||||
|   source = t.prerequisites.select { |prerequisite| prerequisite.end_with? '.s' } |   source = t.prerequisites.select { |prerequisite| prerequisite.end_with? '.s' } | ||||||
|  |  | ||||||
|   sh CROSS_GCC, '-nostdlib', '-o', t.name, *source |   compile(*source, t.name) | ||||||
| end | end | ||||||
|   | |||||||
							
								
								
									
										174
									
								
								boot/stage5.elna
									
									
									
									
									
								
							
							
						
						
									
										174
									
								
								boot/stage5.elna
									
									
									
									
									
								
							| @@ -4,11 +4,11 @@ | |||||||
|  |  | ||||||
| # Stage4 compiler. | # Stage4 compiler. | ||||||
| # | # | ||||||
| # - Taking value of local and global variables. Variables that doesn't begin | # - Stack size increased to 128 bytes per procedure. | ||||||
| #   with "v" are considered global. | #   7 words on the stack, 92 - 120, are reversed for procedure arguments (caller side). | ||||||
| # - Simple variable assignment, e.g. v0 := 5 or v0 := global_variable; | #   7 words on the stack, 64 - 92, are reserved for procedure parameters (callee side). | ||||||
| #   7 words on the stack, 28 - 56, are reversed for procedure arguments (caller side). | #   The first parameter is in 88, the second in 84 and so forth. | ||||||
| # - Take address unary operation "@". | # - Unary negate operation, e.g. -5. | ||||||
|  |  | ||||||
| .section .rodata | .section .rodata | ||||||
|  |  | ||||||
| @@ -37,10 +37,10 @@ keyword_begin: .ascii "begin" | |||||||
| keyword_var: .ascii "var" | keyword_var: .ascii "var" | ||||||
|  |  | ||||||
| .type asm_prologue, @object | .type asm_prologue, @object | ||||||
| asm_prologue: .string "\taddi sp, sp, -64\n\tsw ra, 60(sp)\n\tsw s0, 56(sp)\n\taddi s0, sp, 64\n" | asm_prologue: .string "\taddi sp, sp, -128\n\tsw ra, 124(sp)\n\tsw s0, 120(sp)\n\taddi s0, sp, 128\n" | ||||||
|  |  | ||||||
| .type asm_epilogue, @object | .type asm_epilogue, @object | ||||||
| asm_epilogue: .string "\tlw ra, 60(sp)\n\tlw s0, 56(sp)\n\taddi sp, sp, 64\n\tret\n" | asm_epilogue: .string "\tlw ra, 124(sp)\n\tlw s0, 120(sp)\n\taddi sp, sp, 128\n\tret\n" | ||||||
|  |  | ||||||
| .type asm_type_directive, @object | .type asm_type_directive, @object | ||||||
| asm_type_directive: .string ".type " | asm_type_directive: .string ".type " | ||||||
| @@ -72,11 +72,8 @@ asm_sw: .string "\tsw " | |||||||
| .type asm_addi, @object | .type asm_addi, @object | ||||||
| asm_addi: .string "\taddi " | asm_addi: .string "\taddi " | ||||||
|  |  | ||||||
| .type asm_t0, @object | .type asm_neg, @object | ||||||
| asm_t0: .string "t0" | asm_neg: .string "\tneg " | ||||||
|  |  | ||||||
| .type asm_t1, @object |  | ||||||
| asm_t1: .string "t1" |  | ||||||
|  |  | ||||||
| .type asm_comma, @object | .type asm_comma, @object | ||||||
| asm_comma: .string ", " | asm_comma: .string ", " | ||||||
| @@ -486,7 +483,7 @@ end; | |||||||
| proc _compile_integer_literal(); | proc _compile_integer_literal(); | ||||||
| begin | begin | ||||||
| 	_write_z(@asm_li); | 	_write_z(@asm_li); | ||||||
| 	_write_z(@asm_t0); | 	_write_register('t', 0); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
| 	_read_token(); | 	_read_token(); | ||||||
| @@ -499,7 +496,7 @@ end; | |||||||
| proc _compile_character_literal(); | proc _compile_character_literal(); | ||||||
| begin | begin | ||||||
| 	_write_z(@asm_li); | 	_write_z(@asm_li); | ||||||
| 	_write_z(@asm_t0); | 	_write_register('t', 0); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
| 	_write_c('\''); | 	_write_c('\''); | ||||||
| @@ -532,11 +529,11 @@ begin | |||||||
| 	_compile_designator(); | 	_compile_designator(); | ||||||
|  |  | ||||||
| 	_write_z(@asm_lw); | 	_write_z(@asm_lw); | ||||||
| 	_write_z(@asm_t0); | 	_write_register('t', 0); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
| 	_write_c('('); | 	_write_c('('); | ||||||
| 	_write_z(@asm_t0); | 	_write_register('t', 0); | ||||||
|  |  | ||||||
| 	_write_c(')'); | 	_write_c(')'); | ||||||
| 	_write_c('\n'); | 	_write_c('\n'); | ||||||
| @@ -551,7 +548,23 @@ begin | |||||||
|  |  | ||||||
| end; | end; | ||||||
|  |  | ||||||
| proc _compile_expression(); | proc _compile_negate_expression(); | ||||||
|  | begin | ||||||
|  | 	# Skip the "-" sign. | ||||||
|  | 	_advance_token(1); | ||||||
|  | 	_compile_term(); | ||||||
|  |  | ||||||
|  | 	_write_z(@asm_neg); | ||||||
|  | 	_write_register('t', 0); | ||||||
|  |  | ||||||
|  | 	_write_z(@asm_comma); | ||||||
|  | 	_write_register('t', 0); | ||||||
|  |  | ||||||
|  | 	_write_c('\n'); | ||||||
|  |  | ||||||
|  | end; | ||||||
|  |  | ||||||
|  | proc _compile_term(); | ||||||
| begin | begin | ||||||
| 	la t0, source_code_position | 	la t0, source_code_position | ||||||
| 	lw t0, (t0) | 	lw t0, (t0) | ||||||
| @@ -559,33 +572,45 @@ begin | |||||||
| 	sw a0, 0(sp) | 	sw a0, 0(sp) | ||||||
|  |  | ||||||
| 	li t1, '\'' | 	li t1, '\'' | ||||||
| 	beq a0, t1, .compile_expression_character_literal | 	beq a0, t1, .compile_term_character_literal | ||||||
|  |  | ||||||
| 	li t1, '@' | 	li t1, '@' | ||||||
| 	beq a0, t1, .compile_expression_address | 	beq a0, t1, .compile_term_address | ||||||
|  |  | ||||||
|  | 	li t1, '-' | ||||||
|  | 	beq a0, t1, .compile_term_negation | ||||||
|  |  | ||||||
| 	_is_digit(v0); | 	_is_digit(v0); | ||||||
| 	bnez a0, .compile_expression_integer_literal | 	bnez a0, .compile_term_integer_literal | ||||||
|  |  | ||||||
| 	goto .compile_expression_variable; | 	goto .compile_term_variable; | ||||||
|  |  | ||||||
| .compile_expression_character_literal: | .compile_term_character_literal: | ||||||
| 	_compile_character_literal(); | 	_compile_character_literal(); | ||||||
| 	goto .compile_expression_end; | 	goto .compile_term_end; | ||||||
|  |  | ||||||
| .compile_expression_integer_literal: | .compile_term_integer_literal: | ||||||
| 	_compile_integer_literal(); | 	_compile_integer_literal(); | ||||||
| 	goto .compile_expression_end; | 	goto .compile_term_end; | ||||||
|  |  | ||||||
| .compile_expression_address: | .compile_term_address: | ||||||
| 	_compile_address_expression(); | 	_compile_address_expression(); | ||||||
| 	goto .compile_expression_end; | 	goto .compile_term_end; | ||||||
|  |  | ||||||
| .compile_expression_variable: | .compile_term_negation: | ||||||
|  | 	_compile_negate_expression(); | ||||||
|  | 	goto .compile_term_end; | ||||||
|  |  | ||||||
|  | .compile_term_variable: | ||||||
| 	_compile_variable_expression(); | 	_compile_variable_expression(); | ||||||
| 	goto .compile_expression_end; | 	goto .compile_term_end; | ||||||
|  |  | ||||||
| .compile_expression_end: | .compile_term_end: | ||||||
|  | end; | ||||||
|  |  | ||||||
|  | proc _compile_expression(); | ||||||
|  | begin | ||||||
|  | 	_compile_term(); | ||||||
| end; | end; | ||||||
|  |  | ||||||
| proc _compile_call(); | proc _compile_call(); | ||||||
| @@ -617,14 +642,14 @@ begin | |||||||
|  |  | ||||||
| 	# Save the argument on the stack. | 	# Save the argument on the stack. | ||||||
| 	_write_z(@asm_sw); | 	_write_z(@asm_sw); | ||||||
| 	_write_z(@asm_t0); | 	_write_register('t', 0); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
| 	# Calculate the stack offset: 52 - (4 * argument_counter) | 	# Calculate the stack offset: 116 - (4 * argument_counter) | ||||||
| 	lw t0, 8(sp) | 	lw t0, 8(sp) | ||||||
| 	li t1, 4 | 	li t1, 4 | ||||||
| 	mul t0, t0, t1 | 	mul t0, t0, t1 | ||||||
| 	li t1, 52 | 	li t1, 116 | ||||||
| 	sub a0, t1, t0 | 	sub a0, t1, t0 | ||||||
| 	_write_i(); | 	_write_i(); | ||||||
|  |  | ||||||
| @@ -668,11 +693,11 @@ begin | |||||||
|  |  | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
| 	# Calculate the stack offset: 52 - (4 * argument_counter) | 	# Calculate the stack offset: 116 - (4 * argument_counter) | ||||||
| 	lw t0, 8(sp) | 	lw t0, 8(sp) | ||||||
| 	li t1, 4 | 	li t1, 4 | ||||||
| 	mul t0, t0, t1 | 	mul t0, t0, t1 | ||||||
| 	li t1, 52 | 	li t1, 116 | ||||||
| 	sub a0, t1, t0 | 	sub a0, t1, t0 | ||||||
| 	_write_i(); | 	_write_i(); | ||||||
|  |  | ||||||
| @@ -712,7 +737,7 @@ begin | |||||||
| 	_advance_token(1); | 	_advance_token(1); | ||||||
|  |  | ||||||
| 	_write_z(@asm_addi); | 	_write_z(@asm_addi); | ||||||
| 	_write_z(@asm_t0); | 	_write_register('t', 0); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
| 	_write_z(@asm_sp); | 	_write_z(@asm_sp); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
| @@ -733,7 +758,7 @@ end; | |||||||
| proc _compile_global_designator(); | proc _compile_global_designator(); | ||||||
| begin | begin | ||||||
| 	_write_z(@asm_la); | 	_write_z(@asm_la); | ||||||
| 	_write_z(@asm_t0); | 	_write_register('t', 0); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
| 	_read_token(); | 	_read_token(); | ||||||
| @@ -772,7 +797,7 @@ begin | |||||||
|  |  | ||||||
| 	# Save the assignee address on the stack. | 	# Save the assignee address on the stack. | ||||||
| 	_write_z(@asm_sw); | 	_write_z(@asm_sw); | ||||||
| 	_write_z(@asm_t0); | 	_write_register('t', 0); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
| 	_write_i(20); | 	_write_i(20); | ||||||
| @@ -787,7 +812,7 @@ begin | |||||||
| 	_compile_expression(); | 	_compile_expression(); | ||||||
|  |  | ||||||
| 	_write_z(@asm_lw); | 	_write_z(@asm_lw); | ||||||
| 	_write_z(@asm_t1); | 	_write_register('t', 1); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
| 	_write_i(20); | 	_write_i(20); | ||||||
| @@ -797,11 +822,11 @@ begin | |||||||
| 	_write_c('\n'); | 	_write_c('\n'); | ||||||
|  |  | ||||||
| 	_write_z(@asm_sw); | 	_write_z(@asm_sw); | ||||||
| 	_write_z(@asm_t0); | 	_write_register('t', 0); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
| 	_write_c('('); | 	_write_c('('); | ||||||
| 	_write_z(@asm_t1); | 	_write_register('t', 1); | ||||||
| 	_write_c(')'); | 	_write_c(')'); | ||||||
| end; | end; | ||||||
|  |  | ||||||
| @@ -855,11 +880,8 @@ end; | |||||||
| proc _compile_procedure_body(); | proc _compile_procedure_body(); | ||||||
| begin | begin | ||||||
| .compile_procedure_body_loop: | .compile_procedure_body_loop: | ||||||
| 	la a0, source_code_position | 	# 3 is "end" length. | ||||||
| 	lw a0, (a0) | 	_memcmp(source_code_position, @keyword_end, 3); | ||||||
| 	la a1, keyword_end |  | ||||||
| 	li a2, 3 # "end" length. |  | ||||||
| 	_memcmp(); |  | ||||||
|  |  | ||||||
| 	beqz a0, .compile_procedure_body_epilogue | 	beqz a0, .compile_procedure_body_epilogue | ||||||
|  |  | ||||||
| @@ -869,6 +891,60 @@ begin | |||||||
| .compile_procedure_body_epilogue: | .compile_procedure_body_epilogue: | ||||||
| end; | end; | ||||||
|  |  | ||||||
|  | # Writes a regster name to the standard output. | ||||||
|  | # | ||||||
|  | # Parameters: | ||||||
|  | # a0 - Register character. | ||||||
|  | # a1 - Register number. | ||||||
|  | proc _write_register(); | ||||||
|  | begin | ||||||
|  | 	sw a0, 0(sp) | ||||||
|  | 	sw a1, 4(sp) | ||||||
|  |  | ||||||
|  | 	_write_c(); | ||||||
|  |  | ||||||
|  | 	lw a0, 4(sp) | ||||||
|  | 	li t0, '0' | ||||||
|  | 	add a0, a0, t0 | ||||||
|  | 	_write_c(); | ||||||
|  | end; | ||||||
|  |  | ||||||
|  | proc _compile_procedure_prologue(); | ||||||
|  | begin | ||||||
|  | 	_write_z(@asm_prologue); | ||||||
|  |  | ||||||
|  | 	v0 := 0; | ||||||
|  |  | ||||||
|  | .compile_procedure_prologue_loop: | ||||||
|  | 	_write_z(@asm_sw); | ||||||
|  |  | ||||||
|  | 	li a0, 'a' | ||||||
|  | 	lw a1, 0(sp) | ||||||
|  | 	_write_register(); | ||||||
|  |  | ||||||
|  | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
|  | 	# Calculate the stack offset: 88 - (4 * parameter_counter) | ||||||
|  | 	lw t0, 0(sp) | ||||||
|  | 	li t1, 4 | ||||||
|  | 	mul t0, t0, t1 | ||||||
|  | 	li t1, 88 | ||||||
|  | 	sub a0, t1, t0 | ||||||
|  | 	_write_i(); | ||||||
|  |  | ||||||
|  | 	_write_c('('); | ||||||
|  | 	_write_z(@asm_sp); | ||||||
|  | 	_write_c(')'); | ||||||
|  | 	_write_c('\n'); | ||||||
|  |  | ||||||
|  | 	lw a0, 0(sp) | ||||||
|  | 	addi a0, a0, 1 | ||||||
|  | 	sw a0, 0(sp) | ||||||
|  |  | ||||||
|  | 	li t0, 8 | ||||||
|  | 	bne a0, t0, .compile_procedure_prologue_loop | ||||||
|  | end; | ||||||
|  |  | ||||||
| proc _compile_procedure(); | proc _compile_procedure(); | ||||||
| begin | begin | ||||||
| 	# Skip "proc ". | 	# Skip "proc ". | ||||||
| @@ -883,8 +959,7 @@ begin | |||||||
|  |  | ||||||
| 	_write_token(v0); | 	_write_token(v0); | ||||||
|  |  | ||||||
| 	la a0, asm_type_function | 	_write_z(@asm_type_function); | ||||||
| 	_write_z(); |  | ||||||
|  |  | ||||||
| 	# Write procedure label, _procedure_name: | 	# Write procedure label, _procedure_name: | ||||||
| 	_write_token(v0); | 	_write_token(v0); | ||||||
| @@ -896,8 +971,7 @@ begin | |||||||
| 	addi a0, a0, 10 | 	addi a0, a0, 10 | ||||||
| 	_advance_token(); | 	_advance_token(); | ||||||
|  |  | ||||||
| 	_write_z(@asm_prologue); | 	_compile_procedure_prologue(); | ||||||
|  |  | ||||||
| 	_compile_procedure_body(); | 	_compile_procedure_body(); | ||||||
|  |  | ||||||
| 	# Write the epilogue. | 	# Write the epilogue. | ||||||
|   | |||||||
							
								
								
									
										173
									
								
								boot/stage6.elna
									
									
									
									
									
								
							
							
						
						
									
										173
									
								
								boot/stage6.elna
									
									
									
									
									
								
							| @@ -4,11 +4,10 @@ | |||||||
|  |  | ||||||
| # Stage4 compiler. | # Stage4 compiler. | ||||||
| # | # | ||||||
| # - Taking value of local and global variables. Variables that doesn't begin | # - Stack size increased to 128 per procedure. | ||||||
| #   with "v" are considered global. | #   7 words on the stack, 92 - 120, are reversed for procedure arguments (caller side). | ||||||
| # - Simple variable assignment, e.g. v0 := 5 or v0 := global_variable; | #   7 words on the stack, 64 - 92, are reserved for procedure parameters (callee side). | ||||||
| #   7 words on the stack, 28 - 56, are reversed for procedure arguments (caller side). | #   The first parameter is in 88, the second in 84 and so forth. | ||||||
| # - Take address unary operation "@". |  | ||||||
|  |  | ||||||
| .section .rodata | .section .rodata | ||||||
|  |  | ||||||
| @@ -37,10 +36,10 @@ keyword_begin: .ascii "begin" | |||||||
| keyword_var: .ascii "var" | keyword_var: .ascii "var" | ||||||
|  |  | ||||||
| .type asm_prologue, @object | .type asm_prologue, @object | ||||||
| asm_prologue: .string "\taddi sp, sp, -64\n\tsw ra, 60(sp)\n\tsw s0, 56(sp)\n\taddi s0, sp, 64\n" | asm_prologue: .string "\taddi sp, sp, -128\n\tsw ra, 124(sp)\n\tsw s0, 120(sp)\n\taddi s0, sp, 128\n" | ||||||
|  |  | ||||||
| .type asm_epilogue, @object | .type asm_epilogue, @object | ||||||
| asm_epilogue: .string "\tlw ra, 60(sp)\n\tlw s0, 56(sp)\n\taddi sp, sp, 64\n\tret\n" | asm_epilogue: .string "\tlw ra, 124(sp)\n\tlw s0, 120(sp)\n\taddi sp, sp, 128\n\tret\n" | ||||||
|  |  | ||||||
| .type asm_type_directive, @object | .type asm_type_directive, @object | ||||||
| asm_type_directive: .string ".type " | asm_type_directive: .string ".type " | ||||||
| @@ -72,11 +71,8 @@ asm_sw: .string "\tsw " | |||||||
| .type asm_addi, @object | .type asm_addi, @object | ||||||
| asm_addi: .string "\taddi " | asm_addi: .string "\taddi " | ||||||
|  |  | ||||||
| .type asm_t0, @object | .type asm_neg, @object | ||||||
| asm_t0: .string "t0" | asm_neg: .string "\tneg " | ||||||
|  |  | ||||||
| .type asm_t1, @object |  | ||||||
| asm_t1: .string "t1" |  | ||||||
|  |  | ||||||
| .type asm_comma, @object | .type asm_comma, @object | ||||||
| asm_comma: .string ", " | asm_comma: .string ", " | ||||||
| @@ -486,7 +482,7 @@ end; | |||||||
| proc _compile_integer_literal(); | proc _compile_integer_literal(); | ||||||
| begin | begin | ||||||
| 	_write_z(@asm_li); | 	_write_z(@asm_li); | ||||||
| 	_write_z(@asm_t0); | 	_write_register('t', 0); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
| 	_read_token(); | 	_read_token(); | ||||||
| @@ -499,7 +495,7 @@ end; | |||||||
| proc _compile_character_literal(); | proc _compile_character_literal(); | ||||||
| begin | begin | ||||||
| 	_write_z(@asm_li); | 	_write_z(@asm_li); | ||||||
| 	_write_z(@asm_t0); | 	_write_register('t', 0); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
| 	_write_c('\''); | 	_write_c('\''); | ||||||
| @@ -532,11 +528,11 @@ begin | |||||||
| 	_compile_designator(); | 	_compile_designator(); | ||||||
|  |  | ||||||
| 	_write_z(@asm_lw); | 	_write_z(@asm_lw); | ||||||
| 	_write_z(@asm_t0); | 	_write_register('t', 0); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
| 	_write_c('('); | 	_write_c('('); | ||||||
| 	_write_z(@asm_t0); | 	_write_register('t', 0); | ||||||
|  |  | ||||||
| 	_write_c(')'); | 	_write_c(')'); | ||||||
| 	_write_c('\n'); | 	_write_c('\n'); | ||||||
| @@ -551,7 +547,23 @@ begin | |||||||
|  |  | ||||||
| end; | end; | ||||||
|  |  | ||||||
| proc _compile_expression(); | proc _compile_negate_expression(); | ||||||
|  | begin | ||||||
|  | 	# Skip the "-" sign. | ||||||
|  | 	_advance_token(1); | ||||||
|  | 	_compile_term(); | ||||||
|  |  | ||||||
|  | 	_write_z(@asm_neg); | ||||||
|  | 	_write_register('t', 0); | ||||||
|  |  | ||||||
|  | 	_write_z(@asm_comma); | ||||||
|  | 	_write_register('t', 0); | ||||||
|  |  | ||||||
|  | 	_write_c('\n'); | ||||||
|  |  | ||||||
|  | end; | ||||||
|  |  | ||||||
|  | proc _compile_term(); | ||||||
| begin | begin | ||||||
| 	la t0, source_code_position | 	la t0, source_code_position | ||||||
| 	lw t0, (t0) | 	lw t0, (t0) | ||||||
| @@ -559,33 +571,45 @@ begin | |||||||
| 	sw a0, 0(sp) | 	sw a0, 0(sp) | ||||||
|  |  | ||||||
| 	li t1, '\'' | 	li t1, '\'' | ||||||
| 	beq a0, t1, .compile_expression_character_literal | 	beq a0, t1, .compile_term_character_literal | ||||||
|  |  | ||||||
| 	li t1, '@' | 	li t1, '@' | ||||||
| 	beq a0, t1, .compile_expression_address | 	beq a0, t1, .compile_term_address | ||||||
|  |  | ||||||
|  | 	li t1, '-' | ||||||
|  | 	beq a0, t1, .compile_term_negation | ||||||
|  |  | ||||||
| 	_is_digit(v0); | 	_is_digit(v0); | ||||||
| 	bnez a0, .compile_expression_integer_literal | 	bnez a0, .compile_term_integer_literal | ||||||
|  |  | ||||||
| 	goto .compile_expression_variable; | 	goto .compile_term_variable; | ||||||
|  |  | ||||||
| .compile_expression_character_literal: | .compile_term_character_literal: | ||||||
| 	_compile_character_literal(); | 	_compile_character_literal(); | ||||||
| 	goto .compile_expression_end; | 	goto .compile_term_end; | ||||||
|  |  | ||||||
| .compile_expression_integer_literal: | .compile_term_integer_literal: | ||||||
| 	_compile_integer_literal(); | 	_compile_integer_literal(); | ||||||
| 	goto .compile_expression_end; | 	goto .compile_term_end; | ||||||
|  |  | ||||||
| .compile_expression_address: | .compile_term_address: | ||||||
| 	_compile_address_expression(); | 	_compile_address_expression(); | ||||||
| 	goto .compile_expression_end; | 	goto .compile_term_end; | ||||||
|  |  | ||||||
| .compile_expression_variable: | .compile_term_negation: | ||||||
|  | 	_compile_negate_expression(); | ||||||
|  | 	goto .compile_term_end; | ||||||
|  |  | ||||||
|  | .compile_term_variable: | ||||||
| 	_compile_variable_expression(); | 	_compile_variable_expression(); | ||||||
| 	goto .compile_expression_end; | 	goto .compile_term_end; | ||||||
|  |  | ||||||
| .compile_expression_end: | .compile_term_end: | ||||||
|  | end; | ||||||
|  |  | ||||||
|  | proc _compile_expression(); | ||||||
|  | begin | ||||||
|  | 	_compile_term(); | ||||||
| end; | end; | ||||||
|  |  | ||||||
| proc _compile_call(); | proc _compile_call(); | ||||||
| @@ -617,14 +641,14 @@ begin | |||||||
|  |  | ||||||
| 	# Save the argument on the stack. | 	# Save the argument on the stack. | ||||||
| 	_write_z(@asm_sw); | 	_write_z(@asm_sw); | ||||||
| 	_write_z(@asm_t0); | 	_write_register('t', 0); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
| 	# Calculate the stack offset: 52 - (4 * argument_counter) | 	# Calculate the stack offset: 116 - (4 * argument_counter) | ||||||
| 	lw t0, 8(sp) | 	lw t0, 8(sp) | ||||||
| 	li t1, 4 | 	li t1, 4 | ||||||
| 	mul t0, t0, t1 | 	mul t0, t0, t1 | ||||||
| 	li t1, 52 | 	li t1, 116 | ||||||
| 	sub a0, t1, t0 | 	sub a0, t1, t0 | ||||||
| 	_write_i(); | 	_write_i(); | ||||||
|  |  | ||||||
| @@ -668,11 +692,11 @@ begin | |||||||
|  |  | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
| 	# Calculate the stack offset: 52 - (4 * argument_counter) | 	# Calculate the stack offset: 116 - (4 * argument_counter) | ||||||
| 	lw t0, 8(sp) | 	lw t0, 8(sp) | ||||||
| 	li t1, 4 | 	li t1, 4 | ||||||
| 	mul t0, t0, t1 | 	mul t0, t0, t1 | ||||||
| 	li t1, 52 | 	li t1, 116 | ||||||
| 	sub a0, t1, t0 | 	sub a0, t1, t0 | ||||||
| 	_write_i(); | 	_write_i(); | ||||||
|  |  | ||||||
| @@ -712,7 +736,7 @@ begin | |||||||
| 	_advance_token(1); | 	_advance_token(1); | ||||||
|  |  | ||||||
| 	_write_z(@asm_addi); | 	_write_z(@asm_addi); | ||||||
| 	_write_z(@asm_t0); | 	_write_register('t', 0); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
| 	_write_z(@asm_sp); | 	_write_z(@asm_sp); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
| @@ -733,7 +757,7 @@ end; | |||||||
| proc _compile_global_designator(); | proc _compile_global_designator(); | ||||||
| begin | begin | ||||||
| 	_write_z(@asm_la); | 	_write_z(@asm_la); | ||||||
| 	_write_z(@asm_t0); | 	_write_register('t', 0); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
| 	_read_token(); | 	_read_token(); | ||||||
| @@ -772,7 +796,7 @@ begin | |||||||
|  |  | ||||||
| 	# Save the assignee address on the stack. | 	# Save the assignee address on the stack. | ||||||
| 	_write_z(@asm_sw); | 	_write_z(@asm_sw); | ||||||
| 	_write_z(@asm_t0); | 	_write_register('t', 0); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
| 	_write_i(20); | 	_write_i(20); | ||||||
| @@ -787,7 +811,7 @@ begin | |||||||
| 	_compile_expression(); | 	_compile_expression(); | ||||||
|  |  | ||||||
| 	_write_z(@asm_lw); | 	_write_z(@asm_lw); | ||||||
| 	_write_z(@asm_t1); | 	_write_register('t', 1); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
| 	_write_i(20); | 	_write_i(20); | ||||||
| @@ -797,11 +821,11 @@ begin | |||||||
| 	_write_c('\n'); | 	_write_c('\n'); | ||||||
|  |  | ||||||
| 	_write_z(@asm_sw); | 	_write_z(@asm_sw); | ||||||
| 	_write_z(@asm_t0); | 	_write_register('t', 0); | ||||||
| 	_write_z(@asm_comma); | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
| 	_write_c('('); | 	_write_c('('); | ||||||
| 	_write_z(@asm_t1); | 	_write_register('t', 1); | ||||||
| 	_write_c(')'); | 	_write_c(')'); | ||||||
| end; | end; | ||||||
|  |  | ||||||
| @@ -855,11 +879,8 @@ end; | |||||||
| proc _compile_procedure_body(); | proc _compile_procedure_body(); | ||||||
| begin | begin | ||||||
| .compile_procedure_body_loop: | .compile_procedure_body_loop: | ||||||
| 	la a0, source_code_position | 	# 3 is "end" length. | ||||||
| 	lw a0, (a0) | 	_memcmp(source_code_position, @keyword_end, 3); | ||||||
| 	la a1, keyword_end |  | ||||||
| 	li a2, 3 # "end" length. |  | ||||||
| 	_memcmp(); |  | ||||||
|  |  | ||||||
| 	beqz a0, .compile_procedure_body_epilogue | 	beqz a0, .compile_procedure_body_epilogue | ||||||
|  |  | ||||||
| @@ -869,6 +890,60 @@ begin | |||||||
| .compile_procedure_body_epilogue: | .compile_procedure_body_epilogue: | ||||||
| end; | end; | ||||||
|  |  | ||||||
|  | # Writes a regster name to the standard output. | ||||||
|  | # | ||||||
|  | # Parameters: | ||||||
|  | # a0 - Register character. | ||||||
|  | # a1 - Register number. | ||||||
|  | proc _write_register(); | ||||||
|  | begin | ||||||
|  | 	sw a0, 0(sp) | ||||||
|  | 	sw a1, 4(sp) | ||||||
|  |  | ||||||
|  | 	_write_c(); | ||||||
|  |  | ||||||
|  | 	lw a0, 4(sp) | ||||||
|  | 	li t0, '0' | ||||||
|  | 	add a0, a0, t0 | ||||||
|  | 	_write_c(); | ||||||
|  | end; | ||||||
|  |  | ||||||
|  | proc _compile_procedure_prologue(); | ||||||
|  | begin | ||||||
|  | 	_write_z(@asm_prologue); | ||||||
|  |  | ||||||
|  | 	v0 := 0; | ||||||
|  |  | ||||||
|  | .compile_procedure_prologue_loop: | ||||||
|  | 	_write_z(@asm_sw); | ||||||
|  |  | ||||||
|  | 	li a0, 'a' | ||||||
|  | 	lw a1, 0(sp) | ||||||
|  | 	_write_register(); | ||||||
|  |  | ||||||
|  | 	_write_z(@asm_comma); | ||||||
|  |  | ||||||
|  | 	# Calculate the stack offset: 88 - (4 * parameter_counter) | ||||||
|  | 	lw t0, 0(sp) | ||||||
|  | 	li t1, 4 | ||||||
|  | 	mul t0, t0, t1 | ||||||
|  | 	li t1, 88 | ||||||
|  | 	sub a0, t1, t0 | ||||||
|  | 	_write_i(); | ||||||
|  |  | ||||||
|  | 	_write_c('('); | ||||||
|  | 	_write_z(@asm_sp); | ||||||
|  | 	_write_c(')'); | ||||||
|  | 	_write_c('\n'); | ||||||
|  |  | ||||||
|  | 	lw a0, 0(sp) | ||||||
|  | 	addi a0, a0, 1 | ||||||
|  | 	sw a0, 0(sp) | ||||||
|  |  | ||||||
|  | 	li t0, 8 | ||||||
|  | 	bne a0, t0, .compile_procedure_prologue_loop | ||||||
|  | end; | ||||||
|  |  | ||||||
| proc _compile_procedure(); | proc _compile_procedure(); | ||||||
| begin | begin | ||||||
| 	# Skip "proc ". | 	# Skip "proc ". | ||||||
| @@ -883,8 +958,7 @@ begin | |||||||
|  |  | ||||||
| 	_write_token(v0); | 	_write_token(v0); | ||||||
|  |  | ||||||
| 	la a0, asm_type_function | 	_write_z(@asm_type_function); | ||||||
| 	_write_z(); |  | ||||||
|  |  | ||||||
| 	# Write procedure label, _procedure_name: | 	# Write procedure label, _procedure_name: | ||||||
| 	_write_token(v0); | 	_write_token(v0); | ||||||
| @@ -896,8 +970,7 @@ begin | |||||||
| 	addi a0, a0, 10 | 	addi a0, a0, 10 | ||||||
| 	_advance_token(); | 	_advance_token(); | ||||||
|  |  | ||||||
| 	_write_z(@asm_prologue); | 	_compile_procedure_prologue(); | ||||||
|  |  | ||||||
| 	_compile_procedure_body(); | 	_compile_procedure_body(); | ||||||
|  |  | ||||||
| 	# Write the epilogue. | 	# Write the epilogue. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user