as: support symbols in instruction displacement operands

This commit is contained in:
Mikael Pettersson 2019-09-07 13:44:51 +02:00
parent af93b5caab
commit c41caee3ba
4 changed files with 107 additions and 26 deletions

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
.file "test2.s"
.text
.globl foo
.type foo,@function
foo: jumpa .Lfie
.Lfum: popj 017,
.Lfie: jumpa .Lfum
.size foo,.-foo

View File

@ -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]).

View File

@ -56,7 +56,7 @@ stmt(ScanState) ->
%%
%% <address> ::= "@"? <displacement>? <index>?
%%
%% <displacement> ::= <uinteger>
%% <displacement> ::= <uinteger> | <symbol>
%%
%% <index> ::= "(" <accumulator> ")"
%%
@ -66,6 +66,7 @@ stmt(ScanState) ->
%% popj 017,
%% pushj 017,bar
%% movei 1,@fum(2)
%% jump bar
%%
%% TODO: <displacement> should be <expr> 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 <symbol> <uinteger>", ScanRes)
end.
%% Seen "<symbol> <symbol2>". The <symbol2> is (the start of) the <displacement>.
%% TODO: permit <symbol2> to be the <accumulator> (named register or device).
insn_symbol(ScanState, Name, Symbol2) ->
Displacement = #e_symbol{name = Symbol2},
insn_ea_disp(ScanState, Name, _AccOrDev = false, _At = false, Displacement).
%% <symbol> <accordev> "," . [ ["@"] <displacement> ["(" <index> ")"] ] <newline>
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.
%% <symbol> [<accordev> ","] "@" . <displacement> . ["(" <index> ")"] <newline>
%% <symbol> [<accordev> ","] "@" . <displacement> ["(" <index> ")"] <newline>
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

View File

@ -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.