From 4850c75237cf1d4cb3b03f1f349b40e9ea271bf7 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Wed, 25 Dec 2019 21:51:02 +0100 Subject: [PATCH] as: handle .long directive --- erlang/apps/as/src/assemble.erl | 52 ++++++++++++++++++++++++--------- erlang/apps/as/src/input.erl | 26 +++++++++++++++-- erlang/apps/as/src/parse.erl | 52 +++++++++++++++++++++++++++++++++ erlang/apps/as/src/token.erl | 2 ++ erlang/apps/as/src/token.hrl | 2 ++ erlang/apps/as/src/tunit.hrl | 4 +++ 6 files changed, 121 insertions(+), 17 deletions(-) diff --git a/erlang/apps/as/src/assemble.erl b/erlang/apps/as/src/assemble.erl index 73b2aff..8e9bd76 100644 --- a/erlang/apps/as/src/assemble.erl +++ b/erlang/apps/as/src/assemble.erl @@ -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 diff --git a/erlang/apps/as/src/input.erl b/erlang/apps/as/src/input.erl index 6ffd39a..831d8e4 100644 --- a/erlang/apps/as/src/input.erl +++ b/erlang/apps/as/src/input.erl @@ -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 -------------------------------------------------------------- diff --git a/erlang/apps/as/src/parse.erl b/erlang/apps/as/src/parse.erl index fd37887..d29a29d 100644 --- a/erlang/apps/as/src/parse.erl +++ b/erlang/apps/as/src/parse.erl @@ -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 ", {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(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; diff --git a/erlang/apps/as/src/token.erl b/erlang/apps/as/src/token.erl index bf3b3ae..59d1bc7 100644 --- a/erlang/apps/as/src/token.erl +++ b/erlang/apps/as/src/token.erl @@ -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"; diff --git a/erlang/apps/as/src/token.hrl b/erlang/apps/as/src/token.hrl index 97d3464..c792187 100644 --- a/erlang/apps/as/src/token.hrl +++ b/erlang/apps/as/src/token.hrl @@ -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 diff --git a/erlang/apps/as/src/tunit.hrl b/erlang/apps/as/src/tunit.hrl index 2e106b1..213c8e4 100644 --- a/erlang/apps/as/src/tunit.hrl +++ b/erlang/apps/as/src/tunit.hrl @@ -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{}