From d3e5383f3647ed55f2f91355083f3ad55d358344 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Sat, 7 Sep 2019 17:40:39 +0200 Subject: [PATCH] as: support local labels --- erlang/apps/as/priv/test3.s | 28 ++++++++++++++++++++++++ erlang/apps/as/src/input.erl | 41 ++++++++++++++++++++++++++++++++---- erlang/apps/as/src/parse.erl | 25 ++++++++++++++++++++-- erlang/apps/as/src/scan.erl | 3 ++- erlang/apps/as/src/token.erl | 4 +++- erlang/apps/as/src/token.hrl | 6 ++++-- erlang/apps/as/src/tunit.erl | 11 ++++++++++ erlang/apps/as/src/tunit.hrl | 7 +++++- 8 files changed, 114 insertions(+), 11 deletions(-) create mode 100644 erlang/apps/as/priv/test3.s diff --git a/erlang/apps/as/priv/test3.s b/erlang/apps/as/priv/test3.s new file mode 100644 index 0000000..61f728d --- /dev/null +++ b/erlang/apps/as/priv/test3.s @@ -0,0 +1,28 @@ +/* + * test3.s + * Copyright (C) 2019 Mikael Pettersson + * + * This file is part of pdp10-tools. + * + * pdp10-tools is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pdp10-tools is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pdp10-tools. If not, see . + */ + + .file "test3.s" + .text + .globl foo + .type foo,@function +foo: jumpa 1f +0: popj 017, +1: jumpa 0b + .size foo,.-foo diff --git a/erlang/apps/as/src/input.erl b/erlang/apps/as/src/input.erl index a950666..51ce550 100644 --- a/erlang/apps/as/src/input.erl +++ b/erlang/apps/as/src/input.erl @@ -80,6 +80,7 @@ interpret(ScanState, Tunit, Stmt) -> #s_dot_text{} -> dot_text(ScanState, Tunit, Stmt); #s_dot_type{} -> dot_type(ScanState, Tunit, Stmt); #s_label{} -> label(ScanState, Tunit, Stmt); + #s_local_label{} -> local_label(ScanState, Tunit, Stmt); #s_insn{} -> insn(ScanState, Tunit, Stmt) end. @@ -175,29 +176,61 @@ dot_type(ScanState, Tunit, #s_dot_type{name = Name}) -> label(ScanState, Tunit, #s_label{name = Name}) -> case tunit:get_symbol(Tunit, Name) of - #symbol{section = false, st_value = false} = Symbol -> label2(Tunit, Symbol); + #symbol{section = false, st_value = false} = Symbol -> define_label(Tunit, Symbol); #symbol{} -> fmterr(ScanState, "label ~s already defined", [Name]); - false -> label2(Tunit, #symbol{name = Name, st_size = false, st_info = 0}) + false -> define_new_label(Tunit, Name) end. -label2(Tunit, Symbol) -> +define_new_label(Tunit, Name) -> + define_label(Tunit, #symbol{name = Name, st_size = false, st_info = 0}). + +define_label(Tunit, Symbol) -> #tunit{cursect = Cursect} = Tunit, #section{dot = Dot} = tunit:get_section(Tunit, Cursect), {ok, tunit:put_symbol(Tunit, Symbol#symbol{section = Cursect, st_value = Dot})}. +local_label(_ScanState, Tunit, #s_local_label{number = Number}) -> + Serial = local_label_serial(Tunit, Number) + 1, + Name = local_label_name(Number, Serial), + define_new_label(tunit:put_local_label(Tunit, Number, Serial), Name). + +local_label_serial(Tunit, Number) -> + case tunit:get_local_label(Tunit, Number) of + false -> 0; + Serial -> Serial + end. + +local_label_name(Number, Serial) -> + lists:flatten(io_lib:format(".L~.10b\^B~.10b", [Number, Serial])). + insn(ScanState, Tunit, #s_insn{} = Stmt) -> #tunit{cursect = Cursect} = Tunit, #section{data = {stmts, Stmts}, dot = Dot} = Section = tunit:get_section(Tunit, Cursect), case Dot rem 4 of % FIXME: target-specific 0 -> + NewStmt = insn_fixup(Tunit, Stmt), NewSection = - Section#section{ data = {stmts, [Stmt | Stmts]} + Section#section{ data = {stmts, [NewStmt | Stmts]} , dot = Dot + 4 % FIXME: target-specific }, {ok, tunit:put_section(Tunit, NewSection)}; _ -> fmterr(ScanState, "misaligned address for instruction", []) end. +insn_fixup(Tunit, Insn) -> + case Insn#s_insn.address of + #e_local_label{number = Number, direction = Direction} -> + LabelSerial = local_label_serial(Tunit, Number), + ReferenceSerial = + case Direction of + $b -> LabelSerial; + $f -> LabelSerial + 1 + end, + Name = local_label_name(Number, ReferenceSerial), + Insn#s_insn{address = #e_symbol{name = Name}}; + _ -> Insn + end. + %% Initialization -------------------------------------------------------------- tunit_init() -> diff --git a/erlang/apps/as/src/parse.erl b/erlang/apps/as/src/parse.erl index 1969291..cdd5779 100644 --- a/erlang/apps/as/src/parse.erl +++ b/erlang/apps/as/src/parse.erl @@ -39,6 +39,7 @@ stmt(ScanState) -> {ok, ?T_DOT_TEXT} -> dot_text(ScanState); {ok, ?T_DOT_TYPE} -> dot_type(ScanState); {ok, {?T_SYMBOL, Name}} -> stmt_after_symbol(ScanState, Name); + {ok, {?T_UINTEGER, UInt}} -> stmt_after_uinteger(ScanState, UInt); {ok, ?T_NEWLINE} -> stmt(ScanState); {ok, ?T_EOF} -> eof; ScanRes -> badtok(ScanState, "expected directive, label, or instruction", ScanRes) @@ -48,7 +49,7 @@ stmt(ScanState) -> %% %% Recognize: %% -%%