mirror of
https://github.com/mikpe/pdp10-tools.git
synced 2026-05-05 23:44:34 +00:00
as: add support for Sym1-Sym2 expressions
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
%%% -*- erlang-indent-level: 2 -*-
|
||||
%%%
|
||||
%%% sections assembler for pdp10-elf as
|
||||
%%% Copyright (C) 2013-2020 Mikael Pettersson
|
||||
%%% Copyright (C) 2013-2023 Mikael Pettersson
|
||||
%%%
|
||||
%%% This file is part of pdp10-tools.
|
||||
%%%
|
||||
@@ -183,16 +183,48 @@ exprs_values([Expr | Exprs], Tunit, SectionName, Dot, Size, Context, AccValues,
|
||||
{ok, {Value, Relocs}} = expr_value(Expr, Tunit, SectionName, Dot, Context),
|
||||
exprs_values(Exprs, Tunit, SectionName, Dot + Size, Size, Context, [Value | AccValues], Relocs ++ AccRelocs).
|
||||
|
||||
expr_value(Expr, Tunit, SectionName, Dot, Context) ->
|
||||
#expr{symbol = Name, offset = Offset, modifier = Modifier} = Expr,
|
||||
case Name of
|
||||
false -> make_abs(Context, Modifier, Offset);
|
||||
"." -> make_rel(Context, Modifier, Dot, SectionName, Dot + Offset);
|
||||
_ ->
|
||||
case tunit:get_symbol(Tunit, Name) of
|
||||
#symbol{section = abs, st_value = Value} when Value =/= false ->
|
||||
make_abs(Context, Modifier, Value + Offset);
|
||||
_ -> make_rel(Context, Modifier, Dot, Name, Offset)
|
||||
expr_value(Expr, Tunit, DotSection, Dot, Context) ->
|
||||
#expr{modifier = Modifier} = Expr,
|
||||
case expr_value(Expr, Tunit, DotSection, Dot) of
|
||||
{Symbol, Offset} -> make_rel(Context, Modifier, Dot, Symbol, Offset);
|
||||
Value -> make_abs(Context, Modifier, Value)
|
||||
end.
|
||||
|
||||
%% An expression can evaluate to:
|
||||
%% - Value when is_integer(Value)
|
||||
%% - {Symbol, Addend} when is_string(Symbol), is_integer(Addend)
|
||||
expr_value(Expr, Tunit, DotSection, Dot) ->
|
||||
#expr{operand1 = Opnd1, operator = Op, operand2 = Opnd2} = Expr,
|
||||
case {Op, operand_value(Opnd1, Tunit, DotSection, Dot), operand_value(Opnd2, Tunit, DotSection, Dot)} of
|
||||
{'+', false, Value2} -> Value2;
|
||||
{'+', {Sect1, Off1}, Value2} when is_integer(Value2) -> {Sect1, Off1 + Value2};
|
||||
{'+', Value1, {Sect2, Off2}} when is_integer(Value1) -> {Sect2, Off2 + Value1};
|
||||
{'+', Value1, Value2} when is_integer(Value1), is_integer(Value2) -> Value1 + Value2;
|
||||
{'-', false, Value2} when is_integer(Value2) -> -Value2;
|
||||
{'-', {Sect, Off1}, {Sect, Off2}} -> Off1 - Off2;
|
||||
{'-', {Sect1, Off1}, Value2} when is_integer(Value2) -> {Sect1, Off1 - Value2};
|
||||
{'-', Value1, Value2} when is_integer(Value1), is_integer(Value2) -> Value1 - Value2
|
||||
end.
|
||||
|
||||
%% An operand can evaluate to:
|
||||
%% - false
|
||||
%% if the operand is absent
|
||||
%% - Value when is_integer(Value)
|
||||
%% if the operand is an integer or an absolute symbol
|
||||
%% - {Section, Offset} when is_string(Section), is_integer(Offset)
|
||||
%% if the operand is a label defined in the current translation unit
|
||||
%% - {Symbol, 0} when is_string(Symbol)
|
||||
%% if the operand is an undefined symbol
|
||||
operand_value(Operand, Tunit, DotSection, Dot) ->
|
||||
case Operand of
|
||||
false -> false;
|
||||
Value when is_integer(Value) -> Value;
|
||||
"." -> {DotSection, Dot};
|
||||
Symbol when is_list(Symbol) ->
|
||||
case tunit:get_symbol(Tunit, Symbol) of
|
||||
#symbol{section = abs, st_value = Value} when Value =/= false -> Value;
|
||||
#symbol{section = Section, st_value = Value} when Value =/= false -> {Section, Value};
|
||||
_ -> {Symbol, 0}
|
||||
end
|
||||
end.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
%%% -*- erlang-indent-level: 2 -*-
|
||||
%%%
|
||||
%%% input processing phase for pdp10-elf as
|
||||
%%% Copyright (C) 2013-2020 Mikael Pettersson
|
||||
%%% Copyright (C) 2013-2023 Mikael Pettersson
|
||||
%%%
|
||||
%%% This file is part of pdp10-tools.
|
||||
%%%
|
||||
@@ -634,18 +634,19 @@ insn_fixup(Tunit, Insn) ->
|
||||
Insn#s_insn{address = expr_fixup(Tunit, Address)}.
|
||||
|
||||
expr_fixup(Tunit, Expr) ->
|
||||
case Expr of
|
||||
#expr{symbol = {Number, Direction}} ->
|
||||
LabelSerial = local_label_serial(Tunit, Number),
|
||||
ReferenceSerial =
|
||||
case Direction of
|
||||
$b -> LabelSerial;
|
||||
$f -> LabelSerial + 1
|
||||
end,
|
||||
Name = local_label_name(Number, ReferenceSerial),
|
||||
Expr#expr{symbol = Name};
|
||||
_ -> Expr
|
||||
end.
|
||||
#expr{operand1 = Operand1, operand2 = Operand2} = Expr,
|
||||
Expr#expr{operand1 = operand_fixup(Tunit, Operand1),
|
||||
operand2 = operand_fixup(Tunit, Operand2)}.
|
||||
|
||||
operand_fixup(Tunit, {Number, Direction}) ->
|
||||
LabelSerial = local_label_serial(Tunit, Number),
|
||||
ReferenceSerial =
|
||||
case Direction of
|
||||
$b -> LabelSerial;
|
||||
$f -> LabelSerial + 1
|
||||
end,
|
||||
local_label_name(Number, ReferenceSerial);
|
||||
operand_fixup(_Tunit, Operand) -> Operand.
|
||||
|
||||
%% Initialization --------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
%%% -*- erlang-indent-level: 2 -*-
|
||||
%%%
|
||||
%%% parser for pdp10-elf as
|
||||
%%% Copyright (C) 2013-2020 Mikael Pettersson
|
||||
%%% Copyright (C) 2013-2023 Mikael Pettersson
|
||||
%%%
|
||||
%%% This file is part of pdp10-tools.
|
||||
%%%
|
||||
@@ -605,8 +605,10 @@ section_name(ScanState) ->
|
||||
%%
|
||||
%% <plain_expr> ::= "(" <plain_expr> ")"
|
||||
%% | "-"? <uinteger>
|
||||
%% | (<symbol> | <local_label>) (("+" | "-") <uinteger>)?
|
||||
%% | <symbol_or_label> (("+" | "-") <uinteger>)?
|
||||
%% | <symbol_or_label> "-" <symbol_or_label>
|
||||
%%
|
||||
%% <symbol_or_label> := <symbol> | <local_label>
|
||||
%% <modifier> ::= "w" | "b" | "h"
|
||||
%%
|
||||
%% Note: <modifier> describes how the value should be represented, which also
|
||||
@@ -709,6 +711,10 @@ do_expr_offset(ScanState, Symbol, IsMinus, Modifier) ->
|
||||
case scan:token(ScanState) of
|
||||
{ok, {_Location, {?T_UINTEGER, UInt}}} ->
|
||||
{ok, mk_symbol_expr(Symbol, if IsMinus -> -UInt; true -> UInt end, Modifier)};
|
||||
{ok, {_Location, {?T_LOCAL_LABEL, Number, Direction}}} when IsMinus ->
|
||||
{ok, mk_diff_expr(Symbol, _Symbol2 = {Number, Direction}, Modifier)};
|
||||
{ok, {_Location, {?T_SYMBOL, Symbol2}}} when IsMinus ->
|
||||
{ok, mk_diff_expr(Symbol, Symbol2, Modifier)};
|
||||
ScanRes -> badtok("expected <uinteger> after <sign>", ScanRes)
|
||||
end.
|
||||
|
||||
@@ -720,9 +726,10 @@ symbol_modifier(Symbol) ->
|
||||
_ -> error
|
||||
end.
|
||||
|
||||
mk_integer_expr(Value, Modifier) -> #expr{symbol = false, offset = Value, modifier = Modifier}.
|
||||
mk_symbol_expr(Symbol, Modifier) -> #expr{symbol = Symbol, offset = 0, modifier = Modifier}.
|
||||
mk_symbol_expr(Symbol, Offset, Modifier) -> #expr{symbol = Symbol, offset = Offset, modifier = Modifier}.
|
||||
mk_integer_expr(Value, Modifier) -> #expr{operand1 = false, operator = '+', operand2 = Value, modifier = Modifier}.
|
||||
mk_symbol_expr(Symbol, Modifier) -> #expr{operand1 = false, operator = '+', operand2 = Symbol, modifier = Modifier}.
|
||||
mk_symbol_expr(Symbol, Offset, Modifier) -> #expr{operand1 = Symbol, operator = '+', operand2 = Offset, modifier = Modifier}.
|
||||
mk_diff_expr(Symbol1, Symbol2, Modifier) -> #expr{operand1 = Symbol1, operator = '-', operand2 = Symbol2, modifier = Modifier}.
|
||||
|
||||
%% String Lists ----------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
%%% -*- erlang-indent-level: 2 -*-
|
||||
%%%
|
||||
%%% translation unit declarations for pdp10-elf as.
|
||||
%%% Copyright (C) 2013-2020 Mikael Pettersson
|
||||
%%% Copyright (C) 2013-2023 Mikael Pettersson
|
||||
%%%
|
||||
%%% This file is part of pdp10-tools.
|
||||
%%%
|
||||
@@ -23,9 +23,13 @@
|
||||
|
||||
%% An expression occurring in a statement. (TODO: extend)
|
||||
|
||||
-type operand() :: string() % label or symbol, may be "."
|
||||
| {non_neg_integer(), $b | $f} % local label, eliminated before assembly
|
||||
| integer().
|
||||
-record(expr,
|
||||
{ symbol :: false | string() | {non_neg_integer(), $b | $f}
|
||||
, offset :: integer()
|
||||
{ operand1 :: operand() | false
|
||||
, operator :: '+' | '-'
|
||||
, operand2 :: operand()
|
||||
, modifier :: false | w | b | h
|
||||
}).
|
||||
-type expr() :: #expr{}.
|
||||
|
||||
Reference in New Issue
Block a user