as: add support for Sym1-Sym2 expressions

This commit is contained in:
Mikael Pettersson
2023-10-01 19:06:08 +02:00
parent 81903d1517
commit 39f938c7bb
4 changed files with 76 additions and 32 deletions

View File

@@ -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.

View File

@@ -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 --------------------------------------------------------------

View File

@@ -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 ----------------------------------------------------------------

View File

@@ -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{}.