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:
%%
-%%