mirror of
https://github.com/mikpe/pdp10-tools.git
synced 2026-01-23 19:08:00 +00:00
as: handle .long directive
This commit is contained in:
parent
b96d413aaf
commit
4850c75237
@ -43,7 +43,7 @@ section(Section, Tunit) ->
|
||||
#section{ name = ".text" ++ _
|
||||
, sh_type = ?SHT_PROGBITS
|
||||
, sh_flags = ?SHF_ALLOC bor ?SHF_EXECINSTR
|
||||
} -> text(Section, Tunit);
|
||||
} -> stmts(Section, Tunit);
|
||||
#section{ name = ".comment"
|
||||
, sh_type = ?SHT_PROGBITS
|
||||
, sh_flags = ?SHF_MERGE bor ?SHF_STRINGS
|
||||
@ -76,31 +76,45 @@ image_size([], Acc) -> Acc;
|
||||
image_size(TByte, Acc) when is_integer(TByte), 0 =< TByte, TByte =< 511 ->
|
||||
Acc + 1.
|
||||
|
||||
%% Assemble .text --------------------------------------------------------------
|
||||
%% Assemble user-defined contents ----------------------------------------------
|
||||
|
||||
text(Section = #section{data = {stmts, Stmts}}, Tunit) ->
|
||||
case text_image(Stmts, Tunit) of
|
||||
stmts(Section = #section{data = {stmts, Stmts}}, Tunit) ->
|
||||
case stmts_image(Stmts, Tunit) of
|
||||
{ok, Image} ->
|
||||
{ok, tunit:put_section(Tunit, Section#section{data = {image, Image}})};
|
||||
{error, _Reason} = Error -> Error
|
||||
end.
|
||||
|
||||
text_image(Stmts, Tunit) -> text_image(Stmts, Tunit, []).
|
||||
stmts_image(Stmts, Tunit) -> stmts_image(Stmts, Tunit, []).
|
||||
|
||||
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]);
|
||||
stmts_image([], _Tunit, Acc) -> {ok, Acc}; % the input Stmts were in reverse order
|
||||
stmts_image([Stmt | Stmts], Tunit, Acc) ->
|
||||
case stmt_image(Stmt, Tunit) of
|
||||
{ok, Image} -> stmts_image(Stmts, Tunit, [Image | Acc]);
|
||||
{error, _Reason} = Error -> Error
|
||||
end.
|
||||
|
||||
insn_image(Insn, Tunit) ->
|
||||
stmt_image(Stmt, Tunit) ->
|
||||
case Stmt of
|
||||
#s_dot_long{} -> dot_long_image(Stmt, Tunit);
|
||||
#s_insn{} -> insn_image(Stmt, Tunit)
|
||||
end.
|
||||
|
||||
dot_long_image(Stmt, Tunit) ->
|
||||
#s_dot_long{exprs = Exprs} = Stmt,
|
||||
case exprs_values(Exprs, Tunit) of
|
||||
{ok, Values} ->
|
||||
{ok, [pdp10_extint:uint36_to_ext(Value) || Value <- Values]};
|
||||
{error, _Reason} = Error -> Error
|
||||
end.
|
||||
|
||||
insn_image(Stmt, Tunit) ->
|
||||
#s_insn{ high13 = High13
|
||||
, at = At
|
||||
, address = AddressExpr
|
||||
, index = Index
|
||||
} = Insn,
|
||||
case insn_address(AddressExpr, Tunit) of
|
||||
} = Stmt,
|
||||
case expr_value(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
|
||||
@ -110,8 +124,18 @@ insn_image(Insn, Tunit) ->
|
||||
{error, _Reason} = Error -> Error
|
||||
end.
|
||||
|
||||
insn_address(AddressExpr, Tunit) ->
|
||||
case AddressExpr of
|
||||
exprs_values(Exprs, Tunit) ->
|
||||
exprs_values(Exprs, Tunit, []).
|
||||
|
||||
exprs_values([], _Tunit, Acc) -> {ok, lists:reverse(Acc)};
|
||||
exprs_values([Expr | Exprs], Tunit, Acc) ->
|
||||
case expr_value(Expr, Tunit) of
|
||||
{ok, Value} -> exprs_values(Exprs, Tunit, [Value | Acc]);
|
||||
{error, _Reason} = Error -> Error
|
||||
end.
|
||||
|
||||
expr_value(Expr, Tunit) ->
|
||||
case Expr of
|
||||
#e_integer{value = Value} -> {ok, Value};
|
||||
#e_symbol{name = Name} ->
|
||||
case tunit:get_symbol(Tunit, Name) of
|
||||
|
||||
@ -312,6 +312,7 @@ pass2_stmt(Location, Tunit, Stmt) ->
|
||||
#s_dot_file{} -> dot_file(Location, Tunit, Stmt);
|
||||
#s_dot_globl{} -> dot_globl(Location, Tunit, Stmt);
|
||||
#s_dot_ident{} -> dot_ident(Location, Tunit, Stmt);
|
||||
#s_dot_long{} -> dot_long(Location, Tunit, Stmt);
|
||||
#s_dot_size{} -> dot_size(Location, Tunit, Stmt);
|
||||
#s_dot_type{} -> dot_type(Location, Tunit, Stmt);
|
||||
#s_label{} -> label(Location, Tunit, Stmt);
|
||||
@ -363,6 +364,21 @@ dot_ident(_Location, Tunit, #s_dot_ident{} = Stmt) ->
|
||||
NewSection = OldSection#section{data = {stmts, [Stmt | Stmts]}},
|
||||
{ok, tunit:put_section(Tunit, NewSection)}.
|
||||
|
||||
dot_long(Location, Tunit, #s_dot_long{exprs = Exprs} = 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 ->
|
||||
NewExprs = [expr_fixup(Tunit, Expr) || Expr <- Exprs],
|
||||
NewStmt = Stmt#s_dot_long{exprs = NewExprs},
|
||||
NewSection =
|
||||
Section#section{ data = {stmts, [NewStmt | Stmts]}
|
||||
, dot = Dot + 4 * length(NewExprs) % FIXME: target-specific
|
||||
},
|
||||
{ok, tunit:put_section(Tunit, NewSection)};
|
||||
_ -> fmterr(Location, "misaligned address for .long", [])
|
||||
end.
|
||||
|
||||
dot_size(Location, Tunit, #s_dot_size{name = Name}) ->
|
||||
#tunit{cursect = Cursect} = Tunit,
|
||||
#section{dot = Dot} = tunit:get_section(Tunit, Cursect),
|
||||
@ -448,7 +464,11 @@ insn(Location, Tunit, #s_insn{} = Stmt) ->
|
||||
end.
|
||||
|
||||
insn_fixup(Tunit, Insn) ->
|
||||
case Insn#s_insn.address of
|
||||
Address = Insn#s_insn.address,
|
||||
Insn#s_insn{address = expr_fixup(Tunit, Address)}.
|
||||
|
||||
expr_fixup(Tunit, Expr) ->
|
||||
case Expr of
|
||||
#e_local_label{number = Number, direction = Direction} ->
|
||||
LabelSerial = local_label_serial(Tunit, Number),
|
||||
ReferenceSerial =
|
||||
@ -457,8 +477,8 @@ insn_fixup(Tunit, Insn) ->
|
||||
$f -> LabelSerial + 1
|
||||
end,
|
||||
Name = local_label_name(Number, ReferenceSerial),
|
||||
Insn#s_insn{address = #e_symbol{name = Name}};
|
||||
_ -> Insn
|
||||
#e_symbol{name = Name};
|
||||
_ -> Expr
|
||||
end.
|
||||
|
||||
%% Initialization --------------------------------------------------------------
|
||||
|
||||
@ -38,6 +38,7 @@ stmt(ScanState) ->
|
||||
{ok, {Location, ?T_DOT_FILE}} -> dot_file(ScanState, Location);
|
||||
{ok, {Location, ?T_DOT_GLOBL}} -> dot_globl(ScanState, Location);
|
||||
{ok, {Location, ?T_DOT_IDENT}} -> dot_ident(ScanState, Location);
|
||||
{ok, {Location, ?T_DOT_LONG}} -> dot_long(ScanState, Location);
|
||||
{ok, {Location, ?T_DOT_POPSECTION}} -> dot_popsection(ScanState, Location);
|
||||
{ok, {Location, ?T_DOT_PREVIOUS}} -> dot_previous(ScanState, Location);
|
||||
{ok, {Location, ?T_DOT_PUSHSECTION}} -> dot_pushsection(ScanState, Location);
|
||||
@ -310,6 +311,16 @@ dot_globl(ScanState, Location) ->
|
||||
ScanRes -> badtok("junk after .globl", ScanRes)
|
||||
end.
|
||||
|
||||
dot_long(ScanState, Location) ->
|
||||
case expr_list(ScanState) of
|
||||
{ok, {Exprs, Follow}} ->
|
||||
case Follow of
|
||||
{_Location, ?T_NEWLINE} -> {ok, {Location, #s_dot_long{exprs = Exprs}}};
|
||||
_ -> badtok("junk after .long <exprs>", {ok, Follow})
|
||||
end;
|
||||
{error, _Reason} = Error -> Error
|
||||
end.
|
||||
|
||||
dot_popsection(ScanState, Location) ->
|
||||
case scan:token(ScanState) of
|
||||
{ok, {_Location, ?T_NEWLINE}} -> {ok, {Location, #s_dot_popsection{}}};
|
||||
@ -420,6 +431,47 @@ dot_type(ScanState, Location) ->
|
||||
ScanRes -> badtok("junk after .type", ScanRes)
|
||||
end.
|
||||
|
||||
%% Expressions -----------------------------------------------------------------
|
||||
|
||||
%% <expr_list> ::= (<expr> ("," <expr>)*)?
|
||||
expr_list(ScanState) ->
|
||||
case expr_opt(ScanState) of
|
||||
{false, Follow} -> {ok, {[], Follow}};
|
||||
{ok, Expr} -> expr_list(ScanState, [Expr]);
|
||||
{error, _Reason} = Error -> Error
|
||||
end.
|
||||
|
||||
expr_list(ScanState, Exprs) ->
|
||||
case scan:token(ScanState) of
|
||||
{ok, {_Location, ?T_COMMA}} ->
|
||||
case expr(ScanState) of
|
||||
{ok, Expr} -> expr_list(ScanState, [Expr | Exprs]);
|
||||
{error, _Reason} = Error -> Error
|
||||
end;
|
||||
{ok, Follow} -> {ok, {lists:reverse(Exprs), Follow}};
|
||||
{error, _Reason} = Error -> Error
|
||||
end.
|
||||
|
||||
expr(ScanState) ->
|
||||
case expr_opt(ScanState) of
|
||||
{false, First} -> badtok("invalid start of expr", {ok, First});
|
||||
OkOrError -> OkOrError
|
||||
end.
|
||||
|
||||
expr_opt(ScanState) ->
|
||||
case scan:token(ScanState) of
|
||||
{ok, {_Location, {?T_UINTEGER, UInt}}} ->
|
||||
{ok, #e_integer{value = UInt}};
|
||||
{ok, {_Location, {?T_LOCAL_LABEL, Number, Direction}}} ->
|
||||
{ok, #e_local_label{number = Number, direction = Direction}};
|
||||
{ok, {_Location, {?T_SYMBOL, Symbol}}} ->
|
||||
{ok, #e_symbol{name = Symbol}};
|
||||
{ok, First} ->
|
||||
{false, First};
|
||||
{error, _Reason} = Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
%% Error reporting -------------------------------------------------------------
|
||||
|
||||
badtok(_ErrMsg, {error, _Reason} = Error) -> Error;
|
||||
|
||||
@ -33,6 +33,7 @@ from_symbol(Name) ->
|
||||
".file" -> ?T_DOT_FILE;
|
||||
".globl" -> ?T_DOT_GLOBL;
|
||||
".ident" -> ?T_DOT_IDENT;
|
||||
".long" -> ?T_DOT_LONG;
|
||||
".popsection" -> ?T_DOT_POPSECTION;
|
||||
".previous" -> ?T_DOT_PREVIOUS;
|
||||
".pushsection" -> ?T_DOT_PUSHSECTION;
|
||||
@ -50,6 +51,7 @@ format(Token) ->
|
||||
?T_DOT_FILE -> ".file";
|
||||
?T_DOT_GLOBL -> ".globl";
|
||||
?T_DOT_IDENT -> ".ident";
|
||||
?T_DOT_LONG -> ".long";
|
||||
?T_DOT_POPSECTION -> ".popsection";
|
||||
?T_DOT_PREVIOUS -> ".previous";
|
||||
?T_DOT_PUSHSECTION -> ".pushsection";
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
-define(T_DOT_FILE, 'T_DOT_FILE'). % .file
|
||||
-define(T_DOT_GLOBL, 'T_DOT_GLOBL'). % .globl
|
||||
-define(T_DOT_IDENT, 'T_DOT_IDENT'). % .ident
|
||||
-define(T_DOT_LONG, 'T_DOT_LONG'). % .long
|
||||
-define(T_DOT_POPSECTION, 'T_DOT_POPSECTION'). % .popsection
|
||||
-define(T_DOT_PREVIOUS, 'T_DOT_PREVIOUS'). % .previous
|
||||
-define(T_DOT_PUSHSECTION, 'T_DOT_PUSHSECTION'). % .pushsection
|
||||
@ -63,6 +64,7 @@
|
||||
| ?T_DOT_FILE
|
||||
| ?T_DOT_GLOBL
|
||||
| ?T_DOT_IDENT
|
||||
| ?T_DOT_LONG
|
||||
| ?T_DOT_POPSECTION
|
||||
| ?T_DOT_PREVIOUS
|
||||
| ?T_DOT_PUSHSECTION
|
||||
|
||||
@ -48,6 +48,9 @@
|
||||
%% .ident "..."
|
||||
-record(s_dot_ident, {string :: string()}).
|
||||
|
||||
%% .long [expr (, expr)*]
|
||||
-record(s_dot_long, {exprs :: [expr()]}).
|
||||
|
||||
%% .popsection
|
||||
-record(s_dot_popsection, {}).
|
||||
|
||||
@ -85,6 +88,7 @@
|
||||
| #s_dot_file{}
|
||||
| #s_dot_globl{}
|
||||
| #s_dot_ident{}
|
||||
| #s_dot_long{}
|
||||
| #s_dot_popsection{}
|
||||
| #s_dot_previous{}
|
||||
| #s_dot_pushsection{}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user