From c41caee3bad1d5614a6a7be7d6bfd20459c1d4a9 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Sat, 7 Sep 2019 13:44:51 +0200 Subject: [PATCH] as: support symbols in instruction displacement operands --- erlang/apps/as/priv/test2.s | 28 +++++++++++++++ erlang/apps/as/src/assemble.erl | 61 +++++++++++++++++++++++---------- erlang/apps/as/src/parse.erl | 35 +++++++++++++++---- erlang/apps/as/src/tunit.hrl | 9 +++++ 4 files changed, 107 insertions(+), 26 deletions(-) create mode 100644 erlang/apps/as/priv/test2.s diff --git a/erlang/apps/as/priv/test2.s b/erlang/apps/as/priv/test2.s new file mode 100644 index 0000000..ada805b --- /dev/null +++ b/erlang/apps/as/priv/test2.s @@ -0,0 +1,28 @@ +/* + * test2.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 "test2.s" + .text + .globl foo + .type foo,@function +foo: jumpa .Lfie +.Lfum: popj 017, +.Lfie: jumpa .Lfum + .size foo,.-foo diff --git a/erlang/apps/as/src/assemble.erl b/erlang/apps/as/src/assemble.erl index 6f6c0c7..d6e7c53 100644 --- a/erlang/apps/as/src/assemble.erl +++ b/erlang/apps/as/src/assemble.erl @@ -73,38 +73,61 @@ image_size(Image) -> image_size(Image, 0). image_size([H | T], Acc) -> image_size(T, image_size(H, Acc)); image_size([], Acc) -> Acc; -image_size(TByte, Acc) when is_integer(TByte), 0 =< TByte, TByte =< 511 -> Acc + 1. +image_size(TByte, Acc) when is_integer(TByte), 0 =< TByte, TByte =< 511 -> + Acc + 1. %% Assemble .text -------------------------------------------------------------- text(Section = #section{data = {stmts, Stmts}}, Tunit) -> - Image = text_image(Stmts), - {ok, tunit:put_section(Tunit, Section#section{data = {image, Image}})}. + case text_image(Stmts, Tunit) of + {ok, Image} -> + {ok, tunit:put_section(Tunit, Section#section{data = {image, Image}})}; + {error, _Reason} = Error -> Error + end. -text_image(Stmts) -> text_image(Stmts, []). +text_image(Stmts, Tunit) -> text_image(Stmts, Tunit, []). -text_image([], Acc) -> Acc; % the input Stmts were in reverse order -text_image([Stmt | Stmts], Acc) -> - text_image(Stmts, [insn_image(Stmt) | Acc]). +text_image([], _Tunit, Acc) -> {ok, Acc}; % the input Stmts were in reverse order +text_image([Stmt | Stmts], Tunit, Acc) -> + case insn_image(Stmt, Tunit) of + {ok, Image} -> text_image(Stmts, Tunit, [Image | Acc]); + {error, _Reason} = Error -> Error + end. -insn_image(Insn) -> +insn_image(Insn, Tunit) -> #s_insn{ high13 = High13 , at = At - , address = Address + , address = AddressExpr , index = Index } = Insn, - Word = (((High13 band ((1 bsl 13) - 1)) bsl (36 - 13)) bor - ((case At of true -> 1; false -> 0 end) bsl (36 - 14)) bor - ((Index band ((1 bsl 4) - 1)) bsl (36 - 18)) bor - (Address band ((1 bsl 18) - 1))), - %% big-endian conversion - [(Word bsr 27) band 511, - (Word bsr 18) band 511, - (Word bsr 9) band 511, - Word band 511]. + case insn_address(AddressExpr, Tunit) of + {ok, Address} -> + Word = (((High13 band ((1 bsl 13) - 1)) bsl (36 - 13)) bor + ((case At of true -> 1; false -> 0 end) bsl (36 - 14)) bor + ((Index band ((1 bsl 4) - 1)) bsl (36 - 18)) bor + (Address band ((1 bsl 18) - 1))), + %% big-endian conversion + {ok, [(Word bsr 27) band 511, + (Word bsr 18) band 511, + (Word bsr 9) band 511, + Word band 511]}; + {error, _Reason} = Error -> Error + end. + +insn_address(AddressExpr, Tunit) -> + case AddressExpr of + #e_integer{value = Value} -> {ok, Value}; + #e_symbol{name = Name} -> + case tunit:get_symbol(Tunit, Name) of + #symbol{st_value = Value} when Value =/= false -> {ok, Value}; + _ -> {error, {?MODULE, {undefined_symbol, Name}}} + end + end. %% Error reporting ------------------------------------------------------------- -spec format_error(term()) -> io_lib:chars(). format_error({cannot_assemble, Name}) -> - io_lib:format("don't know how to assemble section ~s", [Name]). + io_lib:format("don't know how to assemble section ~s", [Name]); +format_error({undefined_symbol, Name}) -> + io_lib:format("reference to undefined symbol ~s", [Name]). diff --git a/erlang/apps/as/src/parse.erl b/erlang/apps/as/src/parse.erl index 8d98608..1969291 100644 --- a/erlang/apps/as/src/parse.erl +++ b/erlang/apps/as/src/parse.erl @@ -56,7 +56,7 @@ stmt(ScanState) -> %% %%
::= "@"? ? ? %% -%% ::= +%% ::= | %% %% ::= "(" ")" %% @@ -66,6 +66,7 @@ stmt(ScanState) -> %% popj 017, %% pushj 017,bar %% movei 1,@fum(2) +%% jump bar %% %% TODO: should be and permit parentheses and %% various operators. @@ -92,6 +93,7 @@ stmt_after_symbol(ScanState, Name) -> {ok, ?T_COLON} -> {ok, #s_label{name = Name}}; {ok, ?T_NEWLINE} -> make_insn(ScanState, Name, false, false, false, false); {ok, {?T_UINTEGER, UInt}} -> insn_uint(ScanState, Name, UInt); + {ok, {?T_SYMBOL, Symbol}} -> insn_symbol(ScanState, Name, Symbol); ScanRes -> badtok(ScanState, "junk after symbol", ScanRes) end. @@ -102,27 +104,43 @@ insn_uint(ScanState, Name, UInt) -> {ok, ?T_COMMA} -> % the Uint is the Accumulator, parse EA next insn_ea(ScanState, Name, _AccOrDev = UInt); {ok, ?T_LPAREN} -> % the Uint is the Displacement, parse Index next - insn_ea_index(ScanState, Name, _AccOrDev = false, _At = false, _Displacement = UInt); + Displacement = #e_integer{value = UInt}, + insn_ea_index(ScanState, Name, _AccOrDev = false, _At = false, Displacement); {ok, ?T_NEWLINE} -> % the Uint is the Displacement - make_insn(ScanState, Name, _AccOrDev = false, _At = false, _Displacement = UInt, _Index = false); + Displacement = #e_integer{value = UInt}, + make_insn(ScanState, Name, _AccOrDev = false, _At = false, Displacement, _Index = false); ScanRes -> badtok(ScanState, "junk after ", ScanRes) end. +%% Seen " ". The is (the start of) the . +%% TODO: permit to be the (named register or device). +insn_symbol(ScanState, Name, Symbol2) -> + Displacement = #e_symbol{name = Symbol2}, + insn_ea_disp(ScanState, Name, _AccOrDev = false, _At = false, Displacement). + %% "," . [ ["@"] ["(" ")"] ] insn_ea(ScanState, Name, AccOrDev) -> case scan:token(ScanState) of {ok, ?T_NEWLINE} -> make_insn(ScanState, Name, AccOrDev, _At = false, _Displacement = false, _Index = false); {ok, ?T_AT} -> insn_ea_at(ScanState, Name, AccOrDev); - {ok, {?T_UINTEGER, Displacement}} -> + {ok, {?T_UINTEGER, UInt}} -> + Displacement = #e_integer{value = UInt}, + insn_ea_disp(ScanState, Name, AccOrDev, _At = false, Displacement); + {ok, {?T_SYMBOL, Symbol}} -> + Displacement = #e_symbol{name = Symbol}, insn_ea_disp(ScanState, Name, AccOrDev, _At = false, Displacement); ScanRes -> badtok(ScanState, "junk after comma", ScanRes) end. -%% [ ","] "@" . . ["(" ")"] +%% [ ","] "@" . ["(" ")"] insn_ea_at(ScanState, Name, AccOrDev) -> case scan:token(ScanState) of - {ok, {?T_UINTEGER, Displacement}} -> + {ok, {?T_UINTEGER, UInt}} -> + Displacement = #e_integer{value = UInt}, + insn_ea_disp(ScanState, Name, AccOrDev, _At = true, Displacement); + {ok, {?T_SYMBOL, Symbol}} -> + Displacement = #e_symbol{name = Symbol}, insn_ea_disp(ScanState, Name, AccOrDev, _At = true, Displacement); ScanRes -> badtok(ScanState, "junk after @", ScanRes) end. @@ -167,7 +185,10 @@ make_insn(ScanState, Name, AccOrDev, At, Displacement, Index) -> {error, _Reason} = Error -> Error; ok -> {ok, #s_insn{ high13 = FinalHigh13 , at = At - , address = if Displacement =:= false -> 0; true -> Displacement end + , address = case Displacement of + false -> #e_integer{value = 0}; + _ -> Displacement + end , index = if Index =:= false -> 0; true -> Index end }} end diff --git a/erlang/apps/as/src/tunit.hrl b/erlang/apps/as/src/tunit.hrl index 2adca2e..1090745 100644 --- a/erlang/apps/as/src/tunit.hrl +++ b/erlang/apps/as/src/tunit.hrl @@ -21,6 +21,15 @@ -ifndef(TUNIT_HRL). -define(TUNIT_HRL, 1). +%% An expression occurring in a statement. (TODO: extend) + +-record(e_integer, {value :: integer()}). +-record(e_symbol, {name :: string()}). + +-type expr() :: #e_integer{} + | #e_symbol{} + . + %% A directive, label, or instruction is parsed to a statement, which is %% either interpreted immediately or appended to the representation of the %% current section.