diff --git a/erlang/apps/as/src/assemble.erl b/erlang/apps/as/src/assemble.erl index d873a8b..17807e9 100644 --- a/erlang/apps/as/src/assemble.erl +++ b/erlang/apps/as/src/assemble.erl @@ -100,18 +100,27 @@ stmts_image([Stmt | Stmts], Tunit, Acc) -> stmt_image(Stmt, Tunit) -> case Stmt of + #s_dot_byte{} -> dot_byte_image(Stmt, Tunit); #s_dot_long{} -> dot_long_image(Stmt, Tunit); + #s_dot_short{} -> dot_short_image(Stmt, Tunit); #s_insn{} -> insn_image(Stmt, Tunit) end. -dot_long_image(Stmt, Tunit) -> - #s_dot_long{exprs = Exprs} = Stmt, +dot_byte_image(#s_dot_byte{exprs = Exprs}, Tunit) -> + integer_data_directive(Exprs, Tunit, fun(Value) -> Value band ?PDP10_UINT9_MAX end). + +dot_long_image(#s_dot_long{exprs = Exprs}, Tunit) -> + integer_data_directive(Exprs, Tunit, fun pdp10_extint:uint36_to_ext/1). + +integer_data_directive(Exprs, Tunit, ValueToExt) -> case exprs_values(Exprs, Tunit) of - {ok, Values} -> - {ok, [pdp10_extint:uint36_to_ext(Value) || Value <- Values]}; + {ok, Values} -> {ok, lists:map(ValueToExt, Values)}; {error, _Reason} = Error -> Error end. +dot_short_image(#s_dot_short{exprs = Exprs}, Tunit) -> + integer_data_directive(Exprs, Tunit, fun pdp10_extint:uint18_to_ext/1). + insn_image(Stmt, Tunit) -> #s_insn{ high13 = High13 , at = At diff --git a/erlang/apps/as/src/input.erl b/erlang/apps/as/src/input.erl index ada52af..d2389cc 100644 --- a/erlang/apps/as/src/input.erl +++ b/erlang/apps/as/src/input.erl @@ -313,10 +313,12 @@ pass2_stmts([{Location, Stmt} | Stmts], Tunit) -> pass2_stmt(Location, Tunit, Stmt) -> case Stmt of + #s_dot_byte{} -> dot_byte(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_short{} -> dot_short(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); @@ -324,6 +326,11 @@ pass2_stmt(Location, Tunit, Stmt) -> #s_insn{} -> insn(Location, Tunit, Stmt) end. +dot_byte(Location, Tunit, #s_dot_byte{} = Stmt0) -> + integer_data_directive(Location, Tunit, Stmt0, 1, ".byte", + fun(Stmt) -> Stmt#s_dot_byte.exprs end, + fun(Stmt, Exprs) -> Stmt#s_dot_byte{exprs = Exprs} end). + dot_file(_Location, Tunit, #s_dot_file{string = String}) -> Symbol = #symbol{ name = String , section = false @@ -368,21 +375,34 @@ 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) -> +dot_long(Location, Tunit, #s_dot_long{} = Stmt0) -> + Size = 4, % FIXME: target-specific alignof and sizeof + integer_data_directive(Location, Tunit, Stmt0, Size, ".long", + fun(Stmt) -> Stmt#s_dot_long.exprs end, + fun(Stmt, Exprs) -> Stmt#s_dot_long{exprs = Exprs} end). + +integer_data_directive(Location, Tunit, Stmt, Size, Lexeme, GetExpr, SetExprs) -> + Exprs = GetExpr(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 + case Dot rem Size of 0 -> NewExprs = [expr_fixup(Tunit, Expr) || Expr <- Exprs], - NewStmt = Stmt#s_dot_long{exprs = NewExprs}, + NewStmt = SetExprs(Stmt, NewExprs), NewSection = Section#section{ data = {stmts, [NewStmt | Stmts]} - , dot = Dot + 4 * length(NewExprs) % FIXME: target-specific + , dot = Dot + Size * length(NewExprs) }, {ok, tunit:put_section(Tunit, NewSection)}; - _ -> fmterr(Location, "misaligned address for .long", []) + _ -> fmterr(Location, "misaligned address for ~s", [Lexeme]) end. +dot_short(Location, Tunit, #s_dot_short{} = Stmt0) -> + Size = 2, % FIXME: target-specific alignof and sizeof + integer_data_directive(Location, Tunit, Stmt0, Size, ".short", + fun(Stmt) -> Stmt#s_dot_short.exprs end, + fun(Stmt, Exprs) -> Stmt#s_dot_short{exprs = Exprs} end). + dot_size(Location, Tunit, #s_dot_size{name = Name}) -> #tunit{cursect = Cursect} = Tunit, #section{dot = Dot} = tunit:get_section(Tunit, Cursect), diff --git a/erlang/apps/as/src/parse.erl b/erlang/apps/as/src/parse.erl index d29a29d..d0cd659 100644 --- a/erlang/apps/as/src/parse.erl +++ b/erlang/apps/as/src/parse.erl @@ -34,18 +34,22 @@ -> {ok, {location(), stmt()}} | eof | {error, {module(), term()}}. stmt(ScanState) -> case scan:token(ScanState) of + {ok, {Location, ?T_DOT_BYTE}} -> dot_byte(ScanState, Location); {ok, {Location, ?T_DOT_DATA}} -> dot_data(ScanState, Location); {ok, {Location, ?T_DOT_FILE}} -> dot_file(ScanState, Location); {ok, {Location, ?T_DOT_GLOBL}} -> dot_globl(ScanState, Location); + {ok, {Location, ?T_DOT_HWORD}} -> dot_hword(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); + {ok, {Location, ?T_DOT_SHORT}} -> dot_short(ScanState, Location); {ok, {Location, ?T_DOT_SIZE}} -> dot_size(ScanState, Location); {ok, {Location, ?T_DOT_SUBSECTION}} -> dot_subsection(ScanState, Location); {ok, {Location, ?T_DOT_TEXT}} -> dot_text(ScanState, Location); {ok, {Location, ?T_DOT_TYPE}} -> dot_type(ScanState, Location); + {ok, {Location, ?T_DOT_WORD}} -> dot_word(ScanState, Location); {ok, {Location, {?T_SYMBOL, Name}}} -> stmt_after_symbol(ScanState, Location, Name); {ok, {Location, {?T_UINTEGER, UInt}}} -> stmt_after_uinteger(ScanState, Location, UInt); {ok, {_Location, ?T_NEWLINE}} -> stmt(ScanState); @@ -270,6 +274,10 @@ badinsn(Location, Fmt, Mnemonic) -> %% Directives ------------------------------------------------------------------ +dot_byte(ScanState, Location) -> + integer_data_directive(ScanState, Location, ".byte", + fun(Exprs) -> #s_dot_byte{exprs = Exprs} end). + dot_data(ScanState, Location) -> case scan:token(ScanState) of {ok, {_Location1, ?T_NEWLINE}} -> {ok, {Location, #s_dot_data{nr = 0}}}; @@ -311,12 +319,22 @@ dot_globl(ScanState, Location) -> ScanRes -> badtok("junk after .globl", ScanRes) end. +dot_hword(ScanState, Location) -> + dot_short(ScanState, Location, ".hword"). + dot_long(ScanState, Location) -> + dot_long(ScanState, Location, ".long"). + +dot_long(ScanState, Location, Lexeme) -> + integer_data_directive(ScanState, Location, Lexeme, + fun(Exprs) -> #s_dot_long{exprs = Exprs} end). + +integer_data_directive(ScanState, Location, Lexeme, MkStmt) -> 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}) + {_Location, ?T_NEWLINE} -> {ok, {Location, MkStmt(Exprs)}}; + _ -> badtok("junk after " ++ Lexeme ++ " ", {ok, Follow}) end; {error, _Reason} = Error -> Error end. @@ -360,6 +378,13 @@ dot_pushsection(ScanState, Location, Name) -> ScanRes -> badtok("junk after .pushsection ", ScanRes) end. +dot_short(ScanState, Location) -> + dot_short(ScanState, Location, ".short"). + +dot_short(ScanState, Location, Lexeme) -> + integer_data_directive(ScanState, Location, Lexeme, + fun(Exprs) -> #s_dot_short{exprs = Exprs} end). + %% For now only accepts ".size ,.-". TODO: extend dot_size(ScanState, Location) -> case scan:token(ScanState) of @@ -431,6 +456,9 @@ dot_type(ScanState, Location) -> ScanRes -> badtok("junk after .type", ScanRes) end. +dot_word(ScanState, Location) -> + dot_long(ScanState, Location, ".word"). + %% Expressions ----------------------------------------------------------------- %% ::= ( ("," )*)? diff --git a/erlang/apps/as/src/token.erl b/erlang/apps/as/src/token.erl index 59d1bc7..3ecc880 100644 --- a/erlang/apps/as/src/token.erl +++ b/erlang/apps/as/src/token.erl @@ -29,36 +29,44 @@ -spec from_symbol(string()) -> token(). from_symbol(Name) -> case Name of + ".byte" -> ?T_DOT_BYTE; ".data" -> ?T_DOT_DATA; ".file" -> ?T_DOT_FILE; ".globl" -> ?T_DOT_GLOBL; + ".hword" -> ?T_DOT_HWORD; ".ident" -> ?T_DOT_IDENT; ".long" -> ?T_DOT_LONG; ".popsection" -> ?T_DOT_POPSECTION; ".previous" -> ?T_DOT_PREVIOUS; ".pushsection" -> ?T_DOT_PUSHSECTION; + ".short" -> ?T_DOT_SHORT; ".size" -> ?T_DOT_SIZE; ".subsection" -> ?T_DOT_SUBSECTION; ".text" -> ?T_DOT_TEXT; ".type" -> ?T_DOT_TYPE; + ".word" -> ?T_DOT_WORD; _ -> {?T_SYMBOL, Name} end. -spec format(token()) -> io_lib:chars(). format(Token) -> case Token of + ?T_DOT_BYTE -> ".byte"; ?T_DOT_DATA -> ".data"; ?T_DOT_FILE -> ".file"; ?T_DOT_GLOBL -> ".globl"; + ?T_DOT_HWORD -> ".hword"; ?T_DOT_IDENT -> ".ident"; ?T_DOT_LONG -> ".long"; ?T_DOT_POPSECTION -> ".popsection"; ?T_DOT_PREVIOUS -> ".previous"; ?T_DOT_PUSHSECTION -> ".pushsection"; + ?T_DOT_SHORT -> ".short"; ?T_DOT_SIZE -> ".size"; ?T_DOT_SUBSECTION -> ".subsection"; ?T_DOT_TEXT -> ".text"; ?T_DOT_TYPE -> ".type"; + ?T_DOT_WORD -> ".word"; {?T_SYMBOL, Name} -> io_lib:format("symbol:~s", [Name]); {?T_LOCAL_LABEL, Number, Direction} -> io_lib:format("label: ~.10b~c", [Number, Direction]); diff --git a/erlang/apps/as/src/token.hrl b/erlang/apps/as/src/token.hrl index c792187..23553e9 100644 --- a/erlang/apps/as/src/token.hrl +++ b/erlang/apps/as/src/token.hrl @@ -26,18 +26,22 @@ %% with attributes (ordinary symbols, literals, errors). %% reserved symbols including directives +-define(T_DOT_BYTE, 'T_DOT_BYTE'). % .byte -define(T_DOT_DATA, 'T_DOT_DATA'). % .data -define(T_DOT_FILE, 'T_DOT_FILE'). % .file -define(T_DOT_GLOBL, 'T_DOT_GLOBL'). % .globl +-define(T_DOT_HWORD, 'T_DOT_HWORD'). % .hword -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 +-define(T_DOT_SHORT, 'T_DOT_SHORT'). % .short -define(T_DOT_SIZE, 'T_DOT_SIZE'). % .size -define(T_DOT_SUBSECTION, 'T_DOT_SUBSECTION'). % .subsection -define(T_DOT_TEXT, 'T_DOT_TEXT'). % .text -define(T_DOT_TYPE, 'T_DOT_TYPE'). % .type +-define(T_DOT_WORD, 'T_DOT_WORD'). % .word %% ordinary (non-reserved, non-special non-synthetic) symbols -define(T_SYMBOL, 'T_SYMBOL'). % pushj, foo, .Lbar @@ -60,18 +64,22 @@ -define(T_NEWLINE, 'T_NEWLINE'). % -define(T_EOF, 'T_EOF'). % --type token() :: ?T_DOT_DATA +-type token() :: ?T_DOT_BYTE + | ?T_DOT_DATA | ?T_DOT_FILE | ?T_DOT_GLOBL + | ?T_DOT_HWORD | ?T_DOT_IDENT | ?T_DOT_LONG | ?T_DOT_POPSECTION | ?T_DOT_PREVIOUS | ?T_DOT_PUSHSECTION + | ?T_DOT_SHORT | ?T_DOT_SIZE | ?T_DOT_SUBSECTION | ?T_DOT_TEXT | ?T_DOT_TYPE + | ?T_DOT_WORD | {?T_SYMBOL, string()} | {?T_LOCAL_LABEL, non_neg_integer(), $b | $f} | {?T_STRING, string()} diff --git a/erlang/apps/as/src/tunit.hrl b/erlang/apps/as/src/tunit.hrl index 213c8e4..19b5cb7 100644 --- a/erlang/apps/as/src/tunit.hrl +++ b/erlang/apps/as/src/tunit.hrl @@ -36,6 +36,9 @@ %% either interpreted immediately or appended to the representation of the %% current section. +%% .byte [expr (, expr)*] +-record(s_dot_byte, {exprs :: [expr()]}). + %% .data [nr] -record(s_dot_data, {nr :: non_neg_integer()}). @@ -60,6 +63,9 @@ %% .pushsection name [, nr] (TODO: extend) -record(s_dot_pushsection, {name :: string(), nr :: non_neg_integer()}). +%% .short [expr (, expr)*] +-record(s_dot_short, {exprs :: [expr()]}). + %% .size foo,.-foo (TODO: extend) -record(s_dot_size, {name :: string()}).