mirror of
https://github.com/mikpe/pdp10-tools.git
synced 2026-01-24 19:32:52 +00:00
as: handle .byte, .hword, .short, and .word directives
This commit is contained in:
parent
896378c3b5
commit
9f51730200
@ -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
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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 <exprs>", {ok, Follow})
|
||||
{_Location, ?T_NEWLINE} -> {ok, {Location, MkStmt(Exprs)}};
|
||||
_ -> badtok("junk after " ++ Lexeme ++ " <exprs>", {ok, Follow})
|
||||
end;
|
||||
{error, _Reason} = Error -> Error
|
||||
end.
|
||||
@ -360,6 +378,13 @@ dot_pushsection(ScanState, Location, Name) ->
|
||||
ScanRes -> badtok("junk after .pushsection <name>", 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 <sym>,.-<sym>". 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 -----------------------------------------------------------------
|
||||
|
||||
%% <expr_list> ::= (<expr> ("," <expr>)*)?
|
||||
|
||||
@ -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]);
|
||||
|
||||
@ -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'). % <end-of-line>
|
||||
-define(T_EOF, 'T_EOF'). % <end-of-file>
|
||||
|
||||
-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()}
|
||||
|
||||
@ -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()}).
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user