1645 lines
33 KiB
Plaintext
1645 lines
33 KiB
Plaintext
(*
|
|
s1 - Contains the current position in the source text.
|
|
s2 - Label counter.
|
|
|
|
- The compiler expects valid input, otherwise it will generate invalid
|
|
assembly or hang. There is no error checking, no semantic analysis, no
|
|
type checking.
|
|
|
|
- Imports with only a module name without package, e.g.
|
|
"import dummy", can be parsed, but are ignored.
|
|
|
|
- No loops. Only labels and goto.
|
|
|
|
- Only unsigned number literals are supported (in decimal or
|
|
hexadecimal format).
|
|
|
|
- Comments are accepted only at the end of a line.
|
|
|
|
- Return can be used only as the last statement of a procedure. It
|
|
doesn't actually return, but sets a0 to the appropriate value.
|
|
|
|
- The lvalue of an assignment can only be an identifier.
|
|
*)
|
|
program
|
|
|
|
import dummy
|
|
|
|
const
|
|
SOURCE_BUFFER_SIZE := 81920
|
|
|
|
var
|
|
source_code: [81920]Byte
|
|
|
|
(* Ignores the import. *)
|
|
proc _compile_import()
|
|
var loca0: Word
|
|
begin
|
|
_advance(6);
|
|
_skip_spaces();
|
|
loca0 := _read_token();
|
|
_advance(loca0) (* Skip the imported module name. *)
|
|
end
|
|
|
|
proc _build_binary_expression()
|
|
var
|
|
loca0, loca4, loca8, loca16, loca20: Word
|
|
loca12: ^Byte
|
|
loca24: Bool
|
|
begin
|
|
_build_expression(0);
|
|
|
|
loca4 := 0x2c306120 (* _a0, *);
|
|
loca8 := 0x0a316120 (* _a1\n *);
|
|
|
|
_skip_spaces();
|
|
loca20 := _read_token();
|
|
loca12 := _current();
|
|
|
|
loca16 := 0x26 (* & *);
|
|
loca24 := _token_compare(loca12, loca20, @loca16);
|
|
if loca24 = 0 then
|
|
goto .L_build_binary_expression_and
|
|
end;
|
|
|
|
loca16 := 0x726f (* or *);
|
|
loca24 := _token_compare(loca12, loca20, @loca16);
|
|
if loca24 = 0 then
|
|
goto .L_build_binary_expression_or
|
|
end;
|
|
|
|
loca16 := 0x3d (* = *);
|
|
loca24 := _token_compare(loca12, loca20, @loca16);
|
|
if loca24 = 0 then
|
|
goto .L_build_binary_expression_equal
|
|
end;
|
|
|
|
loca16 := 0x2b (* + *);
|
|
loca24 := _token_compare(loca12, loca20, @loca16);
|
|
if loca24 = 0 then
|
|
goto .L_build_binary_expression_plus
|
|
end;
|
|
|
|
loca16 := 0x2d (* - *);
|
|
loca24 := _token_compare(loca12, loca20, @loca16);
|
|
if loca24 = 0 then
|
|
goto .L_build_binary_expression_minus
|
|
end
|
|
|
|
loca16 := 0x2a (* * *);
|
|
loca24 := _token_compare(loca12, loca20, @loca16);
|
|
if loca24 = 0 then
|
|
goto .L_build_binary_expression_product
|
|
end;
|
|
|
|
goto .Lbuild_binary_expression_end;
|
|
|
|
.L_build_binary_expression_equal;
|
|
_advance(1) (* Skip =. *);
|
|
_build_expression(1);
|
|
|
|
loca0 := 0x627573(* sub *);
|
|
_write_out(@loca0, 3);
|
|
_write_out(@loca4, 4);
|
|
_write_out(@loca4, 4);
|
|
_write_out(@loca8, 4);
|
|
|
|
loca0 := 0x7a716573 (* seqz *);
|
|
_write_out(@loca0, 4);
|
|
_write_out(@loca4, 4);
|
|
_write_out(@loca4, 3);
|
|
_put_char(0x0a) (* \n *);
|
|
|
|
goto .Lbuild_binary_expression_end;
|
|
|
|
.L_build_binary_expression_and;
|
|
_advance(1) (* Skip &. *);
|
|
_build_expression(1);
|
|
loca0 := 0x646e61 (* and *);
|
|
_write_out(@loca0, 3);
|
|
_write_out(@loca4, 4);
|
|
_write_out(@loca4, 4);
|
|
_write_out(@loca8, 4);
|
|
|
|
goto .Lbuild_binary_expression_end;
|
|
|
|
.L_build_binary_expression_or;
|
|
_advance(2) (* Skip or. *);
|
|
_build_expression(1);
|
|
loca0 := 0x726f (* or *);
|
|
_write_out(@loca0, 2);
|
|
_write_out(@loca4, 4);
|
|
_write_out(@loca4, 4);
|
|
_write_out(@loca8, 4);
|
|
|
|
goto .Lbuild_binary_expression_end;
|
|
|
|
.L_build_binary_expression_plus;
|
|
_advance(1) (* Skip +. *);
|
|
_build_expression(1);
|
|
loca0 := 0x646461 (* add *);
|
|
_write_out(@loca0, 3);
|
|
_write_out(@loca4, 4);
|
|
_write_out(@loca4, 4);
|
|
_write_out(@loca8, 4);
|
|
|
|
goto .Lbuild_binary_expression_end;
|
|
|
|
.L_build_binary_expression_minus;
|
|
_advance(1) (* Skip -. *);
|
|
_build_expression(1);
|
|
loca0 := 0x627573 (* sub *);
|
|
_write_out(@loca0, 3);
|
|
_write_out(@loca4, 4);
|
|
_write_out(@loca4, 4);
|
|
_write_out(@loca8, 4);
|
|
|
|
goto .Lbuild_binary_expression_end;
|
|
|
|
.L_build_binary_expression_product;
|
|
_advance(1) (* Skip *. *);
|
|
_build_expression(1);
|
|
loca0 := 0x6c756d (* mul *);
|
|
_write_out(@loca0, 3);
|
|
_write_out(@loca4, 4);
|
|
_write_out(@loca4, 4);
|
|
_write_out(@loca8, 4);
|
|
|
|
goto .Lbuild_binary_expression_end;
|
|
|
|
.Lbuild_binary_expression_end
|
|
end
|
|
|
|
(*
|
|
Parameters:
|
|
a0 - Identifier length.
|
|
a1 - Register number as character.
|
|
*)
|
|
proc _compile_identifier_expression(loca84: Word, loca80: Byte)
|
|
begin
|
|
loca24 := _current();
|
|
loca0 := 0x61636f6c (* loca *);
|
|
loca0 := _memcmp(@loca0, loca24, 4);
|
|
|
|
if loca0 = 0 then
|
|
loca8 := 0x6120776c (* lw a *);
|
|
_write_out(@loca8, 4);
|
|
loca8 := 0x00202c00 or loca80 (* \0,_ *);
|
|
_write_out(@loca8, 3);
|
|
|
|
loca4 := loca24 + 4;
|
|
loca0 := loca84 - 4;
|
|
_write_out(loca4, loca0) (* Skip the "loca" variable prefix. *);
|
|
|
|
loca8 := 0x29707328 (* (sp) *);
|
|
_write_out(@loca8, 4);
|
|
_put_char(0x0a) (* \n *);
|
|
|
|
goto .Lcompile_identifier_expression_end
|
|
end;
|
|
loca0 := _front(loca24);
|
|
loca8 := loca84 = 2;
|
|
loca12 := loca0 = 0x73;
|
|
if loca8 & loca12 then
|
|
loca8 := 0x6120766d (* mv a *);
|
|
_write_out(@loca8, 4);
|
|
loca8 := 0x00202c00 or loca80 (* \0,_ *);
|
|
_write_out(@loca8, 3);
|
|
_write_out(loca24, loca84);
|
|
_put_char(0x0a) (* \n *);
|
|
|
|
goto .Lcompile_identifier_expression_end
|
|
end
|
|
|
|
(* Global identifier. *);
|
|
loca8 := 0x6120616c (* la a *);
|
|
_write_out(@loca8, 4);
|
|
loca8 := 0x00202c00 or loca80;
|
|
_write_out(@loca8, 3);
|
|
|
|
_write_out(loca24, loca84);
|
|
_put_char(0x0a);
|
|
|
|
if _is_upper(loca0) then
|
|
loca8 := 0x6120776c (* lw a *);
|
|
_write_out(@loca8, 4);
|
|
loca8 := 0x28202c00 or loca28 (* \0, ( *);
|
|
_write_out(@loca8, 4);
|
|
_put_char(0x61) (* a *);
|
|
_put_char(loca28);
|
|
_put_char(0x29) (* ) *);
|
|
_put_char(0x0a) (* \n *);
|
|
|
|
goto .Lcompile_identifier_expression_end
|
|
end;
|
|
|
|
.Lcompile_identifier_expression_end
|
|
end
|
|
|
|
(*
|
|
Evalutes an expression and saves the result in a0.
|
|
|
|
a0 - X in aX, the register number to save the result.
|
|
*)
|
|
proc _build_expression()
|
|
var
|
|
loca0, loca20, loca28, loca8: Word
|
|
loca24, loca4: ^Byte
|
|
begin
|
|
(* Make the register number to a character and save it. *)
|
|
loca28 := loca84 + 0x30 (* 0 *);
|
|
|
|
_skip_spaces();
|
|
loca20 := _read_token();
|
|
loca24 := _current();
|
|
loca0 := _front(loca24);
|
|
|
|
(* - *)
|
|
if loca0 = 0x2d then
|
|
goto .Lbuild_expression_negate
|
|
end;
|
|
|
|
(* @ *)
|
|
if loca0 = 0x40 then
|
|
goto .Lbuild_expression_address
|
|
end;
|
|
|
|
if _is_digit(loca0) then
|
|
goto .Lbuild_expression_literal
|
|
end;
|
|
|
|
(* _ *)
|
|
if loca0 = 0x5f then
|
|
goto .Lbuild_expression_call
|
|
end;
|
|
|
|
_compile_identifier_expression(loca20, loca28);
|
|
goto .Lbuild_expression_advance;
|
|
|
|
.Lbuild_expression_negate;
|
|
_advance(1) (* Skip the -. *);
|
|
_build_expression(0);
|
|
|
|
loca8 := 0x2067656e (* neg_ *);
|
|
_write_out(@loca8, 4);
|
|
loca8 := 0x202c3061 (* a0,_ *);
|
|
_write_out(@loca8, 4);
|
|
loca8 := 0x0a3061 (* a0,_ *);
|
|
_write_out(@loca8, 3);
|
|
|
|
goto .Lbuild_expression_advance;
|
|
|
|
.Lbuild_expression_address;
|
|
loca8 := 0x69646461 (* addi *);
|
|
_write_out(@loca8, 4);
|
|
loca8 := 0x6120 (* _a *);
|
|
_write_out(@loca8, 2);
|
|
_put_char(loca28);
|
|
loca8 := 0x7073202c (* , sp *);
|
|
_write_out(@loca8, 4);
|
|
loca8 := 0x202c (* ,_ *);
|
|
_write_out(@loca8, 2);
|
|
|
|
_advance(1) (* Skip @. *);
|
|
_skip_spaces();
|
|
loca24 := _current();
|
|
loca20 := _read_token();
|
|
|
|
(* Skip the "loca" variable prefix. *)
|
|
loca4 := loca24 + 4;
|
|
loca0 := loca20 - 4;
|
|
_write_out(loca4, loca0);
|
|
|
|
_put_char(0xa);
|
|
|
|
goto .Lbuild_expression_advance;
|
|
|
|
.Lbuild_expression_call;
|
|
_advance(loca20);
|
|
_advance(1);
|
|
_compile_call(loca24, loca20);
|
|
|
|
goto .Lbuild_expression_end;
|
|
|
|
.Lbuild_expression_literal;
|
|
loca8 := 0x6120696c (* li a *);
|
|
_write_out(@loca8, 4);
|
|
loca8 := 0x00202c00 or loca28 (* \0,_ *);
|
|
_write_out(@loca8, 3);
|
|
|
|
_write_out(loca24, loca20);
|
|
_put_char(0x0a) (* \n *);
|
|
|
|
goto .Lbuild_expression_advance;
|
|
|
|
.Lbuild_expression_advance;
|
|
_advance(loca20);
|
|
|
|
.Lbuild_expression_end
|
|
end
|
|
|
|
(*
|
|
Compiles an lvalue.
|
|
|
|
Parameters:
|
|
a0 - Pointer to the identifier.
|
|
a1 - Identifier length.
|
|
*)
|
|
proc _compile_designator_expression(loca84: ^Byte, loca80: Word)
|
|
var
|
|
loca0: Word
|
|
begin
|
|
loca0 := 0x61636f6c (* loca *);
|
|
loca4 := _memcmp(@loca0, loca84, 4);
|
|
|
|
if loca4 = 0 then
|
|
loca0 := 0x61207773 (* sw a *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x202c30 (* 0,_ *);
|
|
_write_out(@loca0, 3);
|
|
|
|
loca84 := loca84 + 4;
|
|
loca80 := loca80 - 4;
|
|
_write_out(loca84, loca80);
|
|
|
|
loca0 := 0x29707328 (* (sp) *);
|
|
_write_out(@loca0, 4);
|
|
_put_char(0x0a) (* \n *);
|
|
|
|
goto .Lcompile_designator_expression_end
|
|
end;
|
|
loca8 := _front(loca84);
|
|
loca12 := loca8 = 0x73 (* s *);
|
|
loca16 := loca80 = 2;
|
|
if loca12 & loca16 then
|
|
loca0 := 0x20766d (* mv_ *);
|
|
_write_out(@loca0, 3);
|
|
_write_out(loca84, loca80);
|
|
loca0 := 0x3061202c (* , a0 *);
|
|
_write_out(@loca0, 4);
|
|
_put_char(0x0a) (* \n *);
|
|
|
|
goto .Lcompile_designator_expression_end
|
|
end;
|
|
|
|
.Lcompile_designator_expression_end
|
|
end
|
|
|
|
(*
|
|
Compiles a statement beginning with an identifier.
|
|
|
|
Left values should be variables named "loca n", where n is the offset
|
|
of the variable on the stack, like loca8 or loca4.
|
|
*)
|
|
proc _compile_identifier()
|
|
var
|
|
loca0, loca16, loca8: Word
|
|
loca20, loca12: ^Byte
|
|
loca4: Bool
|
|
begin
|
|
(* Save the pointer to the identifier and its length on the stack. *)
|
|
loca20 := _current();
|
|
loca16 := _read_token();
|
|
|
|
_advance(loca16);
|
|
_skip_spaces();
|
|
|
|
(* Save the pointer and the length of the token following the identifier. *)
|
|
loca12 := _current();
|
|
loca8 := _read_token();
|
|
|
|
_advance(loca8) (* Skip that token. *);
|
|
_skip_spaces();
|
|
|
|
loca0 := 0x3d3a (* := *);
|
|
loca4 := _token_compare(loca12, loca8, @loca0);
|
|
if loca4 = 0 then
|
|
_build_binary_expression();
|
|
_compile_designator_expression(loca20, loca16);
|
|
|
|
goto .Lcompile_identifier_end
|
|
end;
|
|
if _front(loca12) = 0x28 then
|
|
_compile_call(loca20, loca16);
|
|
|
|
goto .Lcompile_identifier_end
|
|
end;
|
|
|
|
.Lcompile_identifier_end
|
|
end
|
|
|
|
(*
|
|
Compiles a procedure call. Expects s1 to point to the first argument.
|
|
a0 - Pointer to the procedure name.
|
|
a1 - Length of the procedure name.
|
|
|
|
Returns the procedure result in a0.
|
|
*)
|
|
proc _compile_call(loca84: ^Byte, loca80: Word)
|
|
var
|
|
loca0, loca4, loca12: Word
|
|
loca8: ^Byte
|
|
begin
|
|
loca12 := 0 (* Argument count for a procedure call. *);
|
|
|
|
.Lcompile_call_paren;
|
|
_skip_spaces();
|
|
loca8 := _current();
|
|
if _front(loca8) = 0x29 then
|
|
goto .Lcompile_call_complete
|
|
end;
|
|
|
|
.Lcompile_call_argument;
|
|
_build_expression(0);
|
|
|
|
loca0 := 0x61207773 (* sw a *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x202c30 (* 0,_ *);
|
|
_write_out(@loca0, 3);
|
|
|
|
(*
|
|
Only 6 arguments are supported with a0-a5.
|
|
Save all arguments on the stack so they aren't overriden afterwards.
|
|
*)
|
|
loca0 := -4 * loca12;
|
|
loca0 := loca0 + 60;
|
|
_printi(loca0);
|
|
|
|
loca0 := 0x29707328 (* (sp) *);
|
|
_write_out(@loca0, 4);
|
|
_put_char(0x0a) (* \n *);
|
|
|
|
_skip_spaces();
|
|
loca8 := _current();
|
|
loca0 := _front(loca8) = 0x2c;
|
|
if loca0 = 0 then
|
|
goto .Lcompile_call_paren
|
|
end
|
|
|
|
loca12 := loca12 + 1 (* Argument count for a procedure call. *);
|
|
|
|
_advance(1) (* Skip the comma between the arguments. *);
|
|
goto .Lcompile_call_argument;
|
|
|
|
.Lcompile_call_complete;
|
|
loca12 := 0;
|
|
|
|
.Lcompile_call_restore;
|
|
(*
|
|
Just go through all a0-a5 registers and read them from stack.
|
|
If this stack value contains garbage, the procedure just shouldn't use it.
|
|
*)
|
|
loca0 := 0x6120776c (* lw a *);
|
|
(* lw a0, 60(sp) *)
|
|
_write_out(@loca0, 4);
|
|
loca4 := 0x36202c30 (* 0, 6 *);
|
|
_write_out(@loca4, 4);
|
|
loca4 := 0x70732830 (* 0(sp *);
|
|
_write_out(@loca4, 4);
|
|
loca4 := 0x0a29 (* )\n *);
|
|
_write_out(@loca4, 2);
|
|
|
|
(* lw a1, 56(sp) *)
|
|
_write_out(@loca0, 4);
|
|
loca4 := 0x35202c31 (* 1, 5 *);
|
|
_write_out(@loca4, 4);
|
|
loca4 := 0x70732836 (* 6(sp *);
|
|
_write_out(@loca4, 4);
|
|
loca4 := 0x0a29 (* )\n *);
|
|
_write_out(@loca4, 2);
|
|
|
|
(* lw a2, 52(sp) *)
|
|
_write_out(@loca0, 4);
|
|
loca4 := 0x35202c32 (* 2, 5 *);
|
|
_write_out(@loca4, 4);
|
|
loca4 := 0x70732832 (* 2(sp *);
|
|
_write_out(@loca4, 4);
|
|
loca4 := 0x0a29 (* )\n *);
|
|
_write_out(@loca4, 2);
|
|
|
|
(* lw a3, 48(sp) *)
|
|
_write_out(@loca0, 4);
|
|
loca4 := 0x34202c33 (* 3, 4 *);
|
|
_write_out(@loca4, 4);
|
|
loca4 := 0x70732838 (* 8(sp *);
|
|
_write_out(@loca4, 4);
|
|
loca4 := 0x0a29 (* )\n *);
|
|
_write_out(@loca4, 2);
|
|
|
|
(* lw a4, 44(sp) *)
|
|
_write_out(@loca0, 4);
|
|
loca4 := 0x34202c34 (* 4, 4 *);
|
|
_write_out(@loca4, 4);
|
|
loca4 := 0x70732834 (* 4(sp *);
|
|
_write_out(@loca4, 4);
|
|
loca4 := 0x0a29 (* )\n *);
|
|
_write_out(@loca4, 2);
|
|
|
|
(* lw a5, 40(sp) *)
|
|
_write_out(@loca0, 4);
|
|
loca4 := 0x34202c35 (* 5, 4 *);
|
|
_write_out(@loca4, 4);
|
|
loca4 := 0x70732830 (* 0(sp *);
|
|
_write_out(@loca4, 4);
|
|
loca4 := 0x0a29 (* )\n *);
|
|
_write_out(@loca4, 2);
|
|
|
|
loca0 := 0x6c6c6163 (* call *);
|
|
_write_out(@loca0, 4);
|
|
_put_char(0x20) (* _ *);
|
|
|
|
_write_out(loca84, loca80);
|
|
_put_char(0x0a) (* \n *);
|
|
|
|
_skip_spaces();
|
|
_advance(1) (* Skip the close paren. *)
|
|
end
|
|
|
|
(*
|
|
Reads a token and returns its length in a0.
|
|
_read_token doesn't change s1, it finds the length of the token s1 is pointing to.
|
|
*)
|
|
proc _read_token()
|
|
var
|
|
loca0, loca4: Word
|
|
loca8: ^Byte
|
|
begin
|
|
loca8 := _current();
|
|
loca0 := _front(loca8) (* t0 = Current character. *);
|
|
loca4 := 0;
|
|
|
|
(* . *)
|
|
if loca0 = 0x2e then
|
|
goto .Ltoken_character_single
|
|
end;
|
|
|
|
(* , *)
|
|
if loca0 = 0x2c then
|
|
goto .Ltoken_character_single
|
|
end;
|
|
|
|
(* : *)
|
|
if loca0 = 0x3a then
|
|
goto .Ltoken_character_colon
|
|
end;
|
|
|
|
(* ; *)
|
|
if loca0 = 0x3b then
|
|
goto .Ltoken_character_single
|
|
end;
|
|
|
|
(* ( *)
|
|
if loca0 = 0x28 then
|
|
goto .Ltoken_character_single
|
|
end;
|
|
|
|
(* ) *)
|
|
if loca0 = 0x29 then
|
|
goto .Ltoken_character_single
|
|
end;
|
|
|
|
(* [ *)
|
|
if loca0 = 0x5b then
|
|
goto .Ltoken_character_single
|
|
end;
|
|
|
|
(* ] *)
|
|
if loca0 = 0x5d then
|
|
goto .Ltoken_character_single
|
|
end;
|
|
|
|
(* ^ *)
|
|
if loca0 = 0x5e then
|
|
goto .Ltoken_character_single
|
|
end;
|
|
|
|
(* & *)
|
|
if loca0 = 0x26 then
|
|
goto .Ltoken_character_single
|
|
end;
|
|
|
|
(* = *)
|
|
if loca0 = 0x3d then
|
|
goto .Ltoken_character_single
|
|
end;
|
|
|
|
(* + *)
|
|
if loca0 = 0x2b then
|
|
goto .Ltoken_character_single
|
|
end;
|
|
|
|
(* - *)
|
|
if loca0 = 0x2d then
|
|
goto .Ltoken_character_single
|
|
end;
|
|
|
|
(* * *)
|
|
if loca0 = 0x2a then
|
|
goto .Ltoken_character_single
|
|
end;
|
|
|
|
(* @ *)
|
|
if loca0 = 0x40 then
|
|
goto .Ltoken_character_single
|
|
end;
|
|
|
|
(* Expect an identifier or a number. *)
|
|
.Ltoken_character_loop_do;
|
|
loca0 := loca8 + loca4;
|
|
loca0 := _front(loca0);
|
|
|
|
if _is_alnum(loca0) then
|
|
loca4 := loca4 + 1;
|
|
goto .Ltoken_character_loop_do;
|
|
|
|
.Ltoken_character_single;
|
|
loca4 := loca4 + 1;
|
|
goto .Ltoken_character_end;
|
|
|
|
.Ltoken_character_colon;
|
|
loca0 := loca8 + 1;
|
|
loca0 := _front(loca0) (* t0 = The character after the colon. *);
|
|
loca4 := loca4 + 1;
|
|
|
|
(* = *)
|
|
if loca0 = 0x3d then
|
|
goto .Ltoken_character_single
|
|
end
|
|
end;
|
|
.Ltoken_character_end;
|
|
return loca4
|
|
end
|
|
|
|
(* Skips the spaces till the next non space character. *)
|
|
proc _skip_spaces()
|
|
var
|
|
loca0: Byte
|
|
loca4: ^Byte
|
|
begin
|
|
.Lspace_loop_do;
|
|
loca4 := _current();
|
|
loca0 := _front(loca4) (* t0 = Current character. *);
|
|
|
|
(* _ *)
|
|
if loca0 = 0x20 then
|
|
goto .Lspace_loop_repeat
|
|
end;
|
|
(* \t *)
|
|
if loca0 = 0x09 then
|
|
goto .Lspace_loop_repeat
|
|
end;
|
|
(* \n *)
|
|
if loca0 = 0x0a then
|
|
goto .Lspace_loop_repeat
|
|
end;
|
|
(* \r *)
|
|
if loca0 = 0x0d then
|
|
goto .Lspace_loop_repeat
|
|
end;
|
|
|
|
goto .Lspace_loop_end;
|
|
.Lspace_loop_repeat;
|
|
_advance(1);
|
|
goto .Lspace_loop_do;
|
|
|
|
.Lspace_loop_end
|
|
end
|
|
|
|
(*
|
|
Parameters:
|
|
a0 - Line length.
|
|
*)
|
|
proc _skip_comment(loca84: Word)
|
|
var
|
|
loca0: ^Byte
|
|
loca4: Word
|
|
loca8: Int
|
|
begin
|
|
loca0 := _current();
|
|
|
|
(* Check whether this is a comment. *)
|
|
loca4 := 0x2a28 (* ( and * *);
|
|
loca8 := _memcmp(loca0, @loca4, 2);
|
|
if loca8 = 0 then
|
|
goto .Lskip_comment_continue
|
|
end;
|
|
goto .Lskip_comment_end;
|
|
|
|
.Lskip_comment_continue;
|
|
_advance(2) (* Skip (*. *);
|
|
|
|
loca4 := 0x292a (* ( and * *);
|
|
|
|
.Lskip_comment_loop;
|
|
loca0 := _current();
|
|
loca8 := _memcmp(loca0, @loca4, 2);
|
|
if loca8 = 0 then
|
|
goto .Lskip_comment_close
|
|
end;
|
|
|
|
_advance(1);
|
|
|
|
goto .Lskip_comment_loop;
|
|
|
|
.Lskip_comment_close;
|
|
_advance(2) (* Skip "*" and ")". *);
|
|
|
|
.Lskip_comment_end
|
|
end
|
|
|
|
(*
|
|
Parameters:
|
|
a0 - Line length.
|
|
*)
|
|
proc _compile_assembly(loca84: Word)
|
|
var loca0: ^Byte
|
|
begin
|
|
(* Write the source to the standard output. *)
|
|
loca0 := _current();
|
|
|
|
_write_out(loca0, loca84);
|
|
_advance(loca84);
|
|
|
|
_put_char(0xa) (* \n *);
|
|
|
|
_advance(1) (* Skip the new line. *)
|
|
end
|
|
|
|
proc _compile_program()
|
|
var loca0: Word
|
|
begin
|
|
(* .global _start *)
|
|
loca0 := 0x6f6c672e (* .glo *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x206c6162 (* bal_ *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x6174735f (* _sta *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x0a7472 (* rt\n *);
|
|
_write_out(@loca0, 3);
|
|
|
|
_advance(8) (* program\n. *)
|
|
end
|
|
|
|
proc _compile_constant_section()
|
|
var
|
|
loca0: Word
|
|
loca4: ^Byte
|
|
begin
|
|
(* .section .rodata *)
|
|
loca0 := 0x6365732e (* .sec *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x6e6f6974 (* tion *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x6f722e20 (* _.ro *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x61746164 (* data *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x0a (* \n *);
|
|
_write_out(@loca0, 1);
|
|
|
|
_advance(6) (* const\n. *);
|
|
|
|
.Lcompile_constant_section_item;
|
|
_skip_spaces();
|
|
loca4 := _current();
|
|
loca0 := _front(loca4);
|
|
if _is_upper(loca0) then
|
|
_compile_constant();
|
|
goto .Lcompile_constant_section_item
|
|
end;
|
|
|
|
.Lcompile_constant_section_end
|
|
end
|
|
|
|
proc _compile_constant()
|
|
var
|
|
loca0, loca4: Word
|
|
loca8: ^Byte
|
|
begin
|
|
loca4 := _read_token();
|
|
loca8 := _current() (* Save the identifier pointer before advancing it. *);
|
|
|
|
_write_out(loca8, loca4);
|
|
_advance(loca4);
|
|
|
|
_skip_spaces();
|
|
_advance(2) (* Skip the assignment sign. *);
|
|
|
|
(* : .long *)
|
|
loca0 := 0x6c2e203a (* : .l *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x20676e6f (* ong_ *);
|
|
_write_out(@loca0, 4);
|
|
|
|
_skip_spaces();
|
|
loca4 := _read_token();
|
|
loca8 := _current() (* Save the literal pointer before advancing it. *);
|
|
|
|
_write_out(loca8, loca4);
|
|
_advance(loca4);
|
|
|
|
_put_char(0x0a) (* \n *)
|
|
end
|
|
|
|
proc _compile_variable_section()
|
|
var
|
|
loca0: Word
|
|
loca4: ^Byte
|
|
begin
|
|
(* .section .bss *)
|
|
loca0 := 0x6365732e (* .sec *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x6e6f6974 (* tion *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x73622e20 (* _.bs *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x0a73 (* s\n *);
|
|
_write_out(@loca0, 2);
|
|
|
|
_advance(4) (* var\n. *);
|
|
|
|
.Lcompile_variable_section_item;
|
|
_skip_spaces();
|
|
loca4 := _current();
|
|
loca0 := _front(loca4);
|
|
|
|
if _is_lower(loca0) = 0 then
|
|
goto .Lcompile_variable_section_end
|
|
end;
|
|
_compile_variable();
|
|
goto .Lcompile_variable_section_item;
|
|
|
|
.Lcompile_variable_section_end
|
|
end
|
|
|
|
proc _compile_variable()
|
|
var
|
|
loca28, loca16: ^Byte
|
|
loca0, loca24, loca20: Word
|
|
begin
|
|
(* Save the identifier on the stack since it should emitted multiple times. *)
|
|
loca24 := _read_token();
|
|
loca28 := _current();
|
|
|
|
_advance(loca24);
|
|
|
|
_skip_spaces();
|
|
_advance(1) (* Skip the colon in front of the type. *);
|
|
|
|
_skip_spaces();
|
|
_advance(1) (* Skip the opening bracket. *);
|
|
|
|
(* Save the array size on the stack since it has to be emitted multiple times. *)
|
|
loca16 := _read_token();
|
|
loca20 := _current();
|
|
_advance(loca16);
|
|
|
|
_skip_spaces();
|
|
_advance(1) (* Skip the closing bracket. *);
|
|
|
|
_skip_spaces();
|
|
loca0 := _read_token();
|
|
_advance(loca0) (* Skip the type. *);
|
|
|
|
(* .type identifier, @object *)
|
|
loca0 := 0x7079742e (* .typ *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x2065 (* e_ *);
|
|
_write_out(@loca0, 2);
|
|
|
|
_write_out(loca28, loca24);
|
|
|
|
loca0 := 0x6f40202c (* , @o *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x63656a62 (* bjec *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x0a74 (* t\n *);
|
|
_write_out(@loca0, 2);
|
|
|
|
(* .size identifier, size *);
|
|
loca0 := 0x7a69732e (* .siz *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x2065 (* e_ *);
|
|
_write_out(@loca0, 2);
|
|
|
|
_write_out(loca28, loca24);
|
|
|
|
loca0 := 0x202c (* ,_ *);
|
|
_write_out(@loca0, 2);
|
|
|
|
_write_out(loca20, loca16);
|
|
_put_char(0x0a) (* \n *);
|
|
|
|
(* identifier: .zero size *)
|
|
_write_out(loca28, loca24);
|
|
|
|
loca0 := 0x7a2e203a (* : .z *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x206f7265 (* ero_ *);
|
|
_write_out(@loca0, 4);
|
|
|
|
_write_out(loca20, loca16);
|
|
|
|
_put_char(0x0a) (* \n *)
|
|
end
|
|
|
|
proc _compile_procedure()
|
|
var
|
|
loca0, loca4, loca8, loca12, loca16: Word
|
|
loca20, loca24: ^Byte
|
|
begin
|
|
_advance(5) (* Skip proc_ *);
|
|
loca16 := _read_token();
|
|
loca20 := _current();
|
|
_advance(loca16);
|
|
|
|
(* .type identifier, @function *);
|
|
loca0 := 0x7079742e (* .typ *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x2065 (* e_ *);
|
|
_write_out(@loca0, 2);
|
|
|
|
_write_out(loca20, loca16);
|
|
|
|
loca0 := 0x6640202c (* , @f *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x74636e75 (* unct *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x0a6e6f69 (* ion\n *);
|
|
_write_out(@loca0, 4);
|
|
|
|
_write_out(loca20, loca16);
|
|
|
|
loca0 := 0x0a3a (* :\n *);
|
|
_write_out(@loca0, 2);
|
|
|
|
_skip_spaces();
|
|
_advance(1) (* Skip opening argument paren. *);
|
|
_skip_spaces();
|
|
_advance(1) (* Skip closing argument paren. *);
|
|
|
|
loca12 := 0x6e (* n *);
|
|
loca8 := 0x69676562 (* begi *);
|
|
|
|
(*
|
|
Skip all declarations until we find the "begin" keyword, denoting the
|
|
beginning of the procedure body.
|
|
*)
|
|
.Lcompile_procedure_begin;
|
|
_skip_spaces();
|
|
loca0 := _read_token();
|
|
|
|
loca24 := _current();
|
|
_advance(loca0);
|
|
loca0 := _token_compare(loca24, loca0, @loca8);
|
|
|
|
if loca0 = 1 then
|
|
goto .Lcompile_procedure_begin
|
|
end;
|
|
|
|
(* Generate the procedure prologue with a predefined stack size. *)
|
|
loca0 := 0x69646461 (* addi *);
|
|
_write_out(@loca0, 4);
|
|
|
|
loca0 := 0x2c707320 (* _sp, *);
|
|
_write_out(@loca0, 4);
|
|
_write_out(@loca0, 4);
|
|
|
|
loca0 := 0x0a36392d (* -96\n *);
|
|
_write_out(@loca0, 4);
|
|
|
|
loca0 := 0x72207773 (* sw r *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x39202c61 (* a, 9 *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x70732832 (* 2(sp *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x0a29 (* )\n *);
|
|
_write_out(@loca0, 2);
|
|
|
|
loca0 := 0x73207773 (* sw s *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x38202c30 (* 0, 8 *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x70732838 (* 8(sp *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x0a29 (* )\n *);
|
|
_write_out(@loca0, 2);
|
|
|
|
loca0 := 0x69646461 (* addi *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x2c307320 (* _s0, *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x2c707320 (* _sp, *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x0a363920 (* _96\n *);
|
|
_write_out(@loca0, 4);
|
|
|
|
(* Save passed arguments on the stack. *)
|
|
loca0 := 0x61207773 (* sw a *);
|
|
_write_out(@loca0, 4);
|
|
loca4 := 0x38202c30 (* 0, 8 *);
|
|
_write_out(@loca4, 4);
|
|
loca8 := 0x70732834 (* 4(sp *);
|
|
_write_out(@loca8, 4);
|
|
loca12 := 0x0a29 (* )\n *);
|
|
_write_out(@loca12, 2);
|
|
|
|
_write_out(@loca0, 4);
|
|
loca4 := 0x38202c31 (* 1, 8 *);
|
|
_write_out(@loca4, 4);
|
|
loca8 := 0x70732830 (* 0(sp *);
|
|
_write_out(@loca8, 4);
|
|
_write_out(@loca12, 2);
|
|
|
|
_write_out(@loca0, 4);
|
|
loca4 := 0x37202c32 (* 2, 7 *);
|
|
_write_out(@loca4, 4);
|
|
loca8 := 0x70732836 (* 6(sp *);
|
|
_write_out(@loca8, 4);
|
|
_write_out(@loca12, 2);
|
|
|
|
_write_out(@loca0, 4);
|
|
loca4 := 0x37202c33 (* 3, 7 *);
|
|
_write_out(@loca4, 4);
|
|
loca8 := 0x70732832 (* 2(sp *);
|
|
_write_out(@loca8, 4);
|
|
_write_out(@loca12, 2);
|
|
|
|
_write_out(@loca0, 4);
|
|
loca4 := 0x36202c34 (* 4, 6 *);
|
|
_write_out(@loca4, 4);
|
|
loca8 := 0x70732838 (* 8(sp *);
|
|
_write_out(@loca8, 4);
|
|
_write_out(@loca12, 2);
|
|
|
|
_write_out(@loca0, 4);
|
|
loca4 := 0x36202c35 (* 5, 6 *);
|
|
_write_out(@loca4, 4);
|
|
loca8 := 0x70732838 (* 4(sp *);
|
|
_write_out(@loca8, 4);
|
|
_write_out(@loca12, 2);
|
|
|
|
(* Generate the body of the procedure. *)
|
|
.Lcompile_procedure_body;
|
|
_skip_spaces();
|
|
loca12 := _read_line();
|
|
loca8 := 0x0a646e65 (* end\n *);
|
|
loca24 := _current();
|
|
loca8 := _memcmp(loca24, @loca8, 4);
|
|
|
|
if loca8 = 0 then
|
|
goto .Lcompile_procedure_end
|
|
end;
|
|
|
|
_compile_line(loca12);
|
|
goto .Lcompile_procedure_body;
|
|
|
|
.Lcompile_procedure_end;
|
|
_advance(4) (* Skip end\n. *);
|
|
|
|
(* Generate the procedure epilogue with a predefined stack size. *)
|
|
loca0 := 0x7220776c (* lw r *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x39202c61 (* a, 9 *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x70732832 (* 2(sp *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x0a29 (* )\n *);
|
|
_write_out(@loca0, 2);
|
|
|
|
loca0 := 0x7320776c (* lw s *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x38202c30 (* 0, 8 *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x70732838 (* 8(sp *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x0a29 (* )\n *);
|
|
_write_out(@loca0, 2);
|
|
|
|
loca0 := 0x69646461 (* addi *);
|
|
_write_out(@loca0, 4);
|
|
|
|
loca0 := 0x2c707320 (* _sp, *);
|
|
_write_out(@loca0, 4);
|
|
_write_out(@loca0, 4);
|
|
|
|
loca0 := 0x0a3639 (* 96\n *);
|
|
_write_out(@loca0, 4);
|
|
|
|
loca0 := 0x0a746572 (* ret\n *);
|
|
_write_out(@loca0, 4)
|
|
end
|
|
|
|
(*
|
|
Compares two string, which of one has a length, the other one is null-terminated.
|
|
|
|
a0 - The address of the token string.
|
|
a1 - The length of the string in a0.
|
|
a2 - The address of the null-terminated string.
|
|
|
|
If the strings match sets a0 to 0, otherwise sets it to 1.
|
|
*)
|
|
proc _token_compare(loca84: ^Byte, loca80: Word, loca76: ^Byte)
|
|
var
|
|
loca0: Bool
|
|
loca4, loca12: Byte
|
|
loca8: Word
|
|
begin
|
|
.Ltoken_compare_loop;
|
|
loca4 := _front(loca76);
|
|
|
|
(*
|
|
Will only be 0 if the current character in the null terminated string is \0 and the remaining length of the
|
|
another string is 0.
|
|
*)
|
|
loca8 := loca4 or loca80;
|
|
if loca8 = 0 then
|
|
goto .Ltoken_compare_equal
|
|
end;
|
|
if loca80 = 0 then
|
|
goto .Ltoken_compare_not_equal
|
|
end;
|
|
if loca4 = 0 then
|
|
goto .Ltoken_compare_not_equal
|
|
end;
|
|
loca12 := _front(loca84);
|
|
if loca4 = loca12 then
|
|
goto .Ltoken_compare_continue
|
|
end;
|
|
goto .Ltoken_compare_not_equal;
|
|
|
|
.Ltoken_compare_continue;
|
|
|
|
loca84 := loca84 + 1;
|
|
loca80 := loca80 - 1;
|
|
loca76 := loca76 + 1;
|
|
goto .Ltoken_compare_loop;
|
|
|
|
.Ltoken_compare_not_equal;
|
|
loca0 := 1;
|
|
goto .Ltoken_compare_end;
|
|
|
|
.Ltoken_compare_equal;
|
|
loca0 := 0;
|
|
|
|
.Ltoken_compare_end;
|
|
return loca0
|
|
end
|
|
|
|
proc _compile_goto()
|
|
var
|
|
loca0: Word
|
|
loca8: ^Byte
|
|
begin
|
|
_advance(4) (* Skip the goto keyword. *);
|
|
|
|
loca0 := 0x206a (* j_ *);
|
|
_write_out(@loca0, 2);
|
|
|
|
_skip_spaces();
|
|
loca8 := _current() (* We should be on dot the label is beginning with. *);
|
|
_advance(1);
|
|
|
|
loca0 := _read_token();
|
|
_advance(loca0);
|
|
loca0 := loca0 + 1 (* Label length and the dot. *);
|
|
_write_out(loca8, loca0);
|
|
|
|
_advance(1) (* Skip the new line. *);
|
|
_put_char(0x0a) (* \n *)
|
|
end
|
|
|
|
(* a0 - Line length. *)
|
|
proc _compile_label(loca84: Word)
|
|
var
|
|
loca0: Word
|
|
begin
|
|
(* Write the whole line as is. *)
|
|
loca0 := _current();
|
|
|
|
loca0 := loca0 + loca84;
|
|
loca0 := loca0 - 1 (* Last character on the line. *);
|
|
loca4 := loca84;
|
|
|
|
loca0 := _front(loca0);
|
|
if loca0 = 0x3b then
|
|
loca4 := loca4 - 1
|
|
end;
|
|
_write_out(s1, loca4);
|
|
|
|
_put_char(0x3a) (* : *);
|
|
_put_char(0x0a) (* \n *);
|
|
|
|
_advance(loca84)
|
|
end
|
|
|
|
proc _compile_return()
|
|
begin
|
|
_advance(6) (* Skip return. *);
|
|
_skip_spaces();
|
|
_build_binary_expression();
|
|
end
|
|
|
|
proc _compile_if()
|
|
var
|
|
loca8, loca12, loca16, loca20: Word
|
|
loca4: ^Byte
|
|
begin
|
|
_advance(2) (* Skip the if. *);
|
|
_skip_spaces();
|
|
|
|
_build_binary_expression();
|
|
|
|
_skip_spaces();
|
|
_advance(4) (* Skip the then. *);
|
|
|
|
loca20 := 0x00646e65 (* if end marker and newline. *);
|
|
loca16 := 0x66694c2e (* Label prefix ".Lif". *);
|
|
|
|
loca12 := 0x7a716562 (* beqz *);
|
|
_write_out(@loca12, 4);
|
|
loca12 := 0x2c306120 (* _a0, *);
|
|
_write_out(@loca12, 4);
|
|
_put_char(0x20) (* _ *);
|
|
|
|
(* Write the label *);
|
|
_write_out(@loca16, 4);
|
|
_printi(s2);
|
|
|
|
_put_char(0x0a) (* \n *);
|
|
|
|
.Lcompile_if_loop;
|
|
_skip_spaces();
|
|
loca12 := _read_token();
|
|
|
|
loca4 := _current();
|
|
loca8 := _token_compare(loca4, loca12, @loca20);
|
|
|
|
if loca8 then
|
|
loca12 := _read_line();
|
|
_compile_line(loca12, 1);
|
|
|
|
goto .Lcompile_if_loop
|
|
end;
|
|
|
|
(* Write the label *)
|
|
_write_out(@loca16, 4);
|
|
_printi(s2);
|
|
|
|
loca12 := 0x0a3a0a3a (* :\n:\n *);
|
|
_write_out(@loca12, 2);
|
|
|
|
(* Increment the label counter. *);
|
|
s2 := s2 + 1;
|
|
_advance(4) (* Skip the end with newline. *)
|
|
end
|
|
|
|
(*
|
|
Parameters:
|
|
a0 - Line length.
|
|
a1 - Whether the section header was already emitted. If not it should be
|
|
emitted before any code is written.
|
|
|
|
Returns 1 in a0 if the parsed line contained a text section element such a
|
|
procedure or the program entry point. Otherwise sets a0 to 0.
|
|
*)
|
|
proc _compile_line(loca84: Word, loca80: Bool)
|
|
var
|
|
loca0: Char
|
|
loca4: Int
|
|
loca8: Bool
|
|
loca12: Word
|
|
loca16: ^Byte
|
|
begin
|
|
if loca84 = 0 then
|
|
goto .Lcompile_line_empty (* Skip an empty line. *)
|
|
end;
|
|
|
|
loca16 := _current();
|
|
loca0 := _front(loca16);
|
|
(* ( *)
|
|
if loca0 = 0x28 then
|
|
goto .Lcompile_line_comment
|
|
end;
|
|
loca16 := _current();
|
|
|
|
loca12 := 0x676f7270 (* prog *);
|
|
loca4 := _memcmp(loca16, @loca12, 4);
|
|
if loca4 = 0 then
|
|
goto .Lcompile_line_program
|
|
end;
|
|
|
|
loca12 := 0x736e6f63 (* cons *);
|
|
loca4 := _memcmp(loca16, @loca12, 4);
|
|
if loca4 = 0 then
|
|
goto .Lcompile_line_const
|
|
end;
|
|
|
|
loca12 := 0x0a726176 (* var\n *);
|
|
loca4 := _memcmp(loca16, @loca12, 4);
|
|
if loca4 = 0 then
|
|
goto .Lcompile_line_var
|
|
end;
|
|
|
|
loca12 := 0x636f7270 (* proc *);
|
|
loca4 := _memcmp(loca16, @loca12, 4);
|
|
if loca4 = 0 then
|
|
goto .Lcompile_line_procedure
|
|
end;
|
|
|
|
loca12 := 0x69676562 (* begi *);
|
|
loca4 := _memcmp(loca16, @loca12, 4);
|
|
if loca4 = 0 then
|
|
goto .Lcompile_line_begin
|
|
end;
|
|
|
|
loca12 := 0x2e646e65 (* end. *);
|
|
loca4 := _memcmp(loca16, @loca12, 4);
|
|
if loca4 = 0 then
|
|
goto .Lcompile_line_exit
|
|
end;
|
|
|
|
loca12 := 0x61636f6c (* loca *);
|
|
loca4 := _memcmp(loca16, @loca12, 4);
|
|
if loca4 = 0 then
|
|
goto .Lcompile_line_identifier
|
|
end;
|
|
loca4 := _front(loca16);
|
|
if loca4 = 0x73 then
|
|
goto .Lcompile_line_identifier
|
|
end;
|
|
|
|
loca12 := 0x6f706d69 (* impo *);
|
|
loca4 := _memcmp(loca16, @loca12, 4);
|
|
if loca4 = 0 then
|
|
goto .Lcompile_line_import
|
|
end;
|
|
|
|
loca12 := 0x6f746f67 (* goto *);
|
|
loca4 := _memcmp(loca16, @loca12, 4);
|
|
if loca4 = 0 then
|
|
goto .Lcompile_line_goto
|
|
end;
|
|
|
|
loca12 := 0x75746572 (* retu *);
|
|
loca4 := _memcmp(loca16, @loca12, 4);
|
|
if loca4 = 0 then
|
|
goto .Lcompile_line_return
|
|
end;
|
|
|
|
loca12 := 0x6669 (* if *);
|
|
loca4 := _memcmp(loca16, @loca12, 2);
|
|
if loca4 = 0 then
|
|
goto .Lcompile_line_if
|
|
end;
|
|
|
|
(* . *)
|
|
if loca0 = 0x2e then
|
|
goto .Lcompile_line_label
|
|
end;
|
|
(* _ *)
|
|
if loca0 = 0x5f then
|
|
goto .Lcompile_line_identifier
|
|
end;
|
|
goto .Lcompile_line_unchanged (* Else. *);
|
|
|
|
.Lcompile_line_if;
|
|
_compile_if();
|
|
goto .Lcompile_line_section;
|
|
|
|
.Lcompile_line_label;
|
|
_compile_label(loca84);
|
|
goto .Lcompile_line_section;
|
|
|
|
.Lcompile_line_return;
|
|
_compile_return();
|
|
goto .Lcompile_line_section;
|
|
|
|
.Lcompile_line_goto;
|
|
_compile_goto();
|
|
goto .Lcompile_line_section;
|
|
|
|
.Lcompile_line_import;
|
|
_compile_import();
|
|
goto .Lcompile_line_section;
|
|
|
|
.Lcompile_line_identifier;
|
|
_compile_identifier();
|
|
goto .Lcompile_line_section;
|
|
|
|
.Lcompile_line_exit;
|
|
_compile_exit();
|
|
goto .Lcompile_line_section;
|
|
|
|
.Lcompile_line_begin;
|
|
|
|
if loca80 = 1 then
|
|
goto .Lcompile_line_compile_entry
|
|
end;
|
|
_compile_text_section();
|
|
.Lcompile_line_compile_entry;
|
|
_compile_entry_point();
|
|
loca8 := 1;
|
|
goto .Lcompile_line_end;
|
|
|
|
.Lcompile_line_const;
|
|
_compile_constant_section();
|
|
goto .Lcompile_line_section;
|
|
|
|
.Lcompile_line_procedure;
|
|
if loca80 = 1 then
|
|
goto .Lcompile_line_compile_procedure
|
|
end;
|
|
_compile_text_section();
|
|
.Lcompile_line_compile_procedure;
|
|
_compile_procedure();
|
|
loca8 := 1;
|
|
goto .Lcompile_line_end;
|
|
|
|
.Lcompile_line_var;
|
|
_compile_variable_section();
|
|
goto .Lcompile_line_section;
|
|
|
|
.Lcompile_line_program;
|
|
_compile_program();
|
|
goto .Lcompile_line_section;
|
|
|
|
.Lcompile_line_comment;
|
|
_skip_comment(loca84);
|
|
goto .Lcompile_line_section;
|
|
|
|
.Lcompile_line_empty;
|
|
_advance(1);
|
|
goto .Lcompile_line_section;
|
|
|
|
.Lcompile_line_unchanged;
|
|
_compile_assembly(loca84);
|
|
goto .Lcompile_line_section;
|
|
|
|
.Lcompile_line_section;
|
|
loca8 := 0;
|
|
|
|
.Lcompile_line_end;
|
|
_skip_spaces();
|
|
_skip_comment();
|
|
|
|
return loca8
|
|
end
|
|
|
|
(* Prints ".section .text" and exits. *)
|
|
proc _compile_text_section()
|
|
var loca0: Word
|
|
begin
|
|
(* .section .text *)
|
|
loca0 := 0x6365732e (* .sec *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x6e6f6974 (* tion *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x65742e20 (* _.te *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x0a7478 (* xt\n *);
|
|
_write_out(@loca0, 3)
|
|
end
|
|
|
|
proc _compile_entry_point()
|
|
var loca0: Word
|
|
begin
|
|
(* .type _start, @function *)
|
|
loca0 := 0x7079742e (* .typ *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x735f2065 (* e _s *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x74726174 (* tart *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x6640202c (* , @f *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x74636e75 (* unct *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x0a6e6f69 (* ion\n *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x6174735f (* _sta *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x0a3a7472 (* rt:\n *);
|
|
_write_out(@loca0, 4);
|
|
|
|
_advance(6) (* Skip begin\n. *)
|
|
end
|
|
|
|
proc _compile_exit()
|
|
var loca0: Word
|
|
begin
|
|
(* li a0, 0 *)
|
|
(* li a7, SYS_EXIT *)
|
|
(* ecall *)
|
|
loca0 := 0x6120696c (* li a *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x30202c30 (* 0, 0 *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x20696c0a (* \nli_ *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x202c3761 (* a7,_ *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x650a3339 (* 93\ne *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x6c6c6163 (* call *);
|
|
_write_out(@loca0, 4);
|
|
loca0 := 0x0a (* \n *);
|
|
_write_out(@loca0, 1);
|
|
|
|
_advance(4) (* Skip end. *);
|
|
_skip_spaces() (* Read the possible new line at the end of the file. *)
|
|
end
|
|
|
|
(* Finds the end of the line and returns its length in a0. *)
|
|
proc _read_line()
|
|
var
|
|
loca0: ^Byte
|
|
loca4: Byte
|
|
begin
|
|
loca0 := _current() (* Local position in the source text. *);
|
|
|
|
.Lread_line_do;
|
|
loca4 := _front(loca0) (* t1 = Current character. *);
|
|
if loca4 = 0 then
|
|
goto .Lread_line_end (* Exit the loop on the NUL character. *)
|
|
end;
|
|
if loca4 = 0x0a then
|
|
goto .Lread_line_end (* Exit the loop on the new line. *)
|
|
end;
|
|
loca0 := loca0 + 1;
|
|
goto .Lread_line_do;
|
|
|
|
.Lread_line_end;
|
|
loca4 := _current();
|
|
return loca0 - loca4 (* Return the line length. *)
|
|
end
|
|
|
|
proc _compile()
|
|
var
|
|
loca0, loca4: Word
|
|
loca8: Bool
|
|
loca12: Char
|
|
loca16: ^Byte
|
|
begin
|
|
loca4 := 0 (* Whether the text section header was already emitted. *);
|
|
|
|
.Lcompile_do;
|
|
loca16 := _current();
|
|
loca12 := _front(loca16) (* t0 = Current character. *);
|
|
|
|
if loca12 = 0 then
|
|
goto .Lcompile_end (* Exit the loop on the NUL character. *)
|
|
end;
|
|
|
|
_skip_spaces();
|
|
loca0 := _read_line();
|
|
loca8 := _compile_line(loca0, loca4);
|
|
|
|
if loca8 = 0 then
|
|
goto .Lcompile_do
|
|
end;
|
|
(* Update whether the text section header was already emitted. *)
|
|
loca4 := loca4 or loca8;
|
|
|
|
goto .Lcompile_do;
|
|
.Lcompile_end
|
|
end
|
|
|
|
(* Returns the pointer to the current position in the source text in a0. *)
|
|
proc _current()
|
|
begin
|
|
return s1
|
|
end
|
|
|
|
(* a0 is the number of bytes to advance in the source text. *)
|
|
proc _advance(loca84: Word)
|
|
begin
|
|
s1 := s1 + loca84
|
|
end
|
|
|
|
(*
|
|
a0 - Pointer to an array to get the first element.
|
|
|
|
Returns the first character in the remaining source text.
|
|
*)
|
|
proc _front(loca84: ^Word)
|
|
begin
|
|
return _get(loca84) & 0xff
|
|
end
|
|
|
|
proc _main()
|
|
begin
|
|
(* Read the source from the standard input. *)
|
|
_read_file(source_code, SOURCE_BUFFER_SIZE);
|
|
|
|
s2 := 1
|
|
end
|
|
|
|
(* Entry point. *)
|
|
begin
|
|
_main();
|
|
_compile()
|
|
end.
|