From 61e6b85528da8872d1f85ea26c657bce6ddb7740 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Thu, 30 Oct 2025 23:29:00 +0100 Subject: [PATCH] Provide binary and unary TAC operations --- boot/stage15.elna | 579 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 477 insertions(+), 102 deletions(-) diff --git a/boot/stage15.elna b/boot/stage15.elna index e88c803..38f3af8 100644 --- a/boot/stage15.elna +++ b/boot/stage15.elna @@ -155,9 +155,27 @@ type ElnaGeneratorKind = ( load_immediate, load_address, - add + add, + add_immediate, + load_word, + store_word, + call, + move, + sub, + div, + rem, + mul, + _xor, + _or, + and, + seqz, + snez, + slt, + xor_immediate, + neg, + not ); - ElnaGeneratorOperand = (register, immediate, symbol); + ElnaGeneratorOperand = (register, immediate, symbol, offset); ElnaGeneratorRegister = ( zero, ra, @@ -615,7 +633,7 @@ begin this^ := operand_length end; -proc _elna_generator_load_immediate(target_register: Word, source_immediate: Word, immediate_length: Word); +proc _elna_generator_instruction_create(kind: Word); var result: Word; instruction_size: Word; @@ -623,8 +641,18 @@ begin instruction_size := _elna_generator_instruction_size(); result := _allocate(instruction_size); - _elna_generator_instruction_set_kind(result, ElnaGeneratorKind.load_immediate); + _elna_generator_instruction_set_kind(result, kind); _elna_generator_instruction_set_next(result, 0); + + return result +end; + +proc _elna_generator_load_immediate(target_register: Word, source_immediate: Word, immediate_length: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind.load_immediate); + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, target_register, 0); _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.immediate, source_immediate, immediate_length); @@ -634,19 +662,253 @@ end; proc _elna_generator_load_address(target_register: Word, source_symbol: Word, symbol_length: Word); var result: Word; - instruction_size: Word; begin - instruction_size := _elna_generator_instruction_size(); - result := _allocate(instruction_size); + result := _elna_generator_instruction_create(ElnaGeneratorKind.load_address); - _elna_generator_instruction_set_kind(result, ElnaGeneratorKind.load_address); - _elna_generator_instruction_set_next(result, 0); _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, target_register, 0); _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.symbol, source_symbol, symbol_length); return result end; +proc _elna_generator_add(destination: Word, lhs: Word, rhs: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind.add); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); + _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); + _elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0); + + return result +end; + +proc _elna_generator_mul(destination: Word, lhs: Word, rhs: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind.mul); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); + _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); + _elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0); + + return result +end; + +proc _elna_generator_sub(destination: Word, lhs: Word, rhs: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind.sub); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); + _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); + _elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0); + + return result +end; + +proc _elna_generator_div(destination: Word, lhs: Word, rhs: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind.div); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); + _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); + _elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0); + + return result +end; + +proc _elna_generator_rem(destination: Word, lhs: Word, rhs: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind.rem); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); + _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); + _elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0); + + return result +end; + +proc _elna_generator_xor(destination: Word, lhs: Word, rhs: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind._xor); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); + _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); + _elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0); + + return result +end; + +proc _elna_generator_xor_immediate(destination: Word, lhs: Word, rhs: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind._xor); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); + _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); + _elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.immediate, rhs, 0); + + return result +end; + +proc _elna_generator_or(destination: Word, lhs: Word, rhs: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind._or); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); + _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); + _elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0); + + return result +end; + +proc _elna_generator_and(destination: Word, lhs: Word, rhs: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind.and); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); + _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); + _elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0); + + return result +end; + +proc _elna_generator_add_immediate(destination: Word, lhs: Word, rhs: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind.add_immediate); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); + _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); + _elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.immediate, rhs, 0); + + return result +end; + +proc _elna_generator_slt(destination: Word, lhs: Word, rhs: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind.slt); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); + _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, lhs, 0); + _elna_generator_instruction_set_operand(result, 3, ElnaGeneratorOperand.register, rhs, 0); + + return result +end; + +proc _elna_generator_call(symbol: Word, length: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind.call); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.symbol, symbol, length); + + return result +end; + +proc _elna_generator_load_word(target: Word, register: Word, offset: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind.load_word); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, target, 0); + _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.offset, register, offset); + + return result +end; + +proc _elna_generator_store_word(target: Word, register: Word, offset: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind.store_word); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, target, 0); + _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.offset, register, offset); + + return result +end; + +proc _elna_generator_move(destination: Word, source: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind.move); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); + _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, source, 0); + + return result +end; + +proc _elna_generator_seqz(destination: Word, source: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind.seqz); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); + _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, source, 0); + + return result +end; + +proc _elna_generator_snez(destination: Word, source: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind.snez); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); + _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, source, 0); + + return result +end; + +proc _elna_generator_neg(destination: Word, source: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind.neg); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); + _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, source, 0); + + return result +end; + +proc _elna_generator_not(destination: Word, source: Word); +var + result: Word; +begin + result := _elna_generator_instruction_create(ElnaGeneratorKind.not); + + _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, destination, 0); + _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.register, source, 0); + + return result +end; + proc _elna_writer_instruction_name(instruction_kind: Word); var argument_count: Word; @@ -660,6 +922,60 @@ begin elsif instruction_kind = ElnaGeneratorKind.add then argument_count := 3; _write_s("\tadd", 4) + elsif instruction_kind = ElnaGeneratorKind.add_immediate then + argument_count := 3; + _write_s("\taddi", 5) + elsif instruction_kind = ElnaGeneratorKind.load_word then + argument_count := 2; + _write_s("\tlw", 3) + elsif instruction_kind = ElnaGeneratorKind.store_word then + argument_count := 2; + _write_s("\tsw", 3) + elsif instruction_kind = ElnaGeneratorKind.call then + argument_count := 1; + _write_s("\tcall", 5) + elsif instruction_kind = ElnaGeneratorKind.move then + argument_count := 2; + _write_s("\tmv", 3) + elsif instruction_kind = ElnaGeneratorKind.sub then + argument_count := 3; + _write_s("\tsub", 4) + elsif instruction_kind = ElnaGeneratorKind.mul then + argument_count := 3; + _write_s("\tmul", 4) + elsif instruction_kind = ElnaGeneratorKind.div then + argument_count := 3; + _write_s("\tdiv", 4) + elsif instruction_kind = ElnaGeneratorKind.rem then + argument_count := 3; + _write_s("\trem", 4) + elsif instruction_kind = ElnaGeneratorKind._xor then + argument_count := 3; + _write_s("\txor", 4) + elsif instruction_kind = ElnaGeneratorKind.xor_immediate then + argument_count := 3; + _write_s("\txori", 5) + elsif instruction_kind = ElnaGeneratorKind._or then + argument_count := 3; + _write_s("\tor", 3) + elsif instruction_kind = ElnaGeneratorKind.and then + argument_count := 3; + _write_s("\tand", 4) + elsif instruction_kind = ElnaGeneratorKind.seqz then + argument_count := 2; + _write_s("\tseqz", 5) + elsif instruction_kind = ElnaGeneratorKind.snez then + argument_count := 2; + _write_s("\tsnez", 5) + elsif instruction_kind = ElnaGeneratorKind.slt then + argument_count := 3; + _write_s("\tslt", 4) + elsif instruction_kind = ElnaGeneratorKind.neg then + argument_count := 2; + _write_s("\tneg", 4) + elsif instruction_kind = ElnaGeneratorKind.not then + argument_count := 2; + _write_s("\tnot", 4) end; return argument_count end; @@ -686,6 +1002,11 @@ begin _write_c(' '); if operand_type = ElnaGeneratorOperand.register then _elna_writer_register(operand_value) + elsif operand_type = ElnaGeneratorOperand.offset then + _write_i(operand_length); + _write_c('('); + _elna_writer_register(operand_value); + _write_c(')') elsif operand_length = 0 then _write_i(operand_value) else @@ -696,13 +1017,22 @@ end; proc _elna_writer_instruction(instruction: Word); var instruction_kind: Word; + argument_count: Word; + current_argument: Word; begin instruction_kind := _elna_generator_instruction_get_kind(instruction); - _elna_writer_instruction_name(instruction_kind); + argument_count := _elna_writer_instruction_name(instruction_kind); + current_argument := 1; - _elna_writer_operand(instruction, 1); - _write_c(','); - _elna_writer_operand(instruction, 2); + .elna_writer_instruction_loop; + if current_argument <= argument_count then + _elna_writer_operand(instruction, current_argument); + current_argument := current_argument + 1 + end; + if current_argument <= argument_count then + _write_c(','); + goto elna_writer_instruction_loop + end; _write_c('\n') end; @@ -776,13 +1106,11 @@ var integer_token: Word; integer_length: Word; token_kind: Word; - instruction: Word; begin integer_token := _integer_literal_node_get_value(integer_literal_node); integer_length := _integer_literal_node_get_length(integer_literal_node); - instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, integer_token, integer_length); - _elna_writer_instructions(instruction) + return _elna_generator_load_immediate(ElnaGeneratorRegister.t0, integer_token, integer_length) end; proc _character_literal_node_size(); @@ -839,13 +1167,11 @@ proc _compile_character_literal(character_literal_node: Word); var character: Word; character_length: Word; - instruction: Word; begin character := _character_literal_node_get_value(character_literal_node); character_length := _character_literal_node_get_length(character_literal_node); - instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, character, character_length); - _elna_writer_instructions(instruction) + return _elna_generator_load_immediate(ElnaGeneratorRegister.t0, character, character_length) end; proc _variable_expression_size(); @@ -912,16 +1238,18 @@ var name: Word; name_token: Word; lookup_result: Word; + instruction: Word; begin name := _variable_expression_get_name(variable_expression); name_token := _variable_expression_get_length(variable_expression); lookup_result := _symbol_table_lookup(symbol_table, name, name_token); if lookup_result <> 0 then - _compile_local_designator(lookup_result) + instruction := _compile_local_designator(lookup_result) else - _compile_global_designator(variable_expression) - end + instruction := _compile_global_designator(variable_expression) + end; + return instruction end; proc _string_literal_node_size(); @@ -980,6 +1308,7 @@ var offset: Word; instruction: Word; first_instruction: Word; + next_instruction: Word; begin token_start := _string_literal_node_get_value(string_literal_node); length := _string_literal_node_get_length(string_literal_node); @@ -988,10 +1317,10 @@ begin first_instruction := _elna_generator_load_address(ElnaGeneratorRegister.t0, "strings", 7); instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t1, offset, 0); _elna_generator_instruction_set_next(first_instruction, instruction); + next_instruction := _elna_generator_add(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1); + _elna_generator_instruction_set_next(instruction, next_instruction); - _elna_writer_instructions(first_instruction); - - _write_z("\tadd t0, t0, t1\n\0") + return first_instruction end; proc _parse_simple_expression(); @@ -1065,25 +1394,26 @@ begin return simple_expression end; -proc _compile_simple_expression(parser_node: Word, symbol_table: Word); +proc _compile_simple_expression(parser_node: Word, symbol_table: Word, is_address: Word); var is_address: Word; node_kind: Word; + instruction: Word; begin - is_address := 0; + is_address^ := 0; node_kind := _node_get_kind(parser_node); if node_kind = NodeKind.character_literal then - _compile_character_literal(parser_node) + instruction := _compile_character_literal(parser_node) elsif node_kind = NodeKind.string_literal then - _compile_string_literal(parser_node) + instruction := _compile_string_literal(parser_node) elsif node_kind = NodeKind.integer_literal then - _compile_integer_literal(parser_node) + instruction := _compile_integer_literal(parser_node) else - _compile_variable_expression(parser_node, symbol_table); - is_address := 1 + instruction := _compile_variable_expression(parser_node, symbol_table); + is_address^ := 1 end; - return is_address + _elna_writer_instructions(instruction) end; proc _unary_expression_size(); @@ -1157,6 +1487,8 @@ var expression_kind: Word; operator: Word; operand: Word; + is_address: Word; + instruction: Word; begin operator := 0; operand := 0; @@ -1171,14 +1503,20 @@ begin end; if operator = '@' then - _compile_designator(operand, symbol_table) - elsif _compile_designator(operand, symbol_table) then - _write_z("\tlw t0, (t0) # Designator is an address.\n\0") + _compile_designator(operand, symbol_table, @is_address) + else + _compile_designator(operand, symbol_table, @is_address); + if is_address then + instruction := _elna_generator_load_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 0); + _elna_writer_instruction(instruction) + end end; if operator = '-' then - _write_z("\tneg t0, t0\n\0") + instruction := _elna_generator_neg(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0); + _elna_writer_instruction(instruction) elsif operator = '~' then - _write_z("\tnot t0, t0\n\0") + instruction := _elna_generator_not(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0); + _elna_writer_instruction(instruction) end end; @@ -1296,6 +1634,8 @@ var token_kind: Word; expression_kind: Word; operand_node: Word; + first_instruction: Word; + instruction: Word; begin expression_kind := _node_get_kind(parser_node); @@ -1307,42 +1647,53 @@ begin operand_node := _binary_expression_get_lhs(parser_node); _compile_unary_expression(operand_node, symbol_table); (* Save the value of the left expression on the stack. *) - _write_z("\tsw t0, 64(sp)\n\0"); + instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.sp, 64); + _elna_writer_instruction(instruction); operand_node := _binary_expression_get_rhs(parser_node); _compile_unary_expression(operand_node, symbol_table); (* Load the left expression from the stack; *) - _write_z("\tlw t1, 64(sp)\n\0"); + instruction := _elna_generator_load_word(ElnaGeneratorRegister.t1, ElnaGeneratorRegister.sp, 64); + _elna_writer_instruction(instruction); if token_kind = LexerTokenKind.plus then - _write_z("\tadd t0, t0, t1\n\0") + first_instruction := _elna_generator_add(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1) elsif token_kind = LexerTokenKind.minus then - _write_z("\tsub t0, t1, t0\n\0"); + first_instruction := _elna_generator_sub(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0) elsif token_kind = LexerTokenKind.multiplication then - _write_z("\tmul t0, t0, t1\n\0") + first_instruction := _elna_generator_mul(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1) elsif token_kind = LexerTokenKind.and then - _write_z("\tand t0, t0, t1\n\0") + first_instruction := _elna_generator_and(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1) elsif token_kind = LexerTokenKind._or then - _write_z("\tor t0, t0, t1\n\0") + first_instruction := _elna_generator_or(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1) elsif token_kind = LexerTokenKind._xor then - _write_z("\txor t0, t0, t1\n\0") + first_instruction := _elna_generator_xor(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1) elsif token_kind = LexerTokenKind.equals then - _write_z("\txor t0, t0, t1\n\tseqz t0, t0\n\0") + first_instruction := _elna_generator_xor(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1); + instruction := _elna_generator_seqz(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0); + _elna_generator_instruction_set_next(first_instruction, instruction) elsif token_kind = LexerTokenKind.remainder then - _write_z("\trem t0, t1, t0\n\0") + first_instruction := _elna_generator_rem(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0) elsif token_kind = LexerTokenKind.division then - _write_z("\tdiv t0, t1, t0\n\0") + first_instruction := _elna_generator_div(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0) elsif token_kind = LexerTokenKind.less_than then - _write_z("\tslt t0, t1, t0\n\0") + first_instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0) elsif token_kind = LexerTokenKind.greater_than then - _write_z("\tslt t0, t0, t1\n\0") + first_instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1) elsif token_kind = LexerTokenKind.less_equal then - _write_z("\tslt t0, t0, t1\n\txori t0, t0, 1\n\0") + first_instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1); + instruction := _elna_generator_xor_immediate(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 1); + _elna_generator_instruction_set_next(first_instruction, instruction) elsif token_kind = LexerTokenKind.not_equal then - _write_z("\txor t0, t0, t1\n\tsnez t0, t0\n\0") + first_instruction := _elna_generator_xor(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1); + instruction := _elna_generator_snez(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0); + _elna_generator_instruction_set_next(first_instruction, instruction) elsif token_kind = LexerTokenKind.greater_equal then - _write_z("\tslt t0, t1, t0\n\txori t0, t0, 1\n\0") - end + first_instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0); + instruction := _elna_generator_xor_immediate(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 1); + _elna_generator_instruction_set_next(first_instruction, instruction) + end; + _elna_writer_instructions(first_instruction) end end; @@ -1429,11 +1780,15 @@ var argument_count: Word; stack_offset: Word; parsed_expression: Word; + instruction: Word; + first_instruction: Word; + current_instruction: Word; begin parsed_expression := _call_get_name(parsed_call); name := _variable_expression_get_name(parsed_expression); name_length := _variable_expression_get_length(parsed_expression); argument_count := 0; + first_instruction := 0; .compile_call_loop; @@ -1444,11 +1799,11 @@ begin _compile_binary_expression(parsed_expression, symbol_table); (* Save the argument on the stack. *) - _write_z("\tsw t0, \0"); - stack_offset := argument_count * 4; - _write_i(116 - stack_offset); - _write_z("(sp)\n\0"); + + instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, + ElnaGeneratorRegister.sp, 116 - stack_offset); + _elna_writer_instruction(instruction); argument_count := argument_count + 1; goto compile_call_loop @@ -1460,24 +1815,27 @@ begin if argument_count <> 0 then (* Decrement the argument counter. *) argument_count := argument_count - 1; - - _write_z("\tlw a\0"); - _write_i(argument_count); - - _write_z(", \0"); + stack_offset := argument_count * 4; (* Calculate the stack offset: 116 - (4 * argument_counter) *) - stack_offset := argument_count * 4; - _write_i(116 - stack_offset); - - _write_z("(sp)\n\0"); + instruction := _elna_generator_load_word(ElnaGeneratorRegister.a0 + argument_count, + ElnaGeneratorRegister.sp, 116 - stack_offset); + if first_instruction = 0 then + first_instruction := instruction + else + _elna_generator_instruction_set_next(current_instruction, instruction) + end; + current_instruction := instruction; goto compile_call_finalize end; - - _write_z("\tcall \0"); - _write_s(name, name_length); - _write_c('\n') + instruction := _elna_generator_call(name, name_length); + if first_instruction = 0 then + first_instruction := instruction + else + _elna_generator_instruction_set_next(current_instruction, instruction) + end; + _elna_writer_instructions(first_instruction) end; (** @@ -1633,25 +1991,24 @@ end; proc _compile_local_designator(symbol: Word); var variable_offset: Word; + instruction: Word; begin - _write_z("\taddi t0, sp, \0"); variable_offset := _parameter_info_get_offset(symbol); - _write_i(variable_offset); - _write_c('\n') + instruction := _elna_generator_add_immediate(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.sp, variable_offset); + return instruction end; proc _compile_global_designator(variable_expression: Word); var name: Word; token_length: Word; + instruction: Word; begin - _write_z("\tla t0, \0"); - name := _variable_expression_get_name(variable_expression); token_length := _variable_expression_get_length(variable_expression); + instruction := _elna_generator_load_address(ElnaGeneratorRegister.t0, name, token_length); - _write_s(name, token_length); - _write_c('\n') + return instruction end; proc _field_access_expression_size(); @@ -1706,6 +2063,7 @@ var member_length: Word; counter: Word; symbol: Word; + instruction: Word; begin symbol := _field_access_expression_get_aggregate(field_access_expression); value_name := _variable_expression_get_name(symbol); @@ -1736,9 +2094,8 @@ begin counter := counter + 1; goto compile_enumeration_value_members end; - _write_z("\tli t0, \0"); - _write_i(counter); - _write_c('\n') + instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, counter, 0); + _elna_writer_instructions(instruction) end end; @@ -1769,31 +2126,32 @@ begin return result end; -proc _compile_designator(parser_node: Word, symbol_table: Word); +proc _compile_designator(parser_node: Word, symbol_table: Word, is_address: Word); var name_token: Word; lookup_result: Word; token_kind: Word; parser_node: Word; - is_address: Word; node_kind: Word; + instruction: Word; begin - is_address := 1; node_kind := _node_get_kind(parser_node); if node_kind = NodeKind.dereference_expression then parser_node := _dereference_expression_get_pointer(parser_node); - _compile_simple_expression(parser_node, symbol_table); - _write_z("\tlw t0, (t0)\n\0") + _compile_simple_expression(parser_node, symbol_table, is_address); + instruction := _elna_generator_load_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 0); + _elna_writer_instructions(instruction) elsif node_kind = NodeKind.field_access_expression then _compile_enumeration_value(parser_node); - is_address := 0 + is_address^ := 0 elsif node_kind = NodeKind.call then _compile_call(parser_node, symbol_table); - _write_z("\tmv t0, a0\n\0"); - is_address := 0 + instruction := _elna_generator_move(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.a0); + _elna_writer_instructions(instruction); + is_address^ := 0 else - is_address := _compile_simple_expression(parser_node, symbol_table) + _compile_simple_expression(parser_node, symbol_table, is_address) end; return is_address end; @@ -1853,18 +2211,25 @@ end; proc _compile_assignment_statement(parser_tree: Word, symbol_table: Word); var current_expression: Word; + is_address: Word; + first_instruction: Word; + instruction: Word; begin current_expression := _assignment_statement_get_assignee(parser_tree); - _compile_designator(current_expression, symbol_table); + _compile_designator(current_expression, symbol_table, @is_address); (* Save the assignee address on the stack. *) - _write_z("\tsw t0, 60(sp)\n\0"); + instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.sp, 60); + _elna_writer_instructions(instruction); (* Compile the assignment. *) current_expression := _assignment_statement_get_assignment(parser_tree); _compile_binary_expression(current_expression, symbol_table); - _write_z("\tlw t1, 60(sp)\n\tsw t0, (t1)\n\0") + first_instruction := _elna_generator_load_word(ElnaGeneratorRegister.t1, ElnaGeneratorRegister.sp, 60); + instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, 0); + _elna_generator_instruction_set_next(first_instruction, instruction); + _elna_writer_instructions(first_instruction) end; proc _return_statement_size(); @@ -1910,10 +2275,12 @@ end; proc _compile_return_statement(parser_node: Word, symbol_table: Word); var return_expression: Word; + instruction: Word; begin return_expression := _return_statement_get_returned(parser_node); _compile_binary_expression(return_expression, symbol_table); - _write_z("\tmv a0, t0\n\0") + instruction := _elna_generator_move(ElnaGeneratorRegister.a0, ElnaGeneratorRegister.t0); + _elna_writer_instructions(instruction) end; (** @@ -1959,6 +2326,7 @@ proc _compile_conditional_statements(parser_node: Word, after_end_label: Word, s var condition_label: Word; current_node: Word; + instruction: Word; begin (* Compile condition. *) current_node := _conditional_statements_get_condition(parser_node); @@ -2821,6 +3189,9 @@ var current_parameter: Word; new_symbol_table: Word; symbol_info: Word; + instruction: Word; + first_instruction: Word; + current_instruction: Word; begin name_pointer := _declaration_get_name(parser_node); name_length := _declaration_get_length(parser_node); @@ -2843,6 +3214,7 @@ begin current_parameter := _procedure_declaration_get_parameters(parser_node); parameter_counter := 0; + first_instruction := 0; .compile_procedure_declaration_parameters; if current_parameter <> 0 then name_pointer := _declaration_get_name(current_parameter); @@ -2851,12 +3223,14 @@ begin symbol_info := _parameter_info_get_offset(symbol_info); - _write_z("\tsw a\0"); - _write_i(parameter_counter); - _write_z(", \0"); - _write_i(symbol_info); - - _write_z("(sp)\n\0"); + instruction := _elna_generator_store_word(ElnaGeneratorRegister.a0 + parameter_counter, + ElnaGeneratorRegister.sp, symbol_info); + if first_instruction = 0 then + first_instruction := instruction + else + _elna_generator_instruction_set_next(current_instruction, instruction) + end; + current_instruction := instruction; (* _read_procedure_parameter(current_parameter, parameter_counter, new_symbol_table); *) parameter_counter := parameter_counter + 1; @@ -2864,6 +3238,7 @@ begin current_parameter := _declaration_get_next(current_parameter); goto compile_procedure_declaration_parameters end; + _elna_writer_instructions(first_instruction); current_parameter := _procedure_declaration_get_body(parser_node); _compile_statements(current_parameter, new_symbol_table); @@ -4255,7 +4630,7 @@ end; proc _initialize_global_state(); begin compiler_strings_position := @compiler_strings; - memory_free_pointer := _mmap(495616); + memory_free_pointer := _mmap(1048576); source_code := _mmap(495616); symbol_table_store := _mmap(495616) end;