summaryrefslogtreecommitdiff
path: root/boot/stage15.elna
diff options
context:
space:
mode:
Diffstat (limited to 'boot/stage15.elna')
-rw-r--r--boot/stage15.elna718
1 files changed, 591 insertions, 127 deletions
diff --git a/boot/stage15.elna b/boot/stage15.elna
index e88c803..431ad6b 100644
--- a/boot/stage15.elna
+++ b/boot/stage15.elna
@@ -155,9 +155,31 @@ 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,
+ jump,
+ beqz,
+ ret,
+ label
);
- ElnaGeneratorOperand = (register, immediate, symbol);
+ ElnaGeneratorOperand = (register, immediate, symbol, offset);
ElnaGeneratorRegister = (
zero,
ra,
@@ -615,7 +637,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 +645,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 +666,287 @@ 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_beqz(target_register: Word, source_symbol: Word, symbol_length: Word);
+var
+ result: Word;
+begin
+ result := _elna_generator_instruction_create(ElnaGeneratorKind.beqz);
+
+ _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_jump(source_symbol: Word, symbol_length: Word);
+var
+ result: Word;
+begin
+ result := _elna_generator_instruction_create(ElnaGeneratorKind.jump);
+
+ _elna_generator_instruction_set_operand(result, 1, 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_generator_label(counter: Word, length: Word);
+var
+ result: Word;
+begin
+ result := _elna_generator_instruction_create(ElnaGeneratorKind.label);
+
+ _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.symbol, counter, length);
+
+ return result
+end;
+
proc _elna_writer_instruction_name(instruction_kind: Word);
var
argument_count: Word;
@@ -660,6 +960,69 @@ 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)
+ elsif instruction_kind = ElnaGeneratorKind.jump then
+ argument_count := 1;
+ _write_s("\tj", 2)
+ elsif instruction_kind = ElnaGeneratorKind.beqz then
+ argument_count := 2;
+ _write_s("\tbeqz", 5)
+ elsif instruction_kind = ElnaGeneratorKind.ret then
+ argument_count := 0;
+ _write_s("\tret", 4)
end;
return argument_count
end;
@@ -686,7 +1049,18 @@ begin
_write_c(' ');
if operand_type = ElnaGeneratorOperand.register then
_elna_writer_register(operand_value)
- elsif operand_length = 0 then
+ elsif operand_type = ElnaGeneratorOperand.offset then
+ _write_i(operand_length);
+ _write_c('(');
+ _elna_writer_register(operand_value);
+ _write_c(')')
+ elsif operand_type = ElnaGeneratorOperand.symbol then
+ if operand_length = 0 then
+ _write_label(operand_value, 0)
+ else
+ _write_s(operand_value, operand_length)
+ end
+ elsif operand_length = 0 then (* ElnaGeneratorOperand.immediate *)
_write_i(operand_value)
else
_write_s(operand_value, operand_length)
@@ -696,13 +1070,33 @@ end;
proc _elna_writer_instruction(instruction: Word);
var
instruction_kind: Word;
+ argument_count: Word;
+ current_argument: Word;
+ operand_value: Word;
+ operand_length: Word;
begin
instruction_kind := _elna_generator_instruction_get_kind(instruction);
- _elna_writer_instruction_name(instruction_kind);
- _elna_writer_operand(instruction, 1);
- _write_c(',');
- _elna_writer_operand(instruction, 2);
+ if instruction_kind = ElnaGeneratorKind.label then
+ argument_count := 0;
+ operand_value := _elna_generator_instruction_get_operand_value(instruction, 1);
+ operand_length := _elna_generator_instruction_get_operand_length(instruction, 1);
+ _write_label(operand_value, operand_length);
+ _write_c(':')
+ else
+ argument_count := _elna_writer_instruction_name(instruction_kind)
+ end;
+ current_argument := 1;
+
+ .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 +1170,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 +1231,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 +1302,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 +1372,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 +1381,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 +1458,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 +1551,8 @@ var
expression_kind: Word;
operator: Word;
operand: Word;
+ is_address: Word;
+ instruction: Word;
begin
operator := 0;
operand := 0;
@@ -1171,14 +1567,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 +1698,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 +1711,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 +1844,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 +1863,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 +1879,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");
-
- (* Calculate the stack offset: 116 - (4 * argument_counter) *)
stack_offset := argument_count * 4;
- _write_i(116 - stack_offset);
- _write_z("(sp)\n\0");
+ (* Calculate the stack offset: 116 - (4 * argument_counter) *)
+ 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;
(**
@@ -1554,13 +1976,17 @@ proc _compile_goto_statement(parser_node: Word);
var
label_name: Word;
label_length: Word;
+ label_with_dot: Word;
+ instruction: Word;
begin
label_name := _goto_statement_get_label(parser_node);
label_length := _goto_statement_get_length(parser_node);
+ label_with_dot := _allocate(label_length + 1);
- _write_z("\tj .\0");
- _write_s(label_name, label_length);
- _write_c('\n')
+ _store_byte('.', label_with_dot);
+ _memcpy(label_with_dot + 1, label_name, label_length);
+
+ return _elna_generator_jump(label_with_dot, label_length + 1)
end;
proc _label_declaration_size();
@@ -1625,33 +2051,30 @@ begin
label_name := _label_declaration_get_label(parser_node);
label_length := _label_declaration_get_length(parser_node);
- _write_c('.');
- _write_s(label_name, label_length);
- _write_z(":\n\0")
+ return _elna_generator_label(label_name, label_length)
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 +2129,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 +2160,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 +2192,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 +2277,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 +2341,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;
(**
@@ -1922,10 +2355,20 @@ end;
* Parameters:
* counter - Label counter.
*)
-proc _write_label(counter: Word);
+proc _write_label(counter: Word, length: Word);
+var
+ first_byte: Word;
begin
- _write_z(".L\0");
- _write_i(counter)
+ if length = 0 then
+ _write_s(".L", 2);
+ _write_i(counter)
+ else
+ first_byte := _load_byte(counter);
+ if first_byte <> '.' then
+ _write_c('.')
+ end;
+ _write_s(counter, length)
+ end
end;
proc _parse_conditional_statements();
@@ -1959,6 +2402,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);
@@ -1968,19 +2412,17 @@ begin
condition_label := label_counter;
label_counter := label_counter + 1;
- _write_z("\tbeqz t0, \0");
- _write_label(condition_label);
- _write_c('\n');
+ instruction := _elna_generator_beqz(ElnaGeneratorRegister.t0, condition_label, 0);
+ _elna_writer_instructions(instruction);
current_node := _conditional_statements_get_statements(parser_node);
_compile_statements(current_node, symbol_table);
- _write_z("\tj \0");
- _write_label(after_end_label);
- _write_c('\n');
+ instruction := _elna_generator_jump(after_end_label, 0);
+ _elna_writer_instructions(instruction);
- _write_label(condition_label);
- _write_z(":\n\0")
+ instruction := _elna_generator_label(condition_label, 0);
+ _elna_writer_instructions(instruction)
end;
(**
@@ -2172,6 +2614,7 @@ var
current_node: Word;
after_end_label: Word;
condition_label: Word;
+ instruction: Word;
begin
after_end_label := label_counter;
label_counter := label_counter + 1;
@@ -2190,25 +2633,27 @@ begin
if current_node <> 0 then
_compile_statements(current_node, symbol_table)
end;
-
- _write_label(after_end_label);
- _write_z(":\n\0")
+ instruction := _elna_generator_label(after_end_label, 0);
+ _elna_writer_instructions(instruction)
end;
proc _compile_statement(parser_node: Word, symbol_table: Word);
var
statement_kind: Word;
+ instruction: Word;
begin
statement_kind := _node_get_kind(parser_node);
if statement_kind = NodeKind.goto_statement then
- _compile_goto_statement(parser_node)
+ instruction := _compile_goto_statement(parser_node);
+ _elna_writer_instructions(instruction)
elsif statement_kind = NodeKind.if_statement then
_compile_if_statement(parser_node, symbol_table)
elsif statement_kind = NodeKind.return_statement then
_compile_return_statement(parser_node, symbol_table)
elsif statement_kind = NodeKind.label_declaration then
- _compile_label_declaration(parser_node)
+ instruction := _compile_label_declaration(parser_node);
+ _elna_writer_instructions(instruction)
elsif statement_kind = NodeKind.call then
_compile_call(parser_node, symbol_table)
elsif statement_kind = NodeKind.assignment_statement then
@@ -2821,6 +3266,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);
@@ -2839,7 +3287,13 @@ begin
_write_z(":\n\0");
(* Write the prologue. *)
- _write_z("\taddi sp, sp, -128\n\tsw ra, 124(sp)\n\tsw s0, 120(sp)\n\taddi s0, sp, 128\n\0");
+ first_instruction := _elna_generator_add_immediate(ElnaGeneratorRegister.sp, ElnaGeneratorRegister.sp, -128);
+ current_instruction := _elna_generator_store_word(ElnaGeneratorRegister.ra, ElnaGeneratorRegister.sp, 124);
+ _elna_generator_instruction_set_next(first_instruction, current_instruction);
+ instruction := _elna_generator_store_word(ElnaGeneratorRegister.s0, ElnaGeneratorRegister.sp, 120);
+ _elna_generator_instruction_set_next(current_instruction, instruction);
+ current_instruction := _elna_generator_add_immediate(ElnaGeneratorRegister.s0, ElnaGeneratorRegister.sp, 128);
+ _elna_generator_instruction_set_next(instruction, current_instruction);
current_parameter := _procedure_declaration_get_parameters(parser_node);
parameter_counter := 0;
@@ -2851,12 +3305,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,11 +3320,19 @@ 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);
(* Write the epilogue. *)
- _write_z("\tlw ra, 124(sp)\n\tlw s0, 120(sp)\n\taddi sp, sp, 128\n\tret\n\0")
+ first_instruction := _elna_generator_load_word(ElnaGeneratorRegister.ra, ElnaGeneratorRegister.sp, 124);
+ current_instruction := _elna_generator_load_word(ElnaGeneratorRegister.s0, ElnaGeneratorRegister.sp, 120);
+ _elna_generator_instruction_set_next(first_instruction, current_instruction);
+ instruction := _elna_generator_add_immediate(ElnaGeneratorRegister.sp, ElnaGeneratorRegister.sp, 128);
+ _elna_generator_instruction_set_next(current_instruction, instruction);
+ current_instruction := _elna_generator_instruction_create(ElnaGeneratorKind.ret);
+ _elna_generator_instruction_set_next(instruction, current_instruction);
+ _elna_writer_instructions(first_instruction)
end;
proc _parse_procedures();
@@ -4255,7 +4719,7 @@ end;
proc _initialize_global_state();
begin
compiler_strings_position := @compiler_strings;
- memory_free_pointer := _mmap(495616);
+ memory_free_pointer := _mmap(4194304);
source_code := _mmap(495616);
symbol_table_store := _mmap(495616)
end;